I'm trying ty figure out how the syncAdapter works, I used the sampleSync Adapter as an example/starting point and I based my first test on it. The only difference is that I'm not working with the default contacts provider, but that I need one of my own.
This method is kinda the same as in the sampleSyncAdapter demo (in AccountAuthenticatorActivity), i've just added the periodic sync.
public void finishLogin(String authToken) {
Log.i(TAG, "finishLogin()");
final Account account = new Account(mUsername, "be.company.syncAdapterTest");
if(mRequestNewAccount) {
mAccountManager.addAccountExplicitly(account, mPassword, null);
ContentResolver.setIsSyncable(account, MY_AUTHORITY, 1);
Bundle params = new Bundle();
params.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
params.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false);
params.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
ContentResolver.addPeriodicSync(account, MY_AUTHORITY, params, 30);
ContentResolver.setSyncAutomatically(account, MY_AUTHORITY, true);
ContentResolver.requestSync(account,MY_AUTHORITY,params);
} else {
mAccountManager.setPassword(account, mPassword);
}
final Intent intent = new Intent();
intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, "ACCOUNT_TEST");
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, "be.company.syncAdapterTest");
setAccountAuthenticatorResult(intent.getExtras());
setResult(RESULT_OK, intent);
finish();
}
In the perfomSync() method i have the following method:
@Override
public void onPerformSync(Account account, Bundle extras, String authority,
ContentProviderClient provider, SyncResult syncResult) {
Log.d(TAG, "onPerformSync() start");
// Testje
try {
final String authToken = mAccountManager.blockingGetAuthToken(account, "be.company.syncAdapterTest", NOTIFY_AUTH_FAILURE);
Log.d(TAG, SAPNetworkUtilities.getWeek(account, authToken, getRandomDate()));
} catch (OperationCanceledException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AuthenticatorException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d(TAG, "onPerformSync() end");
}
Here I just call a simple SAP webservice and show it in the log. Now I have following two questions:
At this moment i do not write the values in the contentProvider, just because i'm trying to figure out how the sync works in detail.
Currently I'm testing on the Android emulator.
Thanks in advance for your feedback.
Kind regards,
Robin
This one works fine for me There are two mistakes in the training guide as far as explaining how to make addPeriodicSync work:
You must call ContentResolver.setSyncAutomatically with true as the third (sync) parameter to enable syncing for your adaptor before addPeriodicSync. like this : ContentResolver.setSyncAutomatically(account,MY_AUTHORITY,true);
The fourth (pollFrequency) parameter of ContentResolver.addPeriodicSync is a number of seconds, as stated here, and not milliseconds, as implied in the training guide. The demo code for addPeriodicSync in the training guide will cause a sync once every thousand hours instead of once an hour. So the minimum frequency is 1 minute.
Refer To this http://digitalassassin.net/2014/03/contentresolver-addperiodicsync-doesnt-work-never-syncs/
Periodic syncing will not work if the device internal storage is almost full, even if all your syncing configurations are set in the right way.I think syncing will stop functioning if 96 or 97% of memory is used.I don't know is their any provision to make it working even if memory is almost full. You can observe the same issue in gmail application in android mobile, where the sync will not work when memory is almost full.You can't receive or send message using android gmail application when device memory is almost full.
I was also struggling with periodic syncing with the sync adapter. I could fire my SyncAdapter manually with requestSync, but addPeriodicSync would not fire.
I noticed that in all of the examples, going into Settings->Accounts showed the SyncAdapter's account with a little "sync wheel" (usually green if it's syncing fine; red if it failed to sync recently) along with a "Last Synced" timestamp. My account (a dummy account copied and pasted from the Google Docs) didn't have anything like a sync wheel or timestamp listed.
Further digging exposed what turned out to be the problem: my content provider didn't have a label in it's XML (I was using it previously with no problems, so I skimmed through that part of the documentation). Adding a simple label for my content provider caused it to show up under my account in the Settings, along with a sync wheel and timestamp.
Here's some code taken from my app for inspiration. Hopefully it will help someone, somewhere!
/res/xml/sync_adapter.xml
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.example.database"
android:allowParallelSyncs="false"
android:contentAuthority="com.example.database.data.provider"
android:isAlwaysSyncable="true"
android:supportsUploading="false"
android:userVisible="true" />
/com/example/database/data/MySyncAdapter
public class MySyncAdapter extends AbstractThreadedSyncAdapter {
private static final String TAG = MySyncAdapter.class.getSimpleName();
Context context;
public MySyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
this.context = context;
}
public MySyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) {
super(context, autoInitialize, allowParallelSyncs);
this.context = context;
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
Log.e(TAG, "Performing Sync");
}
}
AndroidManifest.xml (NEEDS Label for Content Provider to show up in Accounts)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.database">
<uses-sdk tools:node="replace" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:logo="@drawable/chef_collection_logo_white"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<provider
android:name="com.example.database.data.MyContentProvider"
android:authorities="com.example.database.data.provider"
android:label="my provider"
android:exported="false"
android:multiprocess="true"
android:syncable="true" />
<activity
android:name=".app.MainActivity"
android:label="@string/title_activity_main">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.example.database.data.AuthenticatorService"
android:exported="true"
android:process=":auth">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
<service
android:name="com.example.database.data.MySyncAdapterService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/sync_adapter" />
</service>
</application>
</manifest>
MainActivity. I call this code after the first-run setup wizard, but you can call it anywhere. This will attempt to sync every 30 seconds (used for testing). Note that the Google Docs for this are currently wrong, as it mentions that it wants milliseconds instead of seconds. Another thing to note is that you cannot pass null as a bundle. Doing so will throw an IllegalArgumentException or something similar.
//Create Account
mAccount = createSyncAccount(this);
//Turn on periodic syncing
ContentResolver resolver = getContentResolver();
resolver.setIsSyncable(mAccount, AUTHORITY, 1);
resolver.setSyncAutomatically(mAccount, AUTHORITY, true);
resolver.addPeriodicSync(
mAccount,
AUTHORITY,
Bundle.EMPTY,
30);
Periodic Sync does not trigger in some devices if sync option is not set. I went crazy with this issue with a Samsung Galaxy Grand 2 recently...
I just banged my head against a wall for hours trying to figure out why periodic sync wasn't working. It turns out that the poll frequency needs to be in seconds (literal) not milliseconds, and not seconds in milliseconds. So, for example, if you want it to sync every minute and a half, you would need to call:
ContentResolver.addPeriodicSync(
account,
authority,
Bundle.EMPTY,
90
);
Also, the bundle passed in cannot be null as it is in the documentation, it will throw a NullPointerException.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With