SyncAdapter periodicsync() не запускается

Я пытаюсь понять, как работает syncAdapter, я использовал примерSync Adapter в качестве примера/отправной точки, и я основал свой первый тест на нем. Единственное различие заключается в том, что я не работаю с поставщиком контактов по умолчанию, но мне нужен один из моих.

Этот метод является тем же самым, что и в демонстрации sampleSyncAdapter (в AccountAuthenticatorActivity), я только что добавил периодическую синхронизацию.

    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();
}

В методе perfomSync() у меня есть следующий метод:

    @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");
}

Здесь я просто называю простой веб-сервис SAP и показываю его в журнале. Теперь у меня есть два вопроса:

  • SYNC не запускается автоматически, когда я добавляю свою учетную запись в настройки. Мне нужно войти в учетную запись и установить флажок, чтобы начать синхронизацию?
  • Синхронизация не запускается каждые 30 секунд в этом примере... Нужно ли добавлять что-то в метод perfomSync(), чтобы система могла знать, что синхронизация выполнена и что запуск может начаться?

В этот момент я не пишу значения в contentProvider, просто потому, что я пытаюсь выяснить, как синхронизация работает подробно.

В настоящее время я тестирую эмулятор Android.

Заранее благодарим за отзыв.

С уважением,

Робин

Ответ 1

Я также боролся с периодической синхронизацией с адаптером синхронизации. Я могу запустить мой SyncAdapter вручную с помощью requestSync, но addPeriodicSync не будет срабатывать.

Я заметил, что в всех примерах, в "Настройки" > "Учетные записи" была показана учетная запись SyncAdapter с небольшим "колесом синхронизации" (обычно зеленый, если он синхронизируется нормально, красный, если не удалось синхронизировать недавно), а также временную метку "Last Synced". Моя учетная запись (фиктивная учетная запись, скопированная и вставленная из Документов Google) не имела ничего похожего на колесо синхронизации или временную метку.

Дальнейшее копание выявило то, что оказалось проблемой: у моего провайдера контента не было метки в нем XML (я использовал его ранее без каких-либо проблем, поэтому я просмотрел эту часть документация). Добавление простой метки для моего провайдера контента вызвало ее появление в моей учетной записи в настройках вместе с колесом синхронизации и меткой времени.

Вот код, взятый из моего приложения для вдохновения. Надеюсь, это поможет кому-то, где-нибудь!

/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/пример/базы данных/данных/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 для провайдера содержимого для отображения в учетных записях)

<?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. Я вызываю этот код после первого запуска мастера настройки, но вы можете его назвать в любом месте. Это попытается синхронизировать каждые 30 секунд (используется для тестирования). Обратите внимание, что Документы Google для этого в настоящее время ошибочны, так как он упоминает, что ему требуется миллисекунды вместо секунд. Другое дело, что вы не можете передать null как пакет. Это приведет к исключению IllegalArgumentException или что-то подобное.

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

Ответ 2

Периодическая синхронизация не запускается на некоторых устройствах, если опция синхронизации не установлена. Я с ума с этой проблемы с Samsung Galaxy Grand 2 недавно...

enter image description here

Ответ 3

Я просто часами стучал головой о стену, пытаясь понять, почему периодическая синхронизация не работает. Оказывается, частота опроса должна быть в секундах (буквально), а не в миллисекундах, а не в секундах в миллисекундах. Например, если вы хотите синхронизировать каждую минуту с половиной, вам нужно позвонить:

            ContentResolver.addPeriodicSync(
                    account,
                    authority,
                    Bundle.EMPTY,
                    90
            );

Кроме того, переданный пакет не может быть нулевым, как в документации, он выдает исключение NullPointerException.

Ответ 4

Периодическая синхронизация может выполняться только в том случае, если ее автосинхронизация включена, а ее синхронизируемая = истинная. Лучшим подходом к этой проблеме будет использование GCM. Сервер может отправлять push-уведомления устройству (-ам) всякий раз, когда это необходимо знать клиенту. На клиенте мы запрашиваем синхронизацию вручную после получения такого сообщения. Его более эффективная батарея, и мы обновляемся, как только наш сервер, не дожидаясь следующего цикла синхронизации.

Ответ 5

Периодическая синхронизация не будет работать, если внутренняя память устройства почти заполнена, даже если все ваши настройки синхронизации установлены правильно. Я думаю, синхронизация прекратит работу, если используется 96 или 97% памяти. Я не знаете, что это их положение, чтобы заставить его работать, даже если память почти заполнена. Вы можете наблюдать ту же проблему в приложении gmail на мобильном телефоне Android, где синхронизация не будет работать, когда память почти заполнена. Вы не можете получать или отправлять сообщения с помощью приложения gmail для Android, когда память устройства почти заполнена.