天天看點

Android元件系列----BroadcastReceiver廣播接收器

【正文】

一、廣播的功能和特征

廣播的生命周期很短,經過調用對象-->實作onreceive-->結束,整個過程就結束了。從實作的複雜度和代碼量來看,廣播無疑是最迷你的android 元件,實作往往隻需幾行代碼。廣播對象被構造出來後通常隻執行broadcastreceiver.onreceive方法,便結束了其生命周期。是以有的時候我們可以把它當做函數看也未必不可。

和所有元件一樣,廣播對象也是在應用程序的主線程中被構造,是以廣播對象的執行必須是要同步且快速的。也不推薦在裡面開子線程,因為往往線程還未結束,廣播對象就已經執行完畢被系統銷毀。如果需要完成一項比較耗時的工作 , 應該通過發送 intent 給 service, 由 service 來完成。

每次廣播到來時 , 會重新建立 broadcastreceiver 對象 , 并且調用 onreceive() 方法 , 執行完以後 , 該對象即被銷毀 . 當 onreceive() 方法在 10 秒内沒有執行完畢, android 會認為該程式無響應。

二、接收系統廣播:

廣播接收器可以自由地對自己感興趣的廣播進行注冊,這樣當有相應的廣播發出時,廣播接收器就能收到該廣播,并在内部處理相應的邏輯。注冊廣播的方式有兩種,在代碼中注冊和在清單檔案中注冊,前者稱為動态注冊,後者稱為靜态注冊。

1、動态注冊監聽網絡變化:

建立工程檔案,首先在mainactivity中定義一個内部類networkchangereceiver,并重寫父類的onreceive()方法,這樣每當網絡狀态發生變化時,onreceive()方法就會得到執行,這裡使用toast提示一段文本資訊,代碼如下:

緊接着在oncreate方法中進行動态注冊,然後在ondestroy方法中進行取消注冊:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

上方代碼解釋如下:

11行:給意圖過濾器intentfilter添加一個值為android.net.conn.connectivity_change的action。因為每當網絡狀态發生變化時,系統就會發出一條值為android.net.conn.connectivity_chang的廣播。

注:最後要記得,動态注冊的廣播接收器一定要取消注冊才行。

運作程式,就可以了。

不過隻是提醒網絡發生變化還不夠人性化,為了能夠準确的告訴使用者目前是有網絡還是沒有網絡,我們還需要對上述代碼進一步優化,修改networkchangereceiver中的代碼如下:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

上方代碼解釋:

06行:在onreceive()方法中,首先通過通過getsystemservice()方法得到connectionmanager這個系統服務類,專門用于管理網絡連接配接。

07行:然後調用它的getactivenetworkinfo()方法可以得到networkinfo的執行個體,接着調用networkinfo的isavailable()方法,就可以判斷目前是否有網絡了,最後通過toast提示使用者。

另外,查詢系統的網絡狀态是需要申明權限的,打開清單檔案,添加如下權限:

現在運作程式,就可以了。

上方程式完整版代碼如下:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

2、靜态注冊實作開機啟動:

動态注冊的方式比較靈活,但缺點是:必須在程式啟動之後才能接收到廣播,因為注冊的邏輯是寫在oncreate()方法中的。為了讓程式在未啟動的情況下就能接收到廣播,這裡就需要使用到靜态注冊。

這裡我們準備讓程式接收一條開機廣播,當收到這條廣播時,就可以在onreceive()方法中執行相應的邏輯,進而實作開機啟動的功能。

建立一個類:bootcompletereceiver,讓他繼承broadcastreceiver,在onreceive()方法中簡單地toast一下,代碼如下:

可以看到,這裡不再使用内部類的方式來定義廣播接收器,因為稍後我們需要在清單檔案androidmanifest.xml中将這個廣播接收器的類名注冊進去。

然後修改清單檔案androidmanifest.xml,代碼如下:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

代碼解釋如下:

終于,<application>标簽内多了個子标簽<receiver>,所有的靜态注冊的廣播接收器都是在這裡進行注冊的。

22行:name中為廣播接收器的名字

24行:想要接收的廣播。android系統啟動完成後,會發出這條名為android.intent.action.boot_completed的廣播。

05行:監聽系統開機廣播需要聲明權限。

運作程式後,将手機關機重新開機,就能收到這條廣播了。

三、發送自定義廣播

1、發送标準廣播  

建立工程檔案。在發廣播之前,我們先定義一個廣播接收器來接收此廣播才行。是以,建立一個類:mybroadcastreceiver,讓他繼承broadcastreceiver,代碼如下:

這裡,當mybroadcastreceiver 收到自定義的廣播時,就會執行onreceive()方法中的邏輯,彈出一個toast。

緊接着,要在清單檔案androidmanifest.xml中對這個廣播接收器進行注冊:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

代碼解釋:

18行:讓mybroadcastreceiver接收一條值為om.example.m05_broadcastreceiver02.my_broadcast的廣播,是以待會兒在發送廣播的時候,我們就需要發出這樣的一條廣播。

緊接着,修改activity.xml中的代碼,添加一個按鈕button。

然後,修改mainactivity.java中的代碼,添加button的監聽事件:點選按鈕時,發送廣播

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

總結:可以看到,點選按鈕時,發送com.example.m05_broadcastreceiver02.my_broadcast這條廣播,這樣,所有能夠監聽com.example.m05_broadcastreceiver02.my_broadcast這條廣播的廣播接收器就都會同時收到消息,此時發出去的就是一條标準廣播,即無序廣播。是以接下來就需要講到有序廣播。

2、發送有序廣播:

