Запустить приложение после того, как PackageInstaller завершил (самостоятельное) обновление

После успешного (самостоятельного) обновления приложения PackageInstaller приложение закрывается и больше не запускается.

Возможный дубликат: Android 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 для отправки. Я пробовал много вариантов, и ни один из них не работал. Например:

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 секунды. Я нашел следующую ошибку в логарифме системы.

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: теперь я получаю намерение, поэтому приложение работает. Проблема сейчас в том, что он в заднем стеке.

У меня есть приложение запуска, которое может повторно запускать основное (обновленное) приложение, но мне не кажется, что это чистый код.

РЕДАКТИРОВАТЬ3:

Я попробовал ответ Дэвида, но получаю следующую ошибку:

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, а не моим приложением.


person Bako    schedule 23.07.2020    source источник
comment
MY_PACKAGE_REPLACED Intent транслируется Android после обновления вашего приложения. Установка/обновление прошло успешно?   -  person David Wasser    schedule 23.07.2020
comment
@DavidWasser Да, это удалось. Я отредактировал вопрос с дополнительной информацией.   -  person Bako    schedule 23.07.2020


Ответы (2)


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());

Это должно привести к перезапуску вашего приложения после завершения обновления.

person David Wasser    schedule 23.07.2020
comment
ActivityManager выдает исключение. Я отредактировал вопрос в соответствии с этим. - person Bako; 27.07.2020
comment
Похоже, что-то пытается запустить ваше приложение, пока Android все еще выполняет обновление. - person David Wasser; 27.07.2020
comment
Но если вы используете Intent для PackageManager перезапуска вашего приложения, вам, вероятно, не нужно отвечать на трансляцию MY_PACKAGE_REPLACED. Попробуйте удалить это и посмотрите, поможет ли это - person David Wasser; 27.07.2020

Хотя ответ Дэвида Вассера, вероятно, был правильным. Я закрываю свое дело, потому что у меня очень странное и неопределенное поведение, и я почти уверен, что это потому, что я использую пользовательское ПЗУ.

person Bako    schedule 30.07.2020
comment
Это не совсем ответ. Вы должны отредактировать свой вопрос и добавить к нему свои комментарии. - person David Wasser; 30.07.2020
comment
@DavidWasser Вы правы, я напишу более подробное объяснение того, что сработало для меня, чуть позже. Спасибо за ваш вклад. - person Bako; 31.07.2020