Android account

在进行设备账户管理的时候,我们会通过一个 AccountManager 类获取系统的账户管理类,获取的方法如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. AccountManager mAccountManager = (AccountManager) getSystemService(ACCOUNT_SERVICE);  

或者

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. AccountManager accountManager = AccountManager.get(context);  

接下来我们需要通过 AccountManager 对象对账号系统进行操作。

1.获取账户信息

首先我们来查看一下如何获取用户已有的账户信息,如果你希望读取系统当前的账户信息,那么你首先需要在 manifest 文件中申明一个读取账户的权限,如下:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <uses-permission android:name="android.permission.GET_ACCOUNTS"/>  

(1)获取所有账户信息

如果你希望获取到当前设备所有的账户信息,你可以使用:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. accountManager.getAccounts();  

(2)获取特定的账户信息

如果你只希望获取自己或者特定的账户信息,你就应该使用:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. accountManager.getAccountsByType("com.kifile");  

后面的参数是你自己定义的账户类型,怎么设置我会在接下来的文章中写出来。

然后,我们就可以通过上面获取到的工具类,读取到手机上的账户信息了,这里我写了一个 ListView 的 Adapter 用于展示当前系统中的账号信息:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class AccountAdapter extends BaseAdapter {  
  2.         private Account[] mAccounts;  
  3.   
  4.         public AccountAdapter(Account[] accounts) {  
  5.             this.mAccounts = accounts;  
  6.         }  
  7.   
  8.         @Override  
  9.         public int getCount() {  
  10.             return mAccounts != null ? mAccounts.length : 0;  
  11.         }  
  12.   
  13.         @Override  
  14.         public Object getItem(int position) {  
  15.             return mAccounts[position];  
  16.         }  
  17.   
  18.         @Override  
  19.         public long getItemId(int position) {  
  20.             return 0;  
  21.         }  
  22.   
  23.         @Override  
  24.         public View getView(int position, View convertView, ViewGroup parent) {  
  25.             TextView tv = new TextView(getBaseContext());  
  26.             tv.setText(mAccounts[position].name + " " + mAccounts[position].type);  
  27.             return tv;  
  28.         }  
  29.     }  

获取当前所有系统账户信息以及设置 ListView 的 Adapter 的方法如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. mListView.setAdapter(new AccountAdapter(mAccountManager.getAccounts()));  

显示效果如下:


同你当前设备进行对比,你就会发现我们已经将当前所有的账户信息显示了出来,同样地如果你只希望显示部分的账户信息,你就可以通过 getAccountByType 获取对应的账户列表。

2.建立自己的账号服务

通过上面的部分,我们已经知道了如何获取 Android 本身现有的账号信息,现在我们就开始着手建立属于自己的账号系统吧。

你需要知道的是,如果你希望建立自己的账号系统,那么你得在 manifest 文件中声明一个关于账号的Service,如下

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <service  
  2.                 android:name="com.kifile.account.app.account.AccountService"  
  3.                 android:enabled="true"  
  4.                 android:exported="true">  
  5.             <intent-filter>  
  6.                 <action android:name="android.accounts.AccountAuthenticator"/>  
  7.             </intent-filter>  
  8.             <meta-data  
  9.                     android:name="android.accounts.AccountAuthenticator"  
  10.                     android:resource="@xml/authenticator"/>  
  11.         </service>  

在上面的代码中,我们通过设置 intent-filter 告知系统,我们当前应用中有一个账号服务,至于具体的账号信息则放在 meta-data 中的 android:resource 文件中提供, 该文件为authenticator.xml,放置路径为 res/xml,内容如下:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <account-authenticator  
  3.         xmlns:android="http://schemas.android.com/apk/res/android"  
  4.         android:accountType="com.kifile"  
  5.         android:icon="@drawable/ic_launcher"  
  6.         android:smallIcon="@drawable/ic_launcher"  
  7.         android:label="@string/app_name"/>  

在这里,我们就可以向系统提供相关的账户信息,用于在 Android Setting 目录下显示对应的账号信息。例如这里,我们就定义了当前的账户类型为"com.kifile",在账户系统中显示的标签为@string/app_name 对应的 String 对象,显示的 icon 为ic_launcher。

Ok,到了这里,我们已经向系统声明了一个账户相关的服务,现在让我们来具体实现他。

Android 为我们提供了一个叫做 AbstractAccountAuthenticator 的抽象类,也是通过它来实现:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static class Authenticator extends AbstractAccountAuthenticator {  
  2.   
  3.   
  4.         public Authenticator(Context context) {  
  5.             super(context);  
  6.         }  
  7.   
  8.         @Override  
  9.         public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {  
  10.             return null;  
  11.         }  
  12.   
  13.         @Override  
  14.         public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {  
  15.             return null;  
  16.         }  
  17.   
  18.         @Override  
  19.         public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {  
  20.             return null;  
  21.         }  
  22.   
  23.         @Override  
  24.         public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {  
  25.             return null;  
  26.         }  
  27.   
  28.         @Override  
  29.         public String getAuthTokenLabel(String authTokenType) {  
  30.             return null;  
  31.         }  
  32.   
  33.         @Override  
  34.         public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {  
  35.             return null;  
  36.         }  
  37.   
  38.         @Override  
  39.         public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {  
  40.             return null;  
  41.         }  
  42.     }  
