久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

構建自己的Android賬戶與內容同步機制,,例程SampleSyncAdapter的分析

 windli筆記 2011-08-08

裝過Android版的Facebook、lastfm的同學是否對于這些應用的功能感到驚喜,,它們可以定期更新朋友的最新信息,,將最新近況和心情短語集成入聯(lián)系人中。這些應用全部是以Android2.0后的賬戶和同步機制為基礎的,。Google的例程中給出了名為SampleSyncAdpater的例子,,通過分析該例子可以學會Android中的Account驗證、同步Adapter的使用,。

 

詳細例子代碼可以看sdk samples中提供的源碼,,現(xiàn)在拿2.2中的版本來簡要說明。

 

 

首先是 class Authenticator extends AbstractAccountAuthenticator ,,該類是賬戶認證類,,打開手機的Setting里,,有Account&Sync 一項,Authenticator就是實現(xiàn)其中的賬號功能的類,。

  1. // in Authenticator.java   
  2.     public Bundle addAccount(AccountAuthenticatorResponse response,  
  3.         String accountType, String authTokenType, String[] requiredFeatures,  
  4.         Bundle options) {  
  5.         final Intent intent = new Intent(mContext, AuthenticatorActivity.class);  
  6.         intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE,  
  7.             authTokenType);  
  8.         intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,  
  9.             response);  
  10.         final Bundle bundle = new Bundle();  
  11.         bundle.putParcelable(AccountManager.KEY_INTENT, intent);  
  12.         return bundle;  
  13.     }  

 

其中addAccount方法用來定義需要增加賬號時的操作,,如調用AuthenticatorActivity來進行賬號的添加認證。

在AuthenticatorActivity.java中定義了handleLogin(),,此方法由login_activity.xml中的android:onClick="handleLogin"定義與ui中的okbutton的關聯(lián),。

  1. // in layout/login_activity.xml   
  2. <Button  
  3.             android:id="@+id/ok_button"  
  4.             android:layout_width="wrap_content"  
  5.             android:layout_height="wrap_content"  
  6.             android:layout_gravity="center_horizontal"  
  7.             android:minWidth="100dip"  
  8.             android:text="@string/login_activity_ok_button"  
  9.             android:onClick="handleLogin" />  

 

handleLogin()將ui中的用戶名和密碼取得,并創(chuàng)建一個試圖認證的線程,,通過網(wǎng)絡去服務端驗證,。

