Android 通知总结

Android系統的狀態列(Status Bar)上,允許讓Android App顯示一些訊息在上面,這樣的功能就是通知(Notifications),而顯示通知的欄位稱為通知欄(Notification Drawer)。Android系統的狀態列顯示與否是由系統控制的,也就是說,即便使用者現在正在使用一個App,也還是有機會可以看得到別的App發出來的通知訊息。通知是開發Android App很重要的一環,尤其是在Android 5.0之後更為重要。因此學好通知功能是很重要的。

要開發擁有通知功能的Android,建議將Android API版本的下限提升到16(Android 4.1)以上,功能才會比較完善,不然就只能用Version 4 Support Library來擴充了。筆者不太喜歡用Support Library,因此這篇文章將會使用Android API 16來做說明。就算將Android API版本下限設為16,也還是有八成的裝置可以使用,不必太過擔心,而且還可以杜絕掉不穩定的舊版本讓程式閃退的情況(誤)

最簡單的通知

先從最簡單的通知開始講起吧!在Android SDK中,若要發出訊息到通知欄中,需要仰賴系統的通知服務(Notification Service),才可以將通知(Notification)發送(notify)出去。一個通知,就是一個Notification物件,可以使用Notification.Builder來快速產生出來,通知的小圖示(Small Icon)、內容標題(Content Title)和、內容文字(ContentText)是一定要去設定的,不然通知可能會顯示不出來。最簡單的通知可以寫成以下程式:

final int notifyID = 1; // 通知的識別號碼final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.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,用法如下:

final int notifyID = 1; // 通知的識別號碼final int requestCode = notifyID; // PendingIntent的Request Codefinal Intent intent = getIntent(); // 目前Activity的Intentfinal int flags = PendingIntent.FLAG_CANCEL_CURRENT; // ONE_SHOT:PendingIntent只使用一次;CANCEL_CURRENT:PendingIntent執行前會先結束掉之前的;NO_CREATE:沿用先前的PendingIntent,不建立新的PendingIntent;UPDATE_CURRENT:更新先前PendingIntent所帶的額外資料,並繼續沿用final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), requestCode, intent, flags); // 取得PendingIntentfinal NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setContentIntent(pendingIntent).build(); // 建立通知
notificationManager.notify(notifyID, notification); // 發送通知

以上程式,可以讓App的Activity在關閉的狀態下,藉由點擊通知來重新開啟同樣的Activity。但如果開啟的Activity並不是這個App的Main Activity(action: android.intent.action.MAIN),此時若直接按下返回鍵關掉Activity後,並不會退回App的Main Activity。如果要讓開啟的Activity可以退回到Main Activity,可以使用TaskStackBuilder來產生PendingIntent,寫法如下:

final int notifyID = 1; // 通知的識別號碼final int requestCode = notifyID; // PendingIntent的Request Codefinal Intent intent = new Intent(getApplicationContext(), AnotherActivity.class); // 開啟另一個Activity的Intentfinal int flags = PendingIntent.FLAG_UPDATE_CURRENT; // ONE_SHOT:PendingIntent只使用一次;CANCEL_CURRENT:PendingIntent執行前會先結束掉之前的;NO_CREATE:沿用先前的PendingIntent,不建立新的PendingIntent;UPDATE_CURRENT:更新先前PendingIntent所帶的額外資料,並繼續沿用final TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext()); // 建立TaskStackBuilder
stackBuilder.addParentStack(AnotherActivity.class); // 加入目前要啟動的Activity,這個方法會將這個Activity的所有上層的Activity(Parents)都加到堆疊中
stackBuilder.addNextIntent(intent); // 加入啟動Activity的Intentfinal PendingIntent pendingIntent = stackBuilder.getPendingIntent(requestCode, flags); // 取得PendingIntentfinal NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.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可以這樣寫:

<activity    android:name=".AActivity"    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
 
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter></activity><activity    android:name=".BActivity"    android:label="@string/app_name"    android:parentActivityName=".AActivity" ></activity><activity    android:name=".CActivity"    android:label="@string/app_name"    android:parentActivityName=".BActivity" ></activity>

如此一來,點擊通知之後,會直接開啟CActivity。在CActivity按下返回鍵之後,會退回BActivity。在BActivity按下返回建之後,會退回AActivity。

一次性的通知

如果使用者要將通知從通知欄中刪除,可以直接將通知用手指左右滑離,或是使用通知欄的清除所有通知的功能。如果想讓通知在被點擊之後自動消失,可以用Notification.Builder的setAutoCancel方法來設定,最好配合setContentIntent方法一起使用,否則可能無法將通知移除。寫法如下:

final int notifyID = 1; // 通知的識別號碼final boolean autoCancel = true; // 點擊通知後是否要自動移除掉通知
 
final int requestCode = notifyID; // PendingIntent的Request Codefinal Intent intent = getIntent(); // 目前Activity的Intentfinal int flags = PendingIntent.FLAG_CANCEL_CURRENT; // ONE_SHOT:PendingIntent只使用一次;CANCEL_CURRENT:PendingIntent執行前會先結束掉之前的;NO_CREATE:沿用先前的PendingIntent,不建立新的PendingIntent;UPDATE_CURRENT:更新先前PendingIntent所帶的額外資料,並繼續沿用final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), requestCode, intent, flags); // 取得PendingIntent
 
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setContentIntent(pendingIntent).setAutoCancel(autoCancel).build(); // 建立通知
notificationManager.notify(notifyID, notification); // 發送通知

通知的音效

Android允許App在發送通知的時候同時播放音效出來,至於要播放什麼音效則可以用Notification.Builder的setSound方法來設定,用法如下:

final int notifyID = 1; // 通知的識別號碼final Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); // 通知音效的URI,在這裡使用系統內建的通知音效final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setSound(soundUri).build(); // 建立通知
notificationManager.notify(notifyID, notification); // 發送通知

以上程式,直接使用了RingtoneManager來取得Android系統所設置的通知音效的URI,因此會播放出系統設定的通知音效。系統的通知音效可以到系統設定的「音效」設定裡面更改。

Android 如何顯示通知訊息(Notifications)?

擁有進度條的通知

Android的通知可以顯示進度條,可以使用Notification.Builder的setProgress方法來指定,用法如下:

final int notifyID = 1; // 通知的識別號碼
 
final int progressMax = 0; // 進度條的最大值,通常都是設為100。若是設為0,且indeterminate為false的話,表示不使用進度條final int progress = 50; // 進度值final boolean indeterminate = true; // 是否為不確定的進度,如果不確定的話,進度條將不會明確顯示目前的進度。若是設為false,且progressMax為0的話,表示不使用進度條
 
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setProgress(progressMax, progress, indeterminate).build(); // 建立通知
notificationManager.notify(notifyID, notification); // 發送通知

Android 如何顯示通知訊息(Notifications)?

Android 如何顯示通知訊息(Notifications)?

通知的樣式

Notification.Builder提供setStyle方法來設定通知的樣式(Notification.Style)。Android內建數種的通知樣式,以下將分別介紹。

InboxStyle

InboxStyle為一個內容較多的通知,它可以加入一行一行的字串(addLine),以類似清單(List)的方式將字串顯示不出來。當然還是建議不要加入太多的字串到InboxStyle內,太長的話還是會被Android系統省略掉的。

要使用InboxStyle的話,程式可以這樣寫:

final int notifyID = 1; // 通知的識別號碼
 
final Notification.InboxStyle inboxStyle = new Notification.InboxStyle(); // 建立InboxStylefinal String[] lines = new String[] { "magiclen.org 發了一篇新文章", "今天天氣是晴天" }; // InboxStyle要顯示的字串內容
inboxStyle.setBigContentTitle("新訊息:"); // 當InboxStyle顯示時,用InboxStyle的setBigContentTitle覆蓋setContentTitle的設定
inboxStyle.setSummaryText("更多新訊息(3+)"); // InboxStyle的底部訊息for (int i = 0; i < lines.length; i++) {
        inboxStyle.addLine(String.format("%d: %s", i + 1, lines[i])); // 將字串加入InboxStyle}
 
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setStyle(inboxStyle).build(); // 建立通知
notificationManager.notify(notifyID, notification); // 發送通知

通知結果:

Android 如何顯示通知訊息(Notifications)?

BigPictureStyle

BigPictureStyle可以在通知上顯示一張尺寸不小的圖片。

要使用BigPictureStyle的話,程式可以這樣寫:

final int notifyID = 1; // 通知的識別號碼
 
final Notification.BigPictureStyle bigPictureStyle = new Notification.BigPictureStyle(); // 建立BigPictureStyle
bigPictureStyle.setBigContentTitle("magiclen.org 上傳了新照片"); // 當BigPictureStyle顯示時,用BigPictureStyle的setBigContentTitle覆蓋setContentTitle的設定final Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.p)).getBitmap(); // 要顯示在通知上的大圖片
bigPictureStyle.bigPicture(bitmap); // 設定BigPictureStyle的大圖片
 
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setStyle(bigPictureStyle).build(); // 建立通知
notificationManager.notify(notifyID, notification); // 發送通知

