导言:
由于公司定制设备需要静默安装,而不使用我们熟悉的热更新,目前热更新不能完全代替安装(阿里和腾讯系都不能完全覆盖更新),所以就需要静默安装,而静默安装需要root权限,若需要安装后自动启动就需要android 7.0以下系统才行.
热修复现状:
Sophix和Tinker不支持添加四大组件,Amigo由于阿里收购,不再维护并且支持gradle版本过低,导致好的技术丧失,技术的悲剧
静默安装核心步骤:
//1:判定app是否获取root权限
public static boolean isRootPermission() {
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("ls /data/data/\n");
os.writeBytes("exit\n");
os.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();
if (result.contains("com.android.phone")) {
return true;
}
} catch (IOException e) {
return false;
}
return false;
}
//2:安装apk
public boolean install(String apkPath) {
boolean result = false;
DataOutputStream dataOutputStream = null;
BufferedReader errorStream = null;
try {
Process process = Runtime.getRuntime().exec("su");
dataOutputStream = new DataOutputStream(process.getOutputStream());
String command = "pm install -r " + apkPath + "\n";
dataOutputStream.write(command.getBytes(Charset.forName("utf-8")));
dataOutputStream.flush();
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
process.waitFor();
errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String msg = "";
String line;
while ((line = errorStream.readLine()) != null) {
msg += line;
}
if (!msg.contains("Failure")) {
result = true;
}
} catch (Exception e) {
} finally {
try {
if (dataOutputStream != null) {
dataOutputStream.close();
}
if (errorStream != null) {
errorStream.close();
}
} catch (IOException e) {
}
}
return result;
}
//3:静默安装后需要自动启动,因此就需要注册安装替换静态广播,但是必须是7.0以下才行,因为8.0删除了该静态广播注册的功能
public class OpenApkReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent localIntent;
if (intent.getAction().equals("android.intent.action.PACKAGE_REPLACED")) {
localIntent = new Intent(context, MainActivity.class);
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(localIntent);
}
}
}
//androidmanifest.xml静态广播注册
<receiver android:name=".OpenApkReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
结束.