Ответ 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);