SyncAdapter periodicsync() not triggering

一曲冷凌霜 提交于 2019-12-02 17:44:14

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);
malcubierre

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.

A periodic sync can only be run if its auto-sync setting is ON and it’s syncable=true. A better approach to this problem will be to use GCM. The server can send push notification to the device(s) whenever there’s a change the client needs to know about. On the client, we request a sync manually upon receiving such message. It’s more battery efficient and we get updated as soon as our server is, without waiting for the next sync cycle.

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.

This one works fine for me There are two mistakes in the training guide as far as explaining how to make addPeriodicSync work:

  1. 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);

  2. 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/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!