Android 如何顯示通知訊息(Notifications)? - MagicLen
文章推薦指數: 80 %
通知是開發Android App很重要的一環,尤其是在Android 5.0之後更為重要。
... 要的,當Style並未被Android展開(Expend)時(通常只有最上方的通知會被 ...
MagicLen
內容
Android如何顯示通知訊息(Notifications)?
2014年10月24日
MagicLen
研究分享、Android
編輯
本篇文章更新於
2018年6月21日5時
Android系統的狀態列(StatusBar)上,允許讓AndroidApp顯示一些訊息在上面,這樣的功能就是通知(Notifications),而顯示通知的欄位稱為通知欄(NotificationDrawer)。
Android系統的狀態列顯示與否是由系統控制的,也就是說,即便使用者現在正在使用一個App,也還是有機會可以看得到別的App發出來的通知訊息。
通知是開發AndroidApp很重要的一環,尤其是在Android5.0之後更為重要。
因此學好通知功能是很重要的。
要開發擁有通知功能的Android,建議將AndroidAPI版本的下限提升到16(Android4.1)以上,功能才會比較完善,不然就只能用Version4SupportLibrary來擴充了。
筆者不太喜歡用SupportLibrary,因此這篇文章將會使用AndroidAPI16來做說明。
就算將AndroidAPI版本下限設為16,也還是有八成的裝置可以使用,不必太過擔心,而且還可以杜絕掉不穩定的舊版本讓程式閃退的情況(誤)。
Android8.0以上的通知用法有變,本篇文章日後會進行更新。
最簡單的通知
先從最簡單的通知開始講起吧!在AndroidSDK中,若要發出訊息到通知欄中,需要仰賴系統的通知服務(NotificationService),才可以將通知(Notification)發送(notify)出去。
一個通知,就是一個Notification物件,可以使用Notification.Builder來快速產生出來,通知的小圖示(SmallIcon)、內容標題(ContentTitle)和、內容文字(ContentText)是一定要去設定的,不然通知可能會顯示不出來。
最簡單的通知可以寫成以下程式:
finalintnotifyID=1;//通知的識別號碼
finalNotificationManagernotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);//取得系統的通知服務
finalNotificationnotification=newNotification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").build();//建立通知
notificationManager.notify(notifyID,notification);//發送通知
其中,notifyID是通知的識別號碼,只會用在同一個App內,所以不必擔心會和其他App重疊。
一個notifyID,代表著一個通知欄的欄位,也就是說,如果想要覆蓋掉先前的通知,只要使用跟先前通知一樣的notifyID來發送通知即可。
反之,如果notifyID和先前通知不同,就會再多出一個通知欄位來顯示通知訊息。
如果要刪除通知,可以透過NotificationManager的cancel方法來刪除指定notifyID的通知。
除了setContentTitle和setContentText是必須的設定外,另外還有setContentInfo方法可以將文字顯示在通知右方的最後一行,雖然這不是必要設定,但它是很常用的功能,也可以把它當作是必要選項。
自訂通知被點擊後的動作
當通知出現在通知欄之後,在習慣的趨使下,有很大的機率會被使用者點擊。
所以應該要實作出通知被點擊後的動作,好比開啟哪個Activity之類的。
通知被點擊後的動作可以使用PendingIntent來實作,PendingIntent並不是一個Intent,它是一個Intent的容器,可以傳入context物件,並以這個context的身份來做一些事情,例如開啟Activity、開啟Service,或是發送Broadcast。
如果要使通知可以在被點擊之後做點什麼事,可以使用Notification.Builder的setContentIntent方法來替通知加入PendingIntent,用法如下:
finalintnotifyID=1;//通知的識別號碼
finalintrequestCode=notifyID;//PendingIntent的RequestCode
finalIntentintent=getIntent();//目前Activity的Intent
finalintflags=PendingIntent.FLAG_CANCEL_CURRENT;//ONE_SHOT:PendingIntent只使用一次;CANCEL_CURRENT:PendingIntent執行前會先結束掉之前的;NO_CREATE:沿用先前的PendingIntent,不建立新的PendingIntent;UPDATE_CURRENT:更新先前PendingIntent所帶的額外資料,並繼續沿用
finalPendingIntentpendingIntent=PendingIntent.getActivity(getApplicationContext(),requestCode,intent,flags);//取得PendingIntent
finalNotificationManagernotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);//取得系統的通知服務
finalNotificationnotification=newNotification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setContentIntent(pendingIntent).build();//建立通知
notificationManager.notify(notifyID,notification);//發送通知
以上程式,可以讓App的Activity在關閉的狀態下,藉由點擊通知來重新開啟同樣的Activity。
但如果開啟的Activity並不是這個App的MainActivity(action:android.intent.action.MAIN),此時若直接按下返回鍵關掉Activity後,並不會退回App的MainActivity。
如果要讓開啟的Activity可以退回到MainActivity,可以使用TaskStackBuilder來產生PendingIntent,寫法如下:
finalintnotifyID=1;//通知的識別號碼
finalintrequestCode=notifyID;//PendingIntent的RequestCode
finalIntentintent=newIntent(getApplicationContext(),AnotherActivity.class);//開啟另一個Activity的Intent
finalintflags=PendingIntent.FLAG_UPDATE_CURRENT;//ONE_SHOT:PendingIntent只使用一次;CANCEL_CURRENT:PendingIntent執行前會先結束掉之前的;NO_CREATE:沿用先前的PendingIntent,不建立新的PendingIntent;UPDATE_CURRENT:更新先前PendingIntent所帶的額外資料,並繼續沿用
finalTaskStackBuilderstackBuilder=TaskStackBuilder.create(getApplicationContext());//建立TaskStackBuilder
stackBuilder.addParentStack(AnotherActivity.class);//加入目前要啟動的Activity,這個方法會將這個Activity的所有上層的Activity(Parents)都加到堆疊中
stackBuilder.addNextIntent(intent);//加入啟動Activity的Intent
finalPendingIntentpendingIntent=stackBuilder.getPendingIntent(requestCode,flags);//取得PendingIntent
finalNotificationManagernotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);//取得系統的通知服務
finalNotificationnotification=newNotification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setContentIntent(pendingIntent).build();//建立通知
notificationManager.notify(notifyID,notification);//發送通知
Activity的Parent是什麼?這樣說好了,假設有個Activity叫做C,是由另一個叫B的Activity來開啟(startActivity)的;而這個叫作B的Activity,也是由另一個叫A的Activity來開啟的。
A這個Activity是B的Parent,B這個Activity是C的Parent,所以C的Parents為A和B。
那麼TaskStackBuilder要如何知道一個Activity的Parents有哪些?那就要從AndroidManifest.xml這個檔案來對activity設定parentActivityName啦!沿用上述A、B、C三個Activity的例子,AndroidManifest.xml可以這樣寫:
在CActivity按下返回鍵之後,會退回BActivity。
在BActivity按下返回建之後,會退回AActivity。
一次性的通知
如果使用者要將通知從通知欄中刪除,可以直接將通知用手指左右滑離,或是使用通知欄的清除所有通知的功能。
如果想讓通知在被點擊之後自動消失,可以用Notification.Builder的setAutoCancel方法來設定,最好配合setContentIntent方法一起使用,否則可能無法將通知移除。
寫法如下:
finalintnotifyID=1;//通知的識別號碼
finalbooleanautoCancel=true;//點擊通知後是否要自動移除掉通知
finalintrequestCode=notifyID;//PendingIntent的RequestCode
finalIntentintent=getIntent();//目前Activity的Intent
finalintflags=PendingIntent.FLAG_CANCEL_CURRENT;//ONE_SHOT:PendingIntent只使用一次;CANCEL_CURRENT:PendingIntent執行前會先結束掉之前的;NO_CREATE:沿用先前的PendingIntent,不建立新的PendingIntent;UPDATE_CURRENT:更新先前PendingIntent所帶的額外資料,並繼續沿用
finalPendingIntentpendingIntent=PendingIntent.getActivity(getApplicationContext(),requestCode,intent,flags);//取得PendingIntent
finalNotificationManagernotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);//取得系統的通知服務
finalNotificationnotification=newNotification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setContentIntent(pendingIntent).setAutoCancel(autoCancel).build();//建立通知
notificationManager.notify(notifyID,notification);//發送通知
通知的音效
Android允許App在發送通知的時候同時播放音效出來,至於要播放什麼音效則可以用Notification.Builder的setSound方法來設定,用法如下:
finalintnotifyID=1;//通知的識別號碼
finalUrisoundUri=RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);//通知音效的URI,在這裡使用系統內建的通知音效
finalNotificationManagernotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);//取得系統的通知服務
finalNotificationnotification=newNotification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setSound(soundUri).build();//建立通知
notificationManager.notify(notifyID,notification);//發送通知
以上程式,直接使用了RingtoneManager來取得Android系統所設置的通知音效的URI,因此會播放出系統設定的通知音效。
系統的通知音效可以到系統設定的「音效」設定裡面更改。
擁有進度條的通知
Android的通知可以顯示進度條,可以使用Notification.Builder的setProgress方法來指定,用法如下:
finalintnotifyID=1;//通知的識別號碼
finalintprogressMax=0;//進度條的最大值,通常都是設為100。
若是設為0,且indeterminate為false的話,表示不使用進度條
finalintprogress=50;//進度值
finalbooleanindeterminate=true;//是否為不確定的進度,如果不確定的話,進度條將不會明確顯示目前的進度。
若是設為false,且progressMax為0的話,表示不使用進度條
finalNotificationManagernotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);//取得系統的通知服務
finalNotificationnotification=newNotification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setProgress(progressMax,progress,indeterminate).build();//建立通知
notificationManager.notify(notifyID,notification);//發送通知
通知的樣式
Notification.Builder提供setStyle方法來設定通知的樣式(Notification.Style)。
Android內建數種的通知樣式,以下將分別介紹。
InboxStyle
InboxStyle為一個內容較多的通知,它可以加入一行一行的字串(addLine),以類似清單(List)的方式將字串顯示不出來。
當然還是建議不要加入太多的字串到InboxStyle內,太長的話還是會被Android系統省略掉的。
要使用InboxStyle的話,程式可以這樣寫:
finalintnotifyID=1;//通知的識別號碼
finalNotification.InboxStyleinboxStyle=newNotification.InboxStyle();//建立InboxStyle
finalString[]lines=newString[]{"magiclen.org發了一篇新文章","今天天氣是晴天"};//InboxStyle要顯示的字串內容
inboxStyle.setBigContentTitle("新訊息:");//當InboxStyle顯示時,用InboxStyle的setBigContentTitle覆蓋setContentTitle的設定
inboxStyle.setSummaryText("更多新訊息(3+)");//InboxStyle的底部訊息
for(inti=0;i
而且還可能需要讓通知不會被其他通知給擠出通知欄,儘量讓通知保持在通知欄的最上層。
這時可以使用Notification.Builder的setPriority方法和Notification的flags來創建出優先權較高的通知。
程式如下:
finalintnotifyID=1;//通知的識別號碼
finalintpriority=Notification.PRIORITY_MAX;//通知的優先權,可用PRIORITY_MAX、PRIORITY_HIGHT、PRIORITY_LOW、PRIORITY_MIN、PRIORITY_DEFAULT
finalNotificationManagernotificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);//取得系統的通知服務
finalNotificationnotification=newNotification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setPriority(priority).build();//建立通知
notification.flags|=Notification.FLAG_ONGOING_EVENT;//將ongoing(持續)的flag添加到通知中
notificationManager.notify(notifyID,notification);//發送通知
使用這類優先權較高且為持續型的通知,建議提供一些將通知刪除的方式,例如使用AutoCancel或是PendingIntent。
若一直讓通知留在通知欄中,恐怕會引起使用者的反感。
Android、AndroidNotifications、Android通知
關於作者
MagicLen
各位好,我是MagicLen,是這網站的管理員。
我是台灣台中大肚山上人,畢業於台中高工資訊科和台灣科技大學資訊工程系,曾在桃機航警局服役。
我熱愛自然也熱愛科學,喜歡和別人分享自己的知識與經驗。
如果你有興趣認識我,可以加我的Facebook(點我),並且請註明是從MagicLen來的。
載入中……
隨機文章
MuseScore免費開源且跨平台的製譜軟體
2019年6月17日
【回顧文】哈啦客嘗鮮食記之首都品饌198吃到飽
2015年11月27日
Intel760P1TBM.2PCI-E固態硬碟開箱
2020年2月27日
如何用程式進行質因數分解和尋找最大公因數與最小公倍數?
2020年7月9日
Rust效能分析:串接字串時,若要串接的字串還沒產生出來,push_str和write_fmt方法哪個快?
2018年12月19日
免費訂閱本站電子報
交換連結
低調一點
Spaceack'sBlog
電腦綠生活PCGreenLife
坂本Sakamoto.blog-探究科技未知領域
Mayday麥帶先生
iZO手札
港澳資訊
程式的奇技淫巧之道
冠均網頁設計公司
半熟態度-歐美加
Bon部落網
哈啦客談天說地
迴旋人生
Liumang碎碎念
英文練習網
申請交換連結
申請交換連結
×
延伸文章資訊
- 1Android10.0通知Notification的使用这一篇就够了 - CSDN博客
不同android版本上通知功能; 通知的结构; 创建通知; 通知的操作; 从通知启动Activity; 展开式通知; 通知渠道; 通知的级别; 自定义通知.
- 2控管Android 裝置上的通知
您可以依據自己想接收的通知類型,針對手機上的個別或所有應用程式變更相關設定。如要查看通知, ... 瞭解如何查看Android 版本。 ... 回覆、封存、展開及執行其他動作.
- 3Android Koltin 實作Day 15:Notification ... - iT 邦幫忙
從API 26 開始,Android 多了通知頻道(Notification channels)的功能, ... 彈出提醒、音效及震動),不顯示在狀態欄,僅顯示在展開的通知欄中。
- 4Android通知Notification使用全解析,看这篇就够了
通知是Android 在您的应用UI 之外显示的消息,用于向用户提供提醒、来自 ... 用户可以向下拖动抽屉中的通知以显示展开的视图,该视图显示其他内容和 ...
- 5创建展开式通知| Android 开发者
基本通知通常包括标题、一行文本,以及用户可以执行的一项或多项响应操作。如需提供更多信息,您还可以应用本页介绍的多个通知模板之一来创建大型展开 ...