我的应用程序有一个特定的功能,只能在根可用的设备上工作。与其让这个特性在使用时失败(然后向用户显示适当的错误消息),我更希望能够先静默地检查根目录是否可用,如果不可用,则首先隐藏相应的选项。

有办法做到这一点吗?


当前回答

如果你已经在使用Fabric/Firebase Crashlytics,你可以打电话

CommonUtils.isRooted(context)

这是该方法的当前实现:

public static boolean isRooted(Context context) {
    boolean isEmulator = isEmulator(context);
    String buildTags = Build.TAGS;
    if (!isEmulator && buildTags != null && buildTags.contains("test-keys")) {
        return true;
    } else {
        File file = new File("/system/app/Superuser.apk");
        if (file.exists()) {
            return true;
        } else {
            file = new File("/system/xbin/su");
            return !isEmulator && file.exists();
        }
    }
}

public static boolean isEmulator(Context context) {
    String androidId = Secure.getString(context.getContentResolver(), "android_id");
    return "sdk".equals(Build.PRODUCT) || "google_sdk".equals(Build.PRODUCT) || androidId == null;
}

其他回答

http://code.google.com/p/roottools/

如果你不想使用jar文件,请使用下面的代码:

public static boolean findBinary(String binaryName) {
        boolean found = false;
        if (!found) {
            String[] places = { "/sbin/", "/system/bin/", "/system/xbin/",
                    "/data/local/xbin/", "/data/local/bin/",
                    "/system/sd/xbin/", "/system/bin/failsafe/", "/data/local/" };
            for (String where : places) {
                if (new File(where + binaryName).exists()) {
                    found = true;

                    break;
                }
            }
        }
        return found;
    }

程序将尝试查找su文件夹:

private static boolean isRooted() {
        return findBinary("su");
    }

例子:

if (isRooted()) {
   textView.setText("Device Rooted");

} else {
   textView.setText("Device Unrooted");
}

在2021年最后一个季度的今天,我试图使用SafetyNet来回答@HimanshiThakur的答案。但我有个问题,在这里提出了一个问题。还是没有回答。

所以我决定使用RootBeer。它工作得很好,但当Magisk隐藏根时,它就不起作用了。

如果你不在乎这种情况(许多银行应用程序也不能解决这个问题),你可以使用以下步骤:

添加到Gradle:

implementation 'com.scottyab:rootbeer-lib:0.1.0'

用这些句子:

RootBeer rootBeer = new RootBeer(context);
if (rootBeer.isRooted()) {
    //we found indication of root
} else {
    //we didn't find indication of root
}

你可以通过以下代码来做到这一点:

public boolean getRootInfo() {
    if (checkRootFiles() || checkTags()) {
        return true;
    }
    return false;
}

private boolean checkRootFiles() {
    boolean root = false;
    String[] paths = {"/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su",
            "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su"};
    for (String path : paths) {
        root = new File(path).exists();
        if (root)
            break;
    }
    return root;
}

private boolean checkTags() {
    String tag = Build.TAGS;
    return tag != null && tag.trim().contains("test-keys");
}

你也可以检查RootBeer这个库。

一些用于设置系统属性ro的修改版本。Modversion用于此目的。事情似乎已经发生了变化;我几个月前在TheDude上的构建是这样的:

cmb@apollo:~$ adb -d shell getprop |grep build
[ro.build.id]: [CUPCAKE]
[ro.build.display.id]: [htc_dream-eng 1.5 CUPCAKE eng.TheDudeAbides.20090427.235325 test-keys]
[ro.build.version.incremental]: [eng.TheDude.2009027.235325]
[ro.build.version.sdk]: [3]
[ro.build.version.release]: [1.5]
[ro.build.date]: [Mon Apr 20 01:42:32 CDT 2009]
[ro.build.date.utc]: [1240209752]
[ro.build.type]: [eng]
[ro.build.user]: [TheDude]
[ro.build.host]: [ender]
[ro.build.tags]: [test-keys]
[ro.build.product]: [dream]
[ro.build.description]: [kila-user 1.1 PLAT-RC33 126986 ota-rel-keys,release-keys]
[ro.build.fingerprint]: [tmobile/kila/dream/trout:1.1/PLAT-RC33/126986:user/ota-rel-keys,release-keys]
[ro.build.changelist]: [17615# end build properties]

另一方面,来自1.5 SDK的模拟器,运行1.5镜像,也有根,可能类似于Android Dev Phone 1(你可能想要允许),并有这个:

cmb@apollo:~$ adb -e shell getprop |grep build
[ro.build.id]: [CUPCAKE]
[ro.build.display.id]: [sdk-eng 1.5 CUPCAKE 148875 test-keys]
[ro.build.version.incremental]: [148875]
[ro.build.version.sdk]: [3]
[ro.build.version.release]: [1.5]
[ro.build.date]: [Thu May 14 18:09:10 PDT 2009]
[ro.build.date.utc]: [1242349750]
[ro.build.type]: [eng]
[ro.build.user]: [android-build]
[ro.build.host]: [undroid16.mtv.corp.google.com]
[ro.build.tags]: [test-keys]
[ro.build.product]: [generic]
[ro.build.description]: [sdk-eng 1.5 CUPCAKE 148875 test-keys]
[ro.build.fingerprint]: [generic/sdk/generic/:1.5/CUPCAKE/148875:eng/test-keys]

至于零售构建,我手头没有,但在site:xda developers.com下的各种搜索提供了大量信息。这是荷兰的G1, ro。build。tags没有test-key,我认为这可能是最可靠的属性。

谷歌播放服务有安全网络认证API,通过它我们可以评估设备,并确定它是否被根/篡改。

请通过我的回答来处理根设备: https://stackoverflow.com/a/58304556/3908895