Android中pendingIntent的深刻理解

pendingIntent字面意義:等待的,未決定的Intent。
  pendingIntent對象,使用方法類的靜態方法 :html

      getActivity(Context, int, Intent, int)------->跳轉到一個activity組件、android

    getBroadcast(Context, int, Intent, int)------>打開一個廣播組件網絡

    getService(Context, int, Intent, int)-------->打開一個服務組件。app

  分別對應着Intent的3個行爲和參數有4個,比較重要的事第三個和第一個,其次是第四個和第二個。能夠看到,要獲得這個對象,必須傳入一個Intent做爲參數,必須有context做爲參數。less

  pendingIntent是一種特殊的Intent。主要的區別在於Intent的執行馬上的,而pendingIntent的執行不是馬上的。pendingIntent執行的操做實質上是參數傳進來的Intent的操做,可是使用pendingIntent的目的在於它所包含的Intent的操做的執行是須要知足某些條件的。
主要的使用的地方和例子:通知Notificatio的發送,短消息SmsManager的發送和警報器AlarmManager的執行等等。
intent英文意思是意圖,pending表示即將發生或來臨的事情。 
PendingIntent這個類用於處理即將發生的事情。好比在通知Notification中用於跳轉頁面,但不是立刻跳轉。 

  Intent 是及時啓動,intent 隨所在的activity 消失而消失。 
PendingIntent 能夠看做是對intent的包裝,一般經過getActivity,getBroadcast ,getService來獲得pendingintent的實例,當前activity並不能立刻啓動它所包含的intent,而是在外部執行 pendingintent時,調用intent的。正因爲pendingintent中 保存有當前App的Context,使它賦予外部App一種能力,使得外部App能夠如同當前App同樣的執行pendingintent裏的 Intent, 就算在執行時當前App已經不存在了,也能經過存在pendingintent裏的Context照樣執行Intent。另外還能夠處理intent執行後的操做。常和alermanger 和notificationmanager一塊兒使用。 
Intent通常是用做Activity、Sercvice、BroadcastReceiver之間傳遞數據,而Pendingintent,通常用在 Notification上,能夠理解爲延遲執行的intent,PendingIntent是對Intent一個包裝。 ide

Android的狀態欄通知(Notification)函數

  若是須要查看消息,能夠拖動狀態欄到屏幕下方便可查看消息。佈局

步驟:post

  1獲取通知管理器NotificationManager,它也是一個系統服務動畫

  2創建通知Notification notification = new Notification(icon, null, when);

  3爲新通知設置參數(好比聲音,震動,燈光閃爍)

  4把新通知添加到通知管理器

