在 Android 中,如果要使用系統限制的權限(比如 android.permission.WRITE_SECURE_SETTINGS),我們需要把程序安裝到 /system/app/ 下。 下面以 SecureSetting.apk 為例,演示這個操作。需要准備一台已經獲得 Root 權限的手機。
1、通過 USB 連接手機和電腦。
2、使用 adb 控制手機。 源碼打印?
1. $ adb push SecureSetting.apk /sdcard/ // 上傳要安裝的文件,為安裝做准備。
2. $ adb shell
3. $ su // 切換到 root 用戶。如果沒有獲得 Root 權限,這一步不會成功。
4. # mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system // 讓分區可寫。
5. # cat /sdcard/SecureSetting.apk > /system/app/SecureSetting.apk // 這一步可以用 cp 實現,但一 般設備中沒有包含該命令。如果使用 mv 會出現錯誤:failed on '/sdcard/NetWork.apk' - Cross-device link。
6. # mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system // 還原分區屬性,只讀。
7. # exit
8. $ exit $ adb push SecureSetting.apk /sdcard/ // 上傳要安裝的文件,為安裝做准備。
$ adb shell $ su // 切換到 root 用戶。如果沒有獲得 Root 權限,這一步不會成功。
# mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system // 讓分區可寫。
# cat /sdcard/SecureSetting.apk > /system/app/SecureSetting.apk // 這一步可以用 cp 實現,但一般設備中沒有包含該命令。如果使用 mv 會出現錯誤:failed on '/sdcard/NetWork.apk' - Cross-device link。
# mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system // 還原分區屬性,只讀。
# exit $ exit 重啟,可以看到 SecureSetting 已經安裝好。
補充,如果要實現將自己的apk直接安裝到/system/app/,則需要先寫一個installer.apk,在里面執行shell將主要apk通過cat的方式寫入/system/app,再用chmod修改權限,然后執行reboot就行了
附上java執行shell的代碼:
public final class RootCmd { // 執行linux命令並且輸出結果 protected static String execRootCmd(String paramString) { String result = "result : "; try { Process localProcess = Runtime.getRuntime().exec("su ");// 經過Root處理的android系統即有su命令 OutputStream localOutputStream = localProcess.getOutputStream(); DataOutputStream localDataOutputStream = new DataOutputStream( localOutputStream); InputStream localInputStream = localProcess.getInputStream(); DataInputStream localDataInputStream = new DataInputStream( localInputStream); String str1 = String.valueOf(paramString); String str2 = str1 + "\n"; localDataOutputStream.writeBytes(str2); localDataOutputStream.flush(); String str3 = null; // while ((str3 = localDataInputStream.readLine()) != null) { // Log.d("result", str3); // } localDataOutputStream.writeBytes("exit\n"); localDataOutputStream.flush(); localProcess.waitFor(); return result; } catch (Exception localException) { localException.printStackTrace(); return result; } } // 執行linux命令但不關注結果輸出 protected static int execRootCmdSilent(String paramString) { try { Process localProcess = Runtime.getRuntime().exec("su"); Object localObject = localProcess.getOutputStream(); DataOutputStream localDataOutputStream = new DataOutputStream( (OutputStream) localObject); String str = String.valueOf(paramString); localObject = str + "\n"; localDataOutputStream.writeBytes((String) localObject); localDataOutputStream.flush(); localDataOutputStream.writeBytes("exit\n"); localDataOutputStream.flush(); localProcess.waitFor(); int result = localProcess.exitValue(); return (Integer) result; } catch (Exception localException) { localException.printStackTrace(); return -1; } } // 判斷機器Android是否已經root,即是否獲取root權限 protected static boolean haveRoot() { int i = execRootCmdSilent("echo test"); // 通過執行測試命令來檢測 if (i != -1) { return true; } return false; } }