最近在研究Android,遇到了一些Notification(通知)的問題:
1、Notification如何傳遞參數
2、Notification如何區別化
3、從Intent(意圖)尋找Activity(活動)說起,Android的Activity棧。
===============================================================
先從發送通知開始。
首先,在發送一個Notification前,我們需要准備好一個NotificationManager
獲得途徑:
NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
this為Application或者Activity。
然后,定義好我們的Notification:
1、定義一個Notification具備的三個基本參數icon,title,以及when
int icon=R.drawable.teller_call_1; long when = System.currentTimeMillis(); Notification notification = new Notification(icon, null, when);
這個定義比較隨意。
2、為notification添加打開關閉方式:
//點擊notification之后,該notification自動消失
notification.flags = Notification.FLAG_AUTO_CANCEL;
//notification被notify的時候,觸發默認聲音和默認震動
notification.defaults=notification.DEFAULT_SOUND|notification.DEFAULT_VIBRATE;
3、為notification添加一個意圖(Intent):
//該意圖用來打開NotificationList這個新的Activity
Intent openintent= new Intent(this, NotificationList.class);
//包裝該Intent,只有包裝后的Intent才能被Notification所用,這是因為Notification需要指定一些額外的參數
PendingIntent contentIntent = PendingIntent.getActivity(tradeRoom
.getApplicationContext(), 0, openintent,
0);
notification.setLatestEventInfo(tradeRoom.getApplicationContext(),
title, info, contentIntent);
4、發送通知
//notifacation_id由自己指定,為每一個Notification對應的唯一標志
mNotificationManager.notify(notifacation_id, notification);
======================================================
看到這里,我們明白了,我們可以為Notification指定它的圖標,標題,時間,提醒方式,點擊之后的動作。
延展想一下,我們還能做什么呢?
1、由於每個Notification的ID是唯一的,所以我們可以刪除某些通知:
mNotificationManager.cancel(notifacation_id);
2、同理,通過重復發送相同ID的Notification,我們還可以更新某些通知:
mNotificationManager.notify(notifaction_id,newNotification);
3、由於Notification的包裝內容為Intent,我們就可以方便地為通知被點擊的觸發的事件傳值:
Intent openintent= new Intent(this, NotificationList.class);
openintent.putExtra("isRead", true);
openintent.putExtra("name", "CaiYu");
等等,真的可以傳值么?
答案是可以,但是,這樣傳值就完蛋了。
現在回到下面的位置來:
PendingIntent contentIntent = PendingIntent.getActivity(tradeRoom
.getApplicationContext(), 0, openintent,
0);
注意最后一個“0”,0表示什么?表示什么都不做,然后下次你傳進來的Intent,如果被發現是同一個Intent,則所有通知都保持為同一個Intent。好吧,事實上,Intent並不是同一個,只是Extra被保留了。
嗯,你應該會期望每個Notification都能干點不一樣的事情,按上面的方式這樣來,每個具備相同Intent的Notification相互之間,其實是毫無區別的。
好,我們來看下除了0以外Android還有什么設置:
1、PendingIntent.FLAG_UPDATE_CURRENT
Extra會被更新為最后一個傳入的Intent的Extra
2、PendingIntent.FLAG_ONE_SHOT
send()只能被執行一次,即是說,假如該通知點擊后不消失,那么再次點擊不會發生任何事。
3、PendingIntent.FLAG_NO_CREATE
這個最好別用,不創建。
4、PendingIntent.FLAG_CANCEL_CURRENT
這個,會更新Extra,但還是所有的Intent都保持同一個Extra。
嗯,明顯都不是你想要的。
其實答案根本不在PendingIntent包裝上。
PendingIntent所做的全部事情都只是對同樣的Intent進行處理,關鍵詞,在於“同樣的”
既然每次你打開的都一個Intent,那區分PendingIntent就沒有意義了
所以,在Intent定義的時候,你還需要區分Intent
推薦方式:
openintent.setData(Uri.parse("custom://"+System.currentTimeMillis()));
這樣就實現了Intent的區別化,以后每次傳入的Intent都會具備不同的Extra,當然,PendingIntent需要定義為PendingIntent.FLAG_UPDATE_CURRENT
到這個地方,其實還剩下一個問題,很快你就會發現
每次點擊通知,都正確的彈出你要的Activity,但是之前的打開的Activity依舊存在
方法有二:
1、在Activity的onPause()方法體中增加:
finish();
這樣,在打開新的Activity的時候,舊的就進入了暫停態,啟動onPause(),然后執行finish(),活動結束
好吧,這是個蠢辦法,請不要使用
2、設置Intent:
openintent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
是的,這句就夠了,這里我得說一下Activity的棧機制:
我們先來看看Intent的結構new Intent(context(),Notification.class);
第一個參數為產生該意圖(Intent)的活動,這個邏輯再清晰不過了,要做的事情得有個發出的主體
第二個參數為該意圖的對象,即是這個意圖是什么,我們來看看。
呃!??這里沒有對象……
是的,我們只有了一個對象的類名,但遠遠不是某個具體的對象,這是反射么?反射能通過一個類名來找到某個特定的類實例么?
實現如下:
Android有一個棧機制,每個產生的活動在過了產生期后,都會進入這個棧,新的活動壓着舊的活動,每一次尋找類名的時候,都默認提取的是棧頂的活動。這也是為什么Android能快捷的執行返回操作。
回到原點來,我們為Intent添加:
openintent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
之后,這個意圖一旦產生,就會自動清除棧頂的活動,即是說,上一個被打開的活動會被終結掉,於是就實現了沒有兩個相同的活動被同時打開。