PackageInstaller完成(自我)更新后启动应用程序 [英] Launch application after PackageInstaller finished (self) updating

查看:679
本文介绍了PackageInstaller完成(自我)更新后启动应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PackageInstaller成功(自行)更新应用程序后,该应用程序将关闭并且不会再次启动.

After the PackageInstaller successfully (self) updates the application, the application closes and doesn't launch again.

可能重复: Android PackageInstaller,重新打开自行更新后的应用程序

情况非常相似,首先显示一些代码片段.

The situation is pretty similar, ill show some code snippets first.

AndroidManifest.xml

AndroidManifest.xml

<receiver android:name=".UpdateReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
    </intent-filter>
</receiver>

我的PackageInstaller会话在AsyncTask中运行:

My PackageInstaller session runs in an 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的设置.我尝试了许多变体,但没有一个起作用.例如:

At the end of this snippet, you can see the setup of an Intent to send. I've tried many variations and none of them worked. For example:

Intent intent = new Intent(Intents.APK_INSTALL_FINISHED_INTENT);

Intent intent = new Intent("android.intent.action.MY_PACKAGE_REPLACED");

我的接收者从没有收到意图.

My receiver never receives the intent.

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中发现以下错误.

Somehow I managed to restart the app autimatically but it gets killed after a 1-3 seconds. I found the following error in the logcat of the system.

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$1.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$4.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)

我不确定这是否是原因.

I am not sure if this is the reason for it.

现在我收到了意图,因此该应用程序正在运行.现在的问题是它在后面的堆栈中.

Now I receive the intent, thus the app is running. The problem now is that its in the back stack.

我有一个启动器应用程序,可以可以重新启动主(更新的)应用程序,但是听起来不干净.

I have a launcher app that could re-launch the main (updated) app but that doesn't sound clean code to me.

我尝试了大卫的答案,但收到以下错误:

I tried David's answer but I receive the following error:

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系统抛出的,而不是由我的应用程序抛出的.

Note this is thrown by the android system, and not by my app.

推荐答案

更新您的应用后,MY_PACKAGE_REPLACED Intent由Android广播.

The MY_PACKAGE_REPLACED Intent is broadcast by Android after your app is updated.

要在更新后重新启动应用,可以将启动Intent传递给PackageInstaller,如下所示:

To restart your app after the update, you could pass a launch Intent to the PackageInstaller, like this:

Intent intent = getPackageManager().getLaunchIntentForPackage("my.package.name");
PendingIntent pendingIntent = PendingIntent.getActivity(
                mContext.get(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());

这应该导致您的应用在更新完成后重新启动.

This should cause your app to be restarted after the update is completed.

这篇关于PackageInstaller完成(自我)更新后启动应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