从上面的代码中,我们可以看出,Android 需要从我们自定义的 Service 中获取一个   AbstractAccountAuthenticator 对象,然后再调用对象中的方法来实现账号系统的具体操作,每一个方法的意义,我们在本文中就不具体探讨了,如果你有兴趣,可以去看看 API 文档。

当我们创建好了一个AbstractAccountAuthenticator 类后,我们需要从 Service 中取得这个类的对象,代码如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private Authenticator authenticator;  
  2.   
  3.     @Override  
  4.     public void onCreate() {  
  5.         super.onCreate();  
  6.         authenticator = new Authenticator(this);  
  7.     }  
  8.   
  9.     @Override  
  10.     public IBinder onBind(Intent intent) {  
  11.         return authenticator.getIBinder();  
  12.     }  
AccountService 类在 onCreate 的时候创建一个 Authenticator 对象,然后再 bindService 的时候,将 Authenticator 的  IBinder 传递回去,以供调用。

当你完成上面的步骤之后,你就会发现,在你的设置页面点击添加账户时就会出现你自定义的账户了,如下:


3.添加账户

虽然通过上面的步骤,我们已经能够在添加账户的界面看到属于我们自己的账户类别了,但是你会发现当你点击它们的时候,没有任何作用,那么我们应该怎么在设备上完成添加账户的操作呢?

(1)加入添加账户的权限

添加账户也需要对应的权限,你应该在 manifest 文件中加入

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>  

(2)重写 Authenticator 的 addAccount 方法

当用户在添加账户页面选择账户进行添加或者调用accountManager.addAccount 的时候,系统会默认调用 AbstractAccountAuthenticator 中的 addAccount 方法,因此你需要重写 addAccount 方法,直接添加默认账户,或者跳转到某个页面,让用户填写用户信息,然后添加账户。

(3)使用 addAccountExplicitly 直接添加账户

如果你希望直接添加账户信息,你可以使用以下方法:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Account account = new Account("Kifile,,,,12","com.kifile");  
  2.         accountManager.addAccountExplicitly(account,password,userdata);  

使用之后,你就会发现在设置页面出现你所建立的账户,点击进去,会发现账户名什么的也已经成功设置:




(一)同步数据

通常而言,我们会在两种情况下使用我们的账号系统:

(1)登陆验证

登陆验证其实是一个很实用的功能,试想一下,加入你手机丢失了,而手机上又有很多应用,例如淘宝,QQ,拾到手机的人点击应用就可以登陆到你的账号上,这样一来我们就无法保证我们的信息和账户安全。为了防止这种情况的发生,你会修改你的密码,而当手机账户系统运行的时候,他会发现账户系统验证失败,就无法访问你相关账户了,以确保你的账户安全

(2)信息同步

如果你希望不同的设备上,同一账号的用户的某些信息要保持同步的话,那么你就可以通过账户系统自带的同步服务来实现


1.账户信息同步

账户信息同步其实主要来说有两种方式,一种是自动同步,一种是手动同步。从名字上大家就能够看出两者的区别,前者是我们设定一个固定时间间隔,让 android 系统帮我们自动同步数据,后者则是在应用中调用某个方法直接告诉设备,通知系统同步数据。

(1)自动同步:在这里需要留意的是,虽然前者有设置一个固定时间间隔,但是 android 会尽量将所有同步数据的时间都安排在一起,以减少唤醒设备的次数,因此你可能发现虽然你设置了一个固定的间隔时间,但是到了那个时间点,系统其实并没有按时同步数据。

设置自动同步的代码如下:

[java]  view plain copy
  1. ContentResolver.setSyncAutomatically(account1, "com.kifile.provider"true);  
  2.                ContentResolver.addPeriodicSync(account1, "com.kifile.provider", bundle, 10);  
第一句的作用是,设置账号自动同步,第二句的作用则是设定账号同步的间隔时间,单位为秒

(2)手动同步:在我看来手动同步其实是很有作用的,因为当你对账户信息做出更改之后,你不能完全依赖系统的同步机制,他的同步时间可能会在很久之后,因此,你需要手动调用账户同步接口,令系统同步数据。

手动同步的代码如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. ContentResolver.requestSync(account1, "com.kifile.provider", bundle);  

2.处理同步数据时的异常

同步数据时难免会出现问题,例如网络中断,或者是账号密码验证失败。对于这两种情况而言,前者不需要太过留意,只要之后能够同步正确数据即可,但是后者则需要你通知系统中断当前的账号服务,避免出现账号安全问题。


(二)设置账号页面

在账号信息页面,并不意味着只能暂时简单的账户信息,在这里,你可以根据你的需求自定义账号页面效果。

在自定义账号页面之前,你需要首先在authencator.xml(内容见之前的文章)中声明一下你需要使用的界面效果:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. android:accountPreferences="@xml/account_preferences"  
该界面效果是使用Android的Preference设置项页面进行展示的,通过这个设置页面,你能够展示最基本的页面设置信息,并且还能够使用SharedPreferences设置相关的键值信息。

当你设置好界面效果之后,能够发现账号页面除了基本的账号以外,还多了自己设置的相关界面,如下:


虽然界面效果肯定不如我们自己应用的华美,但是我们也能够向用户展示更多信息了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值