Do Facebook and lastfm students installed with Android are pleasantly surprised by the functions of these applications. They can regularly update the latest information of their friends and integrate the latest status and mood phrases into their contacts. All these applications are based on the account and synchronization mechanism after android2.0. The Google routine provides an example named samplesyncadpater. By analyzing this example, you can learn to use the Account Verification and synchronous adapter in Android.
For details about the sample code, see the source code provided in SDK samples. Now we will briefly describe the version 2.2.
The first is class authenticator extends actaccountauthenticator, which is an account authentication class. Open the setting of the mobile phone and there is an account & Sync item. authenticator is the class that implements the account function.
// In authenticator. java <br/> Public bundle addaccount (accountauthenticatorresponse response, <br/> string accounttype, string authtokentype, string [] requiredfeatures, <br/> bundle options) {<br/> final intent = new intent (mcontext, authenticatoractivity. class); <br/> intent. putextra (authenticatoracti.pdf. param_authtoken_type, <br/> authtokentype); <br/> intent. putextra (accountmanager. key_account_authenticator_response, <br/> response); <br/> final bundle = new bundle (); <br/> bundle. putparcelable (accountmanager. key_intent, intent); <br/> return bundle; <br/>}
Here, the addaccount method is used to define the operation when you need to add an account. For example, you can call authenticatgateti.pdf to add and authenticate an account.
Handlelogin () is defined in authenticatoractivity. java. This method is defined by Android: onclick = "handlelogin" in login_activity.xml to associate it with okbutton In the UI.
// In layout/login_activity.xml <br/> <Button <br/> android: id = "@ + id/OK _button" <br/> android: layout_width = "wrap_content" <br/> android: layout_height = "wrap_content" <br/> android: layout_gravity = "center_horizontal" <br/> android: minWidth = "100dip" <br/> android: text = "@ string/login_activity_ OK _button" <br/> android: onClick = "handleLogin"/>
Handlelogin () obtains the user name and password in the UI, creates a thread to authenticate, and authenticates it on the server through the network.
The public static boolean authenticate (String username, String password, Handler handler, final Context context) method in NetworkUtilities. java shows the process of network verification. After the server-side verification result is obtained, onAuthenticationResult () is run in authenticatgateti.pdf by calling handler. post in sendResult. If the onAuthenticationResult () passes the authentication, AuthenticatorActivity is terminated. Otherwise, an error is reported for the user name and password, so that the user can try again in authenticatoracti.pdf.
// AuthenticatorActivity. handleLogin () method in java <br/>/** <br/> * Handles onClick event on the Submit button. sends username/password to <br/> * the server for authentication. <br/> * @ param view The Submit button for which this method is invoked <br/> */<br/> public void handleLogin (View view) {<br/> if (mRequestNewAccount) {<br/> mUsername = mUsernameEdit. getText (). toString (); <br/>}< br/> mPassword = mPasswordEdit. getText (). toString (); <br/> if (TextUtils. isEmpty (mUsername) | TextUtils. isEmpty (mPassword) {<br/> mMessage. setText (getMessage (); <br/>}else {<br/> showProgress (); <br/> // Start authenticating... <br/> mAuthThread = <br/> NetworkUtilities. attemptAuth (mUsername, mPassword, mHandler, <br/> authenticatoractiuth. this); <br/>}< br/>}
// The authenticate () method in networkutilities implements server verification through network access. sendresult () is used to make the call result called by onauthenticationresult () of authenticatoractivity. <Br/>/** <br/> * connects to the voiper server, authenticates the provided username and <br/> * password. <br/> * @ Param username the user's username <br/> * @ Param password the user's password <br/> * @ Param handler hander instance from the calling UI thread. <br/> * @ Param context the context of the calling activity. <br/> * @ return Boolean the boolean result indicating whether the user was <br/> * successfully authenticated. <br/> */<br/> Public static Boolean authenticate (string username, string password, <br/> handler, final context) {<br/> final httpresponse resp; </P> <p> final arraylist <namevaluepair> Params = new arraylist <namevaluepair> (); <br/> Params. add (New basicnamevaluepair (param_username, username); <br/> Params. add (New basicnamevaluepair (param_password, password); <br/> httpentity entity = NULL; <br/> try {<br/> entity = new urlencodedformentity (Params ); <br/>} catch (final unsupportedencodingexception e) {<br/> // This shoshould never happen. <br/> throw new assertionerror (E); <br/>}< br/> final httppost post = new httppost (auth_uri); <br/> post. addheader (entity. getcontenttype (); <br/> post. setentity (entity); <br/> maybecreatehttpclient (); </P> <p> try {<br/> resp = mhttpclient.exe cute (post ); <br/> If (resp. getstatusline (). getstatuscode () = httpstatus. SC _ OK) {<br/> If (log. isloggable (TAG, log. verbose) {<br/> log. V (TAG, "successful authentication"); <br/>}< br/> sendresult (true, handler, context); <br/> return true; <br/>} else {<br/> If (log. isloggable (TAG, log. verbose) {<br/> log. V (TAG, "error authenticating" + resp. getstatusline (); <br/>}< br/> sendresult (false, handler, context); <br/> return false; <br/>}< br/>} catch (final ioexception e) {<br/> If (log. isloggable (TAG, log. verbose) {<br/> log. V (TAG, "ioexception when getting authtoken", e); <br/>}< br/> sendresult (false, handler, context); <br/> return false; <br/>} finally {<br/> If (log. isloggable (TAG, log. verbose) {<br/> log. V (TAG, "getauthtoken completing "); <br/>}</P> <p>/** <br/> * sends the authentication response from server back to the caller main UI <br/> * thread through its handler. <br/> * @ Param result the Boolean holding authentication result <br/> * @ Param handler the main UI thread's handler instance. <br/> * @ Param context the caller activity's context. <br/> */<br/> Private Static void sendresult (final boolean result, final handler, <br/> final context) {<br/> If (handler = NULL | context = NULL) {<br/> return; <br/>}< br/> handler. post (New runnable () {<br/> Public void run () {<br/> (authenticatoractivity) context ). onauthenticationresult (result); <br/>}< br/>}); <br/>}
// The onAuthenticationResult in AuthenticatorActivity. java to end the authentication or try again based on the authentication result. <Br/>/** <br/> * Called when the authentication process completes (see attemptLogin ()). <br/> */<br/> public void onAuthenticationResult (boolean result) {<br/> Log. I (TAG, "onAuthenticationResult (" + result + ")"); <br/> // Hide the progress dialog <br/> hideProgress (); <br/> if (result) {<br/> if (! MConfirmCredentials) {<br/> finishLogin (); <br/>}else {<br/> finishConfirmCredentials (true ); <br/>}< br/>}else {<br/> Log. e (TAG, "onAuthenticationResult: failed to authenticate"); <br/> if (mRequestNewAccount) {<br/> // "Please enter a valid username/password. <br/> mMessage <br/>. setText (getText (R. string. login_activity_loginfail_text_both); <br/>}else {<br/> // "Please enter a valid password. "(Used when the <br/> // account is already in the database but the password <br/> // doesn't work .) <br/> mMessage <br/>. setText (getText (R. string. login_activity_loginfail_text_pwonly); <br/>}< br/>}
After the Account is verified, an Account is generated and the synchronization function can be used. The main logic of synchronization is implemented in public class SyncAdapter extends AbstractThreadedSyncAdapter.
// SyncAdapter. the on‑msync method in java, the main synchronization logic <br/> @ Override <br/> public void on‑msync (Account account Account, Bundle extras, String authority, <br/> ContentProviderClient provider, syncResult syncResult) {<br/> List <User> users; <br/> List <Status> statuses; <br/> String authtoken = null; <br/> try {<br/> // use the account manager to request the credentials <br/> authtoken = <br/> mAccountManager. blockingGetAuthToken (account, <br/> Constants. AUTHTOKEN_TYPE, true/* policyauthfailure */); <br/> // fetch updates from the sample service over the cloud <br/> users = <br/network> utilities. fetchFriendUpdates (account, authtoken, <br/> mLastUpdated); <br/> // update the last synced date. <br/> mLastUpdated = new Date (); <br/> // update platform contacts. <br/> Log. d (TAG, "Calling contactManager's sync contacts"); <br/> ContactManager. syncContacts (mContext, account. name, users); <br/> // fetch and update status messages for all the synced users. <br/> statuses = NetworkUtilities. fetchFriendStatuses (account, authtoken); <br/> ContactManager. insertStatuses (mContext, account. name, statuses); <br/>} catch (final AuthenticatorException e) {<br/> syncResult. stats. numParseExceptions ++; <br/> Log. e (TAG, "AuthenticatorException", e); <br/>} catch (final OperationCanceledException e) {<br/> Log. e (TAG, "OperationCanceledExcetpion", e); <br/>}catch (final IOException e) {<br/> Log. e (TAG, "IOException", e); <br/> syncResult. stats. numIoExceptions ++; <br/>} catch (final AuthenticationException e) {<br/> mAccountManager. invalidateAuthToken (Constants. ACCOUNT_TYPE, <br/> authtoken); <br/> syncResult. stats. numAuthExceptions ++; <br/> Log. e (TAG, "AuthenticationException", e); <br/>} catch (final ParseException e) {<br/> syncResult. stats. numParseExceptions ++; <br/> Log. e (TAG, "ParseException", e); <br/>} catch (final JSONException e) {<br/> syncResult. stats. numParseExceptions ++; <br/> Log. e (TAG, "JSONException", e); <br/>}< br/>}
In the execution process of on‑msync, fetchFriendUpdates and fetchFriendStatuses in NetworkUtilities are used to access the contact updates on the server, and ContactManager encapsulated in the routine is used to read and update the contact information.
How is the relationship between Account and SyncAdapter and their Service and xml definitions? AndroidManifest. xml defines the associations between AccountAuthenticator, SyncAdapter, and corresponding Service and xml definitions.
<Application <br/> android: icon = "@ drawable/icon" <br/> android: label = "@ string/label"> <br/> <! -- The authenticator service --> <br/> <service <br/> android: name = ". authenticator. authenticationService "<br/> android: exported =" true "> <br/> <intent-filter> <br/> <action <br/> android: name =" android. accounts. accountAuthenticator "/> <br/> </intent-filter> <br/> <meta-data <br/> android: name =" android. accounts. accountAuthenticator "<br/> android: resource =" @ xml/authenticator "/> <br/> </service> <br /> <Service <br/> android: name = ". syncadapter. syncService "<br/> android: exported =" true "> <br/> <intent-filter> <br/> <action <br/> android: name =" android. content. syncAdapter "/> <br/> </intent-filter> <br/> <meta-data <br/> android: name =" android. content. syncAdapter "<br/> android: resource =" @ xml/syncadapter "/> <br/> <meta-data <br/> android: name =" android. provider. CONTACTS_STRUCTURE "<br/> android: r Esource = "@ xml/contacts"/> <br/> </service> <br/> <activity <br/> android: name = ". authenticator. authenticatorActivity "<br/> android: label =" @ string/ui_activity_title "<br/> android: theme =" @ android: style/Theme. dialog "<br/> android: excludeFromRecents =" true "<br/> <! -- <Br/> No intent-filter here! This activity is only ever launched by <br/> someone who explicitly knows the class name <br/> --> <br/> </activity> <br/> </application>
For more detailed code details and execution procedures, you can run the SampleSyncAdapter code in the SDK. However, to implement the entire process, you must set up the contact's server, the samplesyncadapter_server directory in the routine also provides simple server-side python code, which needs to be built on the google app engine. I encountered some problems during the setup process. I was not familiar with python for a few days before the setup was completed successfully, you need to create a _ init _ in the model __. is a python module. If you encounter this problem, I hope it will help you.