54

我正在使用NotificationCompat库向系统栏添加通知。此通知有两个操作按钮。此外,AutoCancel()通知上的属性设置为 true。

单击操作按钮时,系统被配置为启动一个IntentService调用NotificationManager.cancel(NOTIFICATION_ID),然后在新任务中启动一个活动。
问题是虽然这个调用从托盘中删除了通知,但它并没有折叠抽屉。被调用的Activity被绘制在抽屉后面。

除了取消通知之外,有人可以说明关闭抽奖需要什么特殊代码吗?

4

5 回答 5

61

如果您的操作是广播或服务的形式,但您打算折叠通知抽屉,您应该从您的 onReceive广播android.intent.action.CLOSE_SYSTEM_DIALOGS 。这将手动关闭抽屉。

于 2014-06-09T23:52:30.673 回答
9

我发现当你在扩展通知中使用操作按钮时,你必须编写额外的代码并且你会受到更多的限制。

在使用扩展通知之前,我的文件下载通知中的默认操作是对文件启动 VIEW 活动。VIEW 意图被选择器意图包裹。我不能直接从通知中为选择器意图使用挂起的意图,因为如果没有查看文件类型的活动,选择器会崩溃。所以我有一个可以启动选择器意图的广播接收器。

通过扩展通知,我决定更改文件下载通知,因此默认操作是显示文件详细信息活动,并带有查看和发送的操作按钮。如 user2536953 所述,从通知启动广播接收器不会关闭通知抽屉。根据他关于活动将关闭抽屉的信息,我将广播接收器更改为没有任何 UI 的 NotificationActivity。

如这篇文章How to dismiss Android notification after action has been clicked中所示,另一个问题是当用户单击操作按钮时,您必须手动取消通知。只有默认操作会自动取消通知。我还在 NotificationActivity 中添加了代码来处理这个问题。

使用查看和发送按钮构建扩展通知:

    NotificationCompat.Builder builder = new NotificationCompat.Builder(m_context).setAutoCancel(true);

    final PendingIntent contentIntent = DownloadedFileIntentUtils.buildPendingItemDetailIntent(m_context, item);
        builder.setContentIntent(contentIntent);

    PendingIntent viewIntent = DownloadedFileIntentUtils.buildNotificationActionIntent(m_context, Intent.ACTION_VIEW,
                m_context.getString(R.string.action_open), uri, MimeTypeUtil.getMimeType(item), id);
    builder.addAction(R.drawable.actionbar_open_with, m_context.getString(R.string.action_open), viewIntent);

    PendingIntent sendIntent = DownloadedFileIntentUtils.buildNotificationActionIntent(m_context, Intent.ACTION_SEND,
                m_context.getString(R.string.action_send), uri, MimeTypeUtil.getMimeType(item), id);
    builder.addAction(R.drawable.actionbar_share, m_context.getString(R.string.action_send), sendIntent);

    builder.setTicker(title)
    .setContentTitle(title)
    .setContentText(text)
    .setSmallIcon(R.drawable.notification_download);
    .setStyle(new NotificationCompat.BigTextStyle().bigText(text));

    getNotificationManager().notify(id, builder.build());

构建从通知操作按钮启动活动的意图:

    public static PendingIntent buildNotificationActionIntent(Context context, String action, String actionTitle, Uri uri,
        String mimeType, int notificationId) {
    // Build the file action intent (e.g. VIEW or SEND) that we eventually want to start.
    final Intent fileIntent = buildFileActionIntent(action, actionTitle, uri, mimeType);

    // Build the intent to start the NotificationActivity.
    final Intent notificationIntent = new Intent(context, NotificationActivity.class);
    // This flag must be set on activities started from a notification.
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // Pass the file action and notification id to the NotificationActivity.
    notificationIntent.putExtra(Intent.EXTRA_INTENT, fileIntent);
    notificationIntent.putExtra(IIntentCode.INTENT_EXTRA_NOTIFICATION_ID, notificationId);

    // Return a pending intent to pass to the notification manager.
    return PendingIntent.getActivity(context, s_intentCode.getAndIncrement(), notificationIntent, PendingIntent.FLAG_ONE_SHOT);
}

public static Intent buildFileActionIntent(String action, String actionTitle, 
        Uri uri, String mimeType) {
    Intent intent = new Intent(action);
    intent.addCategory(Intent.CATEGORY_DEFAULT);

    if (action.equals(Intent.ACTION_SEND)) {
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        intent.setType(mimeType);
    } else {
        intent.setDataAndType(uri, mimeType);
    }

    intent.putExtra(Intent.EXTRA_TITLE, actionTitle);

    // Grant read permission on the file to other apps without declared permission.
    int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
    intent.setFlags(flags);

    return intent;
}

