2013-05-01 140 views
3

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

我已经安装BroadcastReceiver如图所示in the docs,它的几乎工作。

  1. 当我的应用程序在前台时,我不让用户看到通知,只是自动处理它。
  2. 当我的应用程序根本没有运行时,活动开启得很好。
  3. 当我的应用程序在背景中(其总是会发生当A是顶端活动),活动A的第二实例被创建

这是当然的,出了问题。我不想要两个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); 
    } 
} 

更新: 我试图通过调用System.exit(0)当用户按下后退上的活动A.过程结束绕过这个bug,但随后立即重新启动!我的广播接收器不会再次被调用。发生了什么?

更新2: @codeMagic询问了有关应用程序和活动A.

这个程序可以让其用户检讨某些项目和评论对他们的更多信息。活动A在应用程序启动时启动。如果用户的会话不再有效,则启动登录活动。用户登录后,活动A再次变为活动状态。 A只有一个“No items to review”消息和一个“立即尝试”按钮。

当用户登录时,服务器开始发送推送通知,每当有新产品供审查。当应用程序获取通知时,活动A访问服务器并获取下一个项目以供查看。该项目显示在活动B中。一旦将评论提交给服务器,活动B完成,活动A再次成为最高活动。

当用户正在审查的项目(因为活动所取的话)的服务器知道,直到审查提交不发送推送通知 - 意思是通知不能来,如果用户没有登录或者如果用户正在查看活动B.

尽管我同意这里存在细微的竞争条件,但它并不会导致我所看到的问题 - 在测试中,我100%肯定没有竞争条件 - 推送通知仅在后发送活动A再次变为活动状态。

+0

是活动你的应用程序或第三方活动,如相机的一部分..? – 2013-05-01 21:57:08

+0

我自己的活动。 – zmbq 2013-05-01 21:57:32

+0

我可能是错的,但从您所描述的内容来看,听起来并不像“Activity A”必须是“Activity”,但可能是“Service”或“BroadcastReceiver”。如果它只是监视更新并通知'活动B'或如果没有项目显示消息,则可以显示'活动B'的消息 – codeMagic 2013-05-02 12:40:03

回答

12

的解决方案是一个launchMode='singleTask'添加到活动AndroidManifest.xml。结果,调用了相同活动实例的onNewIntent而不是新的活动。

+0

中澄清这么好的答案。精湛的作品。只是想知道哪个方法在片段内调用此 – VVB 2015-11-27 09:54:35

+0

什么是onNewIntent – 2015-12-10 13:35:55

+0

为了澄清,您的意思是singleTask *启动*活动,而不是*启动*活动?两者都不适合我。 – quantumpotato 2016-10-28 23:19:34

3

您可以使用多种Intent Flags之一。 FLAG_ACTIVITY_REORDER_TO_FRONT就是其中之一。这会将Activity置于堆栈的前面(如果它已经在堆栈中),如果没有,则会创建一个新的实例。我相信你仍然需要FLAG_ACTIVITY_NEW_TASK如果你不是从Activity

Intent.FLAG_ACTIVITY_CLEAR_TOP也应该工作。但是这会清除堆栈上的其他Activities。这取决于你需要的其他功能。去翻Intent Flags,看看哪种方式最适合你

+0

不,它不起作用。我的活动创建了两次(onCreate被调用两次,中间没有onDestroy)。 – zmbq 2013-05-01 22:28:52

+0

你在做什么'活动A'?当“Activity”位于堆栈的顶部时,为什么您的应用总是处于后台?你有什么事情我们不知道,因为那些'Flags'将不会创建一个新的实例 – codeMagic 2013-05-01 22:32:39

+0

我会在问题 – zmbq 2013-05-02 05:57:27

-1

好了,两个音符在此:

  • 您可以通过舱单所以它是独立于任何部分注册的广播接收器的应用程序。并使用单例模式(在应用程序某处保留对您活动的静态引用),这样您可以检查它们是否为活动查看并进行相应处理。

    // 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