Android中的sharedUserId
一、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上的使用者統一,來打破不同應用間的沙盒性質,已實現資料、資源的共享。