天天看點

如何建構Android Sync Provider :Part1

Android2.0 SDK帶來的一個好東西就是你可以寫一個普通的同步供應商程式,并将其與系統的聯系薄,月曆等內建。唯一的問題是相關的文檔十分的少。還有一個糟糕的問題在于,如果你在某一個地方出了錯,Android系統就會崩潰重新開機。面臨如此挑戰,我依靠這稀少的文檔,以及很少的文章,還有Android地帶的一些代碼去建立了一個同步程式----Last.fm 。你想要知道怎麼去建立你自己的同步程式麼?讀下去吧

賬戶驗證

這裡定義了該賬戶如何在“賬号&amp;同步”設定中出現的。一個賬号的的驗證需要3部分來實作:1. 一個從onBind方法傳回AbstractAccountAuthenticator 子類的一個服務2. 一個Activityt提供使用者輸入他們的憑據(賬号秘密資訊),一個xml檔案去描述賬号資訊展示給使用者時( an xml file describing how your account should look when displayed to the user.)同時,你也需要在android.mainfest.xml中添加<b>android.permission.AUTHENTICATE_ACCOUNTS</b><b>權限</b>

服務

AccountAuthenticatorService.java

1  <b>import</b> fm.last.android.LastFm; 

2  <b>import</b> android.accounts.AbstractAccountAuthenticator; 

3  <b>import</b> android.accounts.Account; 

4  <b>import</b> android.accounts.AccountAuthenticatorResponse; 

5  <b>import</b> android.accounts.AccountManager; 

6  <b>import</b> android.accounts.NetworkErrorException; 

7  <b>import</b> android.app.Service; 

8  <b>import</b> android.content.Context; 

9  <b>import</b> android.content.Intent; 

10 <b>import</b> android.os.Bundle; 

11 <b>import</b> android.os.IBinder; 

12 <b>import</b> android.util.Log; 

13   

14 /** 

15  * Authenticator service that returns a subclass of AbstractAccountAuthenticator in onBind() 

16  */ 

17 <b>public</b> <b>class</b> AccountAuthenticatorService <b>extends</b> Service { 

18  <b>private</b> <b>static</b> <b>final</b> String TAG = <b>"</b><b>AccountAuthenticatorService</b><b>"</b>; 

19  <b>private</b> <b>static</b> AccountAuthenticatorImpl sAccountAuthenticator = <b>null</b>; 

20   

21  <b>public</b> AccountAuthenticatorService() { 

22   <b>super</b>(); 

23  } 

24   

25  <b>public</b> IBinder onBind(Intent intent) { 

26   IBinder ret = <b>null</b>; 

27   <b>if</b> (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)) 

28    ret = getAuthenticator().getIBinder(); 

29   <b>return</b> ret; 

30  } 

31   

32  <b>private</b> AccountAuthenticatorImpl getAuthenticator() { 

33   <b>if</b> (sAccountAuthenticator == <b>null</b>) 

34    sAccountAuthenticator = <b>new</b> AccountAuthenticatorImpl(<b>this</b>); 

35   <b>return</b> sAccountAuthenticator; 

36  } 

37   

38  <b>private</b> <b>static</b> <b>class</b> AccountAuthenticatorImpl <b>extends</b> AbstractAccountAuthenticator { 

39   <b>private</b> Context mContext; 

40   

41   <b>public</b> AccountAuthenticatorImpl(Context context) { 

42    <b>super</b>(context); 

43    mContext = context; 

44   } 

45   

46   /* 

47    *  The user has requested to add a new account to the system.  We return an intent that will launch our login screen if the user has not logged in yet, 

48    *  otherwise our activity will just pass the user's credentials on to the account manager. 

49    */ 

50   @Override 

51   <b>public</b> Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) 

52     <b>throws</b> NetworkErrorException { 

53    Bundle reply = <b>new</b> Bundle(); 

54     

55    Intent i = <b>new</b> Intent(mContext, LastFm.<b>class</b>); 

56    i.setAction(<b>"</b><b>fm.last.android.sync.LOGIN</b><b>"</b>); 

57    i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); 

58    reply.putParcelable(AccountManager.KEY_INTENT, i); 

59     

60    <b>return</b> reply; 

