参考
> Android提供的一个同步框架,它将所有的数据传输放到同一个地方,系统智能的安排数据传输,优化电池性能。
-
为什么使用SyncAdapter?
SyncAdapter可以智能安排数据传输,如检查网络连接、下载失败后重试等。可以根据不同条件自动发起数据传输,如服务器数据变更、定时同步等。
使用SyncAdapter可以加快应用的加载时间、实现离线功能,可以在数据及时同步和减少网络调用以节约电池电量之间达到一种平衡局面。 -
何时使用SyncAdapter?
SyncAdapter适用于需要同步本地数据和在线账户信息的应用,如电子邮件的定时收取、笔记应用的云备份、天气应用的及时同步等。
SyncAdapter设计为必须与用户账户绑定,即使你的应用不需要账户认证,也需要实现相关的类来处理账户,并可以将其隐藏。
-
创建SyncAdapter:
- 继承AbstractThreadedSyncAdapter基类,在构造方法中做一些初始化设置,如获取ContentResolver实例等。
- 在onPerformSync()方法中添加数据传输的代码,框架将自动将其放在后台线程中运行。除同步相关任务外,也应将网络相关的任务放在此处,将网络操作集中处理可以降低频繁发起网络的功耗。
- 可添加辅助方法syncImmediately(),调用此方法来立即执行同步,可用于“刷新”操作:
-
创建SyncService服务
该服务用于将SyncAdapter开放给framework调用,即将SyncAdapter的binder对象传给framework。通过这个binder,framework即可调用onPerformSync()方法。
在onCreate()中以单实例形式实例化SyncAdapter,这样会将SyncAdapter的实例化延迟到framework首次传输数据创建Service的时候执行。实例化过程须保证线程安全,避免将多次同步响应添加到队列。public class SyncService extends Service { // Storage for an instance of the sync adapter private static SyncAdapter sSyncAdapter = null; // Object to use as a thread-safe lock 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类
该类继承了AbstractAccountAuthenticator类,用于管理账户认证。如果你的应用不需要账户认证,可以提供一个仅包含方法实现的类,Authenticator的信息将被忽略。
/* * Implement AbstractAccountAuthenticator and stub out all * of its methods */ public class Authenticator extends AbstractAccountAuthenticator { // Simple constructor public Authenticator(Context context) { super(context); } // Editing properties is not supported @Override public Bundle editProperties( AccountAuthenticatorResponse r, String s) { throw new UnsupportedOperationException(); } // Don't add additional accounts @Override public Bundle addAccount( AccountAuthenticatorResponse r, String s, String s2, String[] strings, Bundle bundle) throws NetworkErrorException { return null; } // Ignore attempts to confirm credentials @Override public Bundle confirmCredentials( AccountAuthenticatorResponse r, Account account, Bundle bundle) throws NetworkErrorException { return null; } // Getting an authentication token is not supported @Override public Bundle getAuthToken( AccountAuthenticatorResponse r, Account account, String s, Bundle bundle) throws NetworkErrorException { throw new UnsupportedOperationException(); } // Getting a label for the auth token is not supported @Override public String getAuthTokenLabel(String s) { throw new UnsupportedOperationException(); } // Updating user credentials is not supported @Override public Bundle updateCredentials( AccountAuthenticatorResponse r, Account account, String s, Bundle bundle) throws NetworkErrorException { throw new UnsupportedOperationException(); } // Checking features for the account is not supported @Override public Bundle hasFeatures( AccountAuthenticatorResponse r, Account account, String[] strings) throws NetworkErrorException { throw new UnsupportedOperationException(); } }
-
创建AuthenticatorService服务
此服务提供给SyncAdapter framework,用于调用Authenticator的方法。
在onCreat()中创建Authenticator对象,在onBind()中返回一个binder对象用于在Authenticator和framework间传输数据。/** * A bound Service that instantiates the authenticator * when started. */ public class AuthenticatorService extends Service { ... // Instance field that stores the authenticator object private Authenticator mAuthenticator; @Override public void onCreate() { // Create a new authenticator object 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(); } }
-
添加Authenticator的元数据文件
元数据写在一个xml文件中,用于声明账户类型和一些显示给用户的信息,保存在/res/xml/目录。
文件名自定义,一般定义为authenticator.xml,根标签为<account-authenticator>,一般有以下属性:android:accountType
framework把账户类型作为识别SyncAdapter的内部标识,对于需要验证账户的应用,账户类型会和账户名一起发送给服务器进行验证;对于不需要验证的应用,也要提供账户类型,用于标明一个控制域,framework用这个账户类型类管理你的SyncAdapter,但是不会发送给服务器。android:icon
指向用做图标的Drawable资源。如果在res/xml/syncadapter.xml 设置了android:userVisible="true” 属性将Sync adapter对用户可见,则必须要提供一个图标资源。它将显示在“设置”应用的“账号”一项中。-
android:smallIcon
小图标,根据屏幕尺寸可能在设置中代替icon属性。
a- ndroid:label
标识账户类型,一般为应用名。<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="example.com"
android:icon="@drawable/ic_launcher"
android:smallIcon="@drawable/ic_launcher"
android:label="@string/app_name"/>
-
在清单文件中声明AuthenticatorService
<service android:name="com.example.android.syncadapter.AuthenticatorService"> <intent-filter> <action android:name="android.accounts.AccountAuthenticator"/> </intent-filter> <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> </service>
<intent-filter>设置了通过actionandroid.accounts.AccountAuthenticator启动的filter。这个action是由系统发送的。当被触发时,系统会启动封装了你的Authtenticator的AuthenticatorService。
<meta-data>声明了authenticator的元数据。通过android:name 属性将meta-data与认证框架关联。android:resource指定元数据文件。
其他步骤参考原链接