通知結果:

Android 如何顯示通知訊息(Notifications)?

BigTextStyle

BigTextStyle可以在通知上顯示較多的文字內容。

要使用BigTextStyle的話,程式可以這樣寫:

final int notifyID = 1; // 通知的識別號碼
 
final Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle(); // 建立BigTextStyle
bigTextStyle.setBigContentTitle("雲海茫茫(中卷)"); // 當BigTextStyle顯示時,用BigTextStyle的setBigContentTitle覆蓋setContentTitle的設定
bigTextStyle.bigText("獨隱空幽谷,瞻依峻巉巖。\n先行昇闊步,後繼落遷延。\n南北觀青草,西東見玉蘚。\n始終無三秀,何必伴此焉?"); // 設定BigTextStyle的文字內容
 
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").setStyle(bigTextStyle).build(); // 建立通知
notificationManager.notify(notifyID, notification); // 發送通知

通知結果:

Android 如何顯示通知訊息(Notifications)?

都已經設定Style了,還需要setContentTitle和setContentText嗎?

要的,當Style並未被Android展開(Expend)時(通常只有最上方的通知會被展開),就會使用最原始的樣式,因此還是需要setContentTitle和setContentText。

在通知上加入按鈕

透過Notification.Builder的addAction方法,可以替通知加入按鈕,傳入按鈕圖示、文字,以及被點擊時所使用的PendingIntent。如以下程式,在通知添加兩個按鈕,分別用來啟動App和刪除通知。

final int notifyID = 1; // 通知的識別號碼
 
final Intent intent = getIntent(); // 目前Activity的Intentint flags = PendingIntent.FLAG_CANCEL_CURRENT; // ONE_SHOT:PendingIntent只使用一次;CANCEL_CURRENT:PendingIntent執行前會先結束掉之前的;NO_CREATE:沿用先前的PendingIntent,不建立新的PendingIntent;UPDATE_CURRENT:更新先前PendingIntent所帶的額外資料,並繼續沿用final PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, flags); // 取得PendingIntent
 
final Intent cancelIntent = new Intent(getApplicationContext(), CancelNotificationReceiver.class); // 取消通知的的Intent
cancelIntent.putExtra("cancel_notify_id", notifyID); // 傳入通知的識別號碼
flags = PendingIntent.FLAG_ONE_SHOT; // ONE_SHOT:PendingIntent只使用一次;CANCEL_CURRENT:PendingIntent執行前會先結束掉之前的;NO_CREATE:沿用先前的PendingIntent,不建立新的PendingIntent;UPDATE_CURRENT:更新先前PendingIntent所帶的額外資料,並繼續沿用final PendingIntent pendingCancelIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, cancelIntent, flags); // 取得PendingIntent
 
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.Builder(getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("內容標題").setContentText("內容文字").addAction(R.drawable.ic_launcher, "開啟App", pendingIntent).addAction(android.R.drawable.ic_menu_close_clear_cancel, "關閉通知", pendingCancelIntent).build(); // 建立通知
notificationManager.notify(notifyID, notification); // 發送通知

CancelNotificationReceiver的程式如下:

import android.app.NotificationManager;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;
 
public class CancelNotificationReceiver extends BroadcastReceiver {
 
        @Override
        public void onReceive(final Context context, final Intent intent) {
                final int notifyID = intent.getIntExtra("cancel_notify_id", 0);
                final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務
                notificationManager.cancel(notifyID);
        }
 
}

AndroidManifest.xml的application中宣告Receiver:

<receiver android:name=".CancelNotificationReceiver" />

通知結果:

Android 如何顯示通知訊息(Notifications)?

通知的優先權與持續性的通知

在某些情況下可能會需要建立出持續性的通知,使通知常駐在通知欄中而不會被使用者清除。而且還可能需要讓通知不會被其他通知給擠出通知欄,儘量讓通知保持在通知欄的最上層。這時可以使用Notification.Builder的setPriority方法和Notification的flags來創建出優先權較高的通知。程式如下:

final int notifyID = 1; // 通知的識別號碼
 
final int priority = Notification.PRIORITY_MAX; // 通知的優先權,可用PRIORITY_MAX、PRIORITY_HIGHT、PRIORITY_LOW、PRIORITY_MIN、PRIORITY_DEFAULT
 
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 取得系統的通知服務final Notification notification = new Notification.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。若一直讓通知留在通知欄中,恐怕會引起使用者的反感。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值