当一个活动直接从一个通知启动时,你如何构建一个 Android 后台堆栈?

Posted

技术标签:

【中文标题】当一个活动直接从一个通知启动时,你如何构建一个 Android 后台堆栈?【英文标题】:How do you build an Android back stack when an activity is started directly from a notification? 【发布时间】:2011-10-30 03:16:54 【问题描述】:

我有两个活动:

活动 A - 项目列表 活动 B - 项目的详细视图

通常,用户打开应用程序并启动 Activity A。用户看到项目列表,单击其中一项,Activity B 开始显示项目详细信息。

Activity B 也可以通过点击通知直接启动。在这种情况下,没有回栈。

我怎样才能使当 Activity B 直接从通知启动时,用户可以单击“后退”按钮并转到 Activity A?

【问题讨论】:

我从来没有遇到过这种情况,所以我的回答可能并不完美。而不是启动 Activity B...启动 Activity A 并使用接收器的 Intent 传递一个值,并在 Activity A 的 onCreate 中检查该值,如果条件满足启动 Activity B。因此,通过这个,您将在 backStack 中有 Activity A。但唯一要注意的是,用户会看到奇怪的动画,比如 Activity A 到来并过渡到 Activity B。这有意义吗? @gopal 是的,我正在考虑实施类似的东西。我会尽快尝试并报告。 【参考方案1】:

您可以在通知启动的 Intent 中添加一个 Extra,以检测应用程序何时以这种方式启动。

然后您可以覆盖onBackPressed() Activity 方法并处理该场景,例如

  @Override
  public void onBackPressed()
  
    Bundle extras = getIntent().getExtras();

    boolean launchedFromNotif = false;

    if (extras.containsKey("EXTRA_LAUNCHED_BY_NOTIFICATION"))
    
      launchedFromNotif = extras.getBoolean("EXTRA_LAUNCHED_BY_NOTIFICATION");
    

    if (launchedFromNotif)
    
      // Launched from notification, handle as special case
      Intent intent = new Intent(this, ActivityA.class);
      intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
      mActivity.startActivity(intent);
      finish();
    
    else
    
      super.onBackPressed();
        
  

【讨论】:

1up 因为这个解决方案是 api 级别独立的,与 PendingIntent.getActivities() 解决方案相反 (***.com/a/13801159/1894568) 在访问之前检查extras包是否不是null @AndacAydin “PendingIntent.getActivities() 依赖于 API 级别”是什么意思?正如 Cassio Landim 指出的那样,我推荐“TaskStackBuilder”解决方案,按照指南的建议编辑 backStack。【参考方案2】:

您在收到通知时应该注意这一点。

我有类似的情况解决了:

 Intent intent = new Intent(context,ListDetail.class);
 TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
 stackBuilder.addParentStack(ListDetail.class);
 stackBuilder.addNextIntent(intent);
 PendingIntent contentIntent =
            stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
 NotificationManager mNotifM = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
 Notification.Builder mBuilder = new Notification.Builder(context);
 mNotifM.notify(NotificationId.getID(), mBuilder.setStyle(new Notification.BigTextStyle(mBuilder)
            .bigText(bigText)
            .setBigContentTitle(title)
            .setSummaryText(summaryText))
            .setContentTitle(title)
            .setSmallIcon(icon)
            .setContentText(summaryText)
            .setAutoCancel(true)
            .setContentIntent(contentIntent)
            .setTicker(bigText)
            .build());

您需要在您的清单中设置活动的层次结构:

<activity
        android:name=".ListDetail"
        android:label="Detail"
        android:parentActivityName=".List" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value=".List" />
</activity>

【讨论】:

【参考方案3】:

我已经尝试了一个示例。请通过此链接浏览

https://github.com/rajajawahar/NotificationBackStack

您要启动的活动..

Intent launchIntent = new Intent(context, SecondActivity.class).putExtra("Id", id);

父活动,如果后按

Intent parentIntent = new Intent(context, FirstActivity.class);

在任务构建器中添加两个活动

TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); 
    PendingIntent resultPendingIntent = stackBuilder.addNextIntentWithParentStack(parentIntent).addNextIntent(launchIntent).getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder notificationCompatBuilder =
                new NotificationCompat.Builder(context);
        NotificationManager mNotificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(id, notificationCompatBuilder.build());
        NotificationManager mNotifyMgr =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationCompatBuilder.setAutoCancel(true).
                setContentTitle("First Notification").
                setContentText("Sample Text").
                setSmallIcon(R.mipmap.ic_launcher).
                setContentIntent(resultPendingIntent);
        mNotifyMgr.notify(id, notificationCompatBuilder.build());

【讨论】:

【参考方案4】:

用onKeyDown()-方法捕捉后退按钮事件,让用户进入活动A。不要忘记返回true以防止事件被进一步传播。

http://developer.android.com/reference/android/app/Activity.html#onKeyDown(int, android.view.KeyEvent)

【讨论】:

“让用户去Activity A”是指创建一个Intent并启动Activity A吗?如果我这样做了,并且用户在 Activity A 中按下了返回按钮,他们就会回到 Activity B,对吧? 是的,没错。如果您想防止这种行为,请在启动 Activity A 后尝试完成您的 Activity B,即: Intent i = new Intent(this, ActivityA.class);开始活动(一);完成();

以上是关于当一个活动直接从一个通知启动时,你如何构建一个 Android 后台堆栈?的主要内容,如果未能解决你的问题,请参考以下文章

从通知启动时防止重新创建活动活动

如何在从通知(活动2)启动的活动后启动MainActivity(活动1)在后台销毁

如何将参数从通知点击发送到活动?

如何在 Android 中的活动/任务更改时收到通知

当前正在使用相同的活动时,从通知栏启动新活动

如何从科尔多瓦插件的服务中访问活动?