NetworkUtilities.java中的 public static boolean authenticate(String username, String password, Handler handler, final Context context)方法展示了通過網(wǎng)絡驗證的具體流程。得到服務端驗證結果后,,在sendResult()中通過handler.post調用來實現(xiàn)onAuthenticationResult()在AuthenticatorActivity中的運行,。onAuthenticationResult()判斷驗證通過則結束AuthenticatorActivity,否則報出用戶名密碼錯,,讓用戶在AuthenticatorActivity中再次嘗試驗證,。

  1. // AuthenticatorActivity.java中的handleLogin()方法   
  2.     /** 
  3.      * Handles onClick event on the Submit button. Sends username/password to 
  4.      * the server for authentication. 
  5.      *  
  6.      * @param view The Submit button for which this method is invoked 
  7.      */  
  8.     public void handleLogin(View view) {  
  9.         if (mRequestNewAccount) {  
  10.             mUsername = mUsernameEdit.getText().toString();  
  11.         }  
  12.         mPassword = mPasswordEdit.getText().toString();  
  13.         if (TextUtils.isEmpty(mUsername) || TextUtils.isEmpty(mPassword)) {  
  14.             mMessage.setText(getMessage());  
  15.         } else {  
  16.             showProgress();  
  17.             // Start authenticating...   
  18.             mAuthThread =  
  19.                 NetworkUtilities.attemptAuth(mUsername, mPassword, mHandler,  
  20.                     AuthenticatorActivity.this);  
  21.         }  
  22.     }  

 

 

  1. // NetworkUtilities中的authenticate()方法通過網(wǎng)絡訪問具體來實現(xiàn)服務端的驗證,sendResult()來使調用結果被AuthenticatorActivity的onAuthenticationResult()調用,。   
  2.     /** 
  3.      * Connects to the Voiper server, authenticates the provided username and 
  4.      * password. 
  5.      *  
  6.      * @param username The user's username 
  7.      * @param password The user's password 
  8.      * @param handler The hander instance from the calling UI thread. 
  9.      * @param context The context of the calling Activity. 
  10.      * @return boolean The boolean result indicating whether the user was 
  11.      *         successfully authenticated. 
  12.      */  
  13.     public static boolean authenticate(String username, String password,  
  14.         Handler handler, final Context context) {  
  15.         final HttpResponse resp;  
  16.   
  17.         final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();  
  18.         params.add(new BasicNameValuePair(PARAM_USERNAME, username));  
  19.         params.add(new BasicNameValuePair(PARAM_PASSWORD, password));  
  20.         HttpEntity entity = null;  
  21.         try {  
  22.             entity = new UrlEncodedFormEntity(params);  
  23.         } catch (final UnsupportedEncodingException e) {  
  24.             // this should never happen.   
  25.             throw new AssertionError(e);  
  26.         }  
  27.         final HttpPost post = new HttpPost(AUTH_URI);  
  28.         post.addHeader(entity.getContentType());  
  29.         post.setEntity(entity);  
  30.         maybeCreateHttpClient();  
  31.   
  32.         try {  
  33.             resp = mHttpClient.execute(post);  
  34.             if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  
  35.                 if (Log.isLoggable(TAG, Log.VERBOSE)) {  
  36.                     Log.v(TAG, "Successful authentication");  
  37.                 }  
  38.                 sendResult(true, handler, context);  
  39.                 return true;  
  40.             } else {  
  41.                 if (Log.isLoggable(TAG, Log.VERBOSE)) {  
  42.                     Log.v(TAG, "Error authenticating" + resp.getStatusLine());  
  43.                 }  
  44.                 sendResult(false, handler, context);  
  45.                 return false;  
  46.             }  
  47.         } catch (final IOException e) {  
  48.             if (Log.isLoggable(TAG, Log.VERBOSE)) {  
  49.                 Log.v(TAG, "IOException when getting authtoken", e);  
  50.             }  
  51.             sendResult(false, handler, context);  
  52.             return false;  
  53.         } finally {  
  54.             if (Log.isLoggable(TAG, Log.VERBOSE)) {  
  55.                 Log.v(TAG, "getAuthtoken completing");  
  56.             }  
  57.         }  
  58.     }  
  59.   
  60.     /** 
  61.      * Sends the authentication response from server back to the caller main UI 
  62.      * thread through its handler. 
  63.      *  
  64.      * @param result The boolean holding authentication result 
  65.      * @param handler The main UI thread's handler instance. 
  66.      * @param context The caller Activity's context. 
  67.      */  
  68.     private static void sendResult(final Boolean result, final Handler handler,  
  69.         final Context context) {  
  70.         if (handler == null || context == null) {  
  71.             return;  
  72.         }  
  73.         handler.post(new Runnable() {  
  74.             public void run() {  
  75.                 ((AuthenticatorActivity) context).onAuthenticationResult(result);  
  76.             }  
  77.         });  
  78.     }  

 

 

  1. // AuthenticatorActivity.java中的onAuthenticationResult,,來根據(jù)驗證結果來選擇結束認證或重新嘗試。   
  2.     /** 
  3.      * Called when the authentication process completes (see attemptLogin()). 
  4.      */  
  5.     public void onAuthenticationResult(boolean result) {  
  6.         Log.i(TAG, "onAuthenticationResult(" + result + ")");  
  7.         // Hide the progress dialog   
  8.         hideProgress();  
  9.         if (result) {  
  10.             if (!mConfirmCredentials) {  
  11.                 finishLogin();  
  12.             } else {  
  13.                 finishConfirmCredentials(true);  
  14.             }  
  15.         } else {  
  16.             Log.e(TAG, "onAuthenticationResult: failed to authenticate");  
  17.             if (mRequestNewAccount) {  
  18.                 // "Please enter a valid username/password.   
  19.                 mMessage  
  20.                     .setText(getText(R.string.login_activity_loginfail_text_both));  
  21.             } else {  
  22.                 // "Please enter a valid password." (Used when the   
  23.                 // account is already in the database but the password   
  24.                 // doesn't work.)   
  25.                 mMessage  
  26.                     .setText(getText(R.string.login_activity_loginfail_text_pwonly));  
  27.             }  
  28.         }  
  29.     }  

 

 

