Android捆绑通知

时间:2020-02-23 14:28:47  来源:igfitidea点击:

在本教程中,我们将在Android应用程序中实现捆绑通知。
我们已经看到并实现了针对Android Nougat的直接回复。
如果您不了解通知和待定意图,请先阅读本教程,然后再继续。

Android捆绑通知

当垂直堆积过多的通知时,Android捆绑通知非常方便。
捆绑的通知将它们全部折叠到一个通知中,并在组通知上设置了组摘要。
这使我们免于滚动浏览所有通知。
另外,如果您一次收到许多单个通知,则捆绑的通知不会发出多个嘈杂的通知声音,而是会发出单个通知声音。

捆绑通知的格式为:

  • 1摘要通知
  • N个随附的单一通知

我们可以为每个通知设置单独的音调。
每个捆绑通知都将具有相同的组密钥。

添加新通知后,它会与匹配的组密钥合并到捆绑包中。

我们可以为每个通知单击添加单独的操作,也可以为捆绑通知单击添加单独的操作。
捆绑通知可以不带任何附带的通知而存在。

创建捆绑通知

捆绑通知是通过以下方式定义的。

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                  NotificationChannel groupChannel = new NotificationChannel("bundle_channel_id", "bundle_channel_name", NotificationManager.IMPORTANCE_LOW);
                  notificationManager.createNotificationChannel(groupChannel);
              }

NotificationCompat.Builder summaryNotificationBuilder = new NotificationCompat.Builder(this, "bundle_channel_id")
                      .setGroup(bundle_notification_id)
                      .setGroupSummary(true)
                      .setContentTitle("Bundled Notification. " + bundleNotificationId)
                      .setContentText("Content Text for bundle notification")
                      .setSmallIcon(R.mipmap.ic_launcher);

              notificationManager.notify(bundleNotificationId, summaryNotificationBuilder.build());

捆绑通知必须将setGroupSummary()设置为true。

必须在包中包含的所有通知中设置在setGroup()方法中设置的组密钥。

注意:从Android Oreo开始,需要定义bundle_channel_id。
我们已经在另一本教程中详细讨论了通知渠道。

我们已将捆绑包通知渠道的重要性设置为"低",以避免捆绑包同时发出声音和发出单个通知。
我们将为单个通知创建一个单独的渠道。

在示例应用程序中,我们将实现捆绑通知功能。
我们将使用一个按钮创建一个新的捆绑包,并使用另一个按钮在当前的捆绑包中添加新的单一通知。

点击通知后,我们将取消该通知并将其ID显示在Toast中。

在本教程中,我们将不再关注后端的推送通知。
我们的目标是仅了解捆绑通知功能。

Android捆绑通知项目结构

单一活动应用程序。

Android捆绑通知代码

下面给出了" activity_main.xml"布局类的代码。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
  xmlns:app="https://schemas.android.com/apk/res-auto"
  xmlns:tools="https://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.theitroad.bundlednotificationsexample.MainActivity">

  <Button
      android:id="@+id/btnBundleNotification"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="New Bundle Notification"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintTop_toTopOf="parent" 

  <Button
      android:id="@+id/btnSingleNotification"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Add Notification to Bundle"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/btnBundleNotification" 

</android.support.constraint.ConstraintLayout>

下面给出了MainActivity.java类的代码。

