Android中的sharedUserId

1、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>
複製代碼

2、sharedUserId注意事項

  • sharedUserId的value必須包含一個".",不然在打包安裝到手機的時候會報錯。
  • 某些功能的實現須要對相同shareUserId的apk使用相同的簽名。

3、對sharedUserId的理解

咱們都知道android的每個應用都運行在單獨的虛擬機上,以便提升系統的穩定性,每一個應用進程都是由單獨的Linux系統用戶所建立,相同的sharedUserId的應用歸屬的linux相同的用戶,資源共享則有不少的的便利能夠利用。 我作了一個測試,使用adb shell top命令查看進程。 附帶adb shell top命令解析linux

>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 android

不一樣sharedUserId.png

下面這張圖是改爲了相同的sharedUserId shell

相同sharedUserId.png

4、對於相同sharedUserId的使用

如下兩個應用的包名分別爲net.loosash.learnshareduserid(A應用)、net.loosash.learnshareduserid2(B應用) 一、獲取同名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應用中讀取SPbash

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中的數據了,同理數據庫的訪問也一樣共享 二、訪問同名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 目錄app

不一樣sharedUserId報權限錯誤.png
訪問A的 data/data 目錄,無test.txt及test_from_b.txt
目錄中沒有對應文件.png
修改相同sharedUserId,運行B,訪問 data/data 目錄,發現已經存在test.txt及test_from_b.txt
目錄中存在對應文件.png

5、總結

不一樣應用之間能夠經過設置相同sharedUserId來實如今Linux上的用戶統一,來打破不一樣應用間的沙盒性質,已實現數據、資源的共享。測試

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

image
相關文章
相關標籤/搜索