PackageInstaller 完成(自我)更新后启动应用程序

2023-12-26

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

可能重复:Android PackageInstaller,更新后重新打开应用程序 https://stackoverflow.com/questions/43940990/android-packageinstaller-re-open-the-app-after-it-updates-itself

情况非常相似,我先展示一些代码片段。

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 intent = new Intent(Intents.APK_INSTALL_FINISHED_INTENT);

and

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$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)

我不确定这是否是原因。

EDIT2:现在我收到了意图,因此应用程序正在运行。现在的问题是它在后台堆栈中。

我有一个启动器应用程序could重新启动主(更新)应用程序,但这对我来说听起来不是干净的代码。

EDIT3:

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

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


The MY_PACKAGE_REPLACED Intent在您的应用程序更新后由 Android 广播。

要在更新后重新启动应用程序,您可以通过启动Intent to the PackageInstaller, 像这样:

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

这应该会导致您的应用程序在更新完成后重新启动。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PackageInstaller 完成(自我)更新后启动应用程序 的相关文章

随机推荐

  • 如何通过 Android KitKat 在外部 SD 卡上使用 O_DIRECT 或 O_SYNC

    我在一家生产包含硬件加密引擎的 SD 存储卡的公司工作 我们通过写入 读取特殊文件来与加密模块交互 从 KitKat 开始 O DIRECT外部 SD 卡似乎不支持该标志 没有O DIRECT or O SYNC支持 当我们从 SD 卡 通
  • RFID RC522 Raspberry PI 2 Windows 物联网

    我正在寻找一种在 Windows IOT 上的 Raspberry Pi 2 0 上使用 RFID RC522 的方法 当然不是官方兼容的 官方的 OM5577 演示板 在法国太贵了 我还没有找到任何经销商在没有大量运费的情况下出售它 总成
  • JS:获取元素的可见区域坐标

    我需要一个函数 可以计算当前在屏幕上可见的元素的可见区域 而无需隐藏部分overflow scroll position absolute etc 也就是这个函数的结果getVisiblePart el 将Visible Rect is x
  • 将 OpenCV 与 Tkinter 结合使用

    我正在编写一个程序 需要在 Tkinter 窗口中显示视频流 由于还有用于执行各种功能的按钮 因此我使用网格来组织所有内容 以下代码 修改自显示网络摄像头序列 TkInter https stackoverflow com question
  • 绘制按函数分组的多个图形并将其保存为 pdf

    我想创建一个包含 12 个图的 pdf 文件 有两个选项 每页一个图 每页四个图 Using plt savefig months pdf 仅保存最后一个图 MWE import pandas as pd index pd date ran
  • Solr高亮问题

    大家好 我有一个问题 当我查询 Solr 时 它会匹配结果 但是当我在此查询的结果上启用突出显示时 突出显示不起作用 我的查询是 内容 项目 503 内容是文本类型 并且文本项 503 中的一个重要内容显示为 项 503 c 最后的左括号会
  • Vuetify 3 组件无法在 chrome 中工作 - 未捕获类型错误:globalStack.at 不是函数

    我在使用从头开始创建的 vuetify 3 插件项目运行 Vue JS 项目时遇到此错误 我专门使用 v dialog 但它在其他组件的 chrome 中也出现控制台错误 Uncaught TypeError globalStack at
  • Git:强制执行 shell 脚本权限

    在 Git 中 您可以签入具有 644 或 755 权限的文件 我想强制所有 sh 文件始终存储为 755 权限 以便可以立即执行它们 尤其是在windows环境下很容易意外丢失权限 那么 有没有办法配置它 最好像使用 gitattribu
  • jaxb XmlAccessType: PROPERTY 示例

    我正在尝试使用 jaxb 并希望使用 XmlAccessType PROPERTY 让 jaxb 使用 getters setters 而不是直接使用变量 但是 get 不同的错误取决于我的尝试或变量 根本没有像我想要的那样设置 有什么好的
  • 仅显示垂直线的表格

    我需要一种方法来仅显示表格中的垂直线 我尝试将 border left 和 border right 添加到表格和单独的 td 中 两者都带有 1pxsolid red 但它不会添加边框颜色 所以我正在寻找一种创建这些垂直线的简单方法 Us
  • 如何在 SQL Server 中拆分字符串并将值插入到表中

    我有一个像这样的字符串 72594206916 2 1 2 08 Tacoma WA 72594221856 5 5 7 13 San Francisco CA 72594221871 99 12 30 12 Dallas TX 这基本上是
  • 用于创建应用程序注册的服务主体权限

    我使用服务主体作为 azure cli 的登录项 该服务主体的角色是 所有者 我正在尝试运行 az ad app list and az ad app create display name Test application 2 并出现错误
  • 如何触及 HABTM 关系

    如果您有 2 个模型 视频和类别 并且它们彼此之间具有 has and belongs to many 关系 那么当其中一个模型发生更改时 如何执行触摸以使缓存失效 您不能像处理一对多关系那样 触摸 它们 现在 当我更改类别名称时 属于该类
  • 删除sql SELECT中的所有非数字字符

    我想在 SQL 中调用查询时删除所有非数字字符 我有一个函数 在函数中 我这样做 Declare KeepValues as varchar 50 Set KeepValues 0 9 While PatIndex KeepValues T
  • Android Retrofit导致Socket超时异常

    我正在 Android Galaxy S3 Nexus 7 设备上使用改造库对运行 Struts2 的 tomcat 服务器进行 POST 调用 POST 调用失败 tomcat日志显示Socket超时异常 使用通过curl 完成的完全相同
  • Core Data有回调方法吗?

    我想知道当核心数据实体中发生某些情况时是否有任何特殊的方法可以采取行动 这就是我在本案中的意思 我有一个文件名作为属性存储在核心数据实体中 当应用程序运行时 可能会发生具有此文件名的项目从核心数据中删除的情况 在这种情况下 我想要发生的是将
  • 嵌套的 std::transform 效率低吗?

    如果我有一个std string std string s hello 以及一个就地修改它的循环 如下所示 for auto c s c std toupper c 我可以用同等的东西替换它transform std transform s
  • 使用反射查找具有自定义属性的方法

    我有一个自定义属性 public class MenuItemAttribute Attribute 和一个包含一些方法的类 public class HelloWorld MenuItemAttribute public void Sho
  • 蒙特卡洛模拟代码:在 R 中生成给定大小的样本

    我首先使用以下代码生成 500 个 0 到 1 之间均匀分布的随机数的样本 set seed 1234 X lt runif 500 min 0 max 1 现在 我需要编写一个伪代码 为 MC 模拟生成 N 500 的 10000 个样本
  • PackageInstaller 完成(自我)更新后启动应用程序

    PackageInstaller 成功 自行 更新应用程序后 应用程序将关闭并且不会再次启动 可能重复 Android PackageInstaller 更新后重新打开应用程序 https stackoverflow com questio