平時使用廣播的場合比較多,但細節的東西,看過了也沒有總結,以至於某些場合有小問題,還是要把原理和屬性搞清楚才能運用自如。
其實也是自己比較懶,先看別人的blog,有個概念再去官網看英文的能好理解一些。
這篇補充上一篇消息推送的知識,先羅列一些基礎知識,再說自己不足的地方和問題。
照例,先搬磚:
2. Android Service 服務(二)—— BroadcastReceiver
3. Android----基礎----第八天----BroadcaseReceiver和通知
4. Android開發之BroadcastReceiver詳解
第1篇里的重點是:
- Intent和PendingIntent的區別
a. Intent是立即使用的,而PendingIntent可以等到事件發生后觸發,PendingIntent可以cancel
b. Intent在程序結束后即終止,而PendingIntent在程序結束后依然有效
c. PendingIntent自帶Context,而Intent需要在某個Context內運行
d. Intent在原task中運行,PendingIntent在新的task中運行
第2,4篇里的重點是:
BroadcastReceiver,顧名思義就是“廣播接收者”的意思,它是Android四大基本組件之一,這種組件本質上是一種全局的監聽器,用於監聽系統全局的廣播消息。它可以接收來自系統和應用的的廣播。
由於BroadcastReceiver是一種全局的監聽器,因此它可以非常方便地實現系統不同組件之間的通信。比如Activity與通過startService()方法啟動的Service之間通信,就可以借助於BroadcastReceiver來實現。
當應用發出一個Broadcast Intent之后所匹配該Intent的組件都可能被啟動。
- 兩種注冊方式
a. 靜態注冊方式,由系統來管理receiver,而且程序里的所有receiver,可以在xml里面一目了然。通過這種方式注冊的廣播為常駐型廣播,也就是說如果應用程序關閉了,有相應事件觸發,程序還是會被系統自動調用運行。
b. 動態注冊方式,隱藏在代碼中,比較難發現;需要特別注意的是,在退出程序前要記得調用Context.unregisterReceiver()方法。一般在activity的onStart()里面進行注冊, onStop()里面進行注銷。官方提醒,如果在Activity.onResume()里面注冊了,就必須在Activity.onPause()注銷。通過這種方式注冊的廣播為非常駐型廣播,即它會跟隨Activity的生命周期,所以在Activity結束前我們需要調用unregisterReceiver(receiver)方法移除它。
- 生命周期
一個BroadcastReceiver 對象只有在被調用onReceive(Context, Intent)的才有效,當從該函數返回后,該對象就無效的了,結束生命周期。因此從這個特征可以看出,在所調用的onReceive(Context, Intent)函數里,不能有過於耗時的操作,不能使用線程來執行。對於耗時的操作,應該在startService中來完成。因為當得到其他異步操作所返回的結果時,BroadcastReceiver 可能已經無效了。
In particular, you may not show a dialog or bind to a service from within a BroadcastReceiver. For the former, you should instead use the NotificationManager
API. For the latter, you can use Context.startService()
to send a command to the service.
特別的,BroadcastReceiver中也不能展示dialog或者去綁定service。前者可以用NotificationManager代替,后者可以用Context.startService()發送命令給service。
- 有序廣播和無序廣播
第3篇里介紹了廣播和通知的基本知識點,這種腦干圖的學習方式也不錯。
看完上面的知識,還有疑問?
官網:http://developer.android.com/reference/android/content/BroadcastReceiver.html
首先:如果廣播沒有必要在應用之間傳遞,建議用LocalBroadcastManager,能避免很多一般廣播存以下的安全性問題。
Receivers used with the Context
APIs are by their nature a cross-application facility, so you must consider how other applications may be able to abuse your use of them. Some things to consider are:
-
The Intent namespace is global. Make sure that Intent action names and other strings are written in a namespace you own, or else you may inadvertently conflict with other applications.
- Intent的命名空間是全局的,保證自己的Intent的action命名和其他string都是自己指定的名稱,防止與其他應用造成名稱沖突。
-
When you use
registerReceiver(BroadcastReceiver, IntentFilter)
, any application may send broadcasts to that registered receiver. You can control who can send broadcasts to it through permissions described below. - 當用動態注冊時,任何app都能向這個監聽器發送廣播,可以設置權限控制誰能發送這種廣播。permission和user permission,具體官網有介紹。
-
When you publish a receiver in your application's manifest and specify intent-filters for it, any other application can send broadcasts to it regardless of the filters you specify. To prevent others from sending to it, make it unavailable to them with
android:exported="false"
. - 作為接收方,如果是配置文件中的靜態注冊,也設置了intent-filters,那監聽器也會收到其他app也能發送的符合過濾規則的廣播,可以設置android:exported="false",杜絕接受其他app發出的此類廣播。
-
When you use
sendBroadcast(Intent)
or related methods, normally any other application can receive these broadcasts. You can control who can receive such broadcasts through permissions described below. Alternatively, starting withICE_CREAM_SANDWICH
, you can also safely restrict the broadcast to a single application withIntent.setPackage
- 作為發送方,發送廣播時,一般其他app都能收到這些廣播(有可能沒設置上面一條說的,導致收到了其他app不必要的廣播),這樣可以在發送的時候指定誰可以收到這個廣播。比如指定包名等方法。
Process Lifecycle
A process that is currently executing a BroadcastReceiver (that is, currently running the code in its onReceive(Context, Intent)
method) is considered to be a foreground process and will be kept running by the system except under cases of extreme memory pressure.
Once you return from onReceive(), the BroadcastReceiver is no longer active, and its hosting process is only as important as any other application components that are running in it. This is especially important because if that process was only hosting the BroadcastReceiver (a common case for applications that the user has never or not recently interacted with), then upon returning from onReceive() the system will consider its process to be empty and aggressively kill it so that resources are available for other more important processes.
This means that for longer-running operations you will often use a Service
in conjunction with a BroadcastReceiver to keep the containing process active for the entire time of your operation.
正在執行BroadcastReceiver的進程是前台進程,系統會保留這個進程的運行狀態,除非極端內存不足。
一旦從onReceive()返回,BroadcastReceiver不在有效,它的宿主進程和其他運行的application有一樣的重要級別,如果該宿主只有這一個BroadcastReceiver活動(比如用戶一直沒有交互操作的app),此時從onReceive()返回后宿主進程將被視為空進程,很容易被回收。
也就是說,對於耗時操作要用service作為與BroadcastReceiver的對接保證操作過程中進程是活動的。