Android開發(39) 賬戶管理器概述
- 2020 年 3 月 16 日
- 筆記
賬戶管理器概述
這個類提供了訪問到 用戶在線賬戶的集中式註冊中心 的能力。用戶為每賬戶輸入一次 認證信息(credentials,包含用戶名和密碼),過過 點擊一次(one-click)完成認證的方式,授權應用程序(app)訪問 在線的資源。不同的服務具有不同的處理賬戶的認證的方式,而 Account Manager 使用了插件化的認證器模塊 對應不同的賬戶類型。認證器(它由第三方組織編寫)處理 驗證賬戶認證信息的具體實際內容。並且保存賬戶信息。比如 谷歌,facebook,和微軟每個都擁有他們自己的認證器。 許多服務支持 關於單一授權標記(authentication token,簡寫為auth token) 的一些概念,它常常被用於驗證 向服務發出的不包含真實密碼的授權請求。而auth token 常常被創建於獨立包含用戶認證信息(用戶名和密碼)的請求。AccountManager可以為應用程序生成認證標記(auth token),那麼應用程序不在需要去直接處理密碼。autho token常常可重用和被AccountManager緩存,但是被必須周期性刷新。當停止工作的時候,應用程序使得auth token無效化,以讓auth token知道去重新生成它們。 應用程序訪問服務通常通過下面幾個步驟: 獲得一個 AuccountManager的實例,通過 get(Context)方法。 列出可用的賬戶,使用getAccountsByType(String) 或者 getAccountsByTypeAndFeatures(String, String[],AccountManagerCallback, Handler).一般應用程序會對 一種指定的類型 的賬戶 感興趣,它是認證器的標識。賬戶特性被用於標識特定賬戶的子類型和能力。賬戶類型和特性這兩個是認證器規範字符串,並且必須被應用程序所知道,關於協調它們的首選認證器。 選擇一個或者多個可用的賬戶,可能的話詢問用戶他們的偏好。如果沒有匹配的賬戶可以使用,addAccount(String, String, String[], Bundle, Activity, AccountManagerCallback, Handler) 將會被調用,提示用戶創建一個適當類型賬戶 重要的:如果應用正在使用預先被記憶的賬戶選項,它必須確保賬戶仍然存在於一個被 通過 getAccountsByType(String)返 回的賬戶列表。為一個賬戶請求一個認證標記 不再導致 在設備結果中的「一個未定義的失敗」。 使用auth token構建請求。auth token的表單,請求的格式,和使用的協議都特定於你要訪問的服務。應用可以使用任何網絡和協議庫。 重要的:如果請求失敗於一個「授權錯誤」,那麼可能 緩存的auth token過期並且不再被服務端信任。應用必須調用 invalidateAuthToken(String, String)去移除auth token的緩存,另外請求將繼續失敗! 在使得auth token無效後, 立即返回到上面的「請求一個auth token」步驟。如果是第二次出處理失敗了,那麼它將被當做一次誠懇的認證失敗來對待並 且通知用戶或做其他適當處理。 一些AccountManager方法可能需要與用戶交互,提示用戶認證信息,呈現可選項,或者詢問用戶去添加賬戶。調用者可以選擇是否允許AccountManager去直接啟動必要的用戶接口並且等待用戶,或者返回一個intent,它是調用者可以啟動接口。或者一些情況下,安裝一個通知,它是用戶可以選擇去啟動接口。讓AccountManager直接啟動接口,調用者必須提供當前 前端的Activity的Context. 許多AccountManager方法以 AccountManagerCallback 和 Handler作為參數。這些方法立即返回並且異步啟動。如果一個回調被提供,那麼run(AccountManagerFuture) 將在Handler的線程上被調用。結果被重新取得,是通過 「返回值」AccountManagerFuture 的 getResult()方法(也可以通過回調方法獲得)。這個方法等待操作完成(如果需要的話)並且兩者之一:返回結果或者 在操作過程中發生錯誤拋出異常。要使 請求 同步執行,通過方法接收到 future後立即調用 getResult()即可,不再需要提供回調。 請求可能被阻塞,包括getResult()在內,必須保證 從不在主線程被調用。如果在主線程被使用,那些操作將拋出IllegalStateException異常 。
AccountManager的常用方法
為指定賬戶設定密碼
mAccountManager.setPassword(account, mPassword);
添加賬戶到 賬戶中心
final Account account = new Account(mUsername, Constants.ACCOUNT_TYPE); mAccountManager.addAccountExplicitly(account, mPassword, null);
獲得authToken
final String authtoken = mAccountManager.blockingGetAuthToken(account, Constants.AUTHTOKEN_TYPE, NOTIFY_AUTH_FAILURE);
獲得用戶數據
String markerString = mAccountManager.getUserData(account, SYNC_MARKER_KEY);
AbstractAccountAuthenticator 概述
這是一個抽象的基類,用於創建賬戶管理器(AccountAuthenticators)。為了成為一 個 認證器,一個類必須繼承該類,提供抽象方法的實現,並且寫一個服務(service), 在被ACTION_AUTHENTICATOR_INTENT作為action的intent調用時,在該服務的 onBind (android.content.Intent) 方法實現中,直接返回getIBinder() 的返回值結果。在 AndroidManifest.xml 文件中,這個服務必須指定下面的 intent過濾器(intent filter )和元數據標記。
<intent-filter> <action android:name="android.accounts.AccountAuthenticator" /> </intent-filter> <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" />
注意:ACTION_AUTHENTICATOR_INTENT其實是個常量,等於字符串 android.accounts.AccountAuthenticator,其實就是和上面這個intent filter的過 濾器action相同。
上面的xml描述中,android:resource 屬性必須指向一個資源文件,像下面這樣:
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" android:accountType="typeOfAuthenticator" android:icon="@drawable/icon" android:smallIcon="@drawable/miniIcon" android:label="@string/label" android:accountPreferences="@xml/account_preferences" />
使用你自己的資源替換 icon 和 label 屬性指向的值。android:accountType 屬性必須是個字符串,它唯一標識了你的 認證器,並且和 用戶使用AccountManager 調用時 指定的字符串相同,同時 和你的賬戶類型(account type)一致。 android:icon的一個使用者是在 「賬戶和同步」設置頁,android:smallIcon的一個使用者是在 聯繫人 應用程序的標籤面板。
android:accountPreferences屬性指向一個 首選項屏幕設置的xml配置文件 (PreferenceScreen xml ),它包含了一個PreferenceScreen 的列表,可以層級嵌套。 它可以被調用以管理認證器。示例如下:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="@string/title_fmt" /> <PreferenceScreen android:key="key1" android:title="@string/key1_action" android:summary="@string/key1_summary"> <intent android:action="key1.ACTION" android:targetPackage="key1.package" android:targetClass="key1.class" /> </PreferenceScreen> </PreferenceScreen>
一些抽象方法的標準實現模式,像下面這樣:
- 如果為 認證器 提供的參數是足夠的,到達了完全的滿意,這時將會這樣做(will do so )並且返回一個包含了結果的Bundle。
- 如果 認證器 需要 從用戶那裡收集信息才能達到滿意,這時,將創建一個intent打開 「提示用戶信息的activity」,並且完成該請求。這個intent必須返回一個包含了 指定key名稱為 KEY_INTENT 的 Bundle.當完成的時候,這個activity需要返回final修飾的結果。
這個intent應該使用key指示 KEY_ACCOUNT_MANAGER_RESPONSE來包含AccountAuthenticatorResponse。這個activity在結束時必須調用 onResult(Bundle) 或者 onError(int, String) 。 如果認證器不能同步處理請求,並且返回一個結果。那麼當完成請求時,它可以選擇返 回null和使用 AccountManagerResponse 去發送結果。 後續的關於 每個抽象認證器方法 的描述,將不描述 可能的異步原生請求處理,而將描述輸入參數和期望結果來替代。
當寫一個activity去滿足那些請求,一種方式,必須在activity關閉時(或者任何其他情況下activity的作者認為是一個正確的時間去響應時),通過 AccountManagerResponse 並且通過響應返回結果。AccountAuthenticatorActivity 用於處理這些,那麼當寫activity去處理這些請求時,我們可以去繼承(extend) 它。
AccountAuthenticatorActivity概述
這是一個抽象的用於實現activity的基類,常被用於幫助 抽象認證器 (AbstractAccountAuthenticator)的具體實現(implement)。如果 抽象認證器AbstractAccountAuthenticator 需要使用一個activity去捕獲請求,這是它可以 讓一個activity來繼承AccountAuthenticatorActivity。 抽象認證器AbstractAccountAuthenticator 傳遞響應到intent的方法像下面這樣:
intent.putExtra(KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
這個 activity設置(指定)結果時,結果(result)被傳遞到響應通過 setAccountAuthenticatorResult(android.os.Bundle) 方法。當activity結束時,這個結果將被發送作為 請求的結果。如果這從未被設置或者設置為null,那麼 錯誤 ERROR_CODE_CANCELED 將會在響應上被調用。
注意: 賬戶認證器通過intent調用 這個activity,通過intent傳遞參數:
intent.putExtra(KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); 傳遞一個 賬戶認證器響應到 這個activity,作為參數,而這個activity將處理具體實現,處理完畢後,使用 setAccountAuthenticatorResult(android.os.Bundle) 來設置處理的結果。
AccountManagerFuture概述
一個AccountManagerFuture 表現了 異步的AccountManager調用的結果。它提供了一些方法用於判斷計算是否完成,等待計算過程,和獲得運算結果。當運算完成後,阻塞(如果需要的話)知道結果被準備好,結果只能被使用 get 方法獲得。取消操作將被 cancel方法處理。額外的方法被提供為判斷任務被正常完成或者被取消。一旦一個運算被完成,運算就不能被取消了。如果你為了可以取消的意圖而不提供一個有用的結果的方式 來使用這個類,你可以聲明 類似格式 Future<?> 的類型並且返回null作為相關任務的結果。