在 Android 系统中,如果你的应用具有系统权限(如系统签名或安装在 /system/priv-app 目录),就可以使用 PackageInstaller 实现 APK 的静默安装。
安装完成后,我们通常希望应用能够自动重启,以便更新立即生效。
本文将完整展示:
-
BroadcastReceiver监听安装事件 -
捕获自定义安装完成事件 (
INSTALL_FINISH) -
自动启动自身应用
-
使用
PackageInstaller安装 APK 的完整代码
适用于 OTA 升级、企业设备更新、Kiosk 设备、医疗设备等定制系统。
一、监听系统安装广播
Android 在安装、升级应用时,会发送系统广播:
-
android.intent.action.PACKAGE_ADDED------ 第一次安装 -
android.intent.action.PACKAGE_REPLACED------ 覆盖安装(升级时必走) -
自定义广播:安装提交后的回调(PackageInstaller.commit)
清单文件配置如下:
<receiver
android:name=".updata.InstallReceiver"
android:enabled="true"
android:exported="true">
<!-- 覆盖安装(升级) -->
<intent-filter android:priority="999">
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
<!-- 第一次安装 -->
<intent-filter android:priority="999">
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
<!-- PackageInstaller commit 回调 -->
<intent-filter>
<action android:name="com.test.INSTALL_FINISH" />
</intent-filter>
</receiver>
这里我们设置了高优先级,使其在系统广播链路中更早得到回调。
二、安装事件接收器 InstallReceiver
InstallReceiver 的任务:
-
判断是否当前 App 被安装或升级
-
若是,则自动启动
-
接收 PackageInstaller 的提交回调
-
同样执行启动逻辑
完整代码如下:
package com.test.test.updata;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class InstallReceiver extends BroadcastReceiver {
private static final String TAG = "========";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String pkg = null;
if (intent.getData() != null) {
pkg = intent.getData().getSchemeSpecificPart();
}
Log.e("========", "收到广播:" + action + " 包:" + pkg);
// 本应用首次安装或升级安装
if ((Intent.ACTION_PACKAGE_ADDED.equals(action)
|| Intent.ACTION_PACKAGE_REPLACED.equals(action))
&& pkg != null
&& pkg.equals(context.getPackageName())) {
Log.e("========", "捕获安装或升级 → 自动启动");
launchSelf(context);
return;
}
// PackageInstaller 回调(仅首次安装)
if ("com.test.INSTALL_FINISH".equals(action)) {
Log.e("========", "收到 PackageInstaller commit 回调");
launchSelf(context);
}
}
private void launchSelf(Context context) {
Intent launch = context.getPackageManager()
.getLaunchIntentForPackage(context.getPackageName());
if (launch != null) {
launch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(launch);
} else {
Log.e(TAG, "找不到自己的启动 Activity");
}
}
}
安装完成后,会自动重新打开应用,实现无感升级。
三、使用 PackageInstaller 静默安装 APK
核心类:SystemInstaller
实现流程:
-
创建安装 Session
-
将 APK 内容写入 Session
-
commit 提交安装
-
提交完成后系统会回调我们自定义广播
INSTALL_FINISH
代码如下:
package com.test.test.updata;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
public class SystemInstaller {
private static final String TAG = "SystemInstaller";
@SuppressLint("RequestInstallPackagesPolicy")
public static void installApk(Context context, String apkPath) {
try {
File apkFile = new File(apkPath);
if (!apkFile.exists()) {
Log.e(TAG, "APK 文件不存在: " + apkPath);
return;
}
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params =
new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setAppPackageName(null);
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
// 写入 APK
try (OutputStream out = session.openWrite("app_install", 0, apkFile.length());
FileInputStream in = new FileInputStream(apkFile)) {
byte[] buffer = new byte[8192];
int c;
while ((c = in.read(buffer)) != -1) {
out.write(buffer, 0, c);
}
session.fsync(out);
}
// 提交安装,发送 INSTALL_FINISH 回调
session.commit(get(context).getIntentSender());
session.close();
Log.i(TAG, "提交安装成功");
} catch (Exception e) {
Log.e(TAG, "系统安装异常", e);
}
}
public static PendingIntent get(Context context) {
Intent intent = new Intent(context, InstallReceiver.class);
intent.setAction("com.test.INSTALL_FINISH");
return PendingIntent.getBroadcast(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE
);
}
}
四、安装完成自动重启应用的完整链路
整个流程如下:
installApk()
↓ commit
InstallReceiver (INSTALL_FINISH 广播)
↓
launchSelf() 启动应用
系统安装广播 PACKAGE_REPLACED/PACKAGE_ADDED
↓
InstallReceiver 捕获自身包名
↓
launchSelf() 重新启动
无论是首次安装、覆盖安装还是 commit 回调,都能够完成自动启动。
五、注意事项
- 必须是系统应用或具备系统权限,否则静默安装会失败。