天天看點

Android 如何設定 Notification 中PendingIntent 的 Intent

 今天在寫完 “ android notification 的使用 ” 的時候,發現有幾個問題,特别是設定notification的intent使之能夠像 qq 或其他程式一樣能夠正确回調到之前已經放置在背景的task中的對應activity,而不是建立它的一個新執行個體。當然重點便是如何設定該 activity 的 launchmode 與 intent 的 flags 了,說到這裡,我不得不說一下今晚的調試經曆,當然這裡所說的所有的notification都設定了flag_ongoing_event。

  按照 “ (轉載)android下affinities和task ”一文所說的,我們不難得出這樣的結論:

  1、設定當使用者觸發notification時所發出的intent,如果設定 flag_activity_clear_top 與 flag_activity_new_task ,而launchmode保持不變(即預設為:standard),則當使用者用手點選notification時,此時比對到背景的task,并把在堆棧中對應要啟動的activity之前的所有activity全部清除掉,并且由于 standard 預設對于新的intent總是建立新的activity對象。是以存在于該task中舊的activity也會被清除掉,然後在該task中建立新的

activity對象。

  2、設定當使用者觸發notification時所發出的intent,如果設定 flag_activity_clear_top 與 flag_activity_new_task,而launchmode設定為singletop,則當使用者用手點選notification時,同1一樣,隻是存在于該task中舊的activity不會被清除掉,此時intent傳遞給已經存在的activity并不會建立新的activity。

  上面得出的結論,經過傳回測試,1是正确的,2卻存在着很莫名奇妙的問題

  假設現在有個程式x,有2個activity,分别是 a , b ,其中 a 是 設定了android.intent.action.main的activity(入口activity),兩者的launchmode都為預設的 standard,建立該intent的代碼如下:

  intent intent = new intent(this, a.class);

  intent.setflags(intent.flag_activity_clear_top|intent.flag_activity_new_task);

  很明顯我們設定的是當使用者點選 notification 時,應該出現的是 a activity,但無論如何按home鍵退出目前task,并使之成為背景task,在從程式清單啟動該程式總能恢複到task頂端的activity 給使用者,如

目前 b,按home鍵,在從程式清單啟動 x ,這個時候出現的activity任然是 b,但按照如下的方法操作卻會使得從程式清單啟動 x,出現的是新建立的a activity,其中經過log列印得知下面的所有activity都在同一個task中

  1、打開程式出現a,從a startactivity 到b,按home鍵,點notification出現a,再從a startactivity 到 b,按home鍵,從程式清單打開程式 出現新建立的執行個體a

  2、打開程式出現a,從a startactivity 到b,點notification出現a,再從a startactivity 到b,按home鍵,從程式清單打開程式也出現了新建立的執行個體a

  這裡所說的“新建立的執行個體a”都是建立在同一task中的新的a activity執行個體,也就是說按照以上兩種方法,再按傳回鍵,出現的則是 b,再按傳回鍵出現的則是 a。這裡我實在想不出為什麼會在同一task中建立一個新的activity,就算從程式清單打開程式的intent使用了 flag_activity_new_task标記,我也不知道為什麼,如果有朋友知道,一定要告訴我。

  到這裡,我開始發現 從程式清單啟動 的優越性,因為不管是在什麼時候按home,再次從程式清單啟動時,總能傳回到task的棧頂activity。起初我想過一個辦法,便是重載 activity寫一個類實作當onresume的時候更新notification,然後我的所有activity類都直接從該類繼承,使得當按 home 之後總能讓notification記住task的棧頂activity,就像qq一樣,但這種方法當然有點牽強,于是我開始看sdk

中 有關home的simple,終于發現了如果使用如下的intent,便不會調用對應的activity,而是調用task中的棧頂activity

  intent intent = new intent(intent.action_main);

  intent.addcategory(intent.category_launcher);

  intent.setclass(this, main.class);

  intent.setflags(intent.flag_activity_new_task|intent.flag_activity_reset_task_if_needed);

  除了 setclass 可以換成使用 setclassname 綁定,flag_activity_reset_task_if_needed可以不設,其他的選項都缺一不可。設定action_main與 category_launcher是把該intent發給了系統對應建立程式的子產品,然後系統該子產品根據設定的包與類資訊還有flags進行處理。當然所有的intent工作原理都是這樣,隻是對 action_main - category_launchar 的處理較為特殊,使得總是顯示task棧頂的activity而不是setclass設定的activity類。