在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的源代码位置在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)) {

  //假设已经到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的源代码也是在frameworks\base\core\java\android\accounts文件夹

下。

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

android账号与同步之账号管理的更多相关文章

  1. android账号与同步之同步实现

    上一篇博文我先介绍了账号与同步的账号管理,这篇就介绍一下还有一部分.就是android给提供的sync同步机制的使用. 事实上sync机制的使用和上一篇博文中介绍的账号管理非常类似,也是基于binde ...

  2. android账号与同步之发起同步

    上一篇博文我介绍了账号与同步的同步实现过程,当中提供了一个工系统进程调用的服务,那么这个服务究竟是怎么被启动和使用的呢?这篇博文我就大体梳理一下启动过程. 事实上作为一个一般开发者,我们仅仅要知道要想 ...

  3. 将Sql Server迁移到Always on集群 - 账号的同步

    Always on环境的建立,网上资料很多,主要是windows集群的建立以及Sql Server Always on的建立,略 容易忽略的是Sql server账号同步问题(Always on能实现 ...

  4. LINUX 学习笔记 账号与群组的管理

    LINUX 账号与群组的管理 UID:UserID 保存文件:/etc/passwd GID:GroupID 保存文件:/etc/group /etc/passwd 文件结构 一行代表一个账号,里面还 ...

  5. RHEL账号总结一:账号的分类

    账号是一种用来记录单个用户或者多个用户的数据.RHEL中每一个合法的用户都必须拥有账号,才能使用RHEL. 在RHEL上的账号可以分为两类: 用户账号:用来存储单一用户的数据,你也可以使用一个用户账号 ...

  6. iOS “弱账号” 暗转 “强账号”

    一.背景 由于某些历史原因,我们产品中50%以上活跃用户是弱账户.即 客户端按照某种规则生成的一个伪id 存在keychain 里,作为这个用户的唯一标识,实现快速登录.正常情况下是不会有问题. 最近 ...

  7. ebay如何确定同一电脑登陆了多个账号,以及同一账号登陆过多台电脑

    转自hilton 的BLOG http://jimqu.blog.51cto.com/105370/654691 一切要从ebay的买家保护说起 ebay作为一个电子商务平台,之所以可以汇聚如此众多的 ...

  8. Java并发框架——同步状态的管理

    整个AQS框架核心功能都是围绕着其32位整型属性state进行,一般可以说它表示锁的数量,对同步状态的控制可以实现不同的同步工具,例如闭锁.信号量.栅栏等等.为了保证可见性此变量被声明为volatil ...

  9. [转]10+倍性能提升全过程--优酷账号绑定淘宝账号的TPS从500到5400的优化历程

    摘要: # 10+倍性能提升全过程--优酷账号绑定淘宝账号的TPS从500到5400的优化历程 ## 背景说明 > 2016年的双11在淘宝上买买买的时候,天猫和优酷土豆一起做了联合促销,在天猫 ...

随机推荐

  1. leetcode_894. All Possible Full Binary Trees

    https://leetcode.com/problems/all-possible-full-binary-trees/ 给定节点个数,求所有可能二叉树,该二叉树所有节点要么有0个子节点要么有两个子 ...

  2. hibernate 批量抓取

    使用场景: 是查询出来一个集合,然后又查询每个集合对象中的集合.使用set标签中的batch-size属性实现. 数据库中只有5个区道信息: 设置batch-size=”5”,执行的查询语句如下: 而 ...

  3. bind - 将一个名字和一个套接字绑定到一起

    SYNOPSIS 概述 #include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, struct s ...

  4. mysql group_concat函数详解

    group_concat( [DISTINCT]  要连接的字段   [Order BY 排序字段 ASC/DESC]   [Separator '分隔符'] ) 1. --以id分组,把price字 ...

  5. JavaScript中的跨域问题

    跨域问题其实很普遍的存在的,如何解决跨域问题呢,跨域问题到底是怎么产生的,解决方法的由来又是什么?我觉得看了视频讲解,值得写下来,记录下来. 一.跨域问题是怎么产生? 概念:只要协议.域名.端口有任何 ...

  6. BZOJ 2502 Luogu P4843 清理雪道 最小流

    题意: 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机 ...

  7. BZOJ 2039 人员雇佣 二元关系 最小割

    题面太长了,请各位自行品尝—>人员雇佣 分析: 借用题解的描述: a.选择每个人有一个代价Ai b.如果有两个人同时选择就可以获得收益Ei,j c.如果一个人选择另一个不选会产生代价Ei,j 这 ...

  8. CF919F A Game With Numbers

    题目:(luogu翻译错的很多) Alice和Bob玩游戏,每人有8张牌,牌的值为0~4.每一轮当前玩家选择自己的牌A和对手的牌B,然后将A的值变为( A + B )%5,其中A和B都不是0. 当一个 ...

  9. MySQL 快速入门教程

    转:MySQL快速 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数据 ...

  10. python+selenium之元素的八大定位方法

    以百度搜索框为例,先打开百度网页 1.点右上角爬虫按钮 2.点左下角箭头 3.讲箭头移动到百度搜索输入框上,输入框高亮状态 4.下方红色区域就是单位到输入框的属性: <input id=&quo ...