【Android】不彈root請求框檢測手機是否root,androidroot

來源:互聯網
上載者:User

【Android】不彈root請求框檢測手機是否root,androidroot

由於項目需要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      * @return  5      */  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                 // error 52                 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 result 61             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 ? null100                 : successMsg.toString(), errorMsg == null ? null101                 : 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      * @return142      * @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行業人員進入!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.