Account的驗證完畢后,,就生成了賬號,,可以開始使用同步功能了。同步的主要邏輯在public class SyncAdapter extends AbstractThreadedSyncAdapter中實現(xiàn),。

  1. // SyncAdapter.java中的OnPerformSync方法,,主要的同步邏輯   
  2.     @Override  
  3.     public void onPerformSync(Account account, Bundle extras, String authority,  
  4.         ContentProviderClient provider, SyncResult syncResult) {  
  5.         List<User> users;  
  6.         List<Status> statuses;  
  7.         String authtoken = null;  
  8.          try {  
  9.              // use the account manager to request the credentials   
  10.              authtoken =  
  11.                 mAccountManager.blockingGetAuthToken(account,  
  12.                     Constants.AUTHTOKEN_TYPE, true /* notifyAuthFailure */);  
  13.              // fetch updates from the sample service over the cloud   
  14.              users =  
  15.                 NetworkUtilities.fetchFriendUpdates(account, authtoken,  
  16.                     mLastUpdated);  
  17.             // update the last synced date.   
  18.             mLastUpdated = new Date();  
  19.             // update platform contacts.   
  20.             Log.d(TAG, "Calling contactManager's sync contacts");  
  21.             ContactManager.syncContacts(mContext, account.name, users);  
  22.             // fetch and update status messages for all the synced users.   
  23.             statuses = NetworkUtilities.fetchFriendStatuses(account, authtoken);  
  24.             ContactManager.insertStatuses(mContext, account.name, statuses);  
  25.         } catch (final AuthenticatorException e) {  
  26.             syncResult.stats.numParseExceptions++;  
  27.             Log.e(TAG, "AuthenticatorException", e);  
  28.         } catch (final OperationCanceledException e) {  
  29.             Log.e(TAG, "OperationCanceledExcetpion", e);  
  30.         } catch (final IOException e) {  
  31.             Log.e(TAG, "IOException", e);  
  32.             syncResult.stats.numIoExceptions++;  
  33.         } catch (final AuthenticationException e) {  
  34.             mAccountManager.invalidateAuthToken(Constants.ACCOUNT_TYPE,  
  35.                 authtoken);  
  36.             syncResult.stats.numAuthExceptions++;  
  37.             Log.e(TAG, "AuthenticationException", e);  
  38.         } catch (final ParseException e) {  
  39.             syncResult.stats.numParseExceptions++;  
  40.             Log.e(TAG, "ParseException", e);  
  41.         } catch (final JSONException e) {  
  42.             syncResult.stats.numParseExceptions++;  
  43.             Log.e(TAG, "JSONException", e);  
  44.         }  
  45.     }  

 

onPerformSync中的執(zhí)行流程中,使用NetworkUtilities中的fetchFriendUpdates和fetchFriendStatuses來訪問服務端的聯(lián)系人更新,,并使用了例程中自己封裝的ContactManager來讀取、更新聯(lián)系人信息,。

 

那Account和SyncAdapter及其Service和xml定義之間是如何關聯(lián)的呢,? AndroidManifest.xml中定義了AccountAuthenticator,SyncAdapter及對應的Service和xml定義的關聯(lián),。

  1. <application  
  2.     android:icon="@drawable/icon"  
  3.     android:label="@string/label">  
  4.     <!-- The authenticator service -->  
  5.     <service  
  6.         android:name=".authenticator.AuthenticationService"  
  7.         android:exported="true">  
  8.         <intent-filter>  
  9.             <action  
  10.                 android:name="android.accounts.AccountAuthenticator" />  
  11.         </intent-filter>  
  12.         <meta-data  
  13.             android:name="android.accounts.AccountAuthenticator"  
  14.             android:resource="@xml/authenticator" />  
  15.     </service>  
  16.     <service  
  17.         android:name=".syncadapter.SyncService"  
  18.         android:exported="true">  
  19.         <intent-filter>  
  20.             <action  
  21.                 android:name="android.content.SyncAdapter" />  
  22.         </intent-filter>  
  23.         <meta-data  
  24.             android:name="android.content.SyncAdapter"  
  25.             android:resource="@xml/syncadapter" />  
  26.         <meta-data  
  27.             android:name="android.provider.CONTACTS_STRUCTURE"  
  28.             android:resource="@xml/contacts" />  
  29.     </service>  
  30.     <activity  
  31.         android:name=".authenticator.AuthenticatorActivity"  
  32.         android:label="@string/ui_activity_title"  
  33.         android:theme="@android:style/Theme.Dialog"  
  34.         android:excludeFromRecents="true"  
  35.         >  
  36.         <!--  
  37.             No intent-filter here! This activity is only ever launched by  
  38.             someone who explicitly knows the class name  
  39.         -->  
  40.     </activity>  
  41. </application>  

 

 

更詳細的代碼細節(jié)和執(zhí)行流程,,可以去把SDK中的SampleSyncAdapter代碼運行起來體會一下,不過要實現(xiàn)整個流程,,必須搭建聯(lián)系人的服務器端,,例程中在目錄samplesyncadapter_server中也提供了簡單的server端python代碼,需要搭建在google app engine上,。搭建過程遇到一些問題,,由于對python不熟我弄了幾天才解決好搭建成功,,其中遇到的一個model moudle找不到的問題需要你在model中新建一個__init__.py的空文件,來說明是一個python模塊,,如果你也遇到此問題,,希望對你有幫助。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多