【Android】不弹root请求框检测手机是否root

2024-02-02 00:32

本文主要是介绍【Android】不弹root请求框检测手机是否root,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

由于项目需要root安装软件,并且希望在合适的时候引导用户去开启root安装,故需要检测手机是否root。

最基本的判断如下,直接运行一个底层命令。(参考https://github.com/Trinea/android-common/blob/master/src/cn/trinea/android/common/util/ShellUtils.java)

也可参考csdnhttp://blog.csdn.net/fm9333/article/details/12752415

复制代码

  1     /**2      * check whether has root permission   3      *    4      * @return5      */6     public static boolean checkRootPermission() {   7         return execCommand("echo root", true, false).result == 0;   8     }   9     10 11     /**12      * execute shell commands  13      *   14      * @param commands  15      *            command array  16      * @param isRoot  17      *            whether need to run with root  18      * @param isNeedResultMsg  19      *            whether need result msg  20      * @return <ul>  21      *         <li>if isNeedResultMsg is false, {@link CommandResult#successMsg}  22      *         is null and {@link CommandResult#errorMsg} is null.</li>  23      *         <li>if {@link CommandResult#result} is -1, there maybe some  24      *         excepiton.</li>  25      *         </ul>  26      */27     public static CommandResult execCommand(String[] commands, boolean isRoot,  28             boolean isNeedResultMsg) {  29         int result = -1;  30         if (commands == null || commands.length == 0) {  31             return new CommandResult(result, null, null);  32         }  33 34         Process process = null;  35         BufferedReader successResult = null;  36         BufferedReader errorResult = null;  37         StringBuilder successMsg = null;  38         StringBuilder errorMsg = null;  39 40         DataOutputStream os = null;  41         try {  42             process = Runtime.getRuntime().exec(  43                     isRoot ? COMMAND_SU : COMMAND_SH);  44             os = new DataOutputStream(process.getOutputStream());  45             for (String command : commands) {  46                 if (command == null) {  47                     continue;  48                 }  49 50                 // donnot use os.writeBytes(commmand), avoid chinese charset  51                 // error52                 os.write(command.getBytes());  53                 os.writeBytes(COMMAND_LINE_END);  54                 os.flush();  55             }  56             os.writeBytes(COMMAND_EXIT);  57             os.flush();  58 59             result = process.waitFor();  60             // get command result61             if (isNeedResultMsg) {  62                 successMsg = new StringBuilder();  63                 errorMsg = new StringBuilder();  64                 successResult = new BufferedReader(new InputStreamReader(  65                         process.getInputStream()));  66                 errorResult = new BufferedReader(new InputStreamReader(  67                         process.getErrorStream()));  68                 String s;  69                 while ((s = successResult.readLine()) != null) {  70                     successMsg.append(s);  71                 }  72                 while ((s = errorResult.readLine()) != null) {  73                     errorMsg.append(s);  74                 }  75             }  76         } catch (IOException e) {  77             e.printStackTrace();  78         } catch (Exception e) {  79             e.printStackTrace();  80         } finally {  81             try {  82                 if (os != null) {  83                     os.close();  84                 }  85                 if (successResult != null) {  86                     successResult.close();  87                 }  88                 if (errorResult != null) {  89                     errorResult.close();  90                 }  91             } catch (IOException e) {  92                 e.printStackTrace();  93             }  94 95             if (process != null) {  96                 process.destroy();  97             }  98         }  99         return new CommandResult(result, successMsg == null ? null
100                 : successMsg.toString(), errorMsg == null ? null
101                 : errorMsg.toString()); 102     } 103 
104     /**
105      * result of command, 106      * <ul> 107      * <li>{@link CommandResult#result} means result of command, 0 means normal, 108      * else means error, same to excute in linux shell</li> 109      * <li>{@link CommandResult#successMsg} means success message of command 110      * result</li> 111      * <li>{@link CommandResult#errorMsg} means error message of command result</li> 112      * </ul> 113      *  114      * @author Trinea 2013-5-16 115      */
116     public static class CommandResult { 117 
118         /** result of command **/
119         public int result; 120         /** success message of command result **/
121         public String successMsg; 122         /** error message of command result **/
123         public String errorMsg; 124 
125         public CommandResult(int result) { 126             this.result = result; 127         } 128 
129         public CommandResult(int result, String successMsg, String errorMsg) { 130             this.result = result; 131             this.successMsg = successMsg; 132             this.errorMsg = errorMsg; 133         } 134     }    /**
135      * execute shell command, default return result msg 136      *  137      * @param command 138      *            command 139      * @param isRoot 140      *            whether need to run with root 141      * @return
142      * @see ShellUtils#execCommand(String[], boolean, boolean) 143      */
144     public static CommandResult execCommand(String command, boolean isRoot) { 145         return execCommand(new String[] { command }, isRoot, true); 146     }

复制代码

但是这会带来一个问题,每次判断是否root都会弹出一个root请求框。这是十分不友好的一种交互方式,而且,用户如果选择取消,有部分手机是判断为非root的。

这是方法一。交互不友好,而且有误判。

在这个情况下,为了不弹出确认框,考虑到一般root手机都会有一些的特殊文件夹,比如/system/bin/su,/system/xbin/su,里面存放有相关的权限控制文件。

因此只要手机中有一个文件夹存在就判断这个手机root了。

然后经过测试,这种方法在大部分手机都可行。

代码如下:

复制代码

 1     /** 判断是否具有ROOT权限 ,此方法对有些手机无效,比如小米系列 */2     public static boolean isRoot() {  3 4         boolean res = false;  5 6         try {  7             if ((!new File("/system/bin/su").exists())  8                     && (!new File("/system/xbin/su").exists())) {  9                 res = false; 10             } else { 11                 res = true; 12             } 13             ; 14         } catch (Exception e) { 15             res = false; 16         } 17         return res; 18     }

复制代码

这是方法二。交互友好,但是有误判。

后来测试的过程中发现部分国产,比如小米系列,有这个文件夹,但是系统是未root的,判断成了已root。经过分析,这是由于小米有自身的权限控制系统而导致。

考虑到小米手机有大量的用户群,这个问题必须解决,所以不得不寻找第三种方案。

从原理着手,小米手机无论是否root,应该都是具有相关文件的。但是无效的原因应该是,文件设置了相关的权限。导致用户组无法执行相关文件。

从这个角度看,就可以从判断文件的权限入手。

先看下linux的文件权限吧。

linux文件权限详细可参考《鸟叔的linux私房菜》http://vbird.dic.ksu.edu.tw/linux_basic/0210filepermission.php#filepermission_perm

只需要在第二种方法的基础上,再另外判断文件拥有者对这个文件是否具有可执行权限(第4个字符的状态),就基本可以确定手机是否root了。

在已root手机上(三星i9100 android 4.4),文件权限(x或者s,s权限,可参考http://blog.chinaunix.net/uid-20809581-id-3141879.html)如下


未root手机,大部分手机没有这两个文件夹,小米手机有这个文件夹。未root小米手机权限如下(由于手头暂时没有小米手机,过几天补上,或者有同学帮忙补上,那真是感激不尽)。

【等待补充图片】

代码如下:

复制代码

 1     /** 判断手机是否root,不弹出root请求框<br/> */2     public static boolean isRoot() {  3         String binPath = "/system/bin/su";  4         String xBinPath = "/system/xbin/su";  5         if (new File(binPath).exists() && isExecutable(binPath))  6             return true;  7         if (new File(xBinPath).exists() && isExecutable(xBinPath))  8             return true;  9         return false; 10     } 11 
12     private static boolean isExecutable(String filePath) { 13         Process p = null; 14         try { 15             p = Runtime.getRuntime().exec("ls -l " + filePath); 16             // 获取返回内容
17             BufferedReader in = new BufferedReader(new InputStreamReader( 18                     p.getInputStream())); 19             String str = in.readLine(); 20             Log.i(TAG, str); 21             if (str != null && str.length() >= 4) { 22                 char flag = str.charAt(3); 23                 if (flag == 's' || flag == 'x') 24                     return true; 25             } 26         } catch (IOException e) { 27             e.printStackTrace(); 28         }finally{ 29             if(p!=null){ 30                 p.destroy(); 31             } 32         } 33         return false; 34     }

复制代码

这种方法基本可以判断所有的手机,而且不弹出root请求框。这才是我们需要的,perfect。

方法三,交互友好,基本没有误判。

以下是apk以及相关源代码,大家可以下载apk看下运行效果

ROOT检测APK下载地址:http://good.gd/3091610.htm

ROOT检测代码下载:http://good.gd/3091609.htm或者http://download.csdn.net/detail/waylife/7639017

如果有手机使用方法三无法判断,欢迎提出。

也欢迎大家提出其他的更好的办法。

问啊-定制化IT教育平台,牛人一对一服务,有问必答,开发编程社交头条 官方网站:www.wenaaa.com

QQ群290551701 聚集很多互联网精英,技术总监,架构师,项目经理!开源技术研究,欢迎业内人士,大牛及新手有志于从事IT行业人员进入!

这篇关于【Android】不弹root请求框检测手机是否root的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/668949

相关文章

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

你的华为手机升级了吗? 鸿蒙NEXT多连推5.0.123版本变化颇多

《你的华为手机升级了吗?鸿蒙NEXT多连推5.0.123版本变化颇多》现在的手机系统更新可不仅仅是修修补补那么简单了,华为手机的鸿蒙系统最近可是动作频频,给用户们带来了不少惊喜... 为了让用户的使用体验变得很好,华为手机不仅发布了一系列给力的新机,还在操作系统方面进行了疯狂的发力。尤其是近期,不仅鸿蒙O

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

SpringBoot中Get请求和POST请求接收参数示例详解

《SpringBoot中Get请求和POST请求接收参数示例详解》文章详细介绍了SpringBoot中Get请求和POST请求的参数接收方式,包括方法形参接收参数、实体类接收参数、HttpServle... 目录1、Get请求1.1 方法形参接收参数 这种方式一般适用参数比较少的情况,并且前后端参数名称必须

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