多用户机制
Android将Unix的多用户用于实现App的沙箱机制。
Android支持多用户之前:uid = appId;
Android支持多用户之后:uid = userId + appId(如u0_a110
、u10_a110
)。
uid:Unix userId(不要与pid混淆);
userId:Android多用户;
appId:系统为每个App分配的id。
adb shell中查看2个用户打开同一个app时的进程示例,ps | grep -E 'NAME| <keyword>'
- Android 4.2(api 17)开始支持多用户,默认owner的userId为0,其余userId从10开始。
- App私有数据区分不同用户,从/data/data/<pkgname>变更为/data/user/<userId>/<pkgname>;其中owner用户的/data/user/0/通过软链接方式指向/data/data/;
- App代码不区分不同用户,仍为/data/app。
sharedUserId
在android系统中,apk之间可以相互读取数据的条件是:有同样的签名,并且AndroidManifest.xml文件中配置的android:sharedUserId属性值相同,那么两个apk可以互相访问私有数据。但默认2个app运行在不同的进程,除非指定android:process为同一进程,否则无法直接访问内存数据。(实际测试,2个app指定同一个process则启动一个app时另一个会crash,不知为何?)
通过userid访问其他apk资源的方法:
应用程序A和插件(比如皮肤)程序B的AndroidManifest.xml中配置相同的sharedUserId
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lonshine.skin" android:versionCode="1" android:versionName="1.0" android:sharedUserId="com.rongqin" >
应用A访问应用B中的资源
Context context = createPackageContext("com.lonshine.skin", Context.CONTEXT_IGNORE_SECURITY);
获取到com.lonshine.skin对应的Context,通过返回的context对象就可以访问到com.lonshine.skin中的任何资源。
例如,应用A获取应用B中的bg.png:
Resources resources = context.getResources(); int drawableId = resources.getIdentifier("bg", "drawable", "com.lonshine.skin"); Drawable drawable = resources.getDrawable(drawableId);
这样就得到了图片的引用,其他xml资源文件的获取方式也是类似的。
应用A获取应用B中的Preferences中的数据
SharedPreferences prefs = context.getSharedPreferences("pref_conf", Context.MODE_PRIVATE); String str = prefs.getString("pref_user_city", "");
参考
Android多用户模式的特性
Android multiuser model architecture and related security threats
Android的权限机制之—— “沙箱”机制sharedUserId和签名
Android笔记:AndroidManifest.xml属性详解(一)之sharedUserId
Android关于android:sharedUserId和android:process的疑问?
apk,task,进程区别
ps进程命令