Android 7.1 root后静默安装实现
pm install -r apkPath
-l 锁定应用程序
-r 重新安装应用,且保留应用数据
-t 允许测试apk被安装
-i <INSTALLER_PACKAGE_NAME> 指定安装包的包名
-s 安装到sd卡
-f 安装到系统内置存储中(默认安装位置)
-d 允许降级安装(同一应用低级换高级)
-g 授予应用程序清单中列出的所有权限(只有6.0系统可用)
使用-r安装时会有下面的异常,缺少 INTERACT_ACROSS_USERS_FULL权限,
添加 android:sharedUserId="android.uid.system"
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
使用如下命令安装:
pm install -i 包名 --user 0 安装包路径
public class RootUtils {
public static final String[] SU_BINARY_DIRS = {
"/system/bin",
"/system/sbin",
"/system/xbin",
"/vendor/bin",
"/sbin"
};
/**
* 检查设备是否root
*
* @return
*/
public static boolean checkRoot() {
boolean isRoot = false;
try {
for (String dir : SU_BINARY_DIRS) {
File su = new File(dir, "su");
if (su.exists()) {
isRoot = true;
break;
}
}
} catch (Exception e) {
}
return isRoot;
}
private static void closeIO(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (Exception e) {
}
}
/**
* 运行root命令
*
* @return
*/
@SuppressLint("LogUtilsNotUsed")
public static boolean runRootCmd(String cmd) {
boolean grandted;
DataOutputStream outputStream = null;
BufferedReader reader = null;
try {
Process process = Runtime.getRuntime().exec("su");
outputStream = new DataOutputStream(process.getOutputStream());
outputStream.writeBytes(cmd + "\n");
outputStream.writeBytes("exit\n");
outputStream.flush();
process.waitFor();
reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
grandted = true;
String msg = reader.readLine();
if (msg != null) {
Logger.v(RootUtils.class.getSimpleName(), msg);
}
} catch (Exception e) {
e.printStackTrace();
grandted = false;
closeIO(outputStream);
closeIO(reader);
}
return grandted;
}
public static boolean installPkg(String apkPath) {
return runRootCmd("pm install -i 包名 --user 0 " + apkPath);
}
/**
* 为app申请root权限
*
* @param context
* @return
*/
public static boolean grantRoot(Context context) {
return runRootCmd("chmod 777 " + context.getPackageCodePath());
}
}
安装后自动启动需要监听安装完成广播:
<receiver android:name=".receiver.UpdateReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_CHANGED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
public class UpdateReceiver extends BroadcastReceiver {
public static final String APK_FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + Constants.UGO_APK;
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) {
Logger.i("install" + "安装了完成:" + "包名的程序");
File file = new File(APK_FILE_PATH);
if (file.exists() && file.isFile()) {
Logger.i("install" + "删除了文件:" + APK_FILE_PATH);
file.delete();
} else {
Logger.i("install" + "文件不存在:" + APK_FILE_PATH);
}
SPUtils.getInstance(context).saveData(HAS_UPDATE, HAS_UPDATE);
Intent intent1 = context.getPackageManager().getLaunchIntentForPackage("包名");
context.startActivity(intent1);
}
//接收安装广播
if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
String packageName = intent.getDataString();
Logger.e("install" + "安装了:" + packageName + "包名的程序");
}
//接收卸载广播
if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
String packageName = intent.getDataString();
Logger.e("install" + "卸载了:" + packageName + "包名的程序");
}
}
}