1. 程式人生 > >Android中的sharedUserId

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.png

下面這張圖是改成了相同的sharedUserId 相同sharedUserId.png

四、對於相同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應用net.loosash.learnshareduserid應用輸出.png B應用net.loosash.learnshareduserid2應用輸出.png 可見不同的應用共享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 目錄不同sharedUserId報許可權錯誤.png 訪問A的 data/data 目錄,無test.txt及test_from_b.txt目錄中沒有對應檔案.png 修改相同sharedUserId,執行B,訪問 data/data 目錄,發現已經存在test.txt及test_from_b.txt目錄中存在對應檔案.png

五、總結

不同應用之間可以通過設定相同sharedUserId來實現在Linux上的使用者統一,來打破不同應用間的沙盒性質,已實現資料、資源的共享。

關注微信公眾號,最新技術乾貨實時推送

image