通過Android manifest中的sharedUserId屬性的設置來實現apk之間的資源共享

在Android應用的開發中應該都會有兩個進程中需要互相訪問數據的需求,而在APK在安裝到設備裏的時候該應用的userid就已經確定了,

一般情況下都不會再改變,每個應用的進程在默認情況下的userid是不一樣的,如adb shell下top命令顯示的進程信息中的UID,

  PID PR CPU% S  #THR     VSS     RSS PCY UID      Name

 1436  2   0%    S    15 671956K  33284K  bg system   com.android.deskclock
 1459  2   0%    S    13 666772K  29656K  bg u0_a35   com.android.managedprovisioning
 1483  3   0%    S    23 683604K  36020K  bg u0_a42   com.android.mms
 1519  0   0%    S    23 687924K  39484K  bg u0_a36   com.android.email


那麼UID(userid)都有什麼作用呢?

衆所周知,Android是基於Linux內核的操作系統,一般理解爲User Identifier,UID在Linux中就是用戶的ID,表明是哪個用戶運行了這個程序,

主要用於權限的管理。Linux系統中不同的兩個普通用戶之間如果沒有賦予權限是不能互相訪問數據的。

而在Android 中又有所不同,因爲Android爲單用戶系統,這時UID 便被賦予了新的使命——數據共享,爲了實現數據共享,Android爲每個

應用幾乎都分配了不同的UID,不像傳統的Linux,每個進程的用戶相同就爲之分配相同的UID,(當然這也就表明了一個問題,android只

能是單用戶系統,在設計之初就被他們的工程師給閹割了多用戶),使之成了數據共享的工具。


那麼在Android中UID既然是用來進行數據共享的工具,那麼我們怎麼樣才能做到數據共享呢?

Android中的數據共享方式有兩種:

1)通過ContentProvider,這個方式是通過實現ContentProvider的抽象方法將需要共享的數據暴露出去,這個後續在細研究,如果需要實現

     組定義的ContentProvider,建議可以參考code/Lollipop/packages/providers/下的原生實現。

2)  通過在AndroidManifest中將android:sharedUserId屬性,將需要互相訪問的apk中的該屬性設置成相同的,這樣它們的UID就一樣了,就可以

     互相訪問各自的數據啦,包括數據庫和文件等。

     示例:

     a)首先在AndroidManifest.xml中設置相同的sharedUserId(後面簡稱爲UID),可以看到該id的命名可以隨意,當然最好能表達其作用。

      應用一     

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="test.anna.hello"
    android:sharedUserId="anna.uid">
  應用二
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="test.anna.world"
    android:sharedUserId="anna.uid">
  b) 兩個應用程序設置完相同的UID之後,爲了安全起見,建議再到Android.mk中定義相同的簽名,因爲如果不設置相同的簽名,一旦
     應用被破解,所設置的UID被暴露,其它應用通過設定相同的UID也可以任意訪問我們的數據,這樣非安全的共享其實沒有什麼意義了,
     那麼這個簽名怎麼設置呢?
     參考如下:
     vi Android.mk #應用一和應用二都需要添加
     將LOCAL_CERTIFICATE := testkey添加mk文件中
     可能在這裏對於LOCAL_CERTIFICATE的賦值,大家又會有疑問,可以使用的值都有哪些呢?
     在build/target/product/security目錄中有四組默認簽名供Android.mk在編譯APK使用:


1、testkey:普通APK,默認情況下使用。


2、platform:該APK完成一些系統的核心功能。經過對系統中存在的文件夾的訪問測試,這種方式編譯出來的APK所在進程的UID爲system。


3、shared:該APK需要和home/contacts進程共享數據。


4、media:該APK是media/download系統中的一環。


應用程序的Android.mk中有一個LOCAL_CERTIFICATE字段,由它指定用哪個key簽名,未指定的默認用testkey
四組簽名的原生註釋可以查看build/target/product/security/README的說明。


  c)目前已經具備兩個應用之間互相訪問數據的權限,那麼怎麼互相訪問呢?
     一方面是共享資源,要獲取資源只要能拿到對方的context就可以,例如在應用二中創建應用一的context:
     Context context1 = this.createPackageContext(“test.anna.hello”,Context.CONTEXT_IGNORE_SECURITY);
     這裏的this應該是Application或者Activity等有createPackageContext能力的類型相關實例。
     這樣通過context1可以獲取到應用一中的資源,包括:數據庫,preference,資源文件等等
     例如通過context1獲取應用一中的string:
     context1.getString(R.string.toast_message)


           其餘資源獲取方式查看Context的相關API進行使用。
     另一方面可能你還希望能夠在應用二中使用應用一中的一些類,那麼你可以通過修改應用二的Android.mk文件就可以mm通過,在該mk文件中添加如
     下這個編譯變量的定義:
     LOCAL_APK_LIBRARIES += Hello  
     這樣你可以編譯通過,但是可能會有運行時錯誤,這個錯誤可能由於兩個apk的classloader不一致,這個待後續驗證再補充blog,今天累了。。。


參考:

1.http://www.cnblogs.com/perseus/articles/2354173.html

2.http://blog.csdn.net/wirelessqa/article/details/8581652

3.http://blog.csdn.net/hmg25/article/details/6447067




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章