为了账号安全,请及时绑定邮箱和手机立即绑定

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 命令中加入参数

> $ 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 一个属性即可。

寻找源码

在 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;

但是没有 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;
}

那么方法二只是和方法一的属性获取方式不一样:

/**
 * 获取系统构建模式
 *
 * @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 的编译有一点了解。

本文作者: Cafeting

本文链接: http://likfe.com/2017/10/09/android-usermode/

点击查看更多内容
4人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消