在 PackageInstaller 完成(自我)更新后启动应用程序
Launch application after PackageInstaller finished (self) updating
PackageInstaller 成功(自行)更新应用程序后,应用程序关闭并且不再启动。
可能重复:
情况很相似,我先展示一些代码片段。
AndroidManifest.xml
<receiver android:name=".UpdateReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
我的 PackageInstaller 会话在 AsyncTask 中运行:
PackageInstaller packageInstaller = ctx.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams parameters = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
parameters.setAppPackageName(StaticData.TerminalPackageName);
progressChanged(10);
try {
int sessionId = packageInstaller.createSession(parameters);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
ProgressApproximatorHandler progress = startProgressApproximator(10, 100, 5);
OutputStream installerStream = session.openWrite("INSTALL_TERMINAL", 0, mApplicationLength);
installerStream.write(firmwareData, 0, mApplicationLength);
// This call ensures every byte on the stream is committed to disk.
session.fsync(installerStream);
installerStream.close();
Intent intent = new Intent(ctx, UpdateReceiver.class);
intent.setAction(Intents.APK_INSTALL_FINISHED_INTENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
mContext.get(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Sealing the session.
session.commit(pendingIntent.getIntentSender());
session.close();
progress.stop();
} catch (IOException e) {
Logger.error(mLogTag, e, "Failed to create an installer session.");
return false;
}
在此代码段的末尾,您可以看到要发送的 Intent 的设置。我尝试了很多变体,其中 none 个变体起作用了。例如:
Intent intent = new Intent(Intents.APK_INSTALL_FINISHED_INTENT);
和
Intent intent = new Intent("android.intent.action.MY_PACKAGE_REPLACED");
我的接收者从未收到意图。
public class UpdateReceiver extends BroadcastReceiver {
private static final String TAG = "UPDATE";
@Override
public void onReceive(Context context, Intent intent) {
Logger.info(TAG, "Intent action: " + intent.getAction());
Logger.info(TAG, "updated");
}
}
编辑:我以某种方式设法自动重启了应用程序,但它在 1-3 秒后被杀死。我在系统的logcat中发现如下错误。
W/ActivityManager: Unable to send startActivity intent
java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.MY_PACKAGE_REPLACED from pid=-1, uid=10071
at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18195)
at com.android.server.am.ActivityManagerService.broadcastIntentInPackage(ActivityManagerService.java:18777)
at com.android.server.am.PendingIntentRecord.sendInner(PendingIntentRecord.java:308)
at com.android.server.am.PendingIntentRecord.sendWithResult(PendingIntentRecord.java:205)
at com.android.server.am.ActivityManagerService.sendIntentSender(ActivityManagerService.java:7409)
at android.content.IntentSender.sendIntent(IntentSender.java:190)
at android.content.IntentSender.sendIntent(IntentSender.java:154)
at com.android.server.pm.PackageInstallerService$PackageInstallObserverAdapter.onPackageInstalled(PackageInstallerService.java:1069)
at android.app.PackageInstallObserver.onPackageInstalled(PackageInstallObserver.java:34)
at com.android.server.pm.PackageInstallerSession.dispatchSessionFinished(PackageInstallerSession.java:1137)
at com.android.server.pm.PackageInstallerSession.-wrap2(PackageInstallerSession.java)
at com.android.server.pm.PackageInstallerSession.onPackageInstalled(PackageInstallerSession.java:648)
at com.android.server.pm.PackageManagerService.handlePackagePostInstall(PackageManagerService.java:1809)
at com.android.server.pm.PackageManagerService.-wrap25(PackageManagerService.java)
at com.android.server.pm.PackageManagerService$PackageHandler.doHandleMessage(PackageManagerService.java:1438)
at com.android.server.pm.PackageManagerService$PackageHandler.handleMessage(PackageManagerService.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
我不确定是不是这个原因。
EDIT2:现在我收到了意图,因此应用程序是 运行。现在的问题是它在后台堆栈中。
我有一个启动器应用程序,可以重新启动主(更新的)应用程序,但对我来说这不是干净的代码。
编辑 3:
我尝试了 David 的回答,但收到以下错误:
E/ActivityManager: Failure starting process com.example.myapp
java.lang.SecurityException: Package com.example.myapp is currently frozen!
at com.android.server.pm.PackageManagerService.checkPackageStartable(PackageManagerService.java:3197)
at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3789)
at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3749)
at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3630)
at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:1255)
at com.android.server.am.BroadcastQueue$BroadcastHandler.handleMessage(BroadcastQueue.java:172)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
请注意,这是 android 系统抛出的,而不是我的应用程序抛出的。
MY_PACKAGE_REPLACED
Intent
在您的应用程序更新后由 Android 广播。
要在更新后重新启动您的应用,您可以将启动 Intent
传递给 PackageInstaller
,如下所示:
Intent intent = getPackageManager().getLaunchIntentForPackage("my.package.name");
PendingIntent pendingIntent = PendingIntent.getActivity(
mContext.get(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());
这应该会导致您的应用在更新完成后重新启动。
虽然 David Wasser 的回答可能是正确的。我正在关闭我的案例,因为我有非常奇怪和未定义的行为,我很确定那是因为我使用的是自定义 ROM
PackageInstaller 成功(自行)更新应用程序后,应用程序关闭并且不再启动。
可能重复:
情况很相似,我先展示一些代码片段。
AndroidManifest.xml
<receiver android:name=".UpdateReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
我的 PackageInstaller 会话在 AsyncTask 中运行:
PackageInstaller packageInstaller = ctx.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams parameters = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
parameters.setAppPackageName(StaticData.TerminalPackageName);
progressChanged(10);
try {
int sessionId = packageInstaller.createSession(parameters);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
ProgressApproximatorHandler progress = startProgressApproximator(10, 100, 5);
OutputStream installerStream = session.openWrite("INSTALL_TERMINAL", 0, mApplicationLength);
installerStream.write(firmwareData, 0, mApplicationLength);
// This call ensures every byte on the stream is committed to disk.
session.fsync(installerStream);
installerStream.close();
Intent intent = new Intent(ctx, UpdateReceiver.class);
intent.setAction(Intents.APK_INSTALL_FINISHED_INTENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
mContext.get(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Sealing the session.
session.commit(pendingIntent.getIntentSender());
session.close();
progress.stop();
} catch (IOException e) {
Logger.error(mLogTag, e, "Failed to create an installer session.");
return false;
}
在此代码段的末尾,您可以看到要发送的 Intent 的设置。我尝试了很多变体,其中 none 个变体起作用了。例如:
Intent intent = new Intent(Intents.APK_INSTALL_FINISHED_INTENT);
和
Intent intent = new Intent("android.intent.action.MY_PACKAGE_REPLACED");
我的接收者从未收到意图。
public class UpdateReceiver extends BroadcastReceiver {
private static final String TAG = "UPDATE";
@Override
public void onReceive(Context context, Intent intent) {
Logger.info(TAG, "Intent action: " + intent.getAction());
Logger.info(TAG, "updated");
}
}
编辑:我以某种方式设法自动重启了应用程序,但它在 1-3 秒后被杀死。我在系统的logcat中发现如下错误。
W/ActivityManager: Unable to send startActivity intent
java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.MY_PACKAGE_REPLACED from pid=-1, uid=10071
at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18195)
at com.android.server.am.ActivityManagerService.broadcastIntentInPackage(ActivityManagerService.java:18777)
at com.android.server.am.PendingIntentRecord.sendInner(PendingIntentRecord.java:308)
at com.android.server.am.PendingIntentRecord.sendWithResult(PendingIntentRecord.java:205)
at com.android.server.am.ActivityManagerService.sendIntentSender(ActivityManagerService.java:7409)
at android.content.IntentSender.sendIntent(IntentSender.java:190)
at android.content.IntentSender.sendIntent(IntentSender.java:154)
at com.android.server.pm.PackageInstallerService$PackageInstallObserverAdapter.onPackageInstalled(PackageInstallerService.java:1069)
at android.app.PackageInstallObserver.onPackageInstalled(PackageInstallObserver.java:34)
at com.android.server.pm.PackageInstallerSession.dispatchSessionFinished(PackageInstallerSession.java:1137)
at com.android.server.pm.PackageInstallerSession.-wrap2(PackageInstallerSession.java)
at com.android.server.pm.PackageInstallerSession.onPackageInstalled(PackageInstallerSession.java:648)
at com.android.server.pm.PackageManagerService.handlePackagePostInstall(PackageManagerService.java:1809)
at com.android.server.pm.PackageManagerService.-wrap25(PackageManagerService.java)
at com.android.server.pm.PackageManagerService$PackageHandler.doHandleMessage(PackageManagerService.java:1438)
at com.android.server.pm.PackageManagerService$PackageHandler.handleMessage(PackageManagerService.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
我不确定是不是这个原因。
EDIT2:现在我收到了意图,因此应用程序是 运行。现在的问题是它在后台堆栈中。
我有一个启动器应用程序,可以重新启动主(更新的)应用程序,但对我来说这不是干净的代码。
编辑 3:
我尝试了 David 的回答,但收到以下错误:
E/ActivityManager: Failure starting process com.example.myapp
java.lang.SecurityException: Package com.example.myapp is currently frozen!
at com.android.server.pm.PackageManagerService.checkPackageStartable(PackageManagerService.java:3197)
at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3789)
at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3749)
at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3630)
at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:1255)
at com.android.server.am.BroadcastQueue$BroadcastHandler.handleMessage(BroadcastQueue.java:172)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
请注意,这是 android 系统抛出的,而不是我的应用程序抛出的。
MY_PACKAGE_REPLACED
Intent
在您的应用程序更新后由 Android 广播。
要在更新后重新启动您的应用,您可以将启动 Intent
传递给 PackageInstaller
,如下所示:
Intent intent = getPackageManager().getLaunchIntentForPackage("my.package.name");
PendingIntent pendingIntent = PendingIntent.getActivity(
mContext.get(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());
这应该会导致您的应用在更新完成后重新启动。
虽然 David Wasser 的回答可能是正确的。我正在关闭我的案例,因为我有非常奇怪和未定义的行为,我很确定那是因为我使用的是自定义 ROM