發送消息的代碼以下:

  //獲取通知管理器

  NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)

  int icon = android.R.drawable.stat_notify_chat;

  long when = System.currentTimeMillis();//通知發生的時間爲系統當前時間

  Notification notification = new Notification(icon, null, when);//新建一個通知,第一個參數爲圖標,第二個參數爲短暫提示標題,第三個爲通知時間

  notification.defaults = Notification.DEFAULT_SOUND;//發出默認聲音

  notification.flags |= Notification.FLAG_AUTO_CANCEL;//點擊通知後自動清除通知

  Intent openintent = new Intent(this, OtherActivity.class);

  PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);//當點擊消息時就會向系統發送openintent意圖

  notification.setLatestEventInfo(this, 「標題」, 「我是內容", contentIntent);//setLatestEventInfo表示設置點擊該通知的事件

  mNotificationManager.notify(0, notification);//第一個參數爲自定義的通知惟一標識

  重點是setLatestEventInfo( )方法的最後一個參數!!!!它是一個PendingIntent!!!!!!!!!

  這裏使用到了PendingIntent(pend本意是待定,不肯定的意思)

  PendingIntent能夠看做是對Intent的包裝。PendingIntent主要持有的信息是它所包裝的Intent和當前Application的Context。正因爲PendingIntent中保存有當前Application的Context,使它賦予帶他程序一種執行的Intent的能力,就算在執行時當前Application已經不存在了,也能經過存在PendingIntent裏的Context照樣執行Intent。

 

複製代碼
 1 private void showNotify(){   
 2         Notification notice=new Notification();   
 3         notice.icon=R.drawable.icon;   
 4         notice.tickerText="您有一條新的信息";   
 5         notice.defaults=Notification.DEFAULT_SOUND;   
 6         notice.when=10L;   
 7         // 100 毫秒延遲後,震動 250 毫秒,暫停 100 毫秒後,再震動 500 毫秒     
 8         //notice.vibrate = new long[] { 100, 250, 100, 500 };出錯?   
 9         //notice.setLatestEventInfo(this, "通知", "開會啦", PendingIntent.getActivity(this, 0, null, 0));   
10 notice.setLatestEventInfo(this, "通知", "開會啦", PendingIntent.getActivity(this, 0, new Intent(this,Activity2.class), 0));//即將跳轉頁面,還沒跳轉   
11         NotificationManager manager=(NotificationManager)getSystemService(this.NOTIFICATION_SERVICE);   
12         manager.notify(0,notice);   
13     }  
複製代碼
複製代碼
 1 private void showNotify(){  
 2         Notification notice=new Notification();  
 3         notice.icon=R.drawable.icon;  
 4         notice.tickerText="您有一條新的信息";  
 5         notice.defaults=Notification.DEFAULT_SOUND;  
 6         notice.when=10L;  
 7         // 100 毫秒延遲後,震動 250 毫秒,暫停 100 毫秒後,再震動 500 毫秒    
 8         //notice.vibrate = new long[] { 100, 250, 100, 500 };出錯?  
 9         //notice.setLatestEventInfo(this, "通知", "開會啦", PendingIntent.getActivity(this, 0, null, 0));  
10 notice.setLatestEventInfo(this, "通知", "開會啦", PendingIntent.getActivity(this, 0, new Intent(this,Activity2.class), 0));//即將跳轉頁面,還沒跳轉  
11         NotificationManager manager=(NotificationManager)getSystemService(this.NOTIFICATION_SERVICE);  
12         manager.notify(0,notice);  
13     }  
複製代碼
複製代碼
 1 1. GSM網絡中Android發送短信示例
 2 
 3 Java代碼 
 4 String msg ="你好,美女";   
 5 String number = "135****6784";   
 6 SmsManager sms = SmsManager.getDefault();   
 7   
 8 PendingIntent pi = PendingIntent.getBroadcast(SmsActivity.this,0,new Intent(...),0);   
 9 sms.sendTextMessage(number, null, msg, pi, null);   
10 Toast.makeText(SmsActivity.this,"發送成功",Toast.LENGHT_LONG).show();  
複製代碼
複製代碼
1 String msg ="你好,美女";  
2 String number = "135****6784";  
3 SmsManager sms = SmsManager.getDefault();  
4   
5 PendingIntent pi = PendingIntent.getBroadcast(SmsActivity.this,0,new Intent(...),0);  
6 sms.sendTextMessage(number, null, msg, pi, null);  
7 Toast.makeText(SmsActivity.this,"發送成功",Toast.LENGHT_LONG).show(); 
複製代碼

代碼解釋 
      PendingIntent就是一個Intent的描述,咱們能夠把這個描述交給別的程序,別的程序根據這個描述在後面的別的時間作你安排作的事情 (By giving a PendingIntent to another application, you are granting it the right to perform the operation you have specified as if the other application was yourself,就至關於PendingIntent表明了Intent)。本例中別的程序就是發送短信的程序,短信發送成功後要把intent廣播出去 。 
      函數SmsManager.sendTextMessage(String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)中參數解釋: 
      1)PendingIntent sentIntent:當短信發出時,成功的話sendIntent會把其內部的描述的intent廣播出去,不然產生錯誤代碼並經過android.app.PendingIntent.OnFinished進行回調,這個參數最好不爲空,不然會存在資源浪費的潛在問題; 
      2)PendingIntent deliveryIntent:是當消息已經傳遞給收信人後所進行的PendingIntent廣播。 
      查看PendingIntent 類能夠看到許多的Send函數,就是PendingIntent在進行被賦予的相關的操做。

PendingIntent的一個很好的例子:

 

短信系統舉例SmsManager的用於發送短信的方法:

  sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliveryIntent);

  第一個參數:destinationAddress對方手機號碼

  第二個參數:scAddress短信中心號碼通常設置爲空

  第三個參數:text短信內容

  第四個參數:sentIntent判斷短信是否發送成功,若是你沒有SIM卡,或者網絡中斷,則能夠經過這個itent來判斷。注意強調的是「發送」的動做是否成功。那麼至於對於對方是否收到,另當別論

  第五個參數:deliveryIntent當短信發送到收件人時,會收到這個deliveryIntent。即強調了「發送」後的結果

  就是說是在"短信發送成功"和"對方收到此短信"纔會激活 sentIntent和deliveryIntent這兩個Intent。這也至關因而延遲執行了Intent


  上面兩個例子能夠理解,PendingIntent就是一個能夠在知足必定條件下執行的Intent,它相比於Intent的優點在於本身攜帶有Context對象,這樣他就沒必要依賴於某個activity才能夠存在。

//////////////////////////////////////////////////////////////////////////////////////////////

PendingIntent的做用舉例以及和Intent的區別

一、PendingIntent做用

  根據字面意思就知道是延遲的intent,主要用來在某個事件完成後執行特定的Action。PendingIntent包含了Intent及Context,因此就算Intent所屬程序結束,PendingIntent依然有效,能夠在其餘程序中使用。
