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

有办法做到这一点吗?


当前回答

在我的应用程序中,我通过执行“su”命令检查设备是否根。但是今天我删除了这部分代码。为什么?

因为我的应用程序成了内存杀手。怎么做?让我告诉你我的故事。

There were some complaints that my application was slowing down devices(Of course I thought that can not be true). I tried to figure out why. So I used MAT to get heap dumps and analyze, and everything seemed perfect. But after relaunching my app many times I realized that device is really getting slower and stopping my application didn't make it faster (unless I restart device). I analyzed dump files again while device is very slow. But everything was still perfect for dump file. Then I did what must be done at first. I listed processes.

$ adb shell ps

使震惊;我的应用程序有许多进程(应用程序的进程标签在manifest上)。有些是僵尸,有些不是。

对于一个只有一个Activity并只执行“su”命令的示例应用程序,我意识到在每次启动应用程序时都会创建一个僵尸进程。起初,这些僵尸进程分配0KB,但后来发生了一些事情,僵尸进程与我的应用程序的主进程占用了几乎相同的kb,它们成为了标准进程。

在bugs.sun.com: http://bugs.sun.com/view_bug.do?bug_id=6474073上有一个关于相同问题的错误报告,这解释了如果命令没有找到,将使用exec()方法创建僵尸。但我仍然不明白它们为什么以及如何成为标准流程并保持重要的kb。(这并不是一直都在发生)

你可以尝试如果你想下面的代码示例;

String commandToExecute = "su";
executeShellCommand(commandToExecute);

简单的命令执行方法;

private boolean executeShellCommand(String command){
    Process process = null;            
    try{
        process = Runtime.getRuntime().exec(command);
        return true;
    } catch (Exception e) {
        return false;
    } finally{
        if(process != null){
            try{
                process.destroy();
            }catch (Exception e) {
            }
        }
    }
}

总结:总结;我没有建议你确定设备是否扎根。但如果我是你,我不会使用Runtime.getRuntime().exec()。

顺便说一下;RootTools.isRootAvailable()也会引起同样的问题。

其他回答

这确实是一个有趣的问题,到目前为止还没有人获奖。我使用以下代码:

  boolean isRooted() {
      try {
                ServerSocket ss = new ServerSocket(81);
                ss.close();
                                    return true;
            } catch (Exception e) {
                // not sure
            }
    return false;
  }

代码当然不是无懈可击的,因为网络可能不可用,所以会出现异常。如果该方法返回true,则99%可以确定,否则只有50%不确定。网络权限也可能破坏解决方案。

你可以使用isAccessGiven()代替isRootAvailable()。直接从RootTools wiki:

if (RootTools.isAccessGiven()) {
    // your app has been granted root access
}

RootTools.isAccessGiven()不仅检查设备是否已根,它还检查设备是否已根 也为你的应用程序调用su,请求权限,如果返回true 您的应用程序已成功授予根权限。可以使用这个 作为在你的应用程序中的第一个检查,以确保你将被授予 在需要的时候访问。

参考

使用c++和ndk是最好的方法来检测根,即使用户使用的应用程序隐藏了他的根,如RootCloak。我用RootCloak测试了这段代码,即使用户试图隐藏它,我也能够检测到根。 所以你的cpp文件是这样的:

#include <jni.h>
#include <string>


/**
 *
 * function that checks for the su binary files and operates even if 
 * root cloak is installed
 * @return integer 1: device is rooted, 0: device is not 
 *rooted
*/
extern "C"
JNIEXPORT int JNICALL


Java_com_example_user_root_1native_rootFunction(JNIEnv *env,jobject thiz){
const char *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"};

int counter =0;
while (counter<9){
    if(FILE *file = fopen(paths[counter],"r")){
        fclose(file);
        return 1;
    }
    counter++;
}
return 0;
}

您将从java代码中调用该函数,如下所示

public class Root_detect {



   /**
    *
    * function that calls a native function to check if the device is 
    *rooted or not
    * @return boolean: true if the device is rooted, false if the 
    *device is not rooted
   */
   public boolean check_rooted(){

        int checker = rootFunction();

        if(checker==1){
           return true;
        }else {
           return false;
        }
   }
   static {
    System.loadLibrary("cpp-root-lib");//name of your cpp file
   }

   public native int rootFunction();
}

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

RootBeer是一个由Scott和Matthew开发的Android根检查库。 它使用各种检查来指示设备是否已根。

Java检查 CheckRootManagementApps CheckPotentiallyDangerousAppss CheckRootCloakingApps CheckTestKeys checkForDangerousProps checkForBusyBoxBinary checkForSuBinary checkSuExists checkForRWSystem 本地检查 我们调用本地根检查器来运行它自己的一些检查 检查。本地检查通常很难隐藏,所以一些根 斗篷应用程序只是阻止加载本机库包含 某些关键词。 checkForSuBinary