android在apk中获取root权限,并执行下令

android在apk中获取root权限,并执行命令

工程代码:http://download.csdn.net/detail/victoryckl/4610617

    在apk中,有时候需要root权限,例如通过apk更新系统库等system的文件等,避免升级固件,或者在apk中需要直接访问某些设备等。下面是在apk中获取root权限的方法,前提是设备已经root过了。

   关键点在于下面这句,通过执行su产生一个具有root权限的进程:

Process p = Runtime.getRuntime().exec("su");

然后,在向这个进程的写入要执行的命令,即可达到以root权限执行命令:

dos = new DataOutputStream(p.getOutputStream());

dos.writeBytes(cmd + "\n");

dos.flush();

或者用下面的方式:

Runtime.getRuntime().exec(new String[]{"/system/bin/su","-c", cmd});


经过测试,以root权限执行命令,只在真机上测试成功,在模拟器上没有成功过。


第一次运行时,会出现请求root权限的界面,选中记住,并允许:

android在apk中获取root权限,并执行下令


测试程序界面,如果已经root,界面中可以显示出/system分区对应的设备节点:

android在apk中获取root权限,并执行下令

主要文件:RootCmd.java

package org.ckl.root;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import android.util.Log;

public final class RootCmd {

	private static final String TAG = "RootCmd";
	private static boolean mHaveRoot = false;

	// 判断机器Android是否已经root,即是否获取root权限
	public static boolean haveRoot() {
		if (!mHaveRoot) {
			int ret = execRootCmdSilent("echo test"); // 通过执行测试命令来检测
			if (ret != -1) {
				Log.i(TAG, "have root!");
				mHaveRoot = true;
			} else {
				Log.i(TAG, "not root!");
			}
		} else {
			Log.i(TAG, "mHaveRoot = true, have root!");
		}
		return mHaveRoot;
	}

	// 执行命令并且输出结果
	public static String execRootCmd(String cmd) {
		String result = "";
		DataOutputStream dos = null;
		DataInputStream dis = null;
		
		try {
			Process p = Runtime.getRuntime().exec("su");// 经过Root处理的android系统即有su命令
			dos = new DataOutputStream(p.getOutputStream());
			dis = new DataInputStream(p.getInputStream());

			Log.i(TAG, cmd);
			dos.writeBytes(cmd + "\n");
			dos.flush();
			dos.writeBytes("exit\n");
			dos.flush();
			String line = null;
			while ((line = dis.readLine()) != null) {
				Log.d("result", line);
				result += line;
			}
			p.waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (dos != null) {
				try {
					dos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (dis != null) {
				try {
					dis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	// 执行命令但不关注结果输出
	public static int execRootCmdSilent(String cmd) {
		int result = -1;
		DataOutputStream dos = null;
		
		try {
			Process p = Runtime.getRuntime().exec("su");
			dos = new DataOutputStream(p.getOutputStream());
			
			Log.i(TAG, cmd);
			dos.writeBytes(cmd + "\n");
			dos.flush();
			dos.writeBytes("exit\n");
			dos.flush();
			p.waitFor();
			result = p.exitValue();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (dos != null) {
				try {
					dos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}
}

相关文件:SystemPartition.java,获取/system分区设备节点,并支持重新mount /system为可读写:

package org.ckl.root;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import android.util.Log;

public class SystemPartition {
	private static final String TAG = "SystemMount";
	private static String TMP_PATH = "/sdcard/mount.txt";
	private static String mMountPiont = null;
	private static boolean mWriteable = false;
	
	private SystemPartition() {
		Log.i(TAG, "new SystemMount()");
	}
	
	private static class SystemPartitionHolder {
		private static SystemPartition instance = new SystemPartition();
	}
	
	public SystemPartition getInstance() {
		return SystemPartitionHolder.instance;
	}
	
	public static String getSystemMountPiont() {
		DataInputStream dis = null;
		if (mMountPiont == null) { 
			try {
				RootCmd.execRootCmd("mount > " + TMP_PATH);
//				Runtime.getRuntime().exec("mount > " + TMP_PATH);
				
				dis = new DataInputStream(new FileInputStream(TMP_PATH));
				
				String line = null;
				int index = -1;
				while ( (line = dis.readLine()) != null ) {
					index = line.indexOf(" /system ");
					if (index > 0) {
						mMountPiont = line.substring(0, index);
						if (line.indexOf(" rw") > 0) {
							mWriteable = true;
							Log.i(TAG, "/system is writeable !");
						} else {
							mWriteable = false;
							Log.i(TAG, "/system is readonly !");
						}
						break;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (dis != null) {
					try {
						dis.close();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					dis = null;
				}
				
				File f = new File(TMP_PATH);
				if (f.exists()) {
					f.delete();
				}
			}
		}
		
		if (mMountPiont != null) {
			Log.i(TAG, "/system mount piont: " + mMountPiont);
		} else {
			Log.i(TAG, "get /system mount piont failed !!!");
		}
		
		return mMountPiont;
	}
	
	public static boolean isWriteable() {
		mMountPiont = null;
		getSystemMountPiont();
		return mWriteable;
	}
	
	public static void remountSystem(boolean writeable) {
		String cmd = null;
		getSystemMountPiont();
		if (mMountPiont != null && RootCmd.haveRoot()) {
			if (writeable) {
				cmd = "mount -o remount,rw " + mMountPiont + " /system";
			} else {
				cmd = "mount -o remount,ro " + mMountPiont + " /system";
			}
			RootCmd.execRootCmdSilent(cmd);
			
			isWriteable();
		}
	}
}