一、manifest标签包含内容
<manifest xmlns:android="http://schemas.android.com/apk/res/android" // 命名空间
android:versionCode="1" // 版本号,会被gradle中覆盖,不推荐
android:versionName="1.0" // 版本名称,同上
android:sharedUserId="net.loosash.share" // sharedUserId 本文详细介绍
android:sharedUserLabel="@string/app_name" // 为用户提供一个可读的标签,value仅能使用资源id
android:installLocation="internalOnly" // 安装位置 默认internalOnly:只能安装在内部存储中;preferExternal:安装在外部存储中,当不可用时安装在内部存储中,安装后用户可以通过系统设置移动安装位置;auto:用户可以选择安装在内部存储还是外部存储中。
package="net.loosash.learnmanifest">
......
</manifest>
复制代码
二、sharedUserId注意事项
- sharedUserId的value必须包含一个".",否则在打包安装到手机的时候会报错。
- 某些功能的实现需要对相同shareUserId的apk使用相同的签名。
三、对sharedUserId的理解
我们都知道android的每一个应用都运行在单独的虚拟机上,以便提高系统的稳定性,每个应用进程都是由单独的Linux系统用户所创建,相同的sharedUserId的应用归属的linux相同的用户,资源共享则有很多的的便利可以利用。 我做了一个测试,使用adb shell top命令查看进程。 附带adb shell top命令解析
>adb shell top -h
Usage: top [ -m max_procs ] [ -n iterations ] [ -d delay ] [ -s sort_column ] [-t ] [ -h ]
-m num Maximum number of processes to display. 最多显示多少个进程
-n num Updates to show before exiting. 刷新次数
-d num Seconds to wait between updates. 刷新间隔时间(默认5秒)
-s col Column to sort by (cpu,vss,rss,thr). 按哪列排序
-t Show threads instead of processes. 显示线程信息而不是进程
-h Display this help screen. 显示帮助文档
复制代码
这张图是两个应用使用不同的sharedUserId
下面这张图是改成了相同的sharedUserId
四、对于相同sharedUserId的使用
以下两个应用的包名分别为net.loosash.learnshareduserid(A应用)、net.loosash.learnshareduserid2(B应用) 1、获取同名sharedUserId应用SP 当然SP存储的跨应用处理还有其他方式,具体会在SP部分中进行说明,这里特指getSharePreferences(String name ,@PreferencesMode int mode)方法中mode为Context.MODE_PRIVATE情况。 通过拿到Context来操作SP的读取。 A应用中储存
val preferences = getSharedPreferences("sp", Context.MODE_PRIVATE)
preferences.edit().putInt(key_test_int, 1024).apply()
Log.d(tag,"获取sp内$key_test_int 值为${preferences.getInt(key_test_int,0)}")
复制代码
B应用中读取SP
val otherContext = this.createPackageContext("net.loosash.learnshareduserid",Context.CONTEXT_IGNORE_SECURITY)
val preferences = otherContext.getSharedPreferences("sp", Context.MODE_PRIVATE)
Log.d(tag,"获取sp内$key_test_int 值为${preferences.getInt(key_test_int,0)}")
复制代码
查看日志输出 A应用
B应用 可见不同的应用共享SP中的数据了,同理数据库的访问也同样共享 2、访问同名sharedUserId应用 data/data 目录 在A中增加assets文件test.txt,在B中增加文件test_from_b.txt 在B中加入代码 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
复制代码
// var file = File("/data/data/net.loosash.learnshareduserid/test.txt")
var file = File("/data/data/net.loosash.learnshareduserid/test_from_b.txt")
if (!file.exists()) {
file.createNewFile()
}
// 在B中将B的test_from_b写入A
var input = this.assets.open("test_from_b.txt")
// 在B中将A的test写入A
// var input = otherContext.assets.open("test.txt")
var output = FileOutputStream(file)
val buffer = ByteArray(1024)
while (input.read(buffer) != -1) {
output.write(buffer, 0, input.read(buffer))
}
input.close()
output.close()
复制代码
在不同sharedUserId时,运行B,报错Permission denied,无法访问A的data/data 目录
访问A的 data/data 目录,无test.txt及test_from_b.txt 修改相同sharedUserId,运行B,访问 data/data 目录,发现已经存在test.txt及test_from_b.txt五、总结
不同应用之间可以通过设置相同sharedUserId来实现在Linux上的用户统一,来打破不同应用间的沙盒性质,已实现数据、资源的共享。