Android 设备信息
Platform: rk3399
OS: Android 7.1.2
Kernel: version 4.4.103
需求,root 权限下静默安装 可以是本身或者第三方apk
1. AndroidManifest.xml 添加 manifest 节点 添加android:sharedUserId="android.uid.system"属性
需要系统授权
2.添加 权限
<uses-permission android:name="android.permission.INSTALL_PACKAGES"/>
3.shell 使用代码
/**
* 3.1 安装方法
* @param args
* @param filePath
* @return
*/
public static int installBySilent(String [] args,String filePath) {
for(String s:args){
Log.d(TAG, "installBySilent: s " + s);
}
int result = 0;
try {
File file = new File(filePath);
if (filePath == null || filePath.length() == 0 || (file = new File(filePath)) == null
|| file.length() <= 0 || !file.exists() || !file.isFile()) {
return 1;
}
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = new StringBuilder();
StringBuilder errorMsg = new StringBuilder();
try {
process = processBuilder.start();
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 (successResult != null) {
successResult.close();
}
if (errorResult != null) {
errorResult.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (process != null) {
process.destroy();
}
}
if (successMsg.toString().contains("Success") || successMsg.toString().contains("success")) {
result = 1;
} else {
result = 2;
}
Log.d(TAG, "successMsg:" + successMsg + ", ErrorMsg:" + errorMsg);
} catch (Exception e) {
result = -1;
}
return result;
}
3.2 实现广播,接收安装的状态和结果
public class BootBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "cdq BootBroaceiver";
public static final String EXTRA_VOLUME_STATE =
"android.os.storage.extra.VOLUME_STATE";
public static final int STATE_UNMOUNTED = 0;
public static final int STATE_CHECKING = 1;
public static final int STATE_MOUNTED = 2;
public static final int STATE_MOUNTED_READ_ONLY = 3;
public static final int STATE_FORMATTING = 4;
public static final int STATE_EJECTING = 5;
public static final int STATE_UNMOUNTABLE = 6;
public static final int STATE_REMOVED = 7;
public static final int STATE_BAD_REMOVAL = 8;
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
Log.d(TAG, "onReceive:action "+action);
Log.d(TAG, "onReceive:packageName " +intent.getData().getSchemeSpecificPart());
if (action.equals("android.intent.action.PACKAGE_REPLACED")) {
String packageName = intent.getData().getSchemeSpecificPart();
Log.v(TAG, "BootBroadcastReceiver packageName:" + packageName);
if (context.getPackageName().equals(packageName)) {
//此处如果不想写死启动的Activity,也可以通过如下方法获取默认的启动Activity
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(launchIntent);
}
}
}
}
3.3 清单注册广播 ⚠️ <data android:scheme="package"/> 必要
<receiver android:name=".update.BootBroadcastReceiver"
android:exported="true">
<intent-filter android:priority="200">
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
3.4 调用
String filePath = "/mnt/sdcard/Download/app_120.apk";
Log.d(TAG, "installBySilent: filePath " + filePath);
Log.d(TAG, "onCreate: " +Build.VERSION.SDK_INT);
if (Build.VERSION.SDK_INT>=24){
Log.d(TAG, "onCreate: ");
//com.test.tv 为此项目的package name
String [] args={"pm", "install","-i ", "com.test.tv", "-r", "--user", "0", filePath };
installBySilent(args,filePath);
}else{
String[] args ={ "pm", "install", "-r", filePath };
installBySilent(args,filePath);
}
注意
1. 必须拥有设备系统签名,拥有root权限(签名文件硬件方会提供)
2. 升级包apk, 如String filePath = "/mnt/sdcard/Download/app_120.apk";的app_120.apk 也必须进行系统签名
如没有系统签名,本app升级出现签名不一致问题,安装第三方app, 会出现 not belong 1000 这类提示
参考
https://blog.csdn.net/weixin_39966398/article/details/88904030