今天講一下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相同,簽名不同
2013-8-15
Edited by 泡泡糖
Edited by mythou
原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3258715.html