android在apk中獲取root權限,並執行命令

   在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權限的界面,選中記住,並允許:


測試程序界面,如果已經root,界面中可以顯示出/system分區對應的設備節點:

主要文件:RootCmd.java
[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為可讀寫:
[java] 
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(); 
        } 
    } 

You May Also Like