Android账号管理机制

在android提供的sdk中,samples目录下有一个叫SampleSyncAdapter的示例,它是一个账号与同步的实例,比如Google原始的android手机可以使用Google账号进行数据的同步。具体的比如你想实时同步你的通讯录到服务端,这时候你就可以通过这个实例来了解android提供的同步机制,从而实现自己的同步功能。先介绍一下账号的管理部分。至于账号管理的代码主要是在authenticator包下的三个类里面,还有就是一个叫authenticator 的xml文件。

AuthenticationService类

AuthenticationService是一个继承Service的服务,这个服务其实是提供给其他的进程使用的,android系统会通过"android.accounts.AccountAuthenticator"这个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提供你想要的信息。



  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值