2011年12月26日 星期一

Android - Pass Data (6) - android:sharedUserId

不同的package,如果要互相使用對方的數據資料(例如values資料夾下的string.xml裡面的某個值),可以透過android:sharedUserId將兩個apk跑在同一個process裡面,這樣就可以互相使用對方的資料了。

測試程式需要2個package,在第1個apk上面將會抓出第2個apk的values/string.xml裡面的某個字串的值

第1個AndroidManifest.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test.testid1"
      android:versionCode="1"
      android:versionName="1.0"
      android:sharedUserId="com.test.testid">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

java檔程式如下:
public class Main extends Activity {
    private Context OtherContext;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView txt = (TextView) findViewById(R.id.txt1);

        try {
            OtherContext = this.createPackageContext("com.test.testid2",
                    Context.CONTEXT_IGNORE_SECURITY);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }

        txt.setText(OtherContext.getResources().getString(R.string.id));
    }
}

string.xml內容如下
<resources>
    <string name="id">This string is from another package com.test.testid1 -> TestID1.</string>
</resources>

這裡要傳遞的資料是string name="id"的字串,兩個apk的string.xml都要宣告<string name="id">,不然第一支apk在compiler會無法通過, 值當然可以不一樣。

接下來看看第二支apk的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test.testid2"
      android:versionCode="1"
      android:versionName="1.0"
      android:sharedUserId="com.test.testid">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest> 


string.xml內容如下
<resources>
     <string name="id">This string is from another package com.test.testid2 -> TestID2.</string>
</resources>
因為兩支apk都是宣告成android:sharedUserId="com.test.testid",所以可以利用createPackageContext取得另一個apk的context,更進而獲取其相關數據資料。

先將兩支apk都安裝到手機上面,然後執行第1支apk,畫面如下:


















注意字串是This string is from another package com.test.testid2 -> TestID2.

那如何證明兩支apk是跑在同一個process? 利用adb shell進入後,打上ps

可 以看到USER id都是app_37,表示是同一個process,app_37是在安裝該程式時,就由系統自行產生決定的。其它比較重要的USER像是root、 system...等。很多程式為了能夠存取Settings裡面的資料,就需要將USER改為system以獲取權限。

沒有留言:

張貼留言