zoukankan      html  css  js  c++  java
  • 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给client进程。例如以下:
        @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的源代码位置在frameworksasecorejavaandroidaccounts文件夹下。

    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)) {
      //假设已经到server验证过账号并保存到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;
                }
            }

            //假设没有到server验证过账号并保存到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的源代码也是在frameworksasecorejavaandroidaccounts文件夹

    下。

    AuthenticatorActivity基本的一个方法是handleLogin(View view),当点击Sign inbutton时会调用该方法。该方法会启动一个异步任务来请求server验证用户账号。验证成功后有

    一个重要的方法:

     /**
         * 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提供你想要的信息。

  • 相关阅读:
    HRBUST--2317 Game(完全背包)
    k8s的回滚应用
    python练习-2
    k8s HA 补充-(keepalived+haproxy配置)
    Etcd故障恢复记录
    kubernetes 1.14安装部署helm插件
    k8s Prometheus+CAdvisor+node_export+grafana
    k8s ingress部署
    k8s pvc
    k8s pv
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6844097.html
Copyright © 2011-2022 走看看