Android ShareUserId 使用總結

idaretobe發表於2015-01-05

今天講一下Android裡面經常看到卻不太留意的知識點——ShareUserId,在Android裡面每個app都有一個唯一的linux user ID,則這樣許可權就被設定成該應用程式的檔案只對該使用者可見,只對該應用程式自身可見,而我們可以使他們對其他的應用程式可見,這會使我們用到SharedUserId,也就是讓兩個apk使用相同的userID,這樣它們就可以看到對方的檔案。為了節省資源,具有相同ID的apk也可以在相同的linux程式中進行(注意,並不是一定要在一個程式裡面執行),共享一個虛擬機器。

  下面我們看看ShareUserId的作用,資料共享、呼叫其他程式資源。

(PS:新建的QQ群,有興趣可以加入一起討論:Android群:322599434)

 

1、獲取相同ShareUserId程式的Context


//Edited by mythou
//http://www.cnblogs.com/mythou/
//第一個應用程式為的menifest檔案程式碼如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mythou.serviceID"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="com.mythou.share"

>
//.......
//第二個應用程式的menifest檔案程式碼如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mythou.clientID"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="com.mythou.share"
>

  上面給出了兩個程式的menifest定義,兩者共用一個ShareUserId,下面我們看看從一個程式裡面如何獲取另外一個程式的Context。假設我們從package=“com.mythouclientID”的程式獲取package="com.mythou.serviceID"的程式的context:

//Edited by mythou
//http://www.cnblogs.com/mythou/
Context ct=this.createPackageContext("com.mythou.serviceID", Context.CONTEXT_IGNORE_SECURITY);

 

2、利用StartActivity啟動其他應用的

  當我們在不同的application中,如application A中的Activity去start一個application B中的Activity,也許你什麼Exception都不會得到,也可能會直接Force Close掉。因為再Start Activity時,程式碼是有去檢驗permission的。 Uid是使用者ID,Android中每個程式都有一個Uid,預設情況下,Android會給每個程式分配一個普通級別互不相同的 Uid,如果用互相呼叫,只能是Uid相同才行,這就使得共享資料具有了一定安全性,每個軟體之間是不能隨意獲得資料的。而同一個application 只有一個Uid,所以application下的Activity之間不存在訪問許可權的問題。 但是不同的Application下的應用,訪問Activity的時候就存在許可權問題。如果設定同一個ShareUserId可以避免這種情況。

  下面補充一點,如何共享一個程式的資料,如果你需要做一個application,將某些服務service,provider或者activity等的資料,有三個辦法可以方便共享資料。 


1、完全暴露,這就是android:exported=”true”的作用,而一旦設定了intentFilter之後,exported就預設被設定為true了,除非再強制設為false。當然,對那些沒有intentFilter的程式體,它的exported屬性預設仍然是false,也就不能共享出去。 

2、許可權提示暴露,這就是為什麼經常要設定usePermission的原因,如果人家設定了 android:permission=”xxx.xxx.xx”那麼,你就必須在你的application的Manufest中 usepermission xxx.xxx.xx才能訪問人家的東西。 

3、私有暴露,假如說一個公司做了兩個產品,只想這兩個產品之間可互相呼叫,那麼這個時候就必須使用shareUserID將兩個軟體的Uid強制設定為一樣的。這種情況下必須使用具有該公司簽名的簽名文件才能,如果使用一個系統自帶軟體的ShareUID,例如Contact,那麼無須第三方簽名。 

 

3、利用ShareUserID共享資料

  兩個應用的ShareUserId相同,則共享對方的data目錄下的檔案,包括SharePreference, file, lib等檔案,而不是資原始檔。 要共享資原始檔(圖片,layout, string等),並不需要ShareUserId相同,普通方法就能拿到,但前提是你自己的應用裡已經有了名字相同的資原始檔,這樣R檔案才能找到那個id,否則編譯器報錯。 當然你也可以使用上面的獲取context,然後讀取資源。下面給出普通情況下讀取其他程式資源辦法:

    
//Edited by mythou
//http://www.cnblogs.com/mythou/
    try {
            Context ct=this.createPackageContext ("com.mythou.serviceID", Context.CONTEXT_IGNORE_SECURITY);
            String str = ct.getString(R.string.appname);
            Log.d("mythou", str);
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 

  下面我們看看擁有相同的UID的時候,如何訪問data下資料

    
//Edited by mythou
//http://www.cnblogs.com/mythou/
    try {
            Context ct=this.createPackageContext ("com.mythou.serviceID", Context.CONTEXT_IGNORE_SECURITY);
            SharedPreferences sp = ct.getSharedPreferences("appInfo", MODE_PRIVATE);
            String str2 = sp.getString("appname", "service");
            Log.d("mythou", "share preference-->" + str2);
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 

兩個應用ShareUserId相同,包名相同或不同,打包時簽名檔案必須相同否則,在如下情況下,第二個安裝包在安裝時會失敗,錯誤為[INSTALL_FAILED_SHARED_USER_INCOMPATIBLE]:
1.包名相同,簽名相同,ShareUserId不同
2.包名相同或不同,ShareUserId相同,簽名不同

相關文章