Android常用代碼之APK root權限靜默安裝

http://www.trinea.cn/android/android-silent-install/

本文主要介紹程序如何利用root權限靜默安裝(卸載)APK,如何自動選擇普通安裝(卸載)還是靜默安裝(卸載)

 

1、root權限靜默安裝(卸載)調用

引入TrineaAndroidCommon@Github(歡迎star和fork^_^)作爲你項目的library(如何拉取代碼及添加公共庫),或自己抽取PackageUtils.installSlient(PackageUtils.uninstallSilent)函數進行調用,系統授權管理會彈出對話框讓用戶選擇是否允許應用獲得root權限。允許的話即可靜默安裝。

 

該函數返回PackageUtils.INSTALL_SUCCEEDED表示安裝成功,失敗則返回相應錯誤碼,可以得到失敗的詳細原因,包括文件不存在,apk無效,系統內存不足,簽名不正確,缺少公共庫,share user錯誤等等判斷。

注意對於較大apk安裝過程非常耗時,所以最好新啓線程去調用PackageUtils.installSlient

 

 2、root權限靜默安裝實現

PackageUtils.installSlient的實現實際使用的是su pm install -r filePath命令。核心代碼如下:

    public static final String COMMAND_SU       = "su";
    public static final String COMMAND_SH       = "sh";
    public static final String COMMAND_EXIT     = "exit\n";
    public static final String COMMAND_LINE_END = "\n";

    public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) {
        int result = -1;
        if (commands == null || commands.length == 0) {
            return new CommandResult(result, null, null);
        }

        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;

        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
            os = new DataOutputStream(process.getOutputStream());
            for (String command : commands) {
                if (command == null) {
                    continue;
                }

                // donnot use os.writeBytes(commmand), avoid chinese charset error
                os.write(command.getBytes());
                os.writeBytes(COMMAND_LINE_END);
                os.flush();
            }
            os.writeBytes(COMMAND_EXIT);
            os.flush();

            result = process.waitFor();
            // get command result
            if (isNeedResultMsg) {
                successMsg = new StringBuilder();
                errorMsg = new StringBuilder();
                successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
                errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                String s;
                while ((s = successResult.readLine()) != null) {
                    successMsg.append(s);
                }
                while ((s = errorResult.readLine()) != null) {
                    errorMsg.append(s);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (process != null) {
                process.destroy();
            }
        }
        return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
            : errorMsg.toString());
    }
其中commands爲pm install -r . 從中可以看出主要就是使用su切換到root環境下,再調用pm install -r進行安裝。

 

3、普通安裝,系統權限靜默安裝,root權限靜默安裝的自動選擇

查看PackageUtils源碼會發現我還提供了其他幾個安裝函數,其中PackageUtils.install(PackageUtils.uninstall)函數會根據是否是系統應用以及是否擁有root權限,從而確定調用哪種安裝方式(普通安裝方式、root靜默安裝方式還是系統權限靜默安裝),源碼如下:

/**
 * install according conditions
 * <ul>
 * <li>if system application or rooted, see {@link #installSilent(Context, String)}</li>
 * <li>else see {@link #installNormal(Context, String)}</li>
 * </ul>
 * 
 * @param context
 * @param filePath
 * @return
 */
public static final int install(Context context, String filePath) {
	if (!PackageUtils.isSystemApplication(context) && !ShellUtils.checkRootPermission()) {
		return installNormal(context, filePath) ? INSTALL_SUCCEEDED : INSTALL_FAILED_INVALID_URI;
	}

	return installSilent(context, filePath);
}

如果是系統應用記得添加<uses-permission android:name=”android.permission.INSTALL_PACKAGES” />權限,從而走普通安裝方式,不用申請root權限進行靜默安裝。

 

4、PackageUtils 實現靜默卸載應用

調用PackageUtils.uninstallSlient


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章