android是基于linux的操作系统,Google为了安全性的考虑,将每个应用列为独立的用户,用OS层的权限控制来保证应用间内容的可控。Linux下的root用户有最大的权限,有些涉及到文件系统或者底层的操作只能通过这种超级权限才能进行。
要开发基于root的应用程序,需要目标机上装有superuser及busybox软件。前者是提权命令“su”的管理器,后者有基本的linux命令。
网上有段代码,用于检测手机是否能获取到root权限:
1: public static boolean isRooted() {
2: Process p;
3: try {
4: // Preform su to get root privledges
5: p = Runtime.getRuntime().exec("su");
6: // Attempt to write a file to a root-only
7: DataOutputStream os = new DataOutputStream(p.getOutputStream());
8: os.writeBytes("echo . >/system/root.txt ");
9: os.writeBytes("rm /system/root.txt ");
10: // Close the terminal
11: os.writeBytes("exit ");
12: os.flush();
13: try {
14: p.waitFor();
15: if (p.exitValue() != 255) {
16: return true;
17: } else {
18: Log.e(T, "Process Exit Value is : " + p.exitValue());
19: return false;
20: }
21: } catch (InterruptedException e) {
22: Log.e(T, e.getMessage(), e);
23: return false;
24: }
25: } catch (IOException e) {
26: Log.e(T, e.getMessage(), e);
27: return false;
28: }
29: }
---------------
经测试,此法在有些手机上运行不正常。这里我们采用RootTools-0.9.1-sdk3-generic.jar中提供的方法:
1: // check for root on device
2: if (!RootTools.isRootAvailable()) {
3: // su binary does not exist, raise no root dialog
4: 未root
5: } else {
6: // su binary exists, request permission
7: if (!RootTools.isAccessGiven()) {
8: 未获得权限
9: } else {
10: if (!RootTools.isBusyboxAvailable()) {
11: // checking for busybox needs root
12: 未找到busybox
13: }
14: }
15: }
如果要对系统分区进行写操作,就需要先将系统分区挂载为r/w模式。经测试,部分机型中不存在remount命令,因此此处采用直接执行命令的方式。
此处的Process p为执行su命令后的process对象,即有root权限的Process。
1: private static void remount(Process p, boolean ro) throws IOException {
2: DataOutputStream os = new DataOutputStream(p.getOutputStream());
3: DataInputStream is = new DataInputStream(p.getInputStream());
4: os.writeBytes("df -a /etc ");//获取/etc分区的挂载信息
5: BufferedReader br = new BufferedReader(new InputStreamReader(is), 8192);
6: String line = null;
7: String filesystem = null;
8: String mountedOn = null;
9:
10: while ((line = br.readLine()) != null) {
11: line = line.trim();
12: Log.d(T, line);
13: if (line.startsWith("/")) {
14: String[] blocks = line.split("\s+");
15: filesystem = blocks[0];
16: mountedOn=blocks[blocks.length-1];
17: break;
18: }
19: }
20: String cmd = null;
21: if (ro) {
22: cmd = MessageFormat.format("mount -o remount,ro {0} {1} ",
23: filesystem, mountedOn);
24: } else {
25: cmd = MessageFormat.format("mount -o remount,rw {0} {1} ",
26: filesystem, mountedOn);
27: }
28: Log.d(T, cmd);
29: os.writeBytes(cmd);
30: }
31:
root后的相关操作的执行主要还是使用linux系统基本命令来完成,busybox实现了大多数的linux命令。
比如要写一个文件:
1: final static String mOtherLines = "echo "{0}" >>/etc/tests ";
2:
3: private static void writeHostsFile(Process p, Vector<String> lines) throws IOException {
4: DataOutputStream os = new DataOutputStream(p.getOutputStream());
5: remount(p, false);
6: for (String l : lines) {
7: os.writeBytes(MessageFormat.format(mOtherLines, l));
8: }
9: remount(p, true);
10: os.writeBytes("exit ");
11: os.flush();
12: try {
13: p.waitFor();
14: } catch (InterruptedException e) {
15: Log.e(T, e.getMessage(), e);
16: }
17: }