通知欄通知在Android APP中的使用極爲頻繁,好比短信通知,QQ,微信消息通知,App 更新進度轉態顯示,截圖時後圖片進行刪除或分享,查看操做等等。本篇文章記錄瞭如何使用 Notification 顯示消息, 設置提示音,呼吸燈,震動,以及響應用戶對消息的處理動做。android
發送通知的步驟api
Android 7.0 新內容微信
Notification.Builder.serPriority: 設置通知優先級 Notification.Builder.setStyle: 設置通知擴展布局 MessagingStyle: 快速回復app
Android 8.0 新內容ide
NotificationChannel:用戶能夠自定義通知的顯示,以及關閉某個通知的提示音震動等函數
一個簡單的通知包含,一個小圖標,一個標題和內容如圖:佈局
代碼post
// 獲取系統 通知管理 服務 NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 構建 Notification Notification.Builder builder = new Notification.Builder(this); builder.setContentTitle("ContentTitle") .setSmallIcon(R.drawable.ic_launcher_background) .setContentText("Content Text Here"); // 兼容 API 26,Android 8.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ // 第三個參數表示通知的重要程度,默認則只在通知欄閃爍一下 NotificationChannel notificationChannel = new NotificationChannel("AppTestNotificationId", "AppTestNotificationName", NotificationManager.IMPORTANCE_DEFAULT); // 註冊通道,註冊後除非卸載再安裝不然不改變 notificationManager.createNotificationChannel(notificationChannel); builder.setChannelId("AppTestNotificationId"); } // 發出通知 notificationManager.notify(1, builder.build());
構建 Notification 代碼ui
// 構建 Notification Notification.Builder builder = new Notification.Builder(this); builder.setContentTitle("ContentTitle") .setSmallIcon(R.drawable.ic_launcher_background) .setContentText("Content Text Here") .setDefaults(Notification.DEFAULT_ALL);
這裏關鍵的在於 SetDefaults 這個方法,它接收一個 int,可選值以下:this
setVibrate 接收一個long[], 下標爲奇數爲延時,偶數爲震動時長,本例中爲,延時0ms,震動300ms,延時200ms,震動300
builder.setVibrate(new long[]{0, 300, 200, 300}); // Android 8.0 需用如下方法 // notificationChannel.enableVibration(true); // notificationChannel.setVibrationPattern(new long[]{0,300,300,500,300,800});
三個參數依次是 int ARGB 顏色值、亮的時長、不亮的時長。
builder.setLights(0xFFFF0000, 1000,1000); // Android 8.0 需用如下方法,不可設置時長 // notificationChannel.enableLights(true); // notificationChannel.setLightColor(0xFFFF0000);
builder.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.a)) // Android 8.0 需用如下方法, 這裏用的是加載res/raw的聲音資源 // notificationChannel.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.a), null);
這個方法須要使用鎖屏並在設置中隱藏敏感信息才能生效
builder.setVisibility(Notification.VISIBILITY_PUBLIC); // Android 8.0 需用一下方法 // notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
這個方法接收一個 int
持續的通知
如播放音樂,後臺任務,下載, 當這個方法傳入 true 時,表示它是一個持續的通知,用戶沒法刪除它,只能在代碼中讓通知消失。
builder.setOngoing(true);
顯示進度條
在後臺處理某個耗時任務時須要使用到進度條, 參數做用依次是 進度條最大值、當前進度、進度是否肯定,indeterminate 表示任務的進度是否能夠準確獲取
builder.setProgress(int max, int progress, boolean indeterminate);
如何更新通知
只需在發出通知時使用相同的 id 便可更新,若是這條通知已被移除則建立一個新的通知
notificationManager.notify(int id, Notification.Builder);
PendingIntent 是一種特殊的 Intent, 做用和 Intent 同樣是用於啓動一個 Activity或者Service,或發送一條 Broadcast。通知響應用戶動做即是用這個, 當對通知作出一個動做後,系統便會調用 PendingIntent,啓動一個活動,服務或廣播,這取決於你獲取的是那種 PendingIntent。
在 PendingIntent 中傳入的 Context 銷燬之後,PendingIntent 依舊有效,它通常使用在當 Context 銷燬後須要執行 Intent的地方,通常不是用於當即執行的時候,好比在點擊通知後喚醒一個 Activity。。
獲取 PendingIntent
// 獲取用於啓動 Activity PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags); // 獲取用於發送 Broadcast PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags); // 獲取用於啓動服務 PendingIntent.getService(Context context, int requestCode, Intent intent, int flags); PendingIntent.getActivities(Context context, int reqeustCode, Intent[] intents, int flags); PendingIntent.getForgroundService(Context, int reqeustCode, Intent intent, int flags)
各個參數的用途分別以下
其中,requestCode 和 flags 是相關聯的,若是屢次獲取 PendingIntent 時 requestCode 相同,此時返回的結果就須要參考 flags 的值。例如
Intent intent1 = new Intent("NotificationAction"); intent1.putExtra("A", "value AA"); intent1.putExtra("B", "value BB"); Intent intent11 = new Intent("NotificationAction"); intent11.putExtra("B", "BBB"); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent1, PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent pendingIntent11 = PendingIntent.getBroadcast(this, 1, intent11, PendingIntent.FLAG_UPDATE_CURRENT);
這兩個 PendingIntent 的 requestCode 是相同的,第二個獲取時傳入的 flags 爲 PendingIntent.FLAG_UPDATE_CURRENT ,表示存在 requestCode 爲 1,的PendingIntent則更新這個PendingIntent 的 Intent 值,此時 getStringExtr("A") 的值爲 null,getStringExtra("B"), 的值爲 BBB。
當咱們獲取了 PendingIntent 以後,只須要給 builder 的特定方法傳入就能夠響應點擊、清除動做了
設置點擊,清除 PendingIntent 代碼:
builder.setContentIntent(PendingIntent intent); builder.setDeleteIntent(PendingIntent intent);
在須要對通知內容進行簡單操做的時候,好比短信的‘標記爲已讀’,‘刪除’。咱們能夠對按鈕設置圖標、標題以及設置 PendingIntent 以便響應動做。這種按鈕最多能夠添加三個,按添加的順序從左往右依次排列。 api 23 以後圖標不顯示
Intent intent2 = new Intent("NotificationAction"); intent2.putExtra("A", "Action button1 clicked"); PendingIntent pendingIntent1 = PendingIntent.getBroadcast(this, 3, intent2, PendingIntent.FLAG_UPDATE_CURRENT); otification.Action.Builder actionBuilder = new Notification.Action.Builder(Icon.createWithResource(getApplicationContext(), R.drawable.ic_launcher_background), "Action1", pendingIntent1); builder.addAction(actionBuilder.build());
結果如圖,點擊 Action1 按鈕後將發出一條廣播
超長內容的 Notification,好比內容爲文字不少,或者一個大圖片,一個自定義的 View,經過 builder.setStyle(Style style) 這個方法設置。設置 style 以後,以前的 setContent 設置的內容將會失效。各類 style 的高度最大爲 256 dp。
Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle().bigText( "This is big text notification. This is big text notification. " + "This is big text notification. This is big text notification. " + "This is big text notification. This is big text notification. " + "This is big text notification. This is big text notification. " + "This is big text notification. This is big text notification. " + "This is big text notification. This is big text notification. " + "This is big text notification. This is big text notification. " + "This is big text notification. This is big text notification. " + "This is big text notification. This is big text notification. "); builder.setStyle(bigTextStyle);
inboxstyle 顯示爲一個文字列表,顯示 addline 的順序的文字,最多支持六行。
Notification.InboxStyle inboxStyle = new Notification.InboxStyle(); // 添加行 inboxStyle.addLine("First line."); inboxStyle.addLine("Second line"); inboxStyle.addLine("Third line"); inboxStyle.addLine("Last line"); // 設置標題以及簡介文字 inboxStyle.setBigContentTitle("ContentTitle"); inboxStyle.setSummaryText("SummaryText"); builder.setStyle(inboxStyle);
// 構建一個 Style Notification.BigPictureStyle bigPictureStyle = new Notification.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.big)); // 設置標題 bigPictureStyle.setBigContentTitle("ContentTitle"); // 設置副標題,簡介文字 bigPictureStyle.setSummaryText("SummaryText"); // 設置大圖標 bigPictureStyle.bigLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.big)); builder.setStyle(bigPictureStyle);
略
有些時候咱們須要對通知內容進行快速回復,好比收到一條郵件,咱們能夠快速回復。當點擊通知的一個 Action 按鈕後將會出現一個輸入框,能夠進行發送消息。咱們須要添加一個 MessageStyle 和 一個帶 RemoteInput 的 Action,這個通知便能支持快速回復。這個功能須要 api 版本大於 24
首先,構建一個 MessageStyle,並設置好
Notification.MessagingStyle messagingStyle = new Notification .MessagingStyle("UserDisplayName"). addMessage("MessageStyle", 1000, "sender"); builder.setStyle(messagingStyle);
而後再建立一個 Action,Action 需添加一個 RemoteInput,一個響應發送動做的 PendingIntent,這個例子中點擊發送按鈕後將發送一條廣播。
Intent intent = new Intent("NotificationAction"); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 11, intent, PendingIntent.FLAG_UPDATE_CURRENT); RemoteInput remoteInput = new RemoteInput .Builder("RemoteInputKey") .setLabel("RemoteInputLabel") .build(); Notification.Action action = new Notification.Action .Builder(Icon.createWithResource(this, R.mipmap.ic_launcher_round), "ReplayAction", pendingIntent) .addRemoteInput(remoteInput) .build(); // 發送該通知 notificationManager.notify(22, builder.build());
接受輸入數據用的廣播,咱們在獲取到輸入數據後須要手動取消該通知,不然不會自動取消。
class MBroadcast extends Broadcast{ [@Override](https://my.oschina.net/u/1162528) public void onReceive(Context context, Intent intent) { Bundle bundle = RemoteInput.getResultsFromIntent(intent); if (bundle != null){ String replayContent = bundle.getString("RemoteInputKey"); Log.d("MBroadcast", "onReceive: " + replayContent); // 取消該通知 ((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).cancel(22); } } }
在通知欄進行對後臺任務的控制的時候須要用到這個功能, 好比下載一個文件時能夠 取消,暫停,後臺播放音樂時能夠 切換暫停和顯示歌詞等。通知的自定義 view 最大高度爲 256 dp,且只有 Android N 以上版本才支持 自定義 view。
RemoteViews 只支持幾個 View,在這裏我使用 ConstraintLayout 做爲根 Layout 的時候發現會出現 android.app.RemoteServiceException: Bad notification posted from package xxx 這個錯誤,換了 LinearLayout 後就不會出現這個問題。支持的 View 以下
首先構建一個通知,建立一個 RemoteViews,RemoteViews 構造函數接受一個包含 view 所在的包名和一個 View 資源。RemoteViews 意思就是遠程 view,該 view 不存在與 當前 Activity,進程,一般用於通知中的自定義 view 和桌面小部件。
Notification.Builder builder = new Notification.Builder(this) .setContentTitle("ContentTitle") .setTicker("ThisIsTicker") .setSmallIcon(R.drawable.ic_launcher_background) .setContentText("ContentText"); RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notify_view);
這裏的 notify_view 很簡單,以下
<LinearLayout ...> <ImageView id="@+id/notify_iv" .../> <TextView id="@+id/notify_tv" .../> <Button id="@+id/notify_bt" .../> </LinearLayout>
設置 CustomContentView 和 Style。
builder.setCustomContentView(remoteViews); Notification.DecoratedCustomViewStyle viewStyle = new Notification.DecoratedCustomViewStyle(); builder.setStyle(viewStyle);
如今已經添加了一個 view,如何修改 view 中的數據以及響應 view 的事件呢?經過 RemoteViews.setOnClickPendingIntent(int r, PendingIntent intnet) 這個方法爲 一個 view 綁定一個 PendingIntent,當點擊了該view 後便執行相應的操做。
Intent intent = new Intent("NotificationAction"); intent.putExtra("action", "bt_click"); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 12, intent, PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.notify_bt, pendingIntent);
更新 RemoteView 中的數據,更新一個 ImageView中的圖片,對各類 view 更新都有相應的方法。
remoteViews.setBitmap(R.id.notify_iv, "setImageBitmap", BitmapFactory.decodeResource(getResources(), R.drawable.me));
我的博客原文地址 (完)