當你的App想"串門"時:Android不同UID怎么互相訪問資源?
先回憶下上次聊的:Android 中每個應用程序都有一個唯一的 UID,這個 UID 用來標識程序所擁有的資源,比如文件目錄、數據庫訪問、網絡、傳感器和日志等。默認情況下應用之間是不能互相訪問資源的。
默認情況下這些應用就像住在不同小區的住戶——你家防盜門密碼只有自己知道,別人根本進不來。那如果真有需要"串門"的情況怎么辦?咱們今天就扒一扒應用之間"開后門"姿勢。
1?? 共享UID:穿同一條褲衩
適用場景:同一開發者的多應用深度整合
<!-- 在多個應用的 AndroidManifest.xml 中聲明相同 UID -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.reathin.app1"
android:sharedUserId="com.reathin.shareuid">就像兩個租客合租一間房,用同一個門鎖密碼(UID)。注意:
- 必須用同一個簽名文件打包(相當于合租合同要蓋同一個公章)
- 裝完應用就不能改簽名了(房東不讓中途換鎖)
- 能互相訪問私有目錄/data/data/pkg_name
2?? 文件權限大放送
適用場景:臨時文件傳輸(如應用更新包)
在創建文件時手動設置權限:
val file = File(getExternalFilesDir(null), "shared_file.txt")
// 第二個參數false=給所有人讀權限
file.setReadable(true, false)
// 其他應用通過絕對路徑訪問(需知道準確路徑)
val externalDir = File("/storage/emulated/0/Android/data/com.reathin.app1/files")
val sharedFile = File(externalDir, "shared_file.txt")這就相當于在自家門口放個帶密碼的快遞柜,把密碼寫在便利貼上。注意:
- Android 7后禁止 MODE_WORLD_READABLE
- Android 10開始用Scoped Storage后這招不好使了(物業升級了門禁系統)
- 建議改用MediaStore或者SAF(存儲訪問框架)
3?? ContentProvider:開個小賣部窗口
適用場景:跨應用數據共享(如讀取通訊錄、共享配置)
<!-- 在數據提供方聲明權限 -->
<provider
android:name=".MyProvider"
android:authorities="com.reathin.provider"
android:readPermission="com.reathin.READ_DATA"
android:exported="true"/>// 數據請求方申請權限(需在 Manifest 聲明)
if (checkSelfPermission("com.reathin.READ_DATA") == PERMISSION_GRANTED) {
contentResolver.query(Uri.parse("content://com.reathin.provider/data"), ...)
}在小區里開個小賣部,別人通過指定窗口買東西。記得:
- 配置android:permission限制訪問權限(裝個防盜門鈴)
- 用android:grantUriPermissions臨時授權(給訪客發一次性門禁卡)
4?? Binder跨進程通信:空中傳物
通過AIDL接口傳遞數據:
// 服務端
publicclass MyService extends Service {
privatefinal IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
public String getSecretData() {
return"隔壁老王家的WiFi密碼是12345678";
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
// 客戶端
IMyAidlInterface service = IMyAidlInterface.Stub.asInterface(binder);
String data = service.getSecretData();相當于兩家陽臺離得近,直接拋接物品。但要注意:
- 要處理跨進程異常(小心沒接住摔壞東西)
- 別傳敏感數據(扔個蘋果還行,金條容易被劫)
5?? 反射大法:偷物業萬能卡
try {
Class<?> clazz = Class.forName("android.app.ActivityThread");
Method method = clazz.getDeclaredMethod("getPackageInfo", String.class, int.class);
Object packageInfo = method.invoke(null, "com.reathin.app3", 0);
// 然后就能拿到別人的資源ID...
} catch (Exception e) {
// 大概率被系統保安抓住
}這種操作就像偽造門禁卡,某些機型能成功。
- 不同Android版本會失效(物業定期換鎖)
- 上架應用市場必被拒審(被監控拍到)
總結
方式 | 推薦指數 | 適用場景 | 翻車概率 |
共享UID | ?? | 自家兄弟應用 | 中 |
ContentProvider | ???? | 需要精細控制的數據共享 | 低 |
Binder通信 | ??? | 實時交互的功能模塊 | 中 |
文件權限 | ?? | 低版本Android的臨時方案 | 高 |
反射/黑科技 | ? | 測試環境玩玩就行 | 極高 |
現在的Android系統就像高檔小區,物業(系統權限)管得越來越嚴。能走正門就別爬水管,保不準哪天就被逮到封號了!

