經常使用在通知欄及短信發送系統中。

  PendingIntent通常做爲參數傳給某個實例,在該實例完成某個操做後自動執行PendingIntent上的Action,也能夠經過PendingIntent的send函數手動執行,並能夠在send函數中設置OnFinished表示send成功後執行的動做。

二、PendingIntent舉例

a. 系統通知欄

複製代碼
NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int icon = android.R.drawable.stat_notify_chat;
long when = System.currentTimeMillis() + 2000;
Notification n = new Notification(icon, "通知欄demo提醒", when);
n.defaults = Notification.DEFAULT_SOUND;
n.flags |= Notification.FLAG_AUTO_CANCEL;

Intent openintent = new Intent(this, DemoList.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, openintent, PendingIntent.FLAG_CANCEL_CURRENT);
n.setLatestEventInfo(this, "通知欄demo提醒title", "通知欄demo提醒text", pi);
nm.notify(0, n);
複製代碼

  setLatestEventInfo表示設置點擊該通知的事件

b. 短信系統舉例

  以上的兩個PendingIntent sentPI和deliveredPI將分別在短信發送成功和對方接受成功時被廣播

三、Intent和PendingIntent的區別

  a. Intent是當即使用的,而PendingIntent能夠等到事件發生後觸發,PendingIntent能夠cancel
  b. Intent在程序結束後即終止,而PendingIntent在程序結束後依然有效
  c. PendingIntent自帶Context,而Intent須要在某個Context內運行
  d. Intent在原task中運行,PendingIntent在新的task中運行

PendingIntent用於描述Intent及其最終的行爲. 
  你能夠經過getActivity(Context context, int requestCode, Intent intent, int flags)系列方法從系統取得一個用於啓動一個Activity的PendingIntent對象,

  能夠經過getService(Context context, int requestCode, Intent intent, int flags)方法從系統取得一個用於啓動一個Service的PendingIntent對象

  能夠經過getBroadcast(Context context, int requestCode, Intent intent, int flags)方法從系統取得一個用於向BroadcastReceiver的Intent廣播的PendingIntent對象

  返回的PendingIntent能夠遞交給別的應用程序,而後繼續處理。這裏的話你能夠稍後才處理PendingIntent中描述的Intent及其最終行爲。

  當你把PendingIntent遞交給別的程序進行處理時,PendingIntent仍然擁有PendingIntent原程序所擁有的權限(with the same permissions and identity).當你從系統取得一個PendingIntent時,必定要很是當心才行。好比,一般,若是Intent目的地是你本身的component(Activity/Service/BroadcastReceiver)的話,你最好採用在Intent中顯示指定目的component名字的方式,以確保Intent最終能發到目的,不然Intent最後可能不知道發到哪裏了。一個PendingIntent就是Android系統中的一個token(節點,這個應該是Linux或C\C++用語)的一個對象引用,它描述了一些將用於retrieve的數據(這裏,這些數據描述了Intent及其最終的行爲)。

  這就意味着即便PendingIntent原進程結束了的話, PendingIntent自己仍然還存在,可在其餘進程(PendingIntent被遞交到的其餘程序)中繼續使用.若是我在從系統中提取一個PendingIntent的,而系統中有一個和你描述的PendingIntent對等的PendingInent, 那麼系統會直接返回和該PendingIntent實際上是同一token的PendingIntent,而不是一個新的token和PendingIntent。然而你在從提取PendingIntent時,經過FLAG_CANCEL_CURRENT參數,讓這個老PendingIntent的先cancel()掉,這樣獲得的pendingInten和其token的就是新的了。

  經過FLAG_UPDATE_CURRENT參數的話,可讓新的Intent會更新以前PendingIntent中的Intent對象數據,例如更新Intent中的Extras。另外,咱們也能夠在PendingIntent的原進程中調用PendingIntent的cancel ()把其從系統中移除掉。

 

onResume()方法

因爲Bactivity的操做,影響了Aactivity的數據,因此再回到A的時候,須要A可以進行刷新操做。
可是默認跳回去的時候,A界面仍是上次那個。

解決方案:重寫Aactivity的onResume()方法,在onResume()方面裏進行刷新操做。由於按照activity的生命週期模型,當activity恢復的時候,onResume()方法會被調用,因此這是一個刷新的好機會。

 

 

一個Activity活動就是一個界面的佈局。

