【问题标题】:click on notification to go current activity点击通知进入当前活动
【发布时间】:2013-06-02 18:06:55
【问题描述】:

我正在使用这个解决方案:How to make notification intent resume rather than making a new intent?

当我正常运行我的应用程序时,我工作正常。但是我的应用程序具有共享功能。

当我从图库应用程序中选择我想要分享的图像并在我的活动中打开它时,我会在活动中创建一个通知。我希望当用户点击通知时,它会打开现有活动(由图库应用打开)

问题是,当我点击通知时,它不会恢复该活动,而是打开该活动的新实例或之前已打开的另一个实例

编辑: 更多解释

我的应用名为 ShareApp,活动名为 ShareActivity 问题是当我通过图库应用程序打开 ShareActivity 时,会在图库应用程序任务堆栈的顶部创建一个 ShareActivity 实例。现在,当我创建一个指向我的 ShareActivity 的通知时,我使用了意图:

Intent intent = new Intent(this, ShareActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

问题是当我点击通知时,它指向 ShareApp 任务堆栈中的 ShareActivity 实例,而不是图库应用程序任务的堆栈..

知道如何指向正确的任务堆栈吗?

编辑 2:我的代码

        int defaults = Notification.FLAG_NO_CLEAR;
        NotificationCompat.Builder mBuilder =
                    new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentTitle(getString(R.string.app_name))
                        .setContentText(text)
                        .setDefaults(defaults);
        Intent intent = new Intent(this, this.getClass());
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

        mBuilder.setContentIntent(pendingIntent);
        NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(_ID, mBuilder.build());

编辑 3:adb shell dumpsys 活动(在应用 David https://stackoverflow.com/a/16901603/1334268 的代码后)

我的应用名为 shareApp,我的活动是 ShareActivity

点击通知前:

Main stack:
    TaskRecord{41965708 #6 A com.android.gallery3d}
    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108]}
      Hist #2: ActivityRecord{417ccc28 com.yeahman.shareapp/.ShareActivity}
        Intent { act=android.intent.action.SEND_MULTIPLE typ=image/* cmp=com.yeahman.shareapp/.ShareActivity (has extras) }
        ProcessRecord{41c868d0 6088:com.yeahman.shareapp/10116}
      Hist #1: ActivityRecord{4135e540 com.android.gallery3d/.app.Gallery}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108] }

点击通知后:

 Main stack:
    TaskRecord{41965708 #6 A com.android.gallery3d}
    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108]}
      Hist #3: ActivityRecord{4169f358 com.android.gallery3d/.app.Gallery}
        Intent { flg=0x20000000 cmp=com.android.gallery3d/.app.Gallery bnds=[0,205][480,301] }
        ProcessRecord{4175dd28 5808:com.android.gallery3d/10036}
      Hist #2: ActivityRecord{417ccc28 com.yeahman.shareapp/.ShareActivity}
        Intent { act=android.intent.action.SEND_MULTIPLE typ=image/* cmp=com.yeahman.shareapp/.ShareActivity (has extras) }
        ProcessRecord{41c868d0 6088:com.yeahman.shareapp/10116}
      Hist #1: ActivityRecord{4135e540 com.android.gallery3d/.app.Gallery}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108] }

【问题讨论】:

  • 发布您创建IntentPendingIntentNotification 的代码。
  • 我刚刚用我的代码编辑了我的问题
  • 有解决办法吗?我会接受这是不可能的,作为带有备用解释的答案
  • 在阅读教程/文档之后的帖子和教程/文档之后......我得出的结论是,不幸的是这是不可能的:(

标签: android notifications


【解决方案1】:
    Notification.Builder mBuilder =
            new Notification.Builder(this)
            .setSmallIcon(R.drawable.cmplayer)
            .setContentTitle("CoderoMusicPlayer")
            .setContentText("PLayer0!");

    Intent resultIntent = new Intent(this, AndroidBuildingMusicPlayerActivity.class);
    resultIntent.setAction(Intent.ACTION_MAIN);
    resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
            resultIntent, 0);

    mBuilder.setContentIntent(pendingIntent);
    NotificationManager mNotificationManager =
        (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    mNotificationManager.notify(1, mBuilder.build());

只需复制代码并将其粘贴到您的主启动器活动中。

【讨论】:

  • 完美的工作解决方案,特别适用于您有单一活动的实用程序
  • Welcome.Happy Coding.
  • @HasanMasud,太好了,谢谢,它成功了..你能解释一下代码的作用吗?
  • 它非常简单。您可以在任务栏中显示应用程序的图标和说明。如果有人单击任务栏中的图标,他将返回到在后台运行的当前活动。
  • 美丽 没想到它会起作用!就是这两行action and category
【解决方案2】:

如果您有多个ShareActivity 实例在不同的任务中处于活动状态,则您无法通过启动您的活动来告诉 Android 要重新激活哪个任务。在我看来,在这种情况下,您想要做的不是启动您的活动,而是启动 Gallery 应用程序。如果 Gallery 应用程序已经在运行并且您的 Activity 位于任务堆栈的顶部,那么您需要做的就是将 Gallery 应用程序带到前台。为此,请为 Gallery 应用程序创建一个“启动 Intent”,并确保在 Intent 上设置Intent.FLAG_ACTIVITY_NEW_TASK。您应该能够使用getLaunchIntentForPackage()PackageManager 获得“启动意图”

编辑:使用 ActivityManager 的示例代码

你可以试试这个:

// Get the root activity of the task that your activity is running in
ActivityManager am = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
ActivityManager.RunningTaskInfo task = tasks.get(0); // Should be my task
ComponentName rootActivity = task.baseActivity;

// Now build an Intent that will bring this task to the front
Intent intent = new Intent();
intent.setComponent(rootActivity);
// Set the action and category so it appears that the app is being launched
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

注意:您需要GET_TASKS 权限才能执行此操作。我没有尝试过,不能保证它会起作用。文档不鼓励使用getRunningTasks(),但这并不意味着它不适合您的目的。

EDIT 将动作/类别添加到 Intent

注意:我实际上构建了一个小应用程序来测试这一点。我需要将 ACTION=MAIN 和 CATEGORY=LAUNCHER 添加到 Intent 中(如果您使用 PackageManager.getLaunchIntentForPackage(),就会出现。我有一个 HTC One S,所以在我的设备上,“Gallery”应用程序实际上被称为 @987654329 @,但这应该仍然适合你。

【讨论】:

  • 您有使用 PackageManager 的示例吗?如果我使用其他图库应用或文件管理器应用而不是默认图库应用怎么办?
  • 由于您表示您不知道可能是哪个应用程序启动了您的活动,我添加了一个使用ActivityManager 的示例来确定当前任务的根活动。我没有试过这个,但它可能对你有用。告诉我进展如何。
  • 您可以使用adb shell dumpsys activity 查看系统中的任务以及其中的活动。这将使您对正在发生的事情有一个很好的了解。在单击通知之前查看,然后在单击通知后再次查看。也许这会让我们对正在发生的事情有所了解。
  • 我创建了一个小测试程序。我在 HTC One SV 上运行它。我能够重现您的问题。我需要将 ACTION=MAIN 和 CATEGORY=LAUNCHER 添加到 Intent 以获取通知。现在它会做你想做的事(即:点击通知返回到 Gallery 任务,ShareActivity 在顶部)。
  • 是的,根据文档和我自己的经验,使用 FLAG_ACTIVITY_NEW_TASK 应该可以做到这一点。由于某种原因,它没有。我不知道为什么。我需要再挖一些。但至少你现在有了一个可行的解决方案,这是一件“好事”。很高兴我们能提供帮助
【解决方案3】:

设置

android:launchMode="singleTop"

在您的 manifest.xml 中查看您的主要活动,看看是否有帮助。

【讨论】:

  • 您确定要为 pendingIntent 设置标志? i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
  • 是的!我认为的问题是,当从画廊打开活动时,活动进入画廊堆栈而不是我的应用程序(不确定它是否正确)。因此,当我单击通知时,它会尝试从我的应用程序堆栈而不是从图库中打开活动...不确定我所说的是否正确..我现在对 android 的堆栈/实例有点困惑
  • 是的!有效。当然除了在你的活动中实现onNewIntent
【解决方案4】:

这是我多年来一直使用的解决方案。

你的问题是你的 PendingIntent 从一个无应用的内容开始它的目标。

您的第一步是将 Intent 的结果带入您的应用上下文。为此,请让您的通知调用广播到“ForwardingReceiver”

Intent newIntent = new Intent(context, ForwardingReceiver.class);
...
mBuilder.setContentIntent(PendingIntent.getBroadcast(context, category, newIntent, PendingIntent.FLAG_UPDATE_CURRENT));

ForwardingReceiver 扩展 BroadcastReceiver 并在它的 onReceive() 方法中,您现在拥有应用程序当前上下文,并且可以像这样使用 sendOrderedBroadcast()

Intent forwardIntent = new Intent();
forwardIntent.putExtras(intent.getExtras());
forwardIntent.setAction(GenericReceiver.class.getCanonicalName());
context.sendOrderedBroadcast(forwardIntent, null);

现在,有趣的部分。您需要从一个共同的 Activity 父级扩展您的所有应用程序活动。您可能已经为日志记录或分析执行此操作。在这个CommonActivityParentonResume()你需要注册接收优先级在0以上(比如10)的广播

mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        performActionUsingIntent(intent);
    }
};

IntentFilter filter = new IntentFilter();
filter.addAction(GenericReceiver.class.getCanonicalName());
filter.setPriority(10);
registerReceiver(mReceiver, filter);

(记得在 onPause() 中取消注册)

这意味着如果您的应用在前台,它将(间接)收到通知点击并允许您执行操作。

但是,如果您的 Activity 在后台,它不会注册此接收器。没问题,你的“GenericReceiver”应该是这样的

@Override
public void onReceive(Context context, Intent intent) {
    PackageManager pm = context.getPackageManager();
    Intent newIntent = pm.getLaunchIntentForPackage(context.getPackageName());
    newIntent.putExtras(intent.getExtras());
    context.startActivity(newIntent);
}

这将启动您的启动活动。这个启动活动应该在它的 onCreate() 中有代码来检测它是否是任务根。如果不是,它应该立即关闭(因此用户永远不可见)。这有效地将最后一个打开的任务置于前台:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (!isTaskRoot()
            && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
            && getIntent().getAction() != null
            && getIntent().getAction().equals(Intent.ACTION_MAIN)) {

        // Use this space to add the intent to a static singleton. This will be used in CommonActivityParent to perform an action.
        CommonActivityParent.sIntent = getIntent();
        finish();
        return;
    }
}

要完成,请确保在上面的 CommonActivityParent 中调用 registerReceiver() 之后,执行以下检查:

if(sIntent != null) {
     Intent tempIntent = sIntent;
     sIntent = null;
     performActionUsingIntent(tempIntent);
}

嘿,presto - 现在,您的应用程序的行为就像通知点击实际上是来自您的应用程序内的点击一样。所需要的只是大量的工作!

希望有人有一种不那么复杂的方式来做到这一点。

【讨论】:

    【解决方案5】:

    如需更多信息,请不要忘记添加待定意图标志以使 onNewIntent 正常工作!

    是的:

    PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT)
    

    错误:

    PendingIntent.getActivity(context, 0, resultIntent, 0)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      相关资源
      最近更新 更多