前言
智能硬件不同于普通手机,大多是无人值守的,所以升级时只能采用静默升级,即后台自动升级的方式
PackageInstaller是安卓系统底层用于apk安装的管理类,只有系统级别的应用,才能使用这个类的功能
将apk升级为系统应用
一个apk想要成为系统应用,必须满足三个条件
- 安装在内存卡,而不是SD卡中,这个可以在Manifest中配置
- uid设置为系统用户android.uid.system
- 使用编译系统镜像时用的签名证书,对apk进行签名
系统镜像签名文件,是编译系统镜像时指定的
但好在,大多定制ROM,用的都是Google官方镜像的默认证书,不会自己去改证书
设置apk安装到SD卡
设置apk为系统用户
为apk进行系统签名
到此网站,可查看安卓各个版本的源码
http://androidxref.com
进入版本号/build/target/product/security目录
下载里面的platform.pk8和platform.x509.pem这两个签名文件
将签名文件、用于签名的jar包、要签名的apk,放到同一目录,执行以下批处理代码
cd %~dp0
java -jar signapk.jar platform.x509.pem platform.pk8 1.apk 2.apk
pause
签名工具和6.0.1的系统签名文件可以从这里下载
SignAPK.jar+6.0.1官方系统签名
静默安装apk
apkFile是apk文件相当于存储卡根目录的路径
packageName是要安装的apk的包名
安装apk代码
//静默升级APP
@SneakyThrows
public void silenceInstall(String apkFile, String packageName) {
//写入APK到InstallerSession
PackageInstaller installer = activity.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
int sessionId = installer.createSession(params);
PackageInstaller.Session session = installer.openSession(sessionId);
writeApkToSession(session, apkFile, packageName);
//安装APK
Intent intent = new Intent(activity, HomeActivity.class);
intent.setAction("com.android.package.installer.session.PACKAGE_INSTALLED");
PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0, intent, 0);
IntentSender sender = pendingIntent.getIntentSender();
session.commit(sender);
}
//写入APK到InstallerSession
@SneakyThrows
protected void writeApkToSession(PackageInstaller.Session session, String apkFile, String packageName) {
String file = AndroidFile.getAndroidExternalFile(apkFile);
OutputStream os = session.openWrite(packageName, 0, -1);
InputStream is = new FileInputStream(file);
byte[] buffer = new byte[1024 * 1024];
int len;
while ((len = is.read(buffer)) >= 0)
os.write(buffer, 0, len);
os.flush();
os.close();
is.close();
}
调用代码
//调用
WorkThread.post(() -> {
handler2.silenceInstall("222.apk", "com.tencent.qqpinyin");
});
安装回调,安装需要一段时间,由于是静默安装,看不到任何界面,请耐心等待
@Override
protected void onNewIntent(Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
if ("com.android.package.installer.session.PACKAGE_INSTALLED".equals(action)) {
int status = extras.getInt(PackageInstaller.EXTRA_STATUS);
boolean success = status == PackageInstaller.STATUS_SUCCESS;
TipBox.tipInCenter(success ? "静默安装成功" : "静默安装失败");
}
}
之所以能触发此回调,是因为我们在安装的Intent中,设置了对应的Action
只要我们Activity的Action与之相匹配,就可以被该Action调用打开



