SyncAdapter
/** * Define a sync adapter for the app. * <p/> * <p>This class is instantiated in {@link SyncService}, which also binds SyncAdapter to the system. * SyncAdapter should only be initialized in SyncService, never anywhere else. * <p/> * <p>The system calls onPerformSync() via an RPC call through the IBinder object supplied by * SyncService. */ class SyncAdapter extends AbstractThreadedSyncAdapter { /** * Constructor. Obtains handle to content resolver for later use. */ public SyncAdapter(Context context, boolean autoInitialize) { super(context, autoInitialize); } /** * Constructor. Obtains handle to content resolver for later use. */ public SyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) { super(context, autoInitialize, allowParallelSyncs); } @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { //您要在后台执行的作业。 Log.e("" + account.name, "Sync Start"); } }同步服务
/** * Define a Service that returns an IBinder for the * sync adapter class, allowing the sync adapter framework to call * onPerformSync(). */ public class SyncService extends Service { // 同步适配器实例的存储 private static SyncAdapter sSyncAdapter = null; // 用作线程安全锁的对象 private static final Object sSyncAdapterLock = new Object(); /* * Instantiate the sync adapter object. */ @Override public void onCreate() { /* * Create the sync adapter as a singleton. * Set the sync adapter as syncable * Disallow parallel syncs */ synchronized (sSyncAdapterLock) { if (sSyncAdapter == null) { sSyncAdapter = new SyncAdapter(getApplicationContext(), true); } } } /** * Return an object that allows the system to invoke * the sync adapter. */ @Override public IBinder onBind(Intent intent) { /* * Get the object that allows external processes * to call onPerformSync(). The object is created * in the base class code when the SyncAdapter * constructors call super() */ return sSyncAdapter.getSyncAdapterBinder(); } }Authenticator
public class Authenticator extends AbstractAccountAuthenticator { // 简单的构造函数 public Authenticator(Context context) { super(context); } // 不支持编辑属性 @Override public Bundle editProperties( AccountAuthenticatorResponse r, String s) { throw new UnsupportedOperationException(); } // 不要添加其他帐户 @Override public Bundle addAccount( AccountAuthenticatorResponse r, String s, String s2, String[] strings, Bundle bundle) throws NetworkErrorException { return null; } // 忽略尝试确认凭据 @Override public Bundle confirmCredentials( AccountAuthenticatorResponse r, Account account, Bundle bundle) throws NetworkErrorException { return null; } // 不支持获取身份验证令牌 @Override public Bundle getAuthToken( AccountAuthenticatorResponse r, Account account, String s, Bundle bundle) throws NetworkErrorException { throw new UnsupportedOperationException(); } // 不支持获取auth令牌的标签 @Override public String getAuthTokenLabel(String s) { throw new UnsupportedOperationException(); } // 不支持更新用户凭据 @Override public Bundle updateCredentials( AccountAuthenticatorResponse r, Account account, String s, Bundle bundle) throws NetworkErrorException { throw new UnsupportedOperationException(); } // 不支持该帐户的检查功能 @Override public Bundle hasFeatures( AccountAuthenticatorResponse r, Account account, String[] strings) throws NetworkErrorException { throw new UnsupportedOperationException(); } }Authenticator Service
/** * A bound Service that instantiates the authenticator * when started. */ public class AuthenticatorService extends Service { // 实例字段,用于存储身份验证器对象 private Authenticator mAuthenticator; @Override public void onCreate() { // 创建一个新的身份验证器对象 mAuthenticator = new Authenticator(this); } /* * When the system binds to this Service to make the RPC call * return the authenticator's IBinder. */ @Override public IBinder onBind(Intent intent) { return mAuthenticator.getIBinder(); } }AndroidManifest.xml添加项
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <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" /> <service android:name=".syncAdapter.SyncService" android:exported="true"> <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=".authenticator.AuthenticatorService"> <intent-filter> <action android:name="android.accounts.AccountAuthenticator" /> </intent-filter> <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> </service> <provider android:name=".provider.StubProvider" android:authorities="com.yourpackage.provider" android:exported="false" android:syncable="true" />res / xml / authenticator.xml
<?xml version="1.0" encoding="utf-8"?> <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="com.yourpackage" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:smallIcon="@mipmap/ic_launcher" />res / xml / syncadapter.xml
<?xml version="1.0" encoding="utf-8"?> <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="com.yourpackage.android" android:allowParallelSyncs="false" android:contentAuthority="com.yourpackage.provider" android:isAlwaysSyncable="true" android:supportsUploading="false" android:userVisible="false" />StubProvider
/* * Define an implementation of ContentProvider that stubs out * all methods */ public class StubProvider extends ContentProvider { /* * Always return true, indicating that the * provider loaded correctly. */ @Override public boolean onCreate() { return true; } /* * Return no type for MIME type */ @Override public String getType(Uri uri) { return null; } /* * query() always returns no results * */ @Override public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } /* * insert() always returns null (no URI) */ @Override public Uri insert(Uri uri, ContentValues values) { return null; } /* * delete() always returns "no rows affected" (0) */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } /* * update() always returns "no rows affected" (0) */ public int update( Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } }在成功登录后调用此函数以创建具有已登录用户ID的帐户来
public Account CreateSyncAccount(Context context, String accountName) { // 创建帐户类型和默认帐户 Account newAccount = new Account( accountName, "com.yourpackage"); // 获取Android客户经理的实例 AccountManager accountManager = (AccountManager) context.getSystemService( ACCOUNT_SERVICE); /* * Add the account and account type, no password or user data * If successful, return the Account object, otherwise report an error. */ if (accountManager.addAccountExplicitly(newAccount, null, null)) { /* * If you don't set android:syncable="true" in * in your <provider> element in the manifest, * then call context.setIsSyncable(account, AUTHORITY, 1) * here. */ } else { /* * The account exists or some other error occurred. Log this, report it, * or handle it internally. */ } return newAccount; }强制进行同步
Bundle bundle = new Bundle(); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_FORCE, true); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); ContentResolver.requestSync(null, MyContentProvider.getAuthority(), bundle);