目录
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的标签。
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 获取系统权限 - 走看看