繁体   English   中英

如果launchmode设置为'singleTop',如何防止pendingintent重新创建活动?

[英]How to prevent pendingintent from recreating an activity if launchmode set to 'singleTop'?

我在使用 Packagemanager 安装应用程序更新时遇到了一些麻烦。 我的应用程序是为我公司内部使用而设计的,因此我们不能使用 Google Play 来处理这些更新。 因此,在启动应用程序后,它会快速检查版本并下载更新(如果有)。

这是我在我的活动中尝试的(该文件是同一应用程序的下载和更新版本)

    public void installNewApkVersion(File file){
        PackageInstaller.Session session = null;
        try{
            PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
            PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            int sessionId = packageInstaller.createSession(params);
            session = packageInstaller.openSession(sessionId);

            addApkToInstallSession(session, file);
            // Create an install status receiver.
            Context context = LoginActivity.this;
            Intent intent = new Intent(context, LoginActivity.class);
            intent.setAction(ACTION_INSTALL_COMPLETE);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
            IntentSender statusReceiver = pendingIntent.getIntentSender();
            // Commit the session (this will start the installation workflow).
            session.commit(statusReceiver);
        } catch(IOException e){
            throw new RuntimeException("Couldn't install package", e);
        } catch (RuntimeException e){
            if(session != null){
                session.abandon();
            }
            throw e;
        }
    }

为此,我必须像这样覆盖 onNewIntent:

  @Override
    protected void onNewIntent(Intent intent) {
        Bundle extras = intent.getExtras();

        boolean isloggedin = pref.getBoolean("Loggedin", false);



        if (ACTION_INSTALL_COMPLETE.equals(intent.getAction())) {
            int status = extras.getInt(PackageInstaller.EXTRA_STATUS);
            String message = extras.getString(PackageInstaller.EXTRA_STATUS_MESSAGE);

            switch (status) {
                case PackageInstaller.STATUS_PENDING_USER_ACTION:
                    // This test app isn't privileged, so the user has to confirm the install.
                    Intent confirmIntent = (Intent) extras.get(Intent.EXTRA_INTENT);
                    startActivity(confirmIntent);
                    break;
                case PackageInstaller.STATUS_SUCCESS:
                    Log.w(TAG, "Install finished successfully");
                    break;
                case PackageInstaller.STATUS_FAILURE:
                    Toast.makeText(this, "Install failed!", Toast.LENGTH_SHORT).show();
                    Log.w(TAG, "Installation failed - status failure.");
                    break;
                case PackageInstaller.STATUS_FAILURE_ABORTED:
                    Toast.makeText(this, "Install failure aborted!", Toast.LENGTH_SHORT).show();
                    Log.w(TAG, "Installation failed. Aborted.");
                    break;
                case PackageInstaller.STATUS_FAILURE_BLOCKED:
                    Toast.makeText(this, "Install: failure blocked!", Toast.LENGTH_SHORT).show();
                    Log.w(TAG, "Installation failed. Blocked.");
                    break;
                case PackageInstaller.STATUS_FAILURE_CONFLICT:
                    Toast.makeText(this, "Install: failure conflicted!", Toast.LENGTH_SHORT).show();
                    Log.w(TAG, "Installation failed. Found conflicts.");
                    break;
                case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
                    Toast.makeText(this, "Install: incompatible!", Toast.LENGTH_SHORT).show();
                    Log.w(TAG, "Installation failed. Incompatible.");
                    break;
                case PackageInstaller.STATUS_FAILURE_INVALID:
                    Toast.makeText(this, "Install: invalid!", Toast.LENGTH_SHORT).show();
                    Log.w(TAG, "Installation failed. Invalid.");
                    break;
                case PackageInstaller.STATUS_FAILURE_STORAGE:
                    Toast.makeText(this, "Install failed: storage error! " + status + ", " + message,
                            Toast.LENGTH_SHORT).show();
                    Log.w(TAG, "Install failed. Storage error.");
                    break;
                default:
                    Toast.makeText(this, "Unrecognized status received from installer: " + status,
                            Toast.LENGTH_SHORT).show();
                    Log.w(TAG, "Dont know what happened");
            }
        }
    }

此 Activity 在 singleTop 模式下运行,以便接收安装结果。 除非用户在提示时取消它,否则它运行良好。

因为如果是这样,则重新创建活动,而不是将结果传递回@onNewIntent 中的原始结果,从而在后台堆栈中产生相同活动的两个实例。

我怀疑这个问题发生在 android 7 上,当测试 android 10 时,而不是重新创建任务路由到 @onNewIntent (STATUS_FAILURE_ABORTED) 的活动,因为它应该是。

如果用户中止安装,我该如何捕捉?

这样做的真正目的是防止用户使用我的应用程序,如果他们有旧版本。

或者有没有办法以某种方式防止这种重复活动?

在 Android 7 上创建Activity的新实例时,如果Intent包含 package 安装程序状态,您可以在onCreate()中执行此操作:

Intent x = getIntent(); // This contains the package installer status
x.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
startActivity(x);
finish();

这将完成Activity的新实例并恢复Activity的前一个实例并将Intent传递给前一个ActivityonNewIntent()

注意:标志FLAG_ACTIVITY_PREVIOUS_IS_TOP告诉 Android 在决定如何处理startActivity()调用时,它应该忽略当前最顶层的Activity 当您设置此标志时,您是在告诉 Android:“此Activity即将结束,因此在决定是否需要创建新实例或使用现有实例时不要考虑它”

这是一个黑客,但应该工作:-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM