How Do I Implement An Account On Android Without A Syncadapter
Solution 1:
Since this is the only question I've seen related to this problem, here's a >year late answer. I also came across the permanent wake-lock problem due to the android system syncing my custom account automatically.
The best way to handle this, which requires minimum code and actually makes it so the account never syncs unless specifically called to sync in code:
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0);
Now this requires that the moment you create your account you call this static method. Whereas the first parameter being the account to set this setting for, the second parameter being the used contentprovider's authority, and the third being the integer that when set to a positive number enables syncing, when set to 0 disables syncing and when set to anything else makes it unknown. The authority to use can be found inside your "sync_something.xml" under the contentAuthority attribute, which is used by your SyncAdapter :
<sync-adapterxmlns:android="http://schemas.android.com/apk/res/android"android:contentAuthority="com.android.contacts"android:accountType="com.myapp.account"/><!-- This being your own account type-->
The above xml file is specified inside the service part of your AndroidManifest.xml:
<serviceandroid:name=".DummySyncAdapterService"exported="true"android:process=":contacts"><intent-filter><actionandroid:name="android.content.SyncAdapter" /></intent-filter><meta-dataandroid:name="android.content.SyncAdapter"android:resource="@xml/sync_something" /><!--This points to your SyncAdapter XML--></service>
This is the code snippet I use to create my custom account inside my LoginActivity:
Accountaccount=newAccount("John Doe", "com.myapp.account");
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0);
AccountManageram= AccountManager.get(LoginActivity.this);
booleanaccountCreated= am.addAccountExplicitly(account, "Password", null);
Bundleextras= LoginActivity.this.getIntent().getExtras();
if(extras != null){
if (accountCreated) {
AccountAuthenticatorResponseresponse= extras.getParcelable(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
Bundleresult=newBundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, "John Doe");
result.putString(AccountManager.KEY_ACCOUNT_TYPE, "com.myapp.account");
response.onResult(result);
}
}
The great part of this is that when the system tries to sync the service, it checks if the service is syncable first, if it is set to false it cancels the syncing. Now you don't have to create your own ContentProvider
nor does your ContentProvider
get shown under Data and Synchronization. However you do need to have a stub implementation of AbstractThreadedSyncAdapter which returns an IBinder inside it's onBind method. And last but not least it makes it so that an user can't enable syncing or use the "Sync Now" button for this account unless you've added the functionality inside your app.
Solution 2:
I sort of solved my own problem: you cannot return null
from the onBind
method of your service - you must return the IBinder
of an AbstractThreadedSyncAdapter
.
This has the undesired effect of adding an entry into the Data and Synchronization section of the account settings page, even though my implementation of AbstractThreadedSyncAdapter
does nothing; I was hoping to avoid this.
To summarize, in order to make use of the accounts system in Android you must:
- Implement a service that has an
IntentFilter
forandroid.content.SyncAdapter
. - This service must return the
IBinder
of anAbstractThreadedSyncAdapter
implementation from it'sonBind
method. - This then necessitates that you have a
ContentProvider
(can just be a stub implementation) that is referred to as thecontentAuthority
in your SyncAdapter XML file. - This has the down-side that your ContentProvider is listed under the Data and Synchronization header on your account settings page.
Post a Comment for "How Do I Implement An Account On Android Without A Syncadapter"