如果移動端訪問不佳,請使用 => GitHub 版
關鍵詞:Android
、Make
、user
mode
、user
、userdebug
、eng
判定手機系統的構建模式、用戶模式
編譯 Rom 時,需要指定目標構建模式,構建模式有三種:用戶模式 user、用戶調試模式 userdebug 和工程模式 eng
- 用戶模式 user
- 僅安裝標籤爲 user 的模塊
- 設定屬性 ro.secure=1,打開安全檢查功能
- 設定屬性 ro.debuggable=0,關閉應用調試功能
- 默認關閉 adb 功能
- 打開 Proguard 混淆器
- 打開 DEXPREOPT 預先編譯優化
- 用戶調試模式 userdebug
- 安裝標籤爲 user、debug 的模塊
- 設定屬性 ro.secure=1,打開安全檢查功能
- 設定屬性 ro.debuggable=1,啓用應用調試功能
- 默認打開 adb 功能
- 打開 Proguard 混淆器
- 打開 DEXPREOPT 預先編譯優化
- 工程模式 eng
- 安裝標籤爲 user、debug、eng 的模塊
- 設定屬性 ro.secure=0,關閉安全檢查功能
- 設定屬性 ro.debuggable=1,啓用應用調試功能
- 設定屬性 ro.kernel.android.checkjni=1,啓用 JNI 調用檢查
- 默認打開 adb 功能
- 關閉 Proguard 混淆器
- 關閉 DEXPREOPT 預先編譯優化
指定目標構建模式:在
make
命令中加入參數
$ sudo make -j8 PRODUCT-rk312x-user $ sudo make -j8 PRODUCT-rk312x-userdebug $ sudo make -j8 PRODUCT-rk312x-eng
- 1
- 2
- 3
來源:https://www.kancloud.cn/amoy0226/fireprime_android_compile/105885
判斷構建模式
思路:通過觀察以上三個模式的屬性,這裏使用安全檢查功能(ro.securero)和應用調試功能(ro.debuggable)兩個屬性來區分這三個模式:
- user:
- ro.securero = 1
- ro.debuggable = 0
- userdebug
- ro.securero = 1
- ro.debuggable = 1
- eng
- ro.securero = 0
- ro.debuggable = 1
其中,如果只需判斷是否爲 user 模式,使用 ro.debuggable 一個屬性即可。
尋找源碼
在 android.os.Build
的源碼中我發現一個靜態變量:
/**
* Returns true if we are running a debug build such as "user-debug" or "eng".
* @hide
*/
public static final boolean IS_DEBUGGABLE =
SystemProperties.getInt("ro.debuggable", 0) == 1;
- 1
- 2
- 3
- 4
- 5
- 6
但是沒有 ro.securero
這個屬性,進一步發現其調用的是 android.os.SystemProperties
的 getInt()
函數,那可以直接使用它來獲取ro.securero
的值。
由於是 android.os.SystemProperties
是隱藏類,我們可以使用兩種方式來調用其方法:
方法一:使用修改過增加了這些隱藏類的 android.jar 來編譯 APK,此方式問題較多,配置繁瑣,不推薦;
方法二:使用反射調用,普通 App 即可使用,無限制,推薦使用此方法。
代碼實現
先說下方法一下的實現:
/**
* 獲取系統構建模式
*
* @return int(0:未知, 1 user, 2 userdebug, 3 eng)
*/
public static int getOSMode() {
int debug = SystemProperties.getInt("ro.debuggable", -1);
int secure = SystemProperties.getInt("ro.secure", -1);
if (debug == 0 && secure == 1) return 1;
else if (debug == 1 && secure == 1) return 2;
else if (debug == 1 && secure == 0) return 3;
else return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
那麼方法二隻是和方法一的屬性獲取方式不一樣:
/**
* 獲取系統構建模式
*
* @return int(0:未知, 1 user, 2 userdebug, 3 eng)
*/
public static int getOSMode() {
try {
Class clazz = Class.forName("android.os.SystemProperties");
int debug = (int) clazz.getMethod("getInt", String.class, int.class).invoke(clazz, "ro.debuggable", -1);
int secure = (int) clazz.getMethod("getInt", String.class, int.class).invoke(clazz, "ro.secure", -1);
if (debug == 0 && secure == 1) return 1;
else if (debug == 1 && secure == 1) return 2;
else if (debug == 1 && secure == 0) return 3;
else return 0;
} catch (ClassNotFoundException ignore) {
} catch (NoSuchMethodException ignore) {
} catch (IllegalAccessException ignore) {
} catch (InvocationTargetException ignore) {
}
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
這裏未對反射時可能產生的異常做處理,只是簡單的返回 0,有需要請自行處理。
總結
android.os.Build
和 android.os.SystemProperties
的源碼在
Android SDK 中,很方便尋找,比較困難的一步就是了解到所需的屬性和這兩個類有關,這就需要對 Android Rom 的編譯有一點了解。
PS:如果有什麼建議或者問題,可以通過下面的方式和我聯繫
閒聊羣 : 668524118
本羣主要用於編程技術 ,及創意作品 ,思維架構的交流 ,歡迎喜歡創新 ,熱愛生活的朋友加入 !