通知打开活动,返回按钮按下,主活动被打开?

13

我能描述我的问题的最佳方式如下:

  1. 在启动时创建一个通知(使用BroadcastReceiver)。
  2. 打开我的应用程序主活动,并按下主屏幕键(该应用程序仍在后台运行,直到系统关闭它)。
  3. 我拉下状态栏并按下以前在启动时创建的通知。
  4. 开始了某些与主要活动不同的活动。
  5. 我按下返回按钮,主要活动被显示。

如何防止最后一步? 我希望通过返回按钮返回到之前的位置,也就是主屏幕(拥有所有小部件和应用程序图标的桌面)。 我的应用程序主活动应该在后台运行,为什么会被返回按钮调用?

如果相关的话,我创建通知的代码如下:

public void createNotification(int notifyId, int iconId, String contentTitle, String contentText) {
    Intent intent = new Intent(mContext, NewNoteActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.putExtra(AgendaNotesAdapter.KEY_ROW_ID, (long)notifyId);

    PendingIntent contentIntent = PendingIntent.getActivity(mContext, notifyId, intent, 0);

    Notification notification = new Notification(iconId, contentTitle, 0);
    notification.setLatestEventInfo(mContext, contentTitle, contentText, contentIntent);

    mNotificationManager.notify(notifyId, notification);

我尝试向intent添加更多的标志组合,但它们都没有解决我的问题... 有什么建议吗?

5个回答

23

对于那些仍然需要答案的人,看起来这就是你想要实现的:

  

当您从通知中启动一个 Activity 时,必须保留用户期望的导航体验。 点击 返回 应将用户带回到应用程序的正常工作流程,回到主屏幕,点击 最近使用的应用 应显示该活动作为单独的任务。

http://developer.android.com/guide/topics/ui/notifiers/notifications.html#NotificationResponse

你的情况 - 设置一个常规的 activity PendingIntent

在链接中查看完整步骤。 基本上,你需要做:


1. 在AndroidManifest.xml 中定义 Activity 层次结构

<activity
    android:name=".MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity
    android:name=".ResultActivity"
    android:parentActivityName=".MainActivity">
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value=".MainActivity"/>
</activity>


2. 根据启动 ActivityIntent 创建一个基于后退堆栈

...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());

2
这是最好的答案。 - salih kallai
当我点击通知、打开活动并回到主屏幕后,几秒钟后发送新通知时,我会遇到问题,无法再次接收通知。使用上述代码帮助了我。谢谢! - natsumiyu

5

我也遇到了同样的问题。 对我有用的方法是在清单文件中为通知启动的活动设置以下属性:

android:taskAffinity=""

这基本上将通知活动的亲和性与主活动分开,因此操作系统不需要“返回”到主活动,而只需返回到之前的任何内容,例如“桌面”。


4
从你的问题中得知,你的问题包括以下步骤:
1. 在启动后创建通知。 2. 主活动将在启动时调用。 3. 当你按下主屏幕按钮时,主活动会被停止但不会被销毁。 4. 你从状态栏点击通知,这时你的应用程序将恢复,因此你已经在你的返回栈中有了主活动,并且通知将创建一个新活动,如你在问题中提到的 NewNoteActivity 活动将被推入返回栈。所以在这一步骤中,你的返回栈中有两个活动。 5. 你按下返回键,最后一个活动将被销毁,你的主活动将重新开始,但你想要打开主页活动。
所以解决方案是,当你从 NewNoteActivity 活动按下返回键时,你再次启动主活动,并使用 Intent.FLAG_ACTIVITY_CLEAR_TOP 标志,这样你的主活动将重新创建并将接收 onNewIntent() 方法,所以你可以在那里获取标志并结束主活动。
例如:
@Override
    public void onBackPressed() {
        Intent i = new Intent(this, Main.class);
    i.putExtra("exit", true);
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(i);
    super.onBackPressed();
    }

现在您需要在主activity中实现onNewIntent()方法。
从NewNoteActivity活动按下后退按钮后,您的主activity将调用onNewIntent()方法,因此在此方法中,您需要获取从NewNoteActivity活动传递的标志变量。如果您获得了标志并且它为true,则只需完成主activity,以便您将返回主屏幕。
编辑:
您说您已经打开了A、B或C中的任何一个活动,并按下了后退按钮,使该活动关闭。如果您在堆栈中只有一个活动,那么此时您的应用程序将关闭,意味着您将回到主屏幕。但是,如果您有多个活动并且按下了后退按钮,则至少会有一个活动在堆栈中,现在如果您单击通知,则会打开与通知相关联的新活动,因此此活动将被推入该堆栈。现在,如果您按下后退按钮,如果您没有修改该活动中的onBackPressed()方法,则将关闭与通知相关联的最后一个活动,然后它将检查堆栈中是否有任何活动,以便恢复该活动;如果堆栈中没有活动,则将关闭您的应用程序,并返回主屏幕。

几乎就是那样...问题是,我没有主页活动,你误解了我的意思。我的意思是我想回到主屏幕,桌面,你可以在那里看到所有的小部件和壁纸... - rfgamaral
那似乎可以工作,但看起来像是一个不太正规的解决方案。你说的一切都有道理,但我对这样的解决方案并不满意,也不会使用它。但我相信它可以工作并解决问题,所以我将其标记为已接受的答案。 - rfgamaral
我本来要实现你的解决方案,但后来意识到它并不能完全满足我的需求。在你上面的例子中,你使用了 Main.class,如果堆栈顶部的活动不是“Main”呢?假设我有活动A、B和C。如果打开了这些活动中的任何一个,并按下返回按钮,然后点击通知,再次按下返回按钮,我不知道打开的是A、B和C中的哪一个活动,以应用你发布的解决方法。还有其他的解决方案吗?你会如何解决这个问题? - rfgamaral

4

我在我的应用程序中使用这个解决方案。在你从通知跳转到的活动中覆盖onBackPressed方法,并检查你的应用程序是否在栈中。如果没有,则启动你的根活动。用户可以随时从你的根活动导航。这就是我在我的应用程序中所做的。

@Override
public void onBackPressed() {
    if (isTaskRoot()) {
        Intent intent = new Intent(this,YourMainActivity.class);
        startActivity(intent);
        super.onBackPressed();
    }else {
        super.onBackPressed();
    }
}

0

这对我有效。尝试这个:

notifyIntent.setAction(Intent.ACTION_MAIN);
notifyIntent.addCategory(Intent.CATEGORY_LAUNCHER);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接