为了照顾那些着急的同学,先直接给出结论:
private static final String[] rootRelatedDirs = new String[]{ "/su", "/su/bin/su", "/sbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/data/local/su", "/system/xbin/su", "/system/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/system/bin/cufsdosck", "/system/xbin/cufsdosck", "/system/bin/cufsmgr", "/system/xbin/cufsmgr", "/system/bin/cufaevdd", "/system/xbin/cufaevdd", "/system/bin/conbb", "/system/xbin/conbb"}; public static boolean hasRootPrivilege() { boolean hasRootDir = false; String[] rootDirs; int dirCount = (rootDirs = rootRelatedDirs).length; for (int i = 0; i < dirCount; ++i) { String dir = rootDirs[i]; if ((new File(dir)).exists()) { hasRootDir = true; break; } } return Build.TAGS != null && Build.TAGS.contains("test-keys") || hasRootDir; }
好,接下来我们来看看到底是如何得到上述的解决方案的。首先,这是既有的判断root权限的方案,即判定两个root权限相关文件夹是否存在,以及当前账户是否具备访问其内容的权限,如果都成立,那么就认为当前账号具备root权限。然而,这种root方案在一些情况下不能很好地发挥作用。
/** * 判断Android设备是否拥有Root权限 */ public class RootCheck { private final static String TAG = "RootUtil"; public static boolean isRoot() { String binPath = "/system/bin/su"; String xBinPath = "/system/xbin/su"; if (new File(binPath).exists() && isExecutable(binPath)) return true; if (new File(xBinPath).exists() && isExecutable(xBinPath)) return true; return false; } private static boolean isExecutable(String filePath) { Process p = null; try { p = Runtime.getRuntime().exec("ls -l " + filePath); // 获取返回内容 BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); String str = in.readLine(); Log.i(TAG, str); if (str != null && str.length() >= 4) { char flag = str.charAt(3); if (flag == 's' || flag == 'x') return true; } } catch (IOException e) { e.printStackTrace(); } finally { if (p != null) { p.destroy(); } } return false; } }
然后我就找到了如下方案,该方案号称是腾讯bugly的root权限判断方案:
private static final String[] a = new String[]{"/su", "/su/bin/su", "/sbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/data/local/su", "/system/xbin/su", "/system/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/system/bin/cufsdosck", "/system/xbin/cufsdosck", "/system/bin/cufsmgr", "/system/xbin/cufsmgr", "/system/bin/cufaevdd", "/system/xbin/cufaevdd", "/system/bin/conbb", "/system/xbin/conbb"}; public static boolean p() { boolean var0 = false; String[] var1 = a; int var2 = a.length; for(int var3 = 0; var3 < var2; ++var3) { String var4 = var1[var3]; if ((new File(var4)).exists()) { var0 = true; break; } } return Build.TAGS != null && Build.TAGS.contains("test-keys") || var0; }
当然,本人生性多疑,偶像是曹操曹丞相,所以自然不能人云亦云,还是实际确认一下bugly实际上是否是这样实现的,以及确保bugly在新的版本中有没有对该方案有进一步的改进。
然后我就到bugly官网,下载了其最新发布的jar包,笔者下载时最新的版本为4.4.4,然后直接解压,然后在解压的目录中搜索“test-keys”内容。
grep -r test-keys "D:\迅雷下载\Bugly_v3.4.4
最后找到了对应的文件位置和对应方法:com\tencent\bugly\crashreport\common\info\b.class
private static final String[] a = new String[]{"/su", "/su/bin/su", "/sbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/data/local/su", "/system/xbin/su", "/system/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/system/bin/cufsdosck", "/system/xbin/cufsdosck", "/system/bin/cufsmgr", "/system/xbin/cufsmgr", "/system/bin/cufaevdd", "/system/xbin/cufaevdd", "/system/bin/conbb", "/system/xbin/conbb"}; public static boolean l() { boolean var0 = false; String[] var1; int var2 = (var1 = a).length; for(int var3 = 0; var3 < var2; ++var3) { String var4 = var1[var3]; if ((new File(var4)).exists()) { var0 = true; break; } } return Build.TAGS != null && Build.TAGS.contains("test-keys") || var0; }
然后分析一下对应变量的意思,我们就能还原出腾讯判断Root的代码,即我们开头所贴出的解决方案:
private static final String[] rootRelatedDirs = new String[]{ "/su", "/su/bin/su", "/sbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/data/local/su", "/system/xbin/su", "/system/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/system/bin/cufsdosck", "/system/xbin/cufsdosck", "/system/bin/cufsmgr", "/system/xbin/cufsmgr", "/system/bin/cufaevdd", "/system/xbin/cufaevdd", "/system/bin/conbb", "/system/xbin/conbb"}; public static boolean hasRootPrivilege() { boolean hasRootDir = false; String[] rootDirs; int dirCount = (rootDirs = rootRelatedDirs).length; for (int i = 0; i < dirCount; ++i) { String dir = rootDirs[i]; if ((new File(dir)).exists()) { hasRootDir = true; break; } } return Build.TAGS != null && Build.TAGS.contains("test-keys") || hasRootDir; }