Android 移動開發 - 獲取手機系統的構建模式

斷定手機系統的構建模式、用戶模式android

編譯 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 命令中加入參數ide

$ sudo make -j8 PRODUCT-rk312x-user
$ sudo make -j8 PRODUCT-rk312x-userdebug
$ sudo make -j8 PRODUCT-rk312x-eng

來源: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 一個屬性便可。ui

尋找源碼

在 android.os.Build 的源碼中我發現一個靜態變量:spa

/**
 * 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;

可是沒有 ro.securero 這個屬性,進一步發現其調用的是 android.os.SystemProperties 的 getInt() 函數,那能夠直接使用它來獲取ro.securero 的值。debug

因爲是 android.os.SystemProperties 是隱藏類,咱們能夠使用兩種方式來調用其方法:調試

方法一:使用修改過增長了這些隱藏類的 android.jar 來編譯 APK,此方式問題較多,配置繁瑣,不推薦;code

方法二:使用反射調用,普通 App 便可使用,無限制,推薦使用此方法。

源碼產品免費下載地址:http://www.jinhusns.com/Products/Download

代碼實現

先說下方法一下的實現:

/**
 * 獲取系統構建模式
 *
 * @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;
}

那麼方法二隻是和方法一的屬性獲取方式不同:

/**
 * 獲取系統構建模式
 *
 * @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;
}

這裏未對反射時可能產生的異常作處理,只是簡單的返回 0,有須要請自行處理。

總結

android.os.Build 和 android.os.SystemProperties 的源碼在 Android SDK 中,很方便尋找,比較困難的一步就是了解到所需的屬性和這兩個類有關,這就須要對 Android Rom 的編譯有一點了解。

相關文章
相關標籤/搜索