android帳號與同步之帳號管理

來源:互聯網
上載者:User

標籤:android   帳號管理   同步   

在android提供的sdk中,samples目錄下有一個叫SampleSyncAdapter的樣本,它是一個帳號與同步的執行個體,比如Google原始的android手機可以使用Google帳號進行資料的同步。具體

的比如你想即時同步你的通訊錄到服務端,這時候你就可以通過這個執行個體來瞭解android提供的同步機制,從而實現自己的同步功能。
本片博文先介紹一下帳號的管理部分。至於帳號管理的代碼主要是在authenticator包下的三個類裡面,還有就是一個叫authenticator的xml檔案。

AuthenticationService類

AuthenticationService是一個繼承Service的服務,這個服務其實是提供給其他的進程使用的,它的Action為android.accounts.AccountAuthenticator,android系統會通過這個

Action找到它,並通過它來把我們自己的帳號註冊到“設定”中,其實這是一個AIDL的使用,它屬於跨進程的調用。下面是manifest中的註冊:
  <service
            android:name=".authenticator.AuthenticationService"
            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>
這個Service會在onBind方法裡返回一個IBinder給用戶端進程,如下:
    @Override
    public IBinder onBind(Intent intent) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "getBinder()...  returning the AccountAuthenticator binder for intent "
                    + intent);
        }
        return mAuthenticator.getIBinder();
    }


Authenticator類

Authenticator是一個繼承自AbstractAccountAuthenticator的類,AbstractAccountAuthenticator是一個虛類,它定義處理手機“設定”裡“帳號與同步”中Account的添加、刪除和

驗證等功能的基本介面,並實現了一些準系統。AbstractAccountAuthenticator裡面有個繼承於IAccountAuthenticator.Stub的內部類,以用來對AbstractAccountAuthenticator的

遠程介面調用進行封裝。我們可以通過AbstractAccountAuthenticator的getIBinder()方法,返回內部類的IBinder形式,以便對此類進行遠程調用,如上面代碼onBind方法中的調

用。AbstractAccountAuthenticator的源碼位置在frameworks\base\core\java\android\accounts目錄下。

Authenticator只需要繼承和實現AbstractAccountAuthenticator的幾個方法就可以了,像我們所介紹的SampleSyncAdapter執行個體主要繼承了兩個方法,如下
 
//當在“設定”中添加帳號時,會調用這個方法,跳轉到添加帳號頁面
@Override
    public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
            String authTokenType, String[] requiredFeatures, Bundle options) {
        Log.v(TAG, "addAccount()");
 //指定AuthenticatorActivity為添加帳號的頁面,下面會介紹。
        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
        final Bundle bundle = new Bundle();
        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
        return bundle;
    }

//當執行mAccountManager.blockingGetAuthToken(account,Constants.AUTHTOKEN_TYPE, NOTIFY_AUTH_FAILURE);時調用該方法。
    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
            String authTokenType, Bundle loginOptions) throws NetworkErrorException {
        Log.v(TAG, "getAuthToken()");

        // 通過blockingGetAuthToken方法傳來的Constants.AUTHTOKEN_TYPE
        if (!authTokenType.equals(Constants.AUTHTOKEN_TYPE)) {
            final Bundle result = new Bundle();
            result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authTokenType");
            return result;
        }

        final AccountManager am = AccountManager.get(mContext);
        final String password = am.getPassword(account);
        if (password != null) {
            final String authToken = NetworkUtilities.authenticate(account.name, password);
            if (!TextUtils.isEmpty(authToken)) {
  //如果已經到伺服器驗證過帳號並儲存到AccountManager中
                final Bundle result = new Bundle();
                result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
                result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
                result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
                return result;
            }
        }

        //如果沒有到伺服器驗證過帳號並儲存到AccountManager中,則重新倒添加帳號頁面中驗證。
        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
        intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
        intent.putExtra(AuthenticatorActivity.PARAM_AUTHTOKEN_TYPE, authTokenType);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
        final Bundle bundle = new Bundle();
        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
        return bundle;
    }


AuthenticatorActivity類

AuthenticatorActivity是一個繼承自AccountAuthenticatorActivity的activity,AccountAuthenticatorActivity的源碼也是在frameworks\base\core\java\android\accounts目錄

下。AuthenticatorActivity主要的一個方法是handleLogin(View view),當點擊Sign in按鈕時會調用該方法,該方法會啟動一個非同步任務來請求伺服器驗證使用者帳號。驗證成功後有

一個重要的方法:

 /**
     * Called when response is received from the server for authentication
     * request. See onAuthenticationResult(). Sets the
     * AccountAuthenticatorResult which is sent back to the caller. We store the
     * authToken that‘s returned from the server as the ‘password‘ for this
     * account - so we‘re never storing the user‘s actual password locally.
     *
     * @param result the confirmCredentials result.
     */
    private void finishLogin(String authToken) {

        Log.i(TAG, "finishLogin()");
        final Account account = new Account(mUsername, Constants.ACCOUNT_TYPE);
        if (mRequestNewAccount) {
     //直接向AccountManager添加一個帳戶
            mAccountManager.addAccountExplicitly(account, mPassword, null);
            //設定讓這個帳號能夠自動同步
            ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
        } else {
            mAccountManager.setPassword(account, mPassword);
        }
        final Intent intent = new Intent();
        intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mUsername);
        intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
        setAccountAuthenticatorResult(intent.getExtras());
        setResult(RESULT_OK, intent);
        finish();
    }

authenticator.xml

在上面的AuthenticationService註冊中有個meta-data的名字為android.accounts.AccountAuthenticator,它所指向的xml檔案是authenticator.xml,其內容如下:

   <account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.example.android.samplesync"
    android:icon="@drawable/icon"
    android:smallIcon="@drawable/icon"
    android:label="@string/label"
/>

其中賬戶類型為com.example.android.samplesync,就是Constants.ACCOUNT_TYPE的值。這個有點像widget,需要一個xml提供你想要的資訊。

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.