Android:shareUserId知多少

目录

shareUserId简介

shareUserId设置方法

shareUserId的作用之获取系统权限

shareUserId的作用之apk之间的数据访问


shareUserId简介

        在学习shareUserId之前我们先了解一下Android App Sandbox(android沙箱机制)。在Linux中的Sandbox主要做隔离工作,将不同的任务或者用户间的耦合降到最低。Android应用也借用了Linux Sandbox技术,将不同的APP之间做客隔离,其主要表现就是资源和权限访问隔离。每个Android APP都运行在他们自己的Linux线程中(UID不同),每个应用程序彼此独立,默认情况下无法访问其他应用程序资源。APP权限机制为应用程序之间资源的互访提供了可能性,APP必须申请权限并经过用户的授权才能访问Android系统API或者其他服务。

        通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。所以默认就是可以互相访问任意数据。 也可以配置成运行成不同的进程,同时可以访问其他APK的数据目录下的数据库和文件,就像访问本程序的数据一样。

shareUserId设置方法

在需要共享资源的项目的每个AndroidMainfest.xml中添加shareuserId的标签。

扫描二维码关注公众号,回复: 14996931 查看本文章

android:sharedUserId="com.example.XX"

id名自由设置,但必须保证每个项目都使用了相同的sharedUserId。一个mainfest只能有一个Shareuserid标签。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.shareusertesta"
    android:versionCode="1"
    android:versionName="1.0" 
    android:sharedUserId="com.example">

shareUserId的作用之获取系统权限

        step1.在AndroidManifest.xml中添加android:sharedUserId = "android.uid.system"

        step2.在Android.mk文件里面添加LOCAL_CERTIFICATE := platfrom(使用系统签名)

        step3.在源码下面进行mm编译

这样生成的apk能够获取system权限,可以在任意system权限目录下进行目录或者文件的创建,以及访问其他apk资源等。常见的情景有:

  • Setting.apk 在manifest节点中增加android:sharedUserId = "android.uid.system",然后再Android.mk中增加LOCAL_CERTIFICATE:= platfrom
  • Launcher.apk 在manifest节点中增加android:sharedUserId = "android.uid.shared",然后再Android.mk中增加LOCAL_CERTIFICATE:= shared
  • Gallery.apk 在manifest节点中增加android:sharedUserId="android.media",然后在Android.mk中增加LOCAL_CERTIFICATE := media

shareUserId的作用之apk之间的数据访问

在有些时候,我们自己开发了多个APK并且需要他们之间互相共享资源,那么就需要通过设置shareUserId来实现这一目的。下面看一下两个应用A和B如何进行数据访问。

        step1.添加两个APP manifest.xml 文件中属性 android:sharedUserId,均设置为相同的值或名字(其实是设置成相同的UID)。

         step2.两个 APP 要用相同的 private key 来签名

//A应用的代码,保存数据
private void writeData(Context context, String data) {
        FileOutputStream fileOutputStream = null;
        OutputStreamWriter outputStreamWriter = null;
        try {
            //文件保存在/data/data/com.example.test/setting.dat
            //MODE_PRIVATE限制数据类型为私有
            fileOutputStream = openFileOutput("setting.dat",MODE_PRIVATE);
            outputStreamWriter = new OutputStreamWriter(fileOutputStream);
            outputStreamWriter.write(data);
            outputStreamWriter.flush();
            Toast.makeText(context, "Settings saved", Toast.LENGTH_SHORT).show();
        }catch (Exception e){
            Toast.makeText(context, "Settings not saved", Toast.LENGTH_SHORT).show();
        }finally {
            try {
                outputStreamWriter.close();
                fileOutputStream.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test"
    android:sharedUserId="com.example.testID"
    >

B应用读取A的数据:

 private void getData() {
        try {
        //获取com.example.test/A应用的context
            Context context = this.createPackageContext("com.example.test",Context.CONTEXT_IGNORE_SECURITY);
            String msg = readData(context);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

    }

    private String readData(Context context) {
        FileInputStream fileInputStream = null;
        InputStreamReader inputStreamReader = null;
        char[] inputBuffer = new char[255];
        String data = null;
        try {
            //通过文件名settings.dat找到数据
            fileInputStream = context.openFileInput("settings.dat");
            inputStreamReader = new InputStreamReader(fileInputStream);
            inputStreamReader.read(inputBuffer);
            data = new String(inputBuffer);
            Toast.makeText(context, "Settings read", Toast.LENGTH_SHORT).show();
        }catch (Exception e){
            Toast.makeText(context, "Settings not read", Toast.LENGTH_SHORT).show();
        }finally {
            try {
                inputStreamReader.close();
                fileInputStream.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        return data;
    }
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.appb"
    android:sharedUserId="com.example.testID"
    >

B写入数据

 private void writeData(String s,Context context){
        FileOutputStream fileOutputStream = null;
        OutputStreamWriter outputStreamWriter = null;
        try {
            //context还是从程序A里面获取的
            fileOutputStream = context.openFileOutput("strrings.bat",MODE_PRIVATE);
            outputStreamWriter  = new OutputStreamWriter(fileOutputStream);
            outputStreamWriter.write(s);
            outputStreamWriter.flush();
            Toast.makeText(context,"Settings saved",Toast.LENGTH_SHORT).show();
        }catch (Exception e){
            e.printStackTrace();
            Toast.makeText(context,"Settings not saved",Toast.LENGTH_SHORT).show();
        }finally {
            try {
                outputStreamWriter.close();
                fileOutputStream.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

参考链接:

android:sharedUserId 获取系统权限 - 走看看

https://www.iteye.com/blog/wx1568412008-2455378

Android sharedUserId研究记录 - 走看看

猜你喜欢

转载自blog.csdn.net/weixin_43858011/article/details/124865300