通知是什麼?
通知為Notification,基本上是在應用程式的 UI 以外(通常是狀態列)顯示的訊息。
官網參考:https://developer.android.com/guide/topics/ui/notifiers/notifications?hl=zh-tw
如何使用通知
使用通知基本上有 4 個步驟
- 建立NotificationChannel
- 透過Builder建立通知並設定各種選項
- 設定通知要啟動的Action,該Action代表通知按下後要啟動哪個元件
- 透過NotificationManager發出通知
- 建立 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); } }
- 透過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);
- 設定通知要啟動的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()
- 透過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