Determine if running on a rooted device

后端 未结 24 2232
無奈伤痛
無奈伤痛 2020-11-22 06:43

My app has a certain piece of functionality that will only work on a device where root is available. Rather than having this feature fail when it is used (and then show an a

24条回答
  •  [愿得一人]
    2020-11-22 06:57

    Many of the answers listed here have inherent issues:

    • Checking for test-keys is correlated with root access but doesn't necessarily guarantee it
    • "PATH" directories should be derived from the actual "PATH" environment variable instead of being hard coded
    • The existence of the "su" executable doesn't necessarily mean the device has been rooted
    • The "which" executable may or may not be installed, and you should let the system resolve its path if possible
    • Just because the SuperUser app is installed on the device does not mean the device has root access yet

    The RootTools library from Stericson seems to be checking for root more legitimately. It also has lots of extra tools and utilities so I highly recommend it. However, there's no explanation of how it specifically checks for root, and it may be a bit heavier than most apps really need.

    I've made a couple of utility methods that are loosely based on the RootTools library. If you simply want to check if the "su" executable is on the device you can use the following method:

    public static boolean isRootAvailable(){
        for(String pathDir : System.getenv("PATH").split(":")){
            if(new File(pathDir, "su").exists()) {
                return true;
            }
        }
        return false;
    }
    

    This method simply loops through the directories listed in the "PATH" environment variable and checks if a "su" file exists in one of them.

    In order to truly check for root access the "su" command must actually be run. If an app like SuperUser is installed, then at this point it may ask for root access, or if its already been granted/denied a toast may be shown indicating whether access was granted/denied. A good command to run is "id" so that you can verify that the user id is in fact 0 (root).

    Here's a sample method to determine whether root access has been granted:

    public static boolean isRootGiven(){
        if (isRootAvailable()) {
            Process process = null;
            try {
                process = Runtime.getRuntime().exec(new String[]{"su", "-c", "id"});
                BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String output = in.readLine();
                if (output != null && output.toLowerCase().contains("uid=0"))
                    return true;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (process != null)
                    process.destroy();
            }
        }
    
        return false;
    }
    

    It's important to actually test running the "su" command because some emulators have the "su" executable pre-installed, but only allow certain users to access it like the adb shell.

    It's also important to check for the existence of the "su" executable before trying to run it, because android has been known to not properly dispose of processes that try to run missing commands. These ghost processes can run up memory consumption over time.

提交回复
热议问题