Android BroadcastReceiver(一)

來源:互聯網
上載者:User

Android BroadcastReceiver


介紹: broadcastReceiver是android的四大組件之一,大部分的廣播是系統發出來的。例如,螢幕關閉,電池電量不足等等。應用同樣可以建立廣播,例如:當下載完成的時候,要讓其他的應用知道這個情況,需要用到broadcastreceiver,receiver沒有介面,它可能會建立一個status bar notification通知使用者。broadcastreceiver 只是會做一些非常小的工作,例如,它可以出發一個service工作。

 


基類的代碼會收到sendBroadcast()發送過來的Intents.

如果不需要在應用之間發送廣播,可以考慮使用LocalBroadcastManager代替下面介紹的方式。這種方式會有更好的效能,並且不用考慮不同應用之間的安全問題,因為其他的應用有可能可以接收這個廣播。

可以用Context.registerReceiver()動態註冊receiver或者是在AndroidManifest.xml 檔案裡通過<receiver>元素靜態註冊receiver。

注意:    如果在Activity.onResume() 裡面註冊一個receiver,那麼必須在Activity.onPause() 方法裡面登出這個receiver。不要在Activity.onSaveInstanceState() 方法裡面登出receiver,因為當使用者回到曆史堆棧中不會調用它。

這裡有兩種主要的廣播可以收到:

正常的 broadcasts ( Context.sendBroadcast發送的) 都是非同步. 所有的receiver都是沒有順序的,通常在同一時間。這種方式效率更好,這意味著receiver不能使用結果或者終止API。
有序的 broadcasts (Context.sendOrderedBroadcast 發送的) 是同時發送給一個receiver。因為每一個receiver按照順序執行,那麼就可以傳遞結果到下一個receiver,或者它可以完全終止廣播,已達到不傳遞給下一個receiver。有序的receiver啟動並執行時與android:priority 有關係,這個屬性可以控制它執行順序;如果receiver擁有同樣的priority,那麼它們的執行順序是任意的。
即使在正常的廣播中,系統在有些情況下會把廣播同時發給一個receiver。在特殊條件下,可能需要建立一個進程來處理receiver,在某一時間點只有一個receiver會運行,為了避免超負荷工作是系統可能建立新的進程。在這種情況下,然而,這些receiver還是不能夠返回結果和終止他們的廣播。

需要注意,即使Intent類被用來發送和接收廣播,Intent 廣播與啟動activity的機制是完全不同的。BroadcastReceiver 不能處理startActivity()方法發送出來的Intent,沒有這種機制;同樣的,當廣播一個Intent,同樣不能找到或者啟動一個activity。這兩種操作在語義上是完全不同的:通過Intent啟動一個activity是一個前台操作,這是隨著使用者的操作而發生的改變;廣播一個Intent是一種後台操作,使用者是不能意識到的.

下面有三個主題的內容:

Security
Receiver Lifecycle
Process Lifecycle
Security
receiver通常是應用之間通訊的一個工具,因此必須考慮其他的應用可能如何濫用它們。需要考慮的問題有:

Intent的命名空間是全域的。要保證定義的action名字和其他的字串都是屬於自己的應用,要不然會無意識的與系統其他的衝突。

如果是用 registerReceiver(BroadcastReceiver, IntentFilter)註冊Receiver, 任何應用都有可能發送廣播到那個receiver。可以通過定義permissions控制誰能發送廣播給它。

在manifest裡面定義receiver,並且定義了intent-filters, 任何應用都可以忽略指定的過濾條件並發送廣播給它。為了防止其他的應用發送廣播給它,在在manifest裡面定義android:exported="false",這樣其他的應用就不能發送廣播到這個receiver了。

用sendBroadcast(Intent)   或者相關的方法,正常情況,其他的應用可以收到這個廣播。需要通過定義permission控制可以接受這個廣播的receiver。或者是,從 ICE_CREAM_SANDWICH 開始,可以同通過設定Intent.setPackage 來指定receiver。

用 LocalBroadcastManager 就不會有這個些問題,從廣播發出後,都不會出當前進程。

receiver和broadcast都可以設定存取權限。

為了在發送的時候執行permission,必須提供一個非空的permission參數給 sendBroadcast(Intent, String) 或者 sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle). 僅僅定義這個permission的receiver可以接收廣播( AndroidManifest.xml 裡面定義<uses-permission>)。

當收到執行許可權時,在註冊receiver的時候需要提供一個非空的permission參數--要麼當調用registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler) 或者是在AndroidManifest.xml 檔案裡面定義一個靜態<receiver>. 只有授予了指定permission的廣播才能夠發送到receiver中。

Receiver Lifecycle
BroadcastReceiver 對象只有在調用onReceive(Context, Intent)方法是才有效. 一旦從這個方法裡面返回,系統會認為這個對象已經完成並且不在處於活動狀態。

這裡是當實現 onReceive(Context, Intent) 時需要注意: 任何需要非同步操作是不可行的,因為需要從方法裡面返回,但是方法又要處理非同步操作,這樣就可以行了,這種情況下,系統會在非同步作業完成之前可能會殺死BroadcastReceiver的進程。

特殊情況下,在BroadcastReceiver裡面可能不會顯示一個dialog或者綁定一個service。對於前者,用NotificationManager API代替,對後者,可以用 Context.startService() 發送命令給service。

Process Lifecycle
當前正在啟動並執行BroadcastReceiver(運行在onReceive(Context, Intent)方法上)進程需要被認為是前台進程,並且會一直運行除非是系統的記憶體處於極限情況下(系統會回收記憶體)。

一旦從onReceive()返回,BroadcastReceiver不再是活動狀態的,它啟動並執行進程與其他啟動並執行在它裡面的應用組件一樣重要,這是非常特殊並且非常重要的,因為那個進程只是為BroadcastReceiver服務,然後receiver從onReceive()裡面返回,系統會認為這個進程是空的並且會儘快殺死它回收資源。

這就意味著,如果是一個長時間啟動並執行操作,最好是用service和BroadcastReceiver 結合使用,為了保持進程在整個操作中持久運行。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.