摘要:當(dāng)向系統(tǒng)發(fā)出通知時(shí),它將先以圖標(biāo)的形式顯示在通知欄中。通知欄和抽屜式通知欄均是由系統(tǒng)控制,用戶可以隨時(shí)查看。更新通知跟發(fā)送通知使用相同的方式。創(chuàng)建返回棧添加返回棧代碼默認(rèn)情況下,從通知啟動(dòng)一個(gè),按返回鍵會(huì)回到主屏幕。
目錄介紹
1.Notification簡(jiǎn)單概述
2.Notification通知用途
3.Notification的基本操作
3.1 Notification創(chuàng)建必要的屬性
3.2 Notification簡(jiǎn)單創(chuàng)建步驟
3.3 關(guān)于setSmallIcon()與setLargeIcon()區(qū)別
3.4 Notification的Action屬性【交互作用】
3.5 更新Notification
3.6 取消Notification
3.7 設(shè)置flag屬性
3.8 設(shè)置Notification的通知效果
3.9 設(shè)置自定義Notification通知欄布局
4.Notification相關(guān)屬性說(shuō)明
4.1 PendingIntent說(shuō)明
4.2 創(chuàng)建返回棧PendingIntent
4.3 注意要點(diǎn)
5.部分源碼分析思考
5.1 RemoteView是什么?
5.2 查看源碼,了解Notification如何創(chuàng)建布局
6.關(guān)于Android8.0通知欄適配
6.1 Android O(8.0)通知的改變
6.2 報(bào)錯(cuò)內(nèi)容和解決方案
6.3 最終解決方案
7.關(guān)于其他
好消息已經(jīng)解決了8.0以上通知欄不能顯示問(wèn)題。封裝成了lib庫(kù),歡迎大家下載。已經(jīng)放到正式項(xiàng)目運(yùn)行多時(shí)!
項(xiàng)目地址鏈接:https://github.com/yangchong2...
本篇文章已授權(quán)微信公眾號(hào) guolin_blog (郭霖)獨(dú)家發(fā)布
項(xiàng)目截圖說(shuō)明
1.Notification簡(jiǎn)單概述Notification,是一種具有全局效果的通知,可以在系統(tǒng)的通知欄中顯示。當(dāng) APP 向系統(tǒng)發(fā)出通知時(shí),它將先以圖標(biāo)的形式顯示在通知欄中。用戶可以下拉通知欄查看通知的詳細(xì)信息。通知欄和抽屜式通知欄均是由系統(tǒng)控制,用戶可以隨時(shí)查看。
2.Notification通知用途常見(jiàn)的用途
顯示接收到短消息、及時(shí)消息等信息(如QQ、微信、新浪、短信)
顯示客戶端的推送消息,如廣告、優(yōu)惠、版本更新、推薦新聞等,常用的第三方 SDK 有: JPush 、 個(gè)推 、 信鴿 、 網(wǎng)易云信(偏重 IM ) 、 阿里云推送
顯示正在進(jìn)行的事物,例如:后臺(tái)運(yùn)行的程序,如音樂(lè)播放進(jìn)度、下載進(jìn)度等
前兩點(diǎn)可以歸結(jié)為與用戶交互,第三點(diǎn)是實(shí)時(shí)的任務(wù)提醒,但不可否認(rèn)的是,第三點(diǎn)也會(huì)與用戶交互。
3.Notification的基本操作3.1 Notification創(chuàng)建必要的屬性,必須設(shè)置
3.1.1 必須添加的屬性
小圖標(biāo),通過(guò) setSmallIcon() 方法設(shè)置
標(biāo)題,通過(guò) setContentTitle() 方法設(shè)置
內(nèi)容,通過(guò) setContentText() 方法設(shè)置
3.2 Notification創(chuàng)建步驟
3.2.1 Notification 的創(chuàng)建主要涉及到 Notification.Builder 、 Notification 、 NotificationManager
Notification.Builer : 使用建造者模式構(gòu)建 Notification 對(duì)象。由于 Notification.Builder 僅支持 Android 4.1及之后的版本,為了解決兼容性問(wèn)題, Google 在 Android Support v4 中加入了 - NotificationCompat.Builder 類。對(duì)于某些在 Android 4.1 之后才特性,即使 NotificationCompat.Builder 支持該方法,在之前的版本中也不能運(yùn)行。
Notification : 通知對(duì)應(yīng)類,保存通知相關(guān)的數(shù)據(jù)。- NotificationManager 向系統(tǒng)發(fā)送通知時(shí)會(huì)用到。
NotificationManager : NotificationManager 是通知管理類,它是一個(gè)系統(tǒng)服務(wù)。調(diào)用 NotificationManager 的 notify() 方法可以向系統(tǒng)發(fā)送通知。
3.2.2 Notification創(chuàng)建步驟與代碼
// 創(chuàng)建一個(gè)NotificationManager的引用 NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); // 定義Notification的各種屬性 Notification.Builder mBuilder = new Notification.Builder(this.getApplicationContext()) .setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI) // .setSmallIcon(R.mipmap.ic_launcher) //設(shè)置通知的圖標(biāo) .setTicker("有新消息呢") //設(shè)置狀態(tài)欄的標(biāo)題 .setContentTitle("這個(gè)是標(biāo)題") //設(shè)置標(biāo)題 .setContentText("這個(gè)是內(nèi)容") //消息內(nèi)容 .setDefaults(Notification.DEFAULT_ALL) //設(shè)置默認(rèn)的提示音 .setPriority(Notification.PRIORITY_DEFAULT) //設(shè)置該通知的優(yōu)先級(jí) .setOngoing(false) //讓通知左右滑的時(shí)候不能取消通知 .setPriority(Notification.PRIORITY_DEFAULT) //設(shè)置該通知的優(yōu)先級(jí) .setWhen(System.currentTimeMillis()) //設(shè)置通知時(shí)間,默認(rèn)為系統(tǒng)發(fā)出通知的時(shí)間,通常不用設(shè)置 .setAutoCancel(true); //打開(kāi)程序后圖標(biāo)消失 //處理點(diǎn)擊Notification的邏輯 Intent resultIntent = new Intent(this, TestActivity.class); resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //添加為棧頂Activity resultIntent.putExtra("what",5); PendingIntent resultPendingIntent = PendingIntent.getActivity(this,5,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT); mBuilder.setContentIntent(resultPendingIntent); //發(fā)送 mNotificationManager.notify(1, mBuilder.build()); //結(jié)束廣播 //mNotificationManager.cancel(1);
3.3 關(guān)于setSmallIcon()與setLargeIcon()區(qū)別
在 NotificationCompat.Builder 中有設(shè)置通知的大小圖標(biāo)的兩個(gè)方法。這兩個(gè)方法有什么區(qū)別呢?
當(dāng) setSmallIcon() 與 setLargeIcon() 同時(shí)存在時(shí), smallIcon 顯示在通知的右下角, largeIcon 顯示在左側(cè)
當(dāng)只設(shè)置 setSmallIcon() 時(shí), smallIcon 顯示在左側(cè)??聪聢D你就明白了。
對(duì)于部分 ROM ,可能修改過(guò)源碼,如 MIUI 上通知的大圖標(biāo)和小圖標(biāo)是沒(méi)有區(qū)別的。
效果如圖所示:
3.4 Notification的Action屬性
設(shè)置一個(gè) Action ,這樣就可以直接跳轉(zhuǎn)到 App 的某個(gè) Activity 、啟動(dòng)一個(gè) Service 或者發(fā)送一個(gè) Broadcast。否則,Notification 僅僅只能起到通知的效果,而不能與用戶交互。
具體代碼如下所示:
//創(chuàng)建intent Intent resultIntent = new Intent(this, TestActivity.class); resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //添加為棧頂Activity resultIntent.putExtra("what",5); PendingIntent resultPendingIntent = PendingIntent.getActivity(this,5,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT); //發(fā)送pendingIntent mBuilder.setContentIntent(resultPendingIntent);
3.5 更新Notification
更新通知很簡(jiǎn)單,只需要再次發(fā)送相同 ID 的通知即可,如果之前的通知還未被取消,則會(huì)直接更新該通知相關(guān)的屬性;如果之前的通知已經(jīng)被取消,則會(huì)重新創(chuàng)建一個(gè)新通知。更新通知跟發(fā)送通知使用相同的方式。
3.6 取消Notification
取消通知有如下 5 種方式:
點(diǎn)擊通知欄的清除按鈕,會(huì)清除所有可清除的通知
設(shè)置了 setAutoCancel() 或 FLAG_AUTO_CANCEL 的通知,點(diǎn)擊該通知時(shí)會(huì)清除它
通過(guò) NotificationManager 調(diào)用 cancel(int id) 方法清除指定 ID 的通知
通過(guò) NotificationManager 調(diào)用 cancel(String tag, int id) 方法清除指定 TAG 和 ID 的通知
通過(guò) NotificationManager 調(diào)用 cancelAll() 方法清除所有該應(yīng)用之前發(fā)送的通知
注意事項(xiàng)
如果你是通過(guò) NotificationManager.notify(String tag, int id, Notification notify) 方法創(chuàng)建的通知,那么只能通過(guò) NotificationManager.cancel(String tag, int id) 方法才能清除對(duì)應(yīng)的通知,調(diào)用NotificationManager.cancel(int id) 無(wú)效。
3.7 設(shè)置flag屬性
設(shè)置FLAG_NO_CLEAR表示
設(shè)置通知不能被狀態(tài)欄的清除按鈕給清除掉,也不能被手動(dòng)清除,但能通過(guò) cancel() 方法清除
代碼:
private void sendNotification9() { Notification.Builder mBuilder = new Notification.Builder(this.getApplicationContext()) .setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI) .setSmallIcon(R.mipmap.ic_launcher) //設(shè)置通知的圖標(biāo) .setTicker("有新消息呢9") //設(shè)置狀態(tài)欄的標(biāo)題 .setContentTitle("這個(gè)是標(biāo)題9") //設(shè)置標(biāo)題 .setContentText("這個(gè)是內(nèi)容9") //消息內(nèi)容 .setDefaults(Notification.DEFAULT_ALL) //設(shè)置默認(rèn)的提示音 .setOngoing(false) //讓通知左右滑的時(shí)候不能取消通知 .setAutoCancel(true); //打開(kāi)程序后圖標(biāo)消失 Notification notification = mBuilder.build(); //設(shè)置 Notification 的 flags = FLAG_NO_CLEAR //FLAG_NO_CLEAR 表示該通知不能被狀態(tài)欄的清除按鈕給清除掉,也不能被手動(dòng)清除,但能通過(guò) cancel() 方法清除 //flags 可以通過(guò) |= 運(yùn)算疊加效果 notification.flags |= Notification.FLAG_NO_CLEAR; //獲取NotificationManager 對(duì)象 mNotificationManager.notify(9, notification); } //取消通知: if(mNotificationManager!=null){ mNotificationManager.cancelAll(); }
3.8 設(shè)置Notification的通知效果
Notification 有震動(dòng)、響鈴、呼吸燈三種響鈴效果,可以通過(guò) setDefaults(int defualts) 方法來(lái)設(shè)置。 Default 屬性有以下四種,一旦設(shè)置了 Default 效果,自定義的效果就會(huì)失效。樓主在這里踩了坑,愣是調(diào)了半天沒(méi)找到為什么自定義效果會(huì)消失,忘大家慎之。
//設(shè)置系統(tǒng)默認(rèn)提醒效果,一旦設(shè)置默認(rèn)提醒效果,則自定義的提醒效果會(huì)全部失效。具體可看源碼//添加默認(rèn)震動(dòng)效果,需要申請(qǐng)震動(dòng)權(quán)限//Notification.DEFAULT_VIBRATE //添加系統(tǒng)默認(rèn)聲音效果,設(shè)置此值后,調(diào)用setSound()設(shè)置自定義聲音無(wú)效 Notification.DEFAULT_SOUND //添加默認(rèn)呼吸燈效果,使用時(shí)須與 Notification.FLAG_SHOW_LIGHTS 結(jié)合使用,否則無(wú)效 Notification.DEFAULT_LIGHTS //添加上述三種默認(rèn)提醒效果 Notification.DEFAULT_ALL
除了以上幾種設(shè)置 Notification 默認(rèn)通知效果,還可以通過(guò)以下幾種 FLAG 設(shè)置通知效果。
//提醒效果常用 Flag//三色燈提醒,在使用三色燈提醒時(shí)候必須加該標(biāo)志符 Notification.FLAG_SHOW_LIGHTS //發(fā)起正在運(yùn)行事件(活動(dòng)中) Notification.FLAG_ONGOING_EVENT //讓聲音、振動(dòng)無(wú)限循環(huán),直到用戶響應(yīng) (取消或者打開(kāi)) Notification.FLAG_INSISTENT //發(fā)起Notification后,鈴聲和震動(dòng)均只執(zhí)行一次 Notification.FLAG_ONLY_ALERT_ONCE //用戶單擊通知后自動(dòng)消失 Notification.FLAG_AUTO_CANCEL //只有調(diào)用NotificationManager.cancel()時(shí)才會(huì)清除 Notification.FLAG_NO_CLEAR //表示正在運(yùn)行的服務(wù) Notification.FLAG_FOREGROUND_SERVICE
設(shè)置默認(rèn)提醒
// 添加默認(rèn)聲音提醒 builder.setDefaults(Notification.DEFAULT_SOUND); // 添加默認(rèn)呼吸燈提醒,自動(dòng)添加FLAG_SHOW_LIGHTS builder.setDefaults(Notification.DEFAULT_LIGHTS);
設(shè)置鈴聲屬性,用的很少
private void sendNotification11() { Notification.Builder builder = new Notification.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("我是伴有鈴聲效果的通知11") .setContentText("美妙么?安靜聽(tīng)~11") //調(diào)用系統(tǒng)默認(rèn)響鈴,設(shè)置此屬性后setSound()會(huì)無(wú)效 //.setDefaults(Notification.DEFAULT_SOUND) //調(diào)用系統(tǒng)多媒體褲內(nèi)的鈴聲 //.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2")); //調(diào)用自己提供的鈴聲,位于 /res/values/raw 目錄下 .setSound(Uri.parse("android.resource://com.yc.cn.ycnotification/" + R.raw.hah)); //另一種設(shè)置鈴聲的方法 //Notification notify = builder.build(); //調(diào)用系統(tǒng)默認(rèn)鈴聲 //notify.defaults = Notification.DEFAULT_SOUND; //調(diào)用自己提供的鈴聲 //notify.sound = Uri.parse("android.resource://com.yc.cn.ycnotification/"+R.raw.sound); //調(diào)用系統(tǒng)自帶的鈴聲 //notify.sound = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"2"); //mManager.notify(11,notify); mNotificationManager.notify(11, builder.build()); }
設(shè)置震動(dòng)屬性
private void sendNotification12() { //震動(dòng)也有兩種設(shè)置方法,與設(shè)置鈴聲一樣,在此不再贅述 long[] vibrate = new long[]{0, 500, 1000, 1500}; Notification.Builder builder = new Notification.Builder(this) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("我是伴有震動(dòng)效果的通知") .setContentText("顫抖吧,逗比哈哈哈哈哈~") //使用系統(tǒng)默認(rèn)的震動(dòng)參數(shù),會(huì)與自定義的沖突 //.setDefaults(Notification.DEFAULT_VIBRATE) //自定義震動(dòng)效果 .setVibrate(vibrate); //另一種設(shè)置震動(dòng)的方法 //Notification notify = builder.build(); //調(diào)用系統(tǒng)默認(rèn)震動(dòng) //notify.defaults = Notification.DEFAULT_VIBRATE; //調(diào)用自己設(shè)置的震動(dòng) //notify.vibrate = vibrate; //mManager.notify(3,notify); mNotificationManager.notify(12, builder.build()); }
3.9 設(shè)置自定義Notification通知欄布局
代碼如下,注意,這里只取部分代碼,完整代碼可以下載github的完整項(xiàng)目:https://github.com/yangchong2...
.setContent(getRemoteViews()) // 設(shè)置通知欄的布局 //創(chuàng)建自定義布局 private RemoteViews getRemoteViews() { RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_mobile_play); // 設(shè)置 點(diǎn)擊通知欄的上一首按鈕時(shí)要執(zhí)行的意圖 remoteViews.setOnClickPendingIntent(R.id.btn_pre, getActivityPendingIntent(11)); // 設(shè)置 點(diǎn)擊通知欄的下一首按鈕時(shí)要執(zhí)行的意圖 remoteViews.setOnClickPendingIntent(R.id.btn_next, getActivityPendingIntent(12)); // 設(shè)置 點(diǎn)擊通知欄的播放暫停按鈕時(shí)要執(zhí)行的意圖 remoteViews.setOnClickPendingIntent(R.id.btn_start, getActivityPendingIntent(13)); // 設(shè)置 點(diǎn)擊通知欄的根容器時(shí)要執(zhí)行的意圖 remoteViews.setOnClickPendingIntent(R.id.ll_root, getActivityPendingIntent(14)); remoteViews.setTextViewText(R.id.tv_title, "標(biāo)題"); // 設(shè)置通知欄上標(biāo)題 remoteViews.setTextViewText(R.id.tv_artist, "藝術(shù)家"); // 設(shè)置通知欄上藝術(shù)家 return remoteViews; }4.Notification相關(guān)屬性說(shuō)明
4.1 PendingIntent說(shuō)明
4.1.1 PendingIntent基本說(shuō)明
PendingIntent 是一種特殊的 Intent ,字面意思可以解釋為延遲的 Intent ,用于在某個(gè)事件結(jié)束后執(zhí)行特定的 Action 。從上面帶 Action 的通知也能驗(yàn)證這一點(diǎn),當(dāng)用戶點(diǎn)擊通知時(shí),才會(huì)執(zhí)行。
PendingIntent 是 Android 系統(tǒng)管理并持有的用于描述和獲取原始數(shù)據(jù)的對(duì)象的標(biāo)志(引用)。也就是說(shuō),即便創(chuàng)建該P(yáng)endingIntent對(duì)象的進(jìn)程被殺死了,這個(gè)PendingItent對(duì)象在其他進(jìn)程中還是可用的。
日常使用中的短信、鬧鐘等都用到了 PendingIntent。
4.1.2 PendingIntent三種獲取方式
//獲取一個(gè)用于啟動(dòng) Activity 的 PendingIntent 對(duì)象public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags); //獲取一個(gè)用于啟動(dòng) Service 的 PendingIntent 對(duì)象public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags); //獲取一個(gè)用于向 BroadcastReceiver 廣播的 PendingIntent 對(duì)象public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
4.1.3 PendingIntent具有幾種flag
FLAG_CANCEL_CURRENT:如果當(dāng)前系統(tǒng)中已經(jīng)存在一個(gè)相同的 PendingIntent 對(duì)象,那么就將先將已有的 PendingIntent 取消,然后重新生成一個(gè) PendingIntent 對(duì)象。 FLAG_NO_CREATE:如果當(dāng)前系統(tǒng)中不存在相同的 PendingIntent 對(duì)象,系統(tǒng)將不會(huì)創(chuàng)建該 PendingIntent 對(duì)象而是直接返回 null 。 FLAG_ONE_SHOT:該 PendingIntent 只作用一次。 FLAG_UPDATE_CURRENT:如果系統(tǒng)中已存在該 PendingIntent 對(duì)象,那么系統(tǒng)將保留該 PendingIntent 對(duì)象,但是會(huì)使用新的 Intent 來(lái)更新之前 PendingIntent 中的 Intent 對(duì)象數(shù)據(jù),例如更新 Intent 中的 Extras 。
4.2 創(chuàng)建返回棧PendingIntent
4.2.1 添加返回棧代碼
默認(rèn)情況下,從通知啟動(dòng)一個(gè)Activity,按返回鍵會(huì)回到主屏幕。
但某些時(shí)候有按返回鍵仍然留在當(dāng)前應(yīng)用的需求,這就要用到TaskStackBuilder了。
Notification.Builder mBuilder = new Notification.Builder(context) .setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle("廣播接受者標(biāo)題,小楊") .setContentText("廣播接受者內(nèi)容,扯犢子") .setAutoCancel(true); Log.i(TAG, "onReceive: intent" + intent.getClass().getName()); Intent resultIntent = new Intent(context, MainActivity.class); TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); //將該Activity添加為棧頂 stackBuilder.addParentStack(MainActivity.class); stackBuilder.addNextIntent(resultIntent); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); mBuilder.setContentIntent(resultPendingIntent); NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(1, mBuilder.build());
4.3 注意要點(diǎn)
如果用戶的手機(jī)使靜音模式,那么設(shè)置鈴聲或者震動(dòng)效果將會(huì)失效
5.部分源碼分析思考5.1 RemoteView是什么?
5.1.1 什么是RemoteView?
為啥Notification不會(huì)設(shè)計(jì)成和普通View一樣的使用方式?理由很簡(jiǎn)單!狀態(tài)欄不是單單由你的應(yīng)用程序管理.狀態(tài)欄是由Android系統(tǒng)管理的.你需要顯示Notification就必須和系統(tǒng)打交道.必須通過(guò)Notification服務(wù)才能顯示你的Notification.所以設(shè)計(jì)成用一個(gè)Notification實(shí)例代表一個(gè)Notification,然后通過(guò)notificationManager.notify函數(shù)提交給Notification服務(wù).
5.1.2 Notification服務(wù)是什么?是一個(gè)獨(dú)立的線程!
又扯出一個(gè)問(wèn)題.跨線程顯示View.該怎么顯示?不是在本應(yīng)用程序顯示View.這里就要借用RemoteView.
RemoteView理解成對(duì)一個(gè)View的封裝,然后把RemoteView提交給其他線程.其他線程接收到RemoteView并且解析里面View的信息把它顯示出來(lái).
5.1.3 在使用系統(tǒng)自帶的Notification系統(tǒng)會(huì)創(chuàng)建一個(gè)默認(rèn)的RemoteView!
系統(tǒng)默認(rèn)使用R.layout.notification_template_material_base生產(chǎn)一個(gè)RemoteView.
至于這里的布局是怎么查到的,請(qǐng)看下面源碼分析
5.2 查看源碼,了解Notification如何創(chuàng)建布局
5.2.1 首先看Notification中build代碼
5.2.2 然后看上圖中的createContentView()方法
5.2.3 然后看上圖中的createContentView()方法
6.關(guān)于Android8.0通知欄適配 6.1 Android O(8.0)通知的改變NotificationChannel是android8.0新增的特性,如果App的targetSDKVersion>=26,沒(méi)有設(shè)置channel通知渠道的話,就會(huì)導(dǎo)致通知無(wú)法展示。
Android O 引入了 通知渠道(Notification Channels),以提供統(tǒng)一的系統(tǒng)來(lái)幫助用戶管理通知,如果是針對(duì) android O 為目標(biāo)平臺(tái)時(shí),必須實(shí)現(xiàn)一個(gè)或者多個(gè)通知渠道,以向用戶顯示通知。比如聊天軟件,為每個(gè)聊天組設(shè)置一個(gè)通知渠道,指定特定聲音、燈光等配置。
6.2 報(bào)錯(cuò)內(nèi)容和解決方案報(bào)錯(cuò)內(nèi)容:Failed to post notification on channel “null” Target Api is 26
解決方案:
第一種:臨時(shí)方案,google也考慮到適配問(wèn)題,臨時(shí)兼容方案是targetSDKVersion低于26
第二種:創(chuàng)建channel
6.3 最終解決方案
6.3.1 創(chuàng)建NotificationChannel步驟
創(chuàng)建NotificationChannel對(duì)象,指定Channel的id、name和通知的重要程度
使用NotificationMannager的createNotificationChannel方法來(lái)添加Channel。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //android 8.0以上需要特殊處理,也就是targetSDKVersion為26以上 createNotificationChannel(); } @TargetApi(Build.VERSION_CODES.O) private void createNotificationChannel() { NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); channel.canBypassDnd();//是否繞過(guò)請(qǐng)勿打擾模式 channel.enableLights(true);//閃光燈 channel.setLockscreenVisibility(VISIBILITY_SECRET);//鎖屏顯示通知 channel.setLightColor(Color.RED);//閃關(guān)燈的燈光顏色 channel.canShowBadge();//桌面launcher的消息角標(biāo) channel.enableVibration(true);//是否允許震動(dòng) channel.getAudioAttributes();//獲取系統(tǒng)通知響鈴聲音的配置 channel.getGroup();//獲取通知取到組 channel.setBypassDnd(true);//設(shè)置可繞過(guò) 請(qǐng)勿打擾模式 channel.setVibrationPattern(new long[]{100, 100, 200});//設(shè)置震動(dòng)模式 channel.shouldShowLights();//是否會(huì)有燈光 getManager().createNotificationChannel(channel); }
設(shè)置通知重要性級(jí)別
該級(jí)別必須要在 NotificationChannel的構(gòu)造函數(shù)中指定,總共要五個(gè)級(jí)別;范圍是從NotificationManager.IMPORTANCE_NONE(0) ~ NotificationManager.IMPORTANCE_HIGH(4)
如果要支持 Android 7.1(API 25)及以下的設(shè)備,還得調(diào)用NotificationCompat 的 setPriority 方法來(lái)設(shè)置
6.3.2 用戶通知級(jí)別
Android 8.0 及以上是使用NotificationManager.IMPORTANCE_,
Android 7.1 及以下是使用NotificationCompat.PRIORITY_它們都是定義的常量
6.4 封裝的代碼
如下所示
public class NotificationUtils extends ContextWrapper { public static final String CHANNEL_ID = "default"; private static final String CHANNEL_NAME = "Default_Channel"; private NotificationManager mManager; private int[] flags; public NotificationUtils(Context base) { super(base); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //android 8.0以上需要特殊處理,也就是targetSDKVersion為26以上 createNotificationChannel(); } } @TargetApi(Build.VERSION_CODES.O) private void createNotificationChannel() { //第一個(gè)參數(shù):channel_id //第二個(gè)參數(shù):channel_name //第三個(gè)參數(shù):設(shè)置通知重要性級(jí)別 //注意:該級(jí)別必須要在 NotificationChannel 的構(gòu)造函數(shù)中指定,總共要五個(gè)級(jí)別; //范圍是從 NotificationManager.IMPORTANCE_NONE(0) ~ NotificationManager.IMPORTANCE_HIGH(4) NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); channel.canBypassDnd();//是否繞過(guò)請(qǐng)勿打擾模式 channel.enableLights(true);//閃光燈 channel.setLockscreenVisibility(VISIBILITY_SECRET);//鎖屏顯示通知 channel.setLightColor(Color.RED);//閃關(guān)燈的燈光顏色 channel.canShowBadge();//桌面launcher的消息角標(biāo) channel.enableVibration(true);//是否允許震動(dòng) channel.getAudioAttributes();//獲取系統(tǒng)通知響鈴聲音的配置 channel.getGroup();//獲取通知取到組 channel.setBypassDnd(true);//設(shè)置可繞過(guò) 請(qǐng)勿打擾模式 channel.setVibrationPattern(new long[]{100, 100, 200});//設(shè)置震動(dòng)模式 channel.shouldShowLights();//是否會(huì)有燈光 getManager().createNotificationChannel(channel); } /** * 獲取創(chuàng)建一個(gè)NotificationManager的對(duì)象
*/ public NotificationManager getManager() { if (mManager == null) { mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); } return mManager; } /** * 清空所有的通知 */ public void clearNotification(){ getManager().cancelAll(); } /** * 建議使用這個(gè)發(fā)送通知 * 調(diào)用該方法可以發(fā)送通知 * @param notifyId notifyId * @param title title * @param content content */ public void sendNotification(int notifyId, String title, String content , int icon) { Notification build; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //android 8.0以上需要特殊處理,也就是targetSDKVersion為26以上 //通知用到NotificationCompat()這個(gè)V4庫(kù)中的方法。但是在實(shí)際使用時(shí)發(fā)現(xiàn)書(shū)上的代碼已經(jīng)過(guò)時(shí)并且Android8.0已經(jīng)不支持這種寫(xiě)法 Notification.Builder builder = getChannelNotification(title, content, icon); build = builder.build(); } else { NotificationCompat.Builder builder = getNotificationCompat(title, content, icon); build = builder.build(); } if (flags!=null && flags.length>0){ for (int a=0 ; a項(xiàng)目地址鏈接:https://github.com/yangchong2... 關(guān)于其他內(nèi)容介紹 01.關(guān)于博客匯總鏈接0){ for (int a=0 ; a = Build.VERSION_CODES.O) { builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID); } else { //注意用下面這個(gè)方法,在8.0以上無(wú)法出現(xiàn)通知欄。8.0之前是正常的。這里需要增強(qiáng)判斷邏輯 builder = new NotificationCompat.Builder(getApplicationContext()); builder.setPriority(PRIORITY_DEFAULT); } builder.setContentTitle(title); builder.setContentText(content); builder.setSmallIcon(icon); builder.setPriority(priority); builder.setOnlyAlertOnce(onlyAlertOnce); builder.setOngoing(ongoing); if (remoteViews!=null){ builder.setContent(remoteViews); } if (intent!=null){ builder.setContentIntent(intent); } if (ticker!=null && ticker.length()>0){ builder.setTicker(ticker); } if (when!=0){ builder.setWhen(when); } if (sound!=null){ builder.setSound(sound); } if (defaults!=0){ builder.setDefaults(defaults); } //點(diǎn)擊自動(dòng)刪除通知 builder.setAutoCancel(true); return builder; } @RequiresApi(api = Build.VERSION_CODES.O) private Notification.Builder getChannelNotification(String title, String content, int icon){ Notification.Builder builder = new Notification.Builder(getApplicationContext(), CHANNEL_ID); Notification.Builder notificationBuilder = builder //設(shè)置標(biāo)題 .setContentTitle(title) //消息內(nèi)容 .setContentText(content) //設(shè)置通知的圖標(biāo) .setSmallIcon(icon) //讓通知左右滑的時(shí)候是否可以取消通知 .setOngoing(ongoing) //設(shè)置優(yōu)先級(jí) .setPriority(priority) //是否提示一次.true - 如果Notification已經(jīng)存在狀態(tài)欄即使在調(diào)用notify函數(shù)也不會(huì)更新 .setOnlyAlertOnce(onlyAlertOnce) .setAutoCancel(true); if (remoteViews!=null){ //設(shè)置自定義view通知欄 notificationBuilder.setContent(remoteViews); } if (intent!=null){ notificationBuilder.setContentIntent(intent); } if (ticker!=null && ticker.length()>0){ //設(shè)置狀態(tài)欄的標(biāo)題 notificationBuilder.setTicker(ticker); } if (when!=0){ //設(shè)置通知時(shí)間,默認(rèn)為系統(tǒng)發(fā)出通知的時(shí)間,通常不用設(shè)置 notificationBuilder.setWhen(when); } if (sound!=null){ //設(shè)置sound notificationBuilder.setSound(sound); } if (defaults!=0){ //設(shè)置默認(rèn)的提示音 notificationBuilder.setDefaults(defaults); } if (pattern!=null){ //自定義震動(dòng)效果 notificationBuilder.setVibrate(pattern); } return notificationBuilder; } private boolean ongoing = false; private RemoteViews remoteViews = null; private PendingIntent intent = null; private String ticker = ""; private int priority = Notification.PRIORITY_DEFAULT; private boolean onlyAlertOnce = false; private long when = 0; private Uri sound = null; private int defaults = 0; private long[] pattern = null; /** * 讓通知左右滑的時(shí)候是否可以取消通知 * @param ongoing 是否可以取消通知 * @return */ public NotificationUtils setOngoing(boolean ongoing){ this.ongoing = ongoing; return this; } /** * 設(shè)置自定義view通知欄布局 * @param remoteViews view * @return */ public NotificationUtils setContent(RemoteViews remoteViews){ this.remoteViews = remoteViews; return this; } /** * 設(shè)置內(nèi)容點(diǎn)擊 * @param intent intent * @return */ public NotificationUtils setContentIntent(PendingIntent intent){ this.intent = intent; return this; } /** * 設(shè)置狀態(tài)欄的標(biāo)題 * @param ticker 狀態(tài)欄的標(biāo)題 * @return */ public NotificationUtils setTicker(String ticker){ this.ticker = ticker; return this; } /** * 設(shè)置優(yōu)先級(jí) * 注意: * Android 8.0以及上,在 NotificationChannel 的構(gòu)造函數(shù)中指定,總共要五個(gè)級(jí)別; * Android 7.1(API 25)及以下的設(shè)備,還得調(diào)用NotificationCompat 的 setPriority方法來(lái)設(shè)置 * * @param priority 優(yōu)先級(jí),默認(rèn)是Notification.PRIORITY_DEFAULT * @return */ public NotificationUtils setPriority(int priority){ this.priority = priority; return this; } /** * 是否提示一次.true - 如果Notification已經(jīng)存在狀態(tài)欄即使在調(diào)用notify函數(shù)也不會(huì)更新 * @param onlyAlertOnce 是否只提示一次,默認(rèn)是false * @return */ public NotificationUtils setOnlyAlertOnce(boolean onlyAlertOnce){ this.onlyAlertOnce = onlyAlertOnce; return this; } /** * 設(shè)置通知時(shí)間,默認(rèn)為系統(tǒng)發(fā)出通知的時(shí)間,通常不用設(shè)置 * @param when when * @return */ public NotificationUtils setWhen(long when){ this.when = when; return this; } /** * 設(shè)置sound * @param sound sound * @return */ public NotificationUtils setSound(Uri sound){ this.sound = sound; return this; } /** * 設(shè)置默認(rèn)的提示音 * @param defaults defaults * @return */ public NotificationUtils setDefaults(int defaults){ this.defaults = defaults; return this; } /** * 自定義震動(dòng)效果 * @param pattern pattern * @return */ public NotificationUtils setVibrate(long[] pattern){ this.pattern = pattern; return this; } /** * 設(shè)置flag標(biāo)簽 * @param flags flags * @return */ public NotificationUtils setFlags(int... flags){ this.flags = flags; return this; } } ```
1.技術(shù)博客匯總
2.開(kāi)源項(xiàng)目匯總
3.生活博客匯總
4.喜馬拉雅音頻匯總
5.其他匯總
02.關(guān)于我的博客我的個(gè)人站點(diǎn):www.yczbj.org,www.ycbjie.cn
github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
簡(jiǎn)書(shū):http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜馬拉雅聽(tīng)書(shū):http://www.ximalaya.com/zhubo...
開(kāi)源中國(guó):https://my.oschina.net/zbj161...
泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...
郵箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault頭條:https://segmentfault.com/u/xi...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/72307.html
摘要:是新增的,用于向用戶配置和顯示桌面通知。通知不自動(dòng)關(guān)閉,默認(rèn)為自動(dòng)關(guān)閉。在瀏覽器下,沒(méi)有關(guān)閉請(qǐng)求權(quán)限的選項(xiàng),用戶必須選擇同意拒絕。 showImg(https://segmentfault.com/img/remote/1460000018227718); Notification是HTML5新增的API,用于向用戶配置和顯示桌面通知。上次在別的網(wǎng)站上看到別人的通知彈窗,好奇之余也想知...
摘要:簡(jiǎn)介通知在用戶界面的一個(gè)重要部分,其使用方法請(qǐng)看以下內(nèi)容繼承關(guān)系如下簡(jiǎn)介通知是應(yīng)用向用戶顯示的消息提示,當(dāng)發(fā)送通知時(shí),通知將先以圖標(biāo)的形式顯示在通知區(qū)域中。通知區(qū)域和下拉通知欄均是由系統(tǒng)控制的區(qū)域,用戶可以隨時(shí)查看。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 極力推薦文章:歡迎收藏...
摘要:據(jù)猜測(cè)是為瀏覽器翻譯服務(wù)。通知內(nèi)容,顯示在通知標(biāo)題之下,默認(rèn)為空字符串標(biāo)記通知的類型,打上標(biāo)簽,默認(rèn)為空字符串。在最新的技術(shù)評(píng)審稿中,該參數(shù)被舍棄設(shè)置該標(biāo)志表示最終用戶將不能很容易地清除。設(shè)置該標(biāo)志,通知將為永久型通知。 Web Notification 網(wǎng)頁(yè)通知API。這是2011年由谷歌技術(shù)員John Gregg提出的一項(xiàng)網(wǎng)頁(yè)通知api。 定義 請(qǐng)讀者直接參考whatwg工作組對(duì)...
閱讀 2101·2021-11-15 17:58
閱讀 2228·2021-10-19 11:45
閱讀 3739·2021-09-02 15:40
閱讀 2690·2021-07-25 10:50
閱讀 3868·2019-08-30 15:56
閱讀 3248·2019-08-30 12:44
閱讀 1113·2019-08-26 13:38
閱讀 1951·2019-08-23 18:29