Android AccountManager帐号管理(一)
来源:互联网 发布:双色球选号过滤软件 编辑:程序博客网 时间:2024/06/08 06:22
AccountManager简介
AccountManager帐号管理器,集中管理apps注册的不同类型的帐号。
不同类型的帐号服务会使用不同的帐号登录和鉴权方式,所以AccountManager为不同类型的帐号提供一个插件式authenticator模块,authenticators自己处理帐号登录/认证的具体细节,也可以自己存储帐号信息
简言之,AccountManager是一个面向应用程序开发的组件,它提供了一套对应于IAccountManager协议的应用程序接口;这组接口通过Binder机制与系统服务AccountManagerService进行通信,协作完成帐号相关的操作。同时,AccountManager接收authenticators提供的回调,以便在帐号操作完成之后向调用此帐号服务的业务返回对应的接口,同时触发这个业务对结果的处理。
- authenticators 即注册帐号服务的app;
- 业务调用方 即使用authenticators提供的帐号服务的第三方,也可以是authenticator自己
使用AccountManager注册帐号服务
如果应用想要注册一个新的帐号服务,必须实现AbstractAccountAuthenticator类,这是创建一个account authenticator的抽象基础类;然后新建一个authenticator service,注册action必须为”android.accounts.AccountAuthenticator”,且该service要实现onBinder(android.content.Intent)方法,返回AbstractAccountAuthenticator实现类的实例
说下必须要注册一个action为”android.accounts.AccountAuthenticator”的authenticator service:
首先,AbstractAccountAuthenticator是创建一个account authenticator必须实现的抽象基础类,接口协议定义在IAccountAuthenticator中,是一个authenticator自定义自己登录/认证等的接口协议;
那如何将authenticator的实现回调给AccountManagerService,供其调起authenticator的具体实现呢?
就是通过action注册为”android.accounts.AccountAuthenticator”的authenticator service了:
这个action即为AccountManager#ACTION_AUTHENTICATOR_INTENT的常量值,系统服务AccountManagerService是通过bind到action为AccountManager#ACTION_AUTHENTICATOR_INTENT的intent service上来调起某个账号类型的authenticator service,然后通过调用这个service的getBinder()方法来获取AbstractAccountAuthenticator的实现实例,进而调用authenticator对帐号登录认证等服务的具体实现
至于每个帐号服务都定义一个action为”android.accounts.AccountAuthenticator”的service,那AccountManagerService是如何区分的呢?
当然是通过账号类型了,每个accountType只能对应一个authenticator
那系统是如何知道每个authenticator service对应的账号类型?
在AndroidManifest.xml中注册authenticator service时声明帐号属性的meta-data配置,声明的meta-data是一个name为 “android.accounts.AccountAuthenticator”的xml 资源(AccountManager#AUTHENTICATOR_META_DATA_NAME),该XML资源文件定义了account-authenticator用到的一些属性:如accountType;系统解析authenticator service info之后,loadXmlMetaData获取authenticator 的xml属性,然后利用 Xml.asAttributeSet即
final PackageManager pm = mContext.getPackageManager();final List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(new Intent("android.accounts.AccountAuthenticator", PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);for (ResolveInfo resolveInfo : resolveInfos) { android.content.pm.ServiceInfo si = service.serviceInfo; ComponentName componentName = new ComponentName(si.packageName, si.name); PackageManager pm = mContext.getPackageManager(); XmlResourceParser parser = null; try { parser = si.loadXmlMetaData(pm, "android.accounts.AccountAuthenticator") if (parser == null) { throw new XmlPullParserException("No " + mMetaDataName + " meta-data"); } AttributeSet attrs = Xml.asAttributeSet(parser); ...//解析authenticator xml的帐号属性 } ...}
注册一个测试帐号
创建一个继承自AbstractAccountAuthenticator的类TestAccountAuthenticator
public class TestAccountAuthenticator extends AbstractAccountAuthenticator { private Context mContext; public TestAccountAuthenticator(Context context) { super(context); mContext = context; } @Override public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) { return null; } @Override public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {//登录界面的定制化实现 Intent addAccountIntent = new Intent(mContext, LoginActivity.class); addAccountIntent.putExtra("authTokenType", authTokenType); if (options != null) { addAccountIntent.putExtras(options); } addAccountIntent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);//一定要把response传入intent的extra中,便于将登录操作的结果回调给AccountManager Bundle bundle = new Bundle(); bundle.putParcelable(AccountManager.KEY_INTENT, addAccountIntent); return bundle; } @Override public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, Account account) throws NetworkErrorException {//是否允许删除你的账号,这里是不允许删除,可自定义什么时候可以被删除,默认是true Bundle bundle = new Bundle(); bundle.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false); return bundle; } @Override public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {//自己实现:验证用户的密码 return null; } @Override public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {//自己完成获取鉴权token的流程 return null; } @Override public String getAuthTokenLabel(String authTokenType) { return null; } @Override public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { return null; } @Override public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException { return null; }}
创建一个authenticator service—TestAuthenticatiorService,实现onBinder()方法,在onBinder方法里返回TestAccountAuthentcator的实例
public class TestAuthenticatiorService extends Service { private static final String TAG = "XmAuthenticationService"; private TestAccountAuthenticator mAuthenticator; @Override public void onCreate() { super.onCreate(); mAuthenticator = new TestAccountAuthenticator(this); } @Nullable @Override public IBinder onBind(Intent intent) { return mAuthenticator.getIBinder(); }}
在AndroidManifest.xml文件中注册该TestAuthenticatorService
<service android:name=".TestAuthenticatiorService" 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>
其中,authenticator是一个xml的资源文件,定义了account的一些属性
<?xml version="1.0" encoding="utf-8"?> <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="com.test"//账号类型 android:icon="@drawable/icon"//设置-同步-添加 账号类型的icon android:smallIcon="@drawable/miniIcon"//小icon android:label="@string/label"//设置-同步-添加 账号类型的名称 android:accountPreferences="@xml/account_preferences"//在设置中展示的一些偏好 android:customTokens="false"//authenticator是否要自己处理auth token的存储和获取权限/>
ps:说下customTokens属性
如设置为true,就需要在TestAccountAuthenticator类的getAuthToken方法的实现中自己进行caller app的权限检查和token存储问题
如不设置(默认为false)或设置为false,则是使用AccountManager的权限检查和存储机制,默认只有签名相同的app才可调用getAuthToken()方法,存储在系统数据库中,但要app判断是否有效,失效要调用invalidate才可清除系统的存储
到这里,你就成功注册了一个新的帐号类型了
- Android AccountManager帐号管理(一)
- Android AccountManager帐号管理(二)
- android AccountManager and SyncManager
- android AccountManager and SyncManager
- android帐号管理
- AccountManager
- android帐号管理token问题
- 两个APP共享AccountManager管理的账号
- android 8.0 ---AccountManager之行为变更
- 帐号管理
- 帐号管理
- 帐号管理
- Android线程管理(一)
- iOS帐号、证书之漫谈(一)
- iOS帐号、证书之漫谈(一)
- MYSQL用户帐号管理
- C# 管理WinNt 帐号
- Linux:帐号管理
- JavaScript的遍历
- 调用服务的几种方式
- C\C++语言指针的强大用法之减少内存申请次数
- 多线程
- 你不一定看得懂的朴素贝叶斯算法原理
- Android AccountManager帐号管理(一)
- Android 属性动画总结
- R 文件报错解决方式
- c内存操作和宏条件编译
- Bone Collector
- API
- 9.1 在函数上添加包装器
- 指针数组与数组指针
- 机器学习基石-Training versus Testing