61   } 

62   

63   @Override 

64   <b>public</b> Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) {

65    <b>return</b> <b>null</b>; 

66   } 

67   

68   @Override 

69   <b>public</b> Bundle editProperties(AccountAuthenticatorResponse response, String accountType) { 

70    <b>return</b> <b>null</b>; 

71   } 

72   

73   @Override 

74   <b>public</b> Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) <b>throws</b> NetworkErrorException { 

75    <b>return</b> <b>null</b>; 

76   } 

77   

78   @Override 

79   <b>public</b> String getAuthTokenLabel(String authTokenType) { 

80    <b>return</b> <b>null</b>; 

81   } 

82   

83   @Override 

84   <b>public</b> Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) <b>throws</b> NetworkErrorException { 

85    <b>return</b> <b>null</b>; 

86   }  

87   @Override 

88   <b>public</b> Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) { 

89    <b>return</b> <b>null</b>; 

90   } 

91  } 

92 } 

93

該驗證服務需要在Android.Mainfest.xml中使用中繼資料标簽定義一下。如下

Snippet from AndroidManifest.xml

1 &lt;service android:name="AccountAuthenticatorService" 

2 android:exported="true" android:process=":auth"&gt; 

3  &lt;intent-filter&gt; 

4   &lt;action android:name="android.accounts.AccountAuthenticator" /&gt; 

5  &lt;/intent-filter&gt; 

6  &lt;meta-data android:name="android.accounts.AccountAuthenticator" 

7   android:resource="@xml/authenticator" /&gt; 

8 &lt;/service&gt; 

9

Xml檔案

賬号的xml檔案中定義了當應用程式與你的賬号互動的時候,應用程式将會看到的東西(是不是向國内其他應用程式使用QQ一些應用一樣,首先會有一個授權,詢問使用者目前的應用程式可以通路你的使用者的哪些資訊?------我的了解)其中包含了使用者可讀的名字,你所定義的系統賬号類型,圖示,對一個包含當使用者修改賬号時可以看到的PreferenceScreens 的xml檔案。

authenticator.xml

1 &lt;account-authenticator xmlns:android="http://schemas.android.com/apk/res/android" 

2     android:accountType="fm.last.android.account" 

3     android:icon="@drawable/icon" 

4     android:smallIcon="@drawable/icon" 

5     android:label="@string/app_name" 

6     android:accountPreferences="@xml/account_preferences"/&gt; 

7

account_preferences.xml

1  &lt;PreferenceScreen 

2    xmlns:android="http://schemas.android.com/apk/res/android"&gt; 

3      &lt;PreferenceCategory 

4              android:title="General Settings" /&gt; 

5    

6      &lt;PreferenceScreen 

7          android:key="account_settings" 

8          android:title="Account Settings" 

9          android:summary="Sync frequency, notifications, etc."&gt; 

10         &lt;intent 

11             android:action="fm.last.android.activity.Preferences.ACCOUNT_SETUP" 

12             android:targetPackage="fm.last.android" 

13             android:targetClass="fm.last.android.activity.Preferences" /&gt; 

14     &lt;/PreferenceScreen&gt; 

15 &lt;/PreferenceScreen&gt; 

16

內建(putting it all together)

現在我們可以準備開始測試了。Android 賬号的設定部分并不能完好的捕捉異常。如果有地方出錯了,裝置會重新開機。最好的測試方式是運作模拟器後,運作DevTools,點選AcountsTester

<a href="http://hddev.blog.51cto.com/attachment/201108/30/3365350_131470518584Sm.png"></a>

你會看到一個新的賬号類型将會同系統内置的“Corporate”類型的賬号一樣,被添加到清單中。盡管從下拉清單中選擇你的賬号,然後點選增加按鈕,那麼,将會呈現一個你所做的登入框。經過驗證後 ,你的賬号将會出現在按鈕下邊的清單中。在這一點,使用系統的“Account&amp;sync”設定去移除和修改賬戶應該是安全的。

準備好“Data &amp; synchronization”的章節了麼?讓我們開始第二個章節吧。

本文轉自HDDevTeam 51CTO部落格,原文連結:http://blog.51cto.com/hddev/653349,如需轉載請自行聯系原作者

繼續閱讀