Android AccountManager帐号管理(一)
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即
注冊一個測試帳號
創建一個繼承自AbstractAccountAuthenticator的類TestAccountAuthenticator
public class TestAccountAuthenticator extends AbstractAccountAuthenticator {private Context mContext;public TestAccountAuthenticator(Context context) {super(context);mContext = context;}@Overridepublic Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {return null;}@Overridepublic 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中,便于將登錄操作的結果回調給AccountManagerBundle bundle = new Bundle();bundle.putParcelable(AccountManager.KEY_INTENT, addAccountIntent);return bundle;}@Overridepublic Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response, Account account) throws NetworkErrorException {//是否允許刪除你的賬號,這里是不允許刪除,可自定義什么時候可以被刪除,默認是trueBundle bundle = new Bundle();bundle.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);return bundle;}@Overridepublic Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options)throws NetworkErrorException {//自己實現:驗證用戶的密碼return null;}@Overridepublic Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)throws NetworkErrorException {//自己完成獲取鑒權token的流程return null;}@Overridepublic String getAuthTokenLabel(String authTokenType) {return null;}@Overridepublic Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)throws NetworkErrorException {return null;}@Overridepublic 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;@Overridepublic void onCreate() {super.onCreate();mAuthenticator = new TestAccountAuthenticator(this);}@Nullable@Overridepublic 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"//設置-同步-添加 賬號類型的iconandroid:smallIcon="@drawable/miniIcon"//小iconandroid: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帐号管理(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小二郎爱大米
- 下一篇: 读书笔记软件调试之道 :从大局看调试-发