廣播是一種可以跨程序的通信方式,其他應用程式是可以收到的。現在我們來發一條有序廣播。

有序廣播不僅有先後順序,而且前面的廣播還可以将後面的廣播截斷。

在3.1的代碼基礎之上,将按鈕的監聽事件修改如下:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

即将06行代碼修改一下,将sendbroadcast()方法改為sendorderedbroadcast()方法,sendorderedbroadcast()方法接收兩個參數,第二個參數是一個與權限相關的字元串,這裡傳入null即可。

緊接着,修改清單檔案androidmanifest.xml中對廣播接收器的注冊,設定優先級:

即添加第02行代碼。可以看到,通過android:priority屬性給廣播接收器設定了優先級。這個屬性的範圍在-1000到1000,數值越大,優先級越高。

接下來,如果想要攔截這個廣播,防止讓後面的廣播接收器也接收到了這個廣播。可以修改mybroadcastreceiver中的代碼:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

即添加第06行代碼。如果在onreceive()方法中調用了abortbroadcast()方法,就表示是将這條廣播攔截,後面的廣播接收器将無法再接收到。

特别關注:

廣播接收器的生命周期:關鍵在于broadcastreceiver中的onreceive()方法,從onreceive()裡的第一行代碼開始,onreceive()裡的最後一行代碼結束。

一個廣播到來的時候,用什麼方式提醒使用者是最友好的呢?第一種方式是吐司,第二種方式是通知。注:不要使用對話框,以免中斷了使用者正在進行的操作。

四、使用本地廣播:

之前我們發送和接收的廣播全部都是屬于全局廣播,即發出去的廣播可以被其他任何應用程式接收到,并且我們也可以接收來自于其他任何應用程式的廣播。這樣一來,必然會造成安全問題。于是便有了本地廣播:即隻能在本應用程式中發送和接收廣播。這就要使用到了localbroadcastmanager這個類來對廣播進行管理。

我們修改2.1中動态注冊廣播接收器的代碼,即修改mainactivity.java中的代碼如下:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

注:本地廣播是無法通過靜态注冊的方式來接收的。其實也完全可以了解,因為靜态注冊主要就是為了讓程式在未啟動的情況下也能收到廣播。而發送本地廣播時,我們的程式肯定是已經啟動了,沒有必要使用到靜态注冊的功能。

五、各種各樣的廣播: 

在android中有很多系統自帶的intent.action,通過監聽這些事件我們可以完成很多功能。

開機:

string boot_completed_action 廣播:在系統啟動後。這個動作被廣播一次(隻有一次)。監聽: “android.intent.action.boot_completed”

電話撥入:

string answer_action 動作:處理撥入的電話。監聽: “android.intent.action.answer”

電量變化:

string battery_changed_action 廣播:充電狀态,或者電池的電量發生變化。監聽: “android.intent.action.battery_changed”

日期改變:

string date_changed_action 廣播:日期被改變。 監聽:“android.intent.action.date_changed”

取消更新下載下傳:

string fota_cancel_action 廣播:取消所有被挂起的 (pending) 更新下載下傳。 監聽:“android.server.checkin.fota_cancel”

更新開始安裝:

string fota_ready_action 廣播:更新已經被下載下傳 可以開始安裝。監聽 “android.server.checkin.fota_ready”

主螢幕:

string home_category 類别:主螢幕 (activity)。裝置啟動後顯示的第一個 activity。 監聽:"android.intent.category.home”

新應用:

string package_added_action 廣播:裝置上新安裝了一個應用程式包。監聽: “android.intent.action.package_added”

删除應用:

string package_removed_action 廣播:裝置上删除了一個應用程式包。監聽: “android.intent.action.package_removed”

螢幕關閉:

string screen_off_action 廣播:螢幕被關閉。監聽: “android.intent.action.screen_off”

螢幕開啟:

string screen_on_action 廣播:螢幕已經被打開。 監聽:“android.intent.action.screen_on”

時區改變:

string timezone_changed_action 廣播:時區已經改變。監聽: “android.intent.action.timezone_changed”

時間改變:

string time_changed_action 廣播:時間已經改變(重新設定)。 “android.intent.action.time_set”

時間流逝:

string time_tick_action 廣播:目前時間已經變化(正常的時間流逝)。 “android.intent.action.time_tick”

進入大容量存儲模式:

string ums_connected_action 廣播:裝置進入 usb 大容量存儲模式。 “android.intent.action.ums_connected”

退出大容量存儲模式:

string ums_disconnected_action 廣播:裝置從 usb 大容量存儲模式退出。 “android.intent.action.ums_disconnected”

桌面改變:

string wallpaper_changed_action 廣播:系統的牆紙已經改變。 “android.intent.action.wallpaper_changed”

web搜尋:

string web_search_action 動作:執行 web 搜尋。 “android.intent.action.web_search”

網絡變化:

string connectivity_change_action 動作:網絡變化。“android.intent.action.connectivity_change_action”

六、執行個體:使用動态注冊,監聽手機的電量變化。

完整版代碼如下:

(1)activity_main.xml代碼如下:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

(2)mainactivity.java的代碼如下:

Android元件系列----BroadcastReceiver廣播接收器
Android元件系列----BroadcastReceiver廣播接收器

緊接着,在清單檔案中進行權限聲明:

mainactivity.java的代碼解釋如下:

40至45行:固定代碼,用于擷取目前電量

48至50行:當電量低時,可以進行一些操作,例如彈出通知等

運作後,界面如下:

Android元件系列----BroadcastReceiver廣播接收器

繼續閱讀