程序正常啓動時:onCreate()->onStart()->onResume();
onCreate()在活動第一次建立時被調用,主要用於加載佈局
onStart()這個方法在活動由不可見變爲可見的時候調用。
onResume這個方法在活動準備好和用戶進行交互的時候調用。此時的活動必定位於返回棧的棧頂,而且處於運行狀態.
三種調用的場景:
一個Activity啓動另外一個Activity: onPause()->onStop(),再返回:onRestart()->onStart()->onResume()
程序按back 退出: onPause()->onStop()->onDestory(),再進入:onCreate()->onStart()->onResume();
程序按home 退出: onPause()->onStop(),再進入:onRestart()->onStart()->onResume();
生命週期的一些細節:
1     Activity 第一次建立時會調用 onCreate(Bundle)。 該方法用於建立 Activity 的用戶界面,建立所需的後臺線程,並執行其餘的全局初始化。若是能得到Activity之前的狀態,就能夠將包含此狀態的 android.os.Bundle 對象傳給onCreate();不然就傳入一個空引用。在調用 onCreate(Bundle)以後,
Android 總會調用 onStart()。
2      在用戶看到 Activity 以前會調用 onStart()方法。當 Activity 進入前臺時, Android在調用 onStart()以後就會調用onResume();當 Activity 變成隱藏狀態時, Android就會在調用 onStart()以後調用 onStop()。
3      當 Activity 中止後,在其從新啓動以前會調用 onRestart()。在調用 onRestart()以後,Android 會調用 onStart()。
4      在 Activity 開始跟用戶交互以前會調用 onResume()。此時, Activity 得到了焦點,用戶的輸入會發送給該 Activity。當 Activity 必須暫停時,Android 就會在調用onResume()以後調用 onPause()。
5      當 Android 要恢復另外一個 Activity 時會調用 onPause()。該方法通常用於保留未保存的修改,中止可能會消耗處理器資源的動畫等。它應該很快地完成工做,由於只有等該方法返回時,下一個 Activity 才能被從新激活。在調用了 onPause()以後,當 Activity 開始跟用戶交互時, Android 就會使用onResume(),當 Activity 變成隱藏狀態時調用 onStop()。 許多 Activity 執行 onPause()方法來提交數據的改變或者準備中止與用戶的交互操做。
6      當 Activity 變爲隱藏狀態時會調用 onStop()。這種狀況可能發生在 Activity被銷燬,或者另外一個 Activity(正在運行的或新啓動的)被從新激活並將覆蓋前一個 Activity時。在調用 onStop()以後,若是 Activity 從新跟用戶交互, Android 會調用 onRestart()方法;
7     若是 Activity 退出了,就會調用 onDestroy()方法。
8      在 Activity 被銷燬以前會調用 onDestroy(),除非是內存不夠, Android 強行終止了Activity 的進程。在這種狀況下就不會調用 onDestroy()。若是調用了 onDestroy(),那它就是該 Activity 接收的最終調用。在 onPause()、 onStop()或 onDestroy()返回以後, Android 能夠終止託管 Activity 的進程。從 onPause()返回後到調用 onResume()以前, Activity 都處於可終止狀態。在 onPause()再次返回以前, Activity 都不會再處於可終止狀態。

 

android onNewIntent

在Android應用程序開發的時候,從一個Activity啓動另外一個Activity並傳遞一些數據到新的Activity上很是簡單,可是當您須要讓後臺運行的Activity回到前臺並傳遞一些數據可能就會存在一點點小問題。

首先,在默認狀況下,當您經過Intent啓到一個Activity的時候,就算已經存在一個相同的正在運行的Activity,系統都會建立一個新的Activity實例並顯示出來。爲了避免讓Activity實例化屢次,咱們須要經過在AndroidManifest.xml配置activity的加載方式(launchMode)以實現單任務模式,以下所示:


1 <activity android:label="@string/app_name" android:launchmode="singleTask"android:name="Activity1">

2 </activity>


launchMode爲singleTask的時候,經過Intent啓到一個Activity,若是系統已經存在一個實例,系統就會將請求發送到這個實例上,但這個時候,系統就不會再調用一般狀況下咱們處理請求數據的onCreate方法,而是調用onNewIntent方法,以下所示:


1 protected void onNewIntent(Intent intent) {

2   super.onNewIntent(intent);

3   setIntent(intent);//must store the new intent unless getIntent() will return the old one

4   processExtraData();

5 }


不要忘記,系統可能會隨時殺掉後臺運行的Activity,若是這一切發生,那麼系統就會調用onCreate方法,而不調用onNewIntent方法,一個好的解決方法就是在onCreate和onNewIntent方法中調用同一個處理數據的方法,以下所示:


01 public void onCreate(Bundle savedInstanceState) {

02   super.onCreate(savedInstanceState);

03   setContentView(R.layout.main);

04   processExtraData();

05 }

06  

07 protected void onNewIntent(Intent intent) {

08   super.onNewIntent(intent);

09   setIntent(intent);//must store the new intent unless getIntent() will return the old one

10   processExtraData()

11 }

12  

13 private void processExtraData(){

14   Intent intent = getIntent();

15   //use the data received here

16 }

相關文章
相關標籤/搜索