用户IDs与文件访问|权限|Android

用户ID(s)与文件访问(User IDs and File Access)


安装时,Android为每个应用包分配一个独立的Linux用户ID。应用包在设备上的整个生命周期中,这个ID不再改变。不同设备上同一个应用包可能有不同的UID,重要的是在给定的设备上,每个应用包有自己独立的UID。

由于强制安全发生在访问层,通常,两个应用包内的代码不能运行在同一个进程中,因为它们必须作为不同的Linux用户运行。你可以在每个应用包的AndroidManifest.xml的manifest标签下使用shareUserId属性,把它们置于同一个用户ID。这样做了之后,出于安全的目的,这两个包将被当作同一个应用,拥有同一个用户ID和文件权限。注意,为了保持安全性,仅当两个被注册为同一签名的应用(并且它们要有同一个shareUserId)可以被赋予相同的用户ID.

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

以下是具体操作举例,摘自http://hi.baidu.com/augustus_blog/item/3cc122bb5ebf3e4b2aebe38a
比如某个公司开发了多个Android 程序, 那么可以把数据,图片等资源集中放到Apk  A中去. 然后这个公司的所有APK都使用同一个User ID, 那么所有的资源都可以从Apk A中读取.
举个例子:
Apk A 和Apk B 都是C公司的产品,那么如果用户从Apk A中登陆成功.那么打开Apk B的时候就不用再次登陆. 具体实现就是 A和B设置成同一个User ID:

在2个Apk的AndroidManifest.xml 配置User ID:
   

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.android.demo.a1"
    android:sharedUserId="com.c">

   这个"com.c" 就是user id, 然后packagename Apk A就是上面的内容,  APK B可能是"com.android.demo.b1" 这个没有限制

   这个设定好之后, Apk B就可以像打开本地数据库那样 打开Apk A中的数据库了.Apk A把登陆信息存放在A的数据目录下面. Apk B每次启动的时候读取Apk A下面的数据库判断是否已经登陆:
  Apk B中的代码:

friendContext = this.createPackageContext("com.android.demo.a1",Context.CONTEXT_IGNORE_SECURITY);

     通过A的package name 就可以得到A的 packageContext.通过这个context就可以直接打开数据库。

     下面是具体步骤摘要

1. 对每个应用,当打包发布的时候,要使用同一个密钥来签名以确保安全。
2. 确保每个应用都以同一个用户ID运行。在 每个应用的ActivityManifest.xml 中 声明与使用此属性:

android:sharedUserId="my.shared.userid"  


3. 声明每个相关的activity或组件运行在同一个进程中。在 每个应用的ActivityManifest.xml 中 声明与使用此属性:

android:process="my.shared.processname"  

 

 

 

所有存放在一个应用立的数据都将隶属于应用的用户ID,通常不能访问其他的包。当用getSharedPreferences(String, int),openFileOutput(String, int), 或 openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory)创建了一个新的文件时,你就可以用MODE_WORLD_READABLE 和(或)MODE_WORLD_WRITEABLE 标志来读/写文件了。设置好这些标志后,文件还是属于你的应用,但是它的全局读|写权限就被设置,其它的应用将能看到它了。

posted on 2012-10-08 16:40  scwsmile  阅读(1478)  评论(0编辑  收藏  举报