点击通知进入当前活动

时间:2013-06-02 18:06:56

标签: android notifications

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

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

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

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

修改: 更多解释

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

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

问题是,当我点击通知时,它指向ShareApp任务堆栈中的ShareActivity实例,而不是gallery app任务的堆栈..

任何想法如何指向正确的任务的堆栈??

编辑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] }

5 个答案:

答案 0 :(得分:24)

    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());

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

答案 1 :(得分:7)

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

getLaunchIntentForPackage()开始

编辑:使用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为意图添加了操作/类别

注意:我实际上构建了一个小应用程序来测试它。我需要将ACTION = MAIN和CATEGORY = LAUNCHER添加到Intent(如果你使用了PackageManager.getLaunchIntentForPackage(),它会在那里。)我有一个HTC One S,所以在我的设备上&#34; Gallery& #34; app实际上被称为com.htc.album/.AlbumMain.ActivityMainDropList,但这仍然适用于你。

答案 2 :(得分:4)

android:launchMode="singleTop"
在您的主要活动manifest.xml

,看看是否有帮助。

答案 3 :(得分:1)

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

您的问题是您的PendingIntent从无应用内容中启动了它的目标。

您的第一步是将Intent的结果带入您的应用上下文中。要执行此操作,请将通知呼叫广播到&#34; ForwardingReceiver&#34;

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);

现在,有趣的部分。您需要从公共活动父级扩展所有应用程序活动。您可能已经执行此操作以进行日志记录或分析。在此CommonActivityParent onResume()中,您需要注册以接收优先级高于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()中取消注册)

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

但是,如果您的活动在后台,则不会注册此接收者。没问题,你的&#34; GenericReceiver&#34;应该看起来像这样

@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()代码,以检测它是否为root任务。如果它不是立即关闭(因此用户永远不可见)。这有效地迫使最后一个打开的任务进入前台:

@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 - 您的应用程序现在将表现为通知点击实际上是您应用内的点击。所需要的只是一大堆工作!

希望某人有一种不太复杂的方式来做这件事。

答案 4 :(得分:0)

有关其他信息,请不要忘记添加待处理的Intent标志以使onNewIntent起作用!

true:

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

false:

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

如果对您有好处,请投票支持!