活动开了两次

时间:2013-05-01 21:53:44

标签: android android-activity broadcastreceiver

我有一个使用Urban Airship进行推送通知的应用程序。当通知到达并且用户点击它时,我的应用程序中的活动A应该打开并执行某些操作。

我安装了显示in the docsBroadcastReceiver,并且几乎正在工作。

  1. 当我的应用程序位于前台时,我根本不让用户看到通知,只是自动处理。
  2. 当我的应用程序根本没有运行时,活动就会正常运行。
  3. 当我的应用程序在后台时(总是在A是最高活动时发生),创建了活动A的第二个实例
  4. 这当然是一个问题。我不想要两个A活动,我只想要其中一个。这是相关的BroadcastReceiver代码:

    @Override
    public void onReceive(Context ctx, Intent intent)
    {
        Log.i(tag, "Push notification received: " + intent.toString());
        String action = intent.getAction();
        int notificationId = intent.getIntExtra(PushManager.EXTRA_NOTIFICATION_ID, -1);
        if(action.equals(PushManager.ACTION_NOTIFICATION_OPENED))
        {
            Intent intentActivity = new Intent(ctx, ActivityA.class);
            intentActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            UAirship.shared().getApplicationContext().startActivity((intentActivity);
        }
    }
    

    更新: 当用户按下Back on Activity A时,我试图通过调用System.exit(0)来绕过此错误。该过程结束,但随后立即重新启动!我的BroadcastReceiver在第二个实例中没有被再次调用。发生了什么事?

    更新2: @codeMagic要求提供有关应用和活动A的更多信息。

    此应用可让用户查看某些项目并对其进行评论。应用程序启动时启动活动A.如果用户的会话不再有效,则启动Login活动。用户登录后,活动A将再次变为活动状态。 A只有“无需审核的项目”消息和“立即尝试”按钮。

    当用户登录时,只要有新项目可供审阅,服务器就会开始发送推送通知。当应用程序收到通知时,活动A访问服务器并获取要审核的下一个项目。该项目显示在活动B中。一旦将评论提交给服务器,活动B就完成了,活动A再次成为最高活动。

    服务器知道用户何时正在查看某个项目(因为活动A已获取该项目),并且在提交审核之前不会发送推送通知 - 这意味着如果用户未登录或无法通知,则无法通知如果用户正在查看活动B.

    虽然我同意这里有一个微妙的竞争条件,但它并没有引起我所看到的问题 - 在测试中我100%肯定没有竞争条件 - 推送通知仅在之后发送 >活动A再次变为活动状态。

4 个答案:

答案 0 :(得分:18)

解决方案是在launchMode='singleTask'中为活动添加AndroidManifest.xml。因此,调用相同活动实例的onNewIntent而不是新活动。

答案 1 :(得分:3)

您可以使用多个Intent Flags中的一个。 FLAG_ACTIVITY_REORDER_TO_FRONT是其中之一。如果它已经在堆栈中,这将把Activity带到堆栈的前面,如果没有,那么它将创建一个新实例。我相信如果你不是从FLAG_ACTIVITY_NEW_TASK

调用它,你仍然需要Activity

Intent.FLAG_ACTIVITY_CLEAR_TOP也应该有效。但这将清除堆栈上的任何其他Activities。它取决于您需要的其他功能。仔细查看Intent Flags,看看哪种方法最适合您

答案 2 :(得分:0)

有多种情况可能会发生这种情况。其中一个可以这样处理。请在此处查看我的回答:https://stackoverflow.com/a/44117025/2959575

答案 3 :(得分:-1)

好的,关于此的两点说明:

  • 您可以通过清单注册广播接收器,使其独立于应用的任何部分。并使用Singleton模式(在您的应用程序中的某个位置保留对您的活动的静态引用),这样您就可以检查它们是否是一个活动,并相应地进行处理。

    // your activity A
    
    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        myActivityReference = this;
    }
    
    public void onPause() {
        super.onPause();
        if (isFinishing()) {
            myActivityReference = null;
        }
    }
    
  • 或者您可以保持原样,并在清单中使用活动午餐模式标记,例如singleTop, singleInstance ... etc。看看android activity lunch modes