通知是什麼?

通知為Notification,基本上是在應用程式的 UI 以外(通常是狀態列)顯示的訊息。
官網參考:https://developer.android.com/guide/topics/ui/notifiers/notifications?hl=zh-tw


如何使用通知

使用通知基本上有 4 個步驟

  1. 建立NotificationChannel
  2. 透過Builder建立通知並設定各種選項
  3. 設定通知要啟動的Action,該Action代表通知按下後要啟動哪個元件
  4. 透過NotificationManager發出通知

 

  1. 建立 NotificationChannel(NC)

NC的用途為分類並管理通知,在NC中可以設定一些通用項目讓屬於該NC的通知共用。
當裝置的android version在26或以上,必須設定NotificationChannel,否則會出現Toast提示錯誤訊息。
重點為建立NC時所指定的參數(NOTIFICATION_CHANNEL_ID )這個值在建立Notification時也必須設定,否則通知會無法顯示。

private static final String NOTIFICATION_CHANNEL_ID = "notification_channel";
private void createNotificationChannel() {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
      NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "name",
          NotificationManager.IMPORTANCE_HIGH);
      channel.setDescription("channel description");
      channel.enableLights(true);
      channel.setLightColor(Color.GREEN);
      channel.enableVibration(true);
//      channel.setShowBadge(false);
//      channel.setSound(System.ALARM_ALERT);
      mNotificationManager.createNotificationChannel(channel);
    }
  }

 

  1. 透過NotificationCompat.Builder建立通知並設定各種選項

a.透過NotificationCompat.Builder建立通知,最少必須包含一個小圖示,一個標題,一段文字。

    Builder builder = new Builder(mContext, NOTIFICATION_CHANNEL_ID);
    builder.setSmallIcon(android.R.drawable.sym_action_chat);
    builder.setContentTitle(title);
    builder.setContentText(text);

b.如果想設定更多的選項也是透過setxxx來達到,如下的設定就能讓該通知具有Heads-up的外觀,也就是在小型浮動視窗中出現。

    builder.setPriority(NotificationCompat.PRIORITY_HIGH);
    builder.setVibrate(new long[]{0, 1000});
    builder.setAutoCancel(true);

 

  1. 設定通知要啟動的Action,該Action代表按下通知後要啟動哪個元件

Action是透過PendingIntent來設定如下

Intent actionIntent = new Intent(mContext, NotificationLaunchActivity.class);
PendingIntent launchNotificationLaunchActivity = PendingIntent
    .getActivity(mContext, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(launchNotificationLaunchActivity);

Intent actionIntent = new Intent(mContext, NotificationLaunchActivity.class);
設定點擊該通知要啟動的Activity。
PendingIntent launchNotificationLaunchActivity = PendingIntent
.getActivity(mContext, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
包裝actionIntent的PendingIntent。
最後透過setContentIntent設定要啟動的Intent。

builder.setContentIntent(launchNotificationLaunchActivity);

注意:PendingIntent也可以啟動Service或BroadcastReceiver,使用以下方法來指定要啟動的元件。

PendingIntent.getBroadcast();
PendingIntent.getService()

 

  1. 透過NotificationManager發出通知
mNotificationManager.notify(NOTIFICATION_ID, builder.build());

NOTIFICATION_ID
為識別該通知的數值,但不太需要特別設定。
完整程式碼

public class NotificationWrapper {
  public static final int NOTIFICATION_ID = 888;
  private static final String NOTIFICATION_CHANNEL_ID = "notification_channel";
  public static final String DIRECT_REPLY_BUTTON_KEY = "direct_reply_button_key";
  private final Context mContext;
  private NotificationManager mNotificationManager;
  public NotificationWrapper(Context context) {
    mContext = context;
    mNotificationManager = (NotificationManager) mContext
        .getSystemService(mContext.NOTIFICATION_SERVICE);
  }
  private void createNotificationChannel() {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
      NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "name",
          NotificationManager.IMPORTANCE_HIGH);
      channel.setDescription("channel description");
      channel.enableLights(true);
      channel.setLightColor(Color.GREEN);
      channel.enableVibration(true);
//      channel.setShowBadge(false);
//      channel.setSound(System.ALARM_ALERT);
      mNotificationManager.createNotificationChannel(channel);
    }
  }
  private Builder createNotification(String title, String text) {
    Builder builder = new Builder(mContext, NOTIFICATION_CHANNEL_ID);
    builder.setSmallIcon(android.R.drawable.sym_action_chat);
    builder.setContentTitle(title);
    builder.setContentText(text);
    builder.setPriority(NotificationCompat.PRIORITY_HIGH);
    builder.setVibrate(new long[]{0, 1000});
    builder.setAutoCancel(true);
    setBadge(builder);
    setContentIntent(builder);
    return builder;
  }
  private void setBadge(Builder builder) {
    builder.setNumber(100);
    builder.setBadgeIconType(NotificationCompat.BADGE_ICON_LARGE);
  }
  @Deprecated
  private void addDirectReplyButton(Builder builder) {
    RemoteInput remoteInput = new RemoteInput.Builder(DIRECT_REPLY_BUTTON_KEY)
        .setLabel("label")
        .build();
    int requestCode = 999;
    Intent actionIntent = new Intent(mContext, MyBroadcastReceiver.class);
    PendingIntent replyPendingIntent = PendingIntent.getBroadcast(mContext,
        requestCode,
        actionIntent,
        PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Action action =
        new NotificationCompat.Action.Builder(android.R.drawable.sym_action_chat,
            "direct reply action title", replyPendingIntent)
            .addRemoteInput(remoteInput)
            .build();
    builder.addAction(action);
  }
  private void setContentIntent(Builder builder) {
    Intent actionIntent = new Intent(mContext, NotificationLaunchActivity.class);
    PendingIntent launchNotificationLaunchActivity = PendingIntent
        .getActivity(mContext, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    builder.setContentIntent(launchNotificationLaunchActivity);
  }
  public void showNotification(String title, String text) {
    createNotificationChannel();
    Builder builder = createNotification(title, text);
    mNotificationManager.notify(NOTIFICATION_ID, builder.build());
  }
}

使用 NotificationWrapper來發送通知。

new NotificationWrapper(this).showNotification("this is notification title", "this is notification text");


以上是最基本的通知發送範例,下方則是介紹一些進階功能


進階功能

加入動作按鈕
加入動作按鈕和加入設定通知要啟動的Action類似。也是建立PendingIntent,並在其內加入要啟動的元件,最後透過addAction來加入。
需要注意的是動作按鈕最多只有3個,超過3個會忽略。

  private void addActionButton(Builder builder) {
    Intent actionIntent = new Intent(mContext, NotificationActionActivity.class);
    PendingIntent launchNotificationActionActivity =
        PendingIntent.getActivity(mContext, 0, actionIntent, 0);
    builder.addAction(android.R.drawable.sym_action_call, "Launch", launchNotificationActionActivity);
  }

加入動作按鈕後,點擊該按鈕便會啟動指定的元件(NotificationActionActivity)。

 
後續還有多種通知形式可以使用,如加入直接回應按鈕等等
範例可參考
https://github.com/googlesamples/android-Notifications
以及官方教學
https://developer.android.com/guide/topics/ui/notifiers/notifications?hl=zh-tw