没有任何 UI 的通知活动:

public class NotificationActivity extends Activity {
private final static Logger s_logger = LogUtil.getLogger(NotificationActivity.class);

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

    Intent intent = getIntent();

    // Cancel the notification that initiated this activity.
    // This is required when using the action buttons in expanded notifications.
    // While the default action automatically closes the notification, the
    // actions initiated by buttons do not.
    int notificationId = intent.getIntExtra(IIntentCode.INTENT_EXTRA_NOTIFICATION_ID, -1);
    if (notificationId != -1) {
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.cancel(notificationId);
    }

    // If there is an activity to handle the action, start the file action.
    if (DownloadedFileIntentUtils.verifyActivityIsAvailable(this, fileActionIntent, false)) {
            fileActionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            DownloadedFileIntentUtils.startFileActionActivity(this, fileActionIntent);
    }

    // Finish activity.
    finish();
}

public static void startFileActionActivity(Context context, Intent fileActionIntent) {
    // Start chooser intent.
    Intent chooser = Intent.createChooser(fileActionIntent, fileActionIntent.getStringExtra(Intent.EXTRA_TITLE));

    // Copy the flags from fileActionIntent to chooser intent.
    // FileActionExecutor must set FLAG_ACTIVITY_NEW_TASK on the intent passed to startActivity
    // because the flag is required when starting an activity from a context that is not an activity.
    chooser.addFlags(fileActionIntent.getFlags());

    context.startActivity(chooser);
}

不要忘记将 NotificationActivity 添加到 AndroidManifest.xml。

于 2014-02-14T15:26:12.913 回答
1

虽然我非常感谢 Soumyajyoti 的回答应该是正确的……但实际上并非如此……

我在用

Intent CR = new Intent(CRCODE); 
PendingIntent.getBroadcast(getApplicationContext(), MY_ID, CR, 0);

在远程视图布局中以获取正在进行的通知...

我可以向您保证,它不会关闭抽屉,但会触发意图并在打开的抽屉后面绘制活动,以及执行我分配给接收器的其他任务......

我已经测试了 getActivity 和 getService (在我的情况下它们都不起作用,我需要在接收时触发多个意图)并且它们都正确关闭了抽屉......

我知道这不是一个答案,但是当我找到它时,如果我找到它,我会报告回来编辑这个......

疯狂的想法......也许没有内容视图的活动可以称为广播接收器,它会根据需要向其他类或应用程序触发适当的意图......

上面列出的疯狂想法有效...使用 PendingIntent.getActivity 启动一个活动并使用它来中继广播或其他意图,然后自行完成...效果不是直接的,但最终用户无法察觉

于 2013-12-02T11:42:03.747 回答
0

每当您单击通知并启动活动或广播时,android 系统都会为您折叠通知抽屉。我认为没有任何编程方式可以通过您的代码关闭通知抽屉。我建议您检查传递给通知构建器的意图,并确保它们被赋予正确的参考意图。我认为由于您提供的意图,android 通知管理器中的某些内容被阻止了。到目前为止,一旦通知触发了操作,我还没有看到通知抽屉保持打开状态。只是想知道您的目标活动是否有一个半透明区域,之前的活动是可见的,如果是,那么我建议您使背景完全不透明(没有透明/半透明区域)。可能是阻止 android home 启动器完成停止序列,因此不让启动器为您关闭通知抽屉。希望我能帮到你。一切顺利。

于 2013-09-05T05:18:36.410 回答
0

尝试这个:

    NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(getApplicationContext().NOTIFICATION_SERVICE);
    Intent notificationIntent = new Intent(this.getBaseContext(), MainActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder mNotifyBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(
            getApplicationContext())
            .setTicker(getApplicationContext().getText(R.string.app_name))
            .setContentTitle(getApplicationContext().getText(R.string.app_name))
            .setContentText(getApplicationContext().getText(R.string.text))
            .setSmallIcon(R.drawable.smallicon)
            .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.mipmap.ic_launcher))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .setVibrate(new long[]{150, 300});
    mNotifyBuilder.build().flags |= Notification.FLAG_AUTO_CANCEL;
    notificationManager.notify(1, mNotifyBuilder.build());
于 2018-05-05T01:32:27.847 回答