Android多用户及sharedUserId

多用户机制

Android将Unix的多用户用于实现App的沙箱机制。

Android支持多用户之前:uid = appId;
Android支持多用户之后:uid = userId + appId(如u0_a110u10_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资源的方法:

  1. 应用程序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" >
    
  2. 应用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进程命令

2017/3/21 12:10 下午 posted in  Android
 

DataSetObservable中关于ConcurrentModificationException异常的避免

public class DataSetObservable extends Observable<DataSetObserver> {
    public void notifyChanged() {
        synchronized(mObservers) {
            // since onChanged() is implemented by the app, it could do anything, including
            // removing itself from {@link mObservers} - and that could cause problems if
            // an iterator is used on the ArrayList {@link mObservers}.
            // to avoid such problems, just march thru the list in the reverse order.
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
    ...
}    
Read more   2017/3/9 22:58 下午 posted in  Android
 

Broadcasts

接收广播

在manifest文件中声明receiver

<receiver android:name=".MyBroadcastReceiver"  android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
        <action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
    </intent-filter>
</receiver>
Read more   2017/3/9 7:55 上午 posted in  Android
 

Android中的进程和线程

Android中进程的优先级

  1. 前台进程
  2. 可见进程
  3. 服务进程
    使用Service可以保证,无论Activity发生什么情况,该操作至少局部“服务进程”的优先级。
  4. 后台进程
  5. 空进程
Read more   2017/3/8 23:5 下午 posted in  Android
 

ContentValues、Bundle区别

ContentValues用于SQLiteDatebase、ContentResolver。

Read more   2017/3/3 17:5 下午 posted in  Android
 

Intent

基本用例:

  1. 启动Activity startActivity()、startActivityForResult() + onActivityResult()
  2. 启动服务 startService()、bindService()
  3. 传递广播
    sendBroadcast()、sendOrderedBroadcast()、sendStickyBroadcast()

Read more   2017/3/3 14:52 下午 posted in  Android
 

OkHttp相关网络问题

Read more   2017/2/28 19:51 下午 posted in  Android
 

Android测试

Android的测试基于JUnit。

Read more   2017/2/27 15:49 下午 posted in  Android
 

Prefs保存double类型

/**
 * 根据IEEE 754规范
 * 存的时候,转换成long类型表示的二进制位格式
 * doubleToRawLongBits与doubleToLongBits方法的区别在于
 * 前者返回实际的NaN值相应的二进制位格式,
 * 后者将所有的NaN值都归为一个规范的NaN值,并返回该规范的NaN值的二进制位格式
 */
Double.doubleToRawLongBits(double value);

// 取的时候,将long类型表示的二进制位格式转换成double
Double.longBitsToDouble(long value);
2017/2/23 23:4 下午 posted in  Android