官方文档:https://developer.android.com/training/sync-adapters/index.html
1.简介
在Android设备和web服务器之间同步数据会使你的应用更实用,更吸引用户,例如,将手机数据传到服务端实现数据备份,将数据从服务端取回让用户能够脱机使用。在某些情况下,用户会发现这样会更方便:通过web修改信息然后在手机上就可以继续使用,或者隔一段时间将手机上的数据上传到一个总存储区。
虽然你可以在应用中设计自己的数据传输系统,但也应该考虑一下用Android的sync adater框架。它可以协助管理和自动发起数据传输,也可以协调不同应用的同步操作。使用这个同步框架比自己设计数据传输策略有如下优势:
- 插件架构:
可以将数据传输的代码以可调用组件的形式添加到系统中。
- 自动执行:
可以根据不同条件自动发起数据传输,比如数据变更,间隔一定时间,或者是每天定时。而且,系统会将暂时不能运行的操作添加到队列里,在可能的情况下重新发起。
- 自动检查网络:
系统只会在有网络的情况下发起数据传输
- 优化电池性能:
可以集中处理数据传输任务。将你的应用的数据传输与其他应用的传输结合,减少系统切换网络的次数,从而降低功耗。
- 账号管理认证:
如果你的应用需要用户认证功能,你可以选择在数据传输中整合进账号管理认证。
1.1能用来做什么
- Facebook可以定期更新朋友的最新信息,将最新近况和心情短语集成入联系人中。
- 笔记应用的云备份
- 账户信息的同步
2.同步框架结构
账号同步框架组成部分有三,如上。三者缺一不可。账号是入口,里面可以进行账号验证操作,当然不需要这个功能,相应方法返回false或者null即可。通过了账号认证之后,到了同步管理,里面来进行数据的同步的操作,至于数据发生冲突的具体逻辑需要你来处理。还有个StubProvider,是用来配合同步更新操作的。
3.账号管理
3.1AuthenticationService类
- AuthenticationService是一个继承Service的服务,目的是提供跨进程调用,供系统同步框架调用。
- 固定的Action为android.accounts.AccountAuthenticator
下面是manifest中的注册:
<service
android:name=".AuthenticatorService"
android:enabled="true"
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>
对应的服务:
public class AuthenticatorService extends Service {
//mAuthenticator目的是作为账号认证
private Authenticator mAuthenticator;
public AuthenticatorService() {
}
@Override
public void onCreate() {
super.onCreate();
mAuthenticator = new Authenticator(this);
}
@Override
public IBinder onBind(Intent intent) {
//主要起作用的mAuthenticator
return mAuthenticator.getIBinder();
}
}
3.2Authenticator类
Authenticator是一个继承自AbstractAccountAuthenticator的类,AbstractAccountAuthenticator是一个虚类,它定义处理手机“设置”里“账号与同步”中Account的添加、删除和验证等功能的基本接口,并实现了一些基本功能。
AbstractAccountAuthenticator里面有个继承于IAccountAuthenticator.Stub的内部类,以用来对AbstractAccountAuthenticator的远程接口调用进行包装。我们可以通过AbstractAccountAuthenticator的getIBinder()方法,返回内部类的IBinder形式,以便对此类进行远程调用,如上面代码onBind方法中的调用。
其中比较重要需要重载的方法是addAccount():
@Override
public Bundle addAccount(AccountAuthenticatorResponse accountAuthenticatorResponse, String s, String s1, String[] strings, Bundle bundle) throws NetworkErrorException {
Log.d(TAG, "Authenticator addAccount : ");
Intent intent = new Intent("com.jiahui.xx.syncadapter");
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, accountAuthenticatorResponse);
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
//return null;
}
如上图,这个addAccount()在用户进入设置-账户-添加账户的时候触发的,这里面把自己设置账户的页面的信息封装给bundle,然后传出去即可。如果返回null表示不做任何触发。
3.3authenticator.xml
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.crazyman.accountsyncdemo.type"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"