0

Have an issue with using of SyncAdapter. I've created it as in this guide, but when I try to use addPeriodicSync I don't get any effect.

I read all answers which I found on Stack Overflow but still don't have any idea where is the trouble. Kindly ask about help.

Code:

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.igordotsenko.dotsenkorssreader" >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_SYNC_STATS" />

    <application
        android:name="com.activeandroid.app.Application"
        android:allowBackup="true"
        android:icon="@mipmap/ic_rss"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".ItemListActivity" >
        </activity>
        <activity android:name=".ItemContentActivity" >
        </activity>

        <service android:name=".RefreshService" />

        <provider
            android:name=".ReaderContentProvider"
            android:authorities="com.igordotsenko.dotsenkorssreader"
            android:enabled="true"
            android:exported="true" >
        </provider>

        <service
            android:name=".syncadapter.SyncService"
            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/syncadapter" />
        </service>

        <service
            android:name=".syncadapter.AuthenticatorService"
            android:exported="true"
            >
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator"/>
            </intent-filter>
            <meta-data
                android:name="android.accounts.AccountAuthenticator"
                android:resource="@xml/authenticator" />

        </service>
    </application>

</manifest>

SyncAdapter implementation

package com.igordotsenko.dotsenkorssreader.syncadapter;

import android.accounts.Account;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SyncResult;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;

import com.igordotsenko.dotsenkorssreader.ReaderContentProvider;

public class ReaderSyncAdapter extends AbstractThreadedSyncAdapter {
    public  static final String SA_LOG = "syncAdapter_log";

    private static final String AUTHORITY = "com.igordotsenko.dotsenkorssreader";
    private static final Uri CHANNEL_CONTENT_URI = Uri.parse(
            "content://" + AUTHORITY + "/" + ReaderContentProvider.ReaderRawData.CHANNEL_TABLE);

    private static final Uri ITEM_CONTENT_URI = Uri.parse(
            "content://" + AUTHORITY + "/" + ReaderContentProvider.ReaderRawData.ITEM_TABLE);

    private ContentResolver contentResolver;


    public ReaderSyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);

        this.contentResolver = context.getContentResolver();
        Log.i(SA_LOG, "ReaderSyncAdapter created");
    }


    @Override
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
        Log.i(SA_LOG, "onPerformSync started");
        // trying to crash my programm to understand, that onPerforSync was started. Brutal,isn't it?
        String str = "a";

        if ( true ) str = null;

        str.equals("a");
    }
}

SyncService

package com.igordotsenko.dotsenkorssreader.syncadapter;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import java.util.Objects;

public class SyncService extends Service {
    private static final Object syncAdapterLock = new Object();
    private static ReaderSyncAdapter syncAdapter;

    public SyncService() {
        synchronized (syncAdapterLock) {
            Log.i(ReaderSyncAdapter.SA_LOG, "SyncService started");
            if ( syncAdapter == null )
                syncAdapter = new ReaderSyncAdapter(getApplicationContext(), true);
            Log.i(ReaderSyncAdapter.SA_LOG, "SyncService finished");
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(ReaderSyncAdapter.SA_LOG, "SyncService onBind");
        return syncAdapter.getSyncAdapterBinder();
    }
}

syncadapter.xml

<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
    android:contentAuthority="com.igordotsenko.dotsenkorssreader"
    android:accountType="dummy.com"
    android:userVisible="false"
    android:supportsUploading="false"
    android:allowParallelSyncs="false"
    android:isAlwaysSyncable="true"
    />

AuthenticatorService

package com.igordotsenko.dotsenkorssreader.syncadapter;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class AuthenticatorService extends Service {
    private ReaderAccountAuthenticator readerAccountAuthenticator;

    public AuthenticatorService() {
        readerAccountAuthenticator = new ReaderAccountAuthenticator(this);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return readerAccountAuthenticator.getIBinder();
    }
}

ReaderAccountAuthenticator

Just basic methods withoud implementation as my account is just "dummy"

authenticator.xml

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="dummy.com"
    />

Usage in MainActivity in onCreate() method:

account = new Account(ACCOUNT, ACCOUNT_TYPE);
        AccountManager accountManager = (AccountManager) MainActivity.this.getSystemService(ACCOUNT_SERVICE);
        accountManager.addAccountExplicitly(account, null, null);

        ContentResolver.setIsSyncable(account, AUTHORITY, 1);
        ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
        ContentResolver.addPeriodicSync(account, AUTHORITY, Bundle.EMPTY, 2);
Igor Dotsenko
  • 85
  • 1
  • 8

3 Answers3

3

I have found that issue was in that fact, that minimal interval for periodic synchronization is 1 minute, so synchronization was triggered every minute, but not 2 seconds as I set.

Issue solved.

Igor Dotsenko
  • 85
  • 1
  • 8
  • 1
    @user1506104 My answer was actual for Kit-Kat version, and I found [it in source code](https://android.googlesource.com/platform/frameworks/base/+/kitkat-mr1-release/services/java/com/android/server/content/ContentService.java#366). Now it seems to be set at least for 1 hour, which (see `pollFrequency` in [docs](https://developer.android.com/reference/android/content/ContentResolver.html#addPeriodicSync(android.accounts.Account,%20java.lang.String,%20android.os.Bundle,%20long))) – Igor Dotsenko Oct 19 '16 at 12:46
1

addPeriodicSync() only works with supportsUploading as true in your syncadapter.xml. That's it.

android:supportsUploading="true"
Shahbaz Akhtar
  • 303
  • 2
  • 9
0

The periodic sync should be more, as stated in the documentation:

… how frequently the sync should be performed, in seconds. On Android API level 24 and above, a minimum interval of 15 minutes is enforced. On previous versions, the minimum interval is 1 hour.

So, if you are working on it with short intervals, it will appear that it is not working.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Jojo Gee
  • 17
  • 4