多用户,即是为一部手机实现多个相互隔离的使用环境。利用多用户,既可以实现多个用户共享一部手机,例如:儿童模式等受限用户的应用;也可以为一个用户提供多种使用环境,例如为政企员工开发的工作模式。
在android里,有两种userId:一种是linux进程的userId、即linux操作系统的userId。android系统就是通过把每个应用分别指派为不同的linux user,来实现的app沙箱环境。
另一种userid才是本文所讨论的多用户的id,主用户的userId=0,开机自动运行并且不会关闭。其他user id从10开始,通过createUser创建。(希望不要混淆了两种userid)
三个getuserid的api:
UserHandle.myUserId() //获取当前进程的userId
UserHandle.getUserId(Binder.getCallingUid()) //获取调用者进程的userId
ActivityManager.getCurrentUser() //获取运行在前台的userId,注意此方法需要申请跨用户权限
开启多用户,/frameworks/base/core/res/res/values/config.xml中,将属性<integer name="config_multiuserMaximumUsers">8</integer>设置成大于1的值,ams的一个工具类UserController中定义了static final int MAX_RUNNING_USERS = 3; 同时最多可以运行3个用户,当启动的用户超过3个时,android会基于最近最少使用缓存算法,来关闭多余的用户。主用户永远不会被关闭。
多用户的元数据:
/data/system/users/userlist.xml 是用户列表
/data/system/users/0.xml (10.xml) 等是每个用户的信息
/data/system/users/0(10等)目录,是系统相关的多用户数据,如系统设置等。
/data/user/0(10等)/app_dir/ 是app的数据
外部存储的挂在路径:/storage/emulator/0(10等)/ , 因为mount路径不同,所以不同用户的外部存储也是独立的。
如何访问其他用户的provider数据的三种方法:
1、改变uri:multiUser_uri = ContentProvider.maybeAddUserId(CONTENT_URI, user.id) //通过URI指定启动不同用户的provider进程,此api会将将uri改为(userid@uri),从而匹配指定用户下的provider进程。
2、启动调用者进程为指定用户的进程,然后用原uri即可访问指定用户下的provider数据
Context.startActivityAsUser(Intent, UserHandle) //启动指定用户的进程
Context.bindServiceAsUser(Intent, …, UserHandle) //启动指定用户的进程
Context.startServiceAsUser(Intent, …, UserHandle) //启动指定用户的进程
3、将provider设置为singleuser属性,这样该provider只有在主用户下存在一份数据。注意,该属性会使export属性失效。
android:SingleUser=true 设置此标记的provider,在多用户下只有一份存储数据。
数据的监控和通知:如果你想知道另一个用户的provider数据发生变化,那么必须调用以下接口对指定用户的数据进行监控,或者当数据发生变化时,通知的用户指定为UserHandle.ALL
public final void registerContentObserver(Uri uri, … )
public final void registerContentObserver(Uri uri, … , int userHandle)
系统settings provider多用户接口:
Settings.Secure.getIntForUser(…);
Settings.Secure.putIntForUser(…);
getContext().getContentResolver().notifyChange(MmsSms.CONTENT_URI, null, true, UserHandle.USER_ALL);
Context.sendBroadcastAsUser(Intent, … , UserHandle)
Context.registerReceiverAsUser(mIntent, UserHandle.ALL, …)
跨用户访问需要的权限:
INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)