package com.theitroad.bundlednotificationsexample;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

  Button btnBundleNotification, btnSingleNotification;
  NotificationManager notificationManager;
  int bundleNotificationId = 100;
  int singleNotificationId = 100;
  NotificationCompat.Builder summaryNotificationBuilder;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
      btnBundleNotification = findViewById(R.id.btnBundleNotification);
      btnSingleNotification = findViewById(R.id.btnSingleNotification);
      btnBundleNotification.setOnClickListener(this);
      btnSingleNotification.setOnClickListener(this);
  }

  @Override
  public void onClick(View v) {
      switch (v.getId()) {
          case R.id.btnBundleNotification:

              if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                  NotificationChannel groupChannel = new NotificationChannel("bundle_channel_id", "bundle_channel_name", NotificationManager.IMPORTANCE_LOW);
                  notificationManager.createNotificationChannel(groupChannel);
              }
              bundleNotificationId += 100;
              singleNotificationId = bundleNotificationId;
              String bundle_notification_id = "bundle_notification_" + bundleNotificationId;
              Intent resultIntent = new Intent(this, MainActivity.class);
              resultIntent.putExtra("notification", "Summary Notification Clicked");
              resultIntent.putExtra("notification_id", bundleNotificationId);
              resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
              PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);

              summaryNotificationBuilder = new NotificationCompat.Builder(this, "bundle_channel_id")
                      .setGroup(bundle_notification_id)
                      .setGroupSummary(true)
                      .setContentTitle("Bundled Notification. " + bundleNotificationId)
                      .setContentText("Content Text for bundle notification")
                      .setSmallIcon(R.mipmap.ic_launcher)
                      .setContentIntent(resultPendingIntent);

              notificationManager.notify(bundleNotificationId, summaryNotificationBuilder.build());

              break;

          case R.id.btnSingleNotification:

              bundle_notification_id = "bundle_notification_" + bundleNotificationId;

              resultIntent = new Intent(this, MainActivity.class);
              resultIntent.putExtra("notification", "Summary Notification Clicked");
              resultIntent.putExtra("notification_id", bundleNotificationId);
              resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
              resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);

              //We need to update the bundle notification every time a new notification comes up.
              if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                  if (notificationManager.getNotificationChannels().size() < 2) {
                      NotificationChannel groupChannel = new NotificationChannel("bundle_channel_id", "bundle_channel_name", NotificationManager.IMPORTANCE_LOW);
                      notificationManager.createNotificationChannel(groupChannel);
                      NotificationChannel channel = new NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT);
                      notificationManager.createNotificationChannel(channel);
                  }
              }
              summaryNotificationBuilder = new NotificationCompat.Builder(this, "bundle_channel_id")
                      .setGroup(bundle_notification_id)
                      .setGroupSummary(true)
                      .setContentTitle("Bundled Notification " + bundleNotificationId)
                      .setContentText("Content Text for group summary")
                      .setSmallIcon(R.mipmap.ic_launcher)
                      .setContentIntent(resultPendingIntent);

              if (singleNotificationId == bundleNotificationId)
                  singleNotificationId = bundleNotificationId + 1;
              else
                  singleNotificationId++;

              resultIntent = new Intent(this, MainActivity.class);
              resultIntent.putExtra("notification", "Single notification clicked");
              resultIntent.putExtra("notification_id", singleNotificationId);
              resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
              resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);

              NotificationCompat.Builder notification = new NotificationCompat.Builder(this, "channel_id")
                      .setGroup(bundle_notification_id)
                      .setContentTitle("New Notification " + singleNotificationId)
                      .setContentText("Content for the notification")
                      .setSmallIcon(R.mipmap.ic_launcher)
                      .setGroupSummary(false)
                      .setContentIntent(resultPendingIntent);

              notificationManager.notify(singleNotificationId, notification.build());
              notificationManager.notify(bundleNotificationId, summaryNotificationBuilder.build());
              break;

      }
  }

  @Override
  protected void onNewIntent(Intent intent) {
      super.onNewIntent(intent);

      Bundle extras = intent.getExtras();
      if (extras != null) {
          int notification_id = extras.getInt("notification_id");
          Toast.makeText(getApplicationContext(), "Notification with ID " + notification_id + " is cancelled", Toast.LENGTH_LONG).show();
          notificationManager.cancel(notification_id);
      }
  }
}
  • btnSingleNotification在当前捆绑通知中添加一个通知。
    如果当前的捆绑包通知不存在,它将首先创建一个。

  • btnBundleNotification创建一个新的Bundle Notification,并通过增加ID来更新组密钥。

  • 我们最初设置了一个等于" singleNotificationId"的" bundleNotificationId"。

  • 每次创建新的包通知时,我们都会将bundleNotificationId增加100。

  • 每次在包通知中创建单个通知时,我们都会在当前bundleNotificationId上将" singleNotificationId"增加1。

  • 我们为捆绑通知和单一通知创建了单独的渠道。

  • 通知点击会触发onNewIntent。
    它从意图数据中获取通知ID,并取消相应的通知。

Android捆绑通知应用程序输出

让我们看看上面代码的输出。

请注意,在上面的输出中,单击任何通知只会取消最后添加的通知。

为什么?

由于PendingIntent将数据更新为最新数据,因此我们将每个PendingIntent的请求代码都设为0。
因此,它仅返回最新数据。

我们需要为每个通知设置不同的请求代码。

让我们将请求代码设置为" bundleNotificationId"(用于捆绑包通知)和" singleNotificationId"(用于单个通知)。

@Override
  public void onClick(View v) {
      switch (v.getId()) {
          case R.id.btnBundleNotification:

              if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                  NotificationChannel groupChannel = new NotificationChannel("bundle_channel_id", "bundle_channel_name", NotificationManager.IMPORTANCE_LOW);
                  notificationManager.createNotificationChannel(groupChannel);
              }
              bundleNotificationId += 100;
              singleNotificationId = bundleNotificationId;
              String bundle_notification_id = "bundle_notification_" + bundleNotificationId;
              Intent resultIntent = new Intent(this, MainActivity.class);
              resultIntent.putExtra("notification", "Summary Notification Clicked");
              resultIntent.putExtra("notification_id", bundleNotificationId);
              resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
              PendingIntent resultPendingIntent = PendingIntent.getActivity(this, bundleNotificationId, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);

              summaryNotificationBuilder = new NotificationCompat.Builder(this, "bundle_channel_id")
                      .setGroup(bundle_notification_id)
                      .setGroupSummary(true)
                      .setContentTitle("Bundled Notification. " + bundleNotificationId)
                      .setContentText("Content Text for bundle notification")
                      .setSmallIcon(R.mipmap.ic_launcher)
                      .setContentIntent(resultPendingIntent);

              notificationManager.notify(bundleNotificationId, summaryNotificationBuilder.build());

              break;

          case R.id.btnSingleNotification:

              bundle_notification_id = "bundle_notification_" + bundleNotificationId;

              resultIntent = new Intent(this, MainActivity.class);
              resultIntent.putExtra("notification", "Summary Notification Clicked");
              resultIntent.putExtra("notification_id", bundleNotificationId);
              resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
              resultPendingIntent = PendingIntent.getActivity(this, bundleNotificationId, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);

              //We need to update the bundle notification every time a new notification comes up.
              if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                  if (notificationManager.getNotificationChannels().size() < 2) {
                      NotificationChannel groupChannel = new NotificationChannel("bundle_channel_id", "bundle_channel_name", NotificationManager.IMPORTANCE_LOW);
                      notificationManager.createNotificationChannel(groupChannel);
                      NotificationChannel channel = new NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT);
                      notificationManager.createNotificationChannel(channel);
                  }
              }
              summaryNotificationBuilder = new NotificationCompat.Builder(this, "bundle_channel_id")
                      .setGroup(bundle_notification_id)
                      .setGroupSummary(true)
                      .setContentTitle("Bundled Notification " + bundleNotificationId)
                      .setContentText("Content Text for group summary")
                      .setSmallIcon(R.mipmap.ic_launcher)
                      .setContentIntent(resultPendingIntent);

              if (singleNotificationId == bundleNotificationId)
                  singleNotificationId = bundleNotificationId + 1;
              else
                  singleNotificationId++;

              resultIntent = new Intent(this, MainActivity.class);
              resultIntent.putExtra("notification", "Single notification clicked");
              resultIntent.putExtra("notification_id", singleNotificationId);
              resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
              resultPendingIntent = PendingIntent.getActivity(this, singleNotificationId, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); //singleNotificationId is set as the request code.

              NotificationCompat.Builder notification = new NotificationCompat.Builder(this, "channel_id")
                      .setGroup(bundle_notification_id)
                      .setContentTitle("New Notification " + singleNotificationId)
                      .setContentText("Content for the notification")
                      .setSmallIcon(R.mipmap.ic_launcher)
                      .setGroupSummary(false)
                      .setContentIntent(resultPendingIntent);

              notificationManager.notify(singleNotificationId, notification.build());
              notificationManager.notify(bundleNotificationId, summaryNotificationBuilder.build());
              break;

      }
  }