BroadcastReceiver

本文介紹Broadcast Receiver,包括幾部分內容:Broadcast Receiver概述及實例、自定義Broadcast Receiver、Broadcast Receiver的實現細節、生命周期等。

? ? ? ?csdn貌似今天出問題了,無法上傳圖片。

? ? ? ? 資料來源:最牛網,《官方解讀BroadcastReceiver》《Android中Broadcast Receiver組件詳解》《(轉)第二十一講:Broadcast Receiver 使用入門》

? ? ? ??BroadcastReceiver(廣播接收器)是Android中的四大組件之一。
? ? ? ??下面是Android Doc中關于BroadcastReceiver的概述:
? ? ? ??①廣播接收器是一個專注于接收廣播通知信息,并做出對應處理的組件。很多廣播是源自于系統代碼的──比如,通知時區改變、電池電量低、拍攝了一張照片或者用戶改變了語言選項。應用程序也可以進行廣播──比如說,通知其它應用程序一些數據下載完成并處于可用狀態。
? ? ? ??②應用程序可以擁有任意數量的廣播接收器以對所有它感興趣的通知信息予以響應。所有的接收器均繼承自BroadcastReceiver基類。
? ? ? ??③廣播接收器沒有用戶界面。然而,它們可以啟動一個activity來響應它們收到的信息,或者用NotificationManager來通知用戶。通知可以用很多種方式來吸引用戶的注意力──閃動背燈、震動、播放聲音等等。一般來說是在狀態欄上放一個持久的圖標,用戶可以打開它并獲取消息。
Android中的廣播事件有兩種,一種就是系統廣播事件,比如:ACTION_BOOT_COMPLETED(系統啟動完成后觸發),ACTION_TIME_CHANGED(系統時間改變時觸發),ACTION_BATTERY_LOW(電量低時觸發)等等。另外一種是我們自定義的廣播事件。
? ? ? ??廣播事件的流程
? ? ? ??①注冊廣播事件:注冊方式有兩種,一種是靜態注冊,就是在AndroidManifest.xml文件中定義,注冊的廣播接收器必須要繼承BroadcastReceiver;另一種是動態注冊,是在程序中使用Context.registerReceiver注冊,注冊的廣播接收器相當于一個匿名類。兩種方式都需要IntentFIlter。
? ? ? ??②發送廣播事件:通過Context.sendBroadcast來發送,由Intent來傳遞注冊時用到的Action。
? ? ? ??③接收廣播事件:當發送的廣播被接收器監聽到后,會調用它的onReceive()方法,并將包含消息的Intent對象傳給它。onReceive中代碼的執行時間不要超過5s,否則Android會彈出超時dialog。

Broadcast Receiver接收系統自帶的廣播
我們做一個例子,功能是在系統啟動時播放一首音樂。
1、建立一個項目Lesson21_BroadcastReceiver,拷貝一首音樂進res/raw目錄
2、建立HelloBroadcastReceiver.java 內容如下:

Codepackage android.basic.lesson21;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.util.Log;public class HelloBroadReciever extends BroadcastReceiver {//如果接收的事件發生
    @Overridepublic void onReceive(Context context, Intent intent) {//則輸出日志Log.e("HelloBroadReciever", "BOOT_COMPLETED!!!!!!!!!!!!!!!!!!!!!!!!!");Log.e("HelloBroadReciever", ""+intent.getAction());//則播放一首音樂
        MediaPlayer.create(context, R.raw.babayetu).start();}
}

3、在AndroidManifest.xml中注冊此Receiver :

Code<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionname="1.0" android:versioncode="1" package="android.basic.lesson21"><application android:icon="@drawable/icon" android:label="@string/app_name"><activity android:label="@string/app_name" android:name=".MainBroadcastReceiver"><intent -filter=""><action android:name="android.intent.action.MAIN"><category android:name="android.intent.category.LAUNCHER"></category></action></intent></activity><!-- 定義Broadcast Receiver 指定監聽的Action --><receiver android:name="HelloBroadReciever"><intent -filter=""><action android:name="android.intent.action.BOOT_COMPLETED"></action></intent></receiver>
</application></manifest>

4、發布程序,啟動模擬器,可以在Logcat中看到:

同時能聽到音樂播放的聲音。說明我們確實接收到了系統啟動的廣播事件,并做出了響應。

三、自定義廣播
下面我們學習自己制作一個廣播。我們接著剛才的例子,繼續寫下去。
5、在MainBroadcastReceiver.java中填寫如下代碼:

Codepackage android.basic.lesson21;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;public class MainBroadcastReceiver extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Button b1 = (Button) findViewById(R.id.Button01);b1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//定義一個intentIntent intent = new Intent().setAction("android.basic.lesson21.Hello").putExtra("yaoyao","yaoyao is 189 days old ,27 weeks -- 2010-08-10");//廣播出去
                sendBroadcast(intent);}});}
}

6、更改 HelloBroadReceiver.java 內容如下:

Codepackage android.basic.lesson21;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.util.Log;public class HelloBroadReciever extends BroadcastReceiver {//如果接收的事件發生
    @Overridepublic void onReceive(Context context, Intent intent) {//對比Action決定輸出什么信息if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){Log.e("HelloBroadReciever", "BOOT_COMPLETED !!!!!!!!!!!!!!!!!!!!!!!!!");}if(intent.getAction().equals("android.basic.lesson21.Hello")){Log.e("HelloBroadReciever", "Say Hello to Yaoyao !!!!!!!!!!!!!!!!!!!!!!!!!");Log.e("HelloBroadReciever", intent.getStringExtra("yaoyao"));}//播放一首音樂
        MediaPlayer.create(context, R.raw.babayetu).start();}
}

7、更改 AndroidManifest.xml 內容如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.basic.lesson21" android:versionname="1.0" android:versioncode="1"><application android:icon="@drawable/icon" android:label="@string/app_name"><activity android:label="@string/app_name" android:name=".MainBroadcastReceiver"><intent -filter=""><action android:name="android.intent.action.MAIN"><category android:name="android.intent.category.LAUNCHER"></category></action></intent></activity><!-- 定義Broadcast Receiver 指定監聽的Action 這里我們的接收器,接收了2個Action,一個系統的一個我們自定義的  --><receiver android:name="HelloBroadReciever"><intent -filter=""><action android:name="android.intent.action.BOOT_COMPLETED"></action></intent><intent -filter=""><action android:name="android.basic.lesson21.HelloYaoYao"></action></intent></receiver>
</application>
<uses -sdk="" android:minsdkversion="8">
</uses></manifest>

8、運行程序,點擊按鈕,查看LogCat,聽聽聲音

?

? ? ? ??在使用Broadcast 時我們應該注意到,BroadcastReceiver的子類別都是無狀態的類別,每次收到發送廣播事件后,BroadcastReceiver都會創建一個新的對象,然后再執行onReceive()函數,當onReceive()函數執行完畢后,就立刻刪掉該對象,下一次再收到此廣播后,又會創建一個新的對象。所以說Broadcast組建是Android中最輕薄、最短小的組建。我們增加了一個static的變量numStatic ,和num變量 。代碼如下:

/*** Broadcaster.java* com.androidtest.broadcaster** Function: TODO**   ver     date              author* ──────────────────────────────────*            2011-6-9         Leon** Copyright (c) 2011, TNT All Rights Reserved.
*/package com.androidtest.broadcaster;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;/*** ClassName:Broadcaster* Function: TODO ADD FUNCTION* Reason:     TODO ADD REASON** @author   Leon* @version* @since    Ver 1.1* @Date     2011-6-9*/
public class Broadcaster extends BroadcastReceiver{private  static  final  String TAG = "Broadcaster";private  static  int  numStatic  =100 ;private  int  num =100 ;@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubString string = intent.getAction();numStatic= numStatic+50;num=100+50;Log.v(TAG  , "The action is "+ string + "Static Number is :" + numStatic+ " Object num is :" + num);}}

多次發送廣播,然后輸出的結果如下,我們可以看到static Number 每次執行都會增加,而Object Num因為每次都要創建所以一直都是一個固定的值。?

?

? ? ? ??上文中提到了BroadcastReceiver是Android中最輕薄、最短小的組件,它的對象生命周期十分短暫,經過傻蛋測試在BroadcastReceiver中讓線程睡眠10秒(Activity是5秒鐘)的話,Android就會彈出錯誤(和Activity超時的錯誤相同),同時需要注意的是Activity、Service和BroadcastReceiver都是運行在本進程的主線程里面的。通過這個測試讓傻蛋進一步產生了疑問,如果在Service中處理一個長時間的任務會怎么樣?
? ? ? ??啟動一個Service,然后在Service的onCreate()方法中添加如下代碼:

try {  Log.v(TAG , "sleep start …..");  Thread.sleep(20000);  Log.v(TAG,"sleep end …..");  
} catch (InterruptedException e) {  / / TODO Auto-generated catch block  e.printStackTrace();  
} 

很簡單就是讓Service睡眠20秒鐘,我們會發現,sleep start…. 和 sleep end….這兩個日志打印出來了,但是后臺還會出現如下錯誤,前臺彈出no response超時對話框。?

?

? ? ? ??在onCreate()中新啟動一個線程來,睡眠時,程序正常。
? ? ? 所以總結一下:無論是 Activity、BroadcastReceiver還是Service,只要是有長時間處理的任務,就需要重新開一個線程來處理,為什么會這樣?因為他們都是運行在主線程中的。
? ? ? ?在使用BroadcastReceiver時還有一個我們需要注意的:在BroadcastReceiver的onReceive(Context context , Intent intent )這第一個context到底是哪一個context?是Activity還是Application?通過測試發現:
如果你的BroadcastReceiver是通過在Activity中的this.registerReceiver(myBroadcaster, filter); 來注冊的話,那么這個context就是這個Activity,而如果是通過AndroidManifest來注冊的話,那么這個context就是:android.app.ReceiverRestrictedContext。


? ? ? ??BroadcastReceiver是接收從sendBroadcast()發出的intent的基類。你可以通過Context.registerReceiver()方法在代碼中動態的注冊一個BroadcastReceiver的實例,也可以通過再AndroidManifest.xml文件中用<receiver>標簽來靜態聲明。
? ? ? ?注意:如果你實在Activity.onResume()方法中注冊的一個receiver,那么你必須在Activity.onPause()方法中進行注銷。(當一個activity處于暫停狀態是不會接收intents的,并且這樣做也可以減小系統不必要的開銷)。不要在Activity.onSaveInstanceState()方法中注銷receiver,因為activity從棧中恢復的時候并不會調用這個方法了。
? ? ? ?可以接收的broadcast主要分為兩種類型:
? ? ? 普通的broadcasts(通過Context.sendBroadcast發送)是完全異步的。這個broadcast的receiver以無序的狀態運行,經常是在同一時刻運行。這種做法是十分高效的,但是也意味著receiver不能夠利用相互處理的結果或者是調用退出的API來退出(因為不知道哪個receiver先接收到intent)。
? ? ? 有序的broadcasts(通過Context.sendOrderedBroadcast發送)一次只發送給一個receiver。每一個receiver是有序的處理這個intent的,前面的receiver可以傳遞結果給下一個receiver,或者任意一個receiver都可以完全的退出,這樣intent就不會傳遞給其他的receivers.receiver的執行順序可以通過匹配的intent-filter中的android:priority屬性來控制;如果有多個receivers處于同一個優先級,那么這幾個receivers將會以任意的順序來執行。
? ? ? 即使是在廣播普通的broadcasts的情況下,系統也有可能在某些情況下轉換為一次發送一個broadcast給一個receriver。特別是當receivers需要創建進程時,在同一時刻僅僅一個receiver可以運行,避免系統因為這些新建的進程而過載。
? ? ? 注意:盡管Intent類是用來發送和接受這些broadcasts,這里的Intent broadcast機制和那些通過Context.startActivity()方法來啟動activity的intent是完全獨立的。一個BroadcastReceiver是沒辦法觀察和捕獲一個用于啟動activity的intent的;同樣的,當你通過intent來發出broadcast時,你也不可能(通過這個intent)找到或者啟動一個activity的。這兩種操作是完全不同的:通過一個intent來啟動一個activity是一個前臺操作,會改變用戶當前交互的對象;而通過intent來發出broadcast是一個后臺操作,用戶經常是察覺不到的。
? ? ? BroadcastReceiver類(通過一個manifest的<receiver>標簽作為一個組件啟動)是應用程序全局聲明周期重要的一部分。

討論的主題
? ?1、Receiver的生命周期
? ?2、權限
? ?3、進程的生命周期
??
開發者指南
? ?更詳細的關于如何獲取和解析一個Intent的內容,請詳見Intents and Intent Filters開發者指南
??
Receiver的生命周期
? ? ? ?一個BroadcastReceiver的對象僅僅在調用onReceiver(COntext, Intent)的時間中有效。一旦你的代碼從這個函數中返回,那么系統就認為這個對象應該結束了,不能再被激活。
? ? ? 你在onReceive(Context, Intent)中的實現有著非常重要的影響:任何對于異步操作的請求都是不允許的,因為你可能需要從這個函數中返回去處理異步的操作,但是在那種情況下,BroadcastReceiver將不會再被激活,因此系統就會再異步操作之前殺死這個進程。
? ? ? 特別是,你不應該再一個BroadcastReceiver中顯示一個對話框或者綁定一個服務。對于前者(顯示一個對話框),你應該用NotificationManagerAPI來替代,對于后者(綁定一個服務),你可以使用Context.startService()發送一個命令給那個服務來實現綁定效果。
權限
? ? ?存取的權限可以通過在發送方的Intent或者接收方的Intent中強制指定。
? ? ?在發送一個broadcast時強制指定權限,就必須提供一個非空的peemission參數給sendBroadcast(Intent, String)或者是sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handel, int, String, Bundle).只有那些擁有這些權限(通過在ANdroidManifest.xml文件中相應的聲明<uses-permission>標簽)的receiver能夠接收這些broadcast。
? ? ? 在接收一個broadcast時強制指定權限,就必須在注冊receiver時提供一個非空的permission參數--無論是在調用registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)或者是通過再AndroidManifest.xml文件中通過<receiver>靜態標簽來聲明。只有那些擁有這些權限(通過在相應的AndroidManifest.xml文件中查詢<uses-permission>標簽來獲知)的發送方將能夠給這個receiver發送Intent。
? ? ? 對于安全和權限的詳細內容請查看Security and Permission文檔。
進程的生命周期
? ? ? 一個正在執行BroadcastReceiver(也就是,正在執行onReceive(COntext, Intent)方法)的進程被認為是一個前臺的進程,將會一直運行,除非系統處于內存極度低的情況下。
? ? ? 一旦從OnReceive()方法中返回,這個BroadcastReceiver將不會再被激活,此時它的主進程就和任何其他運行于此應用程序中的組件擁有相同的優先級。這一點非常重要,如果進程僅僅只是擁有BroadReceiver(一個普遍的情況是用戶從不或者是最近沒有和它進行交互),因此一旦它從onReceive()方法中返回時,系統就會認為進程是空的并且主動的殺死它,以便這些資源可以被其他重要的進程利用。
? ? ? 這意味著對于耗時的操作,可以采用將Service和BroadcastReceiver結合使用以確保執行這個操作的進程在整個執行過程中都保持激活狀態。

轉載于:https://www.cnblogs.com/maydow/p/5082763.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458509.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458509.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458509.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何確定VS編譯器版本--_MSC_VER || #if _MSC_VER 1000 #pragma once #endif

如何確定VS編譯器版本 _MSC_VER是MSVC編譯器的內置宏&#xff0c;定義了編譯器的版本&#xff0c;_MSC_VER 值對應版本關系 MSVC 11.0 _MSC_VER 1700 (Visual Studio 2012) MSVC 10.0 _MSC_VER 1600 (Visual Studio 2010) MSVC 9.0 _MSC_VER 1500 (Visual Studio 2008) …

NIO復習02

Selector 1. Selector&#xff08;選擇器&#xff09;是Java NIO中能夠檢測一到多個NIO通道&#xff0c;并能夠知曉通道是否為諸如讀寫事件做好準備的組件。這樣&#xff0c;一個單獨的線程可以管理多個channel&#xff0c;從而管理多個網絡連接。 2. Selector的創建&#xff1…

c/c++標準預定義宏

C標準中的一些預定義宏昨天寫代碼時需要在代碼獲取當前編譯時間&#xff0c;從而可動態地作為版本信息&#xff0c;因此用到了C標準中的一些預定義的宏。在此將C標準中定義的幾個宏一并總結一下&#xff1a; __DATE__ 進行預處理的日期&#xff08;“Mmm dd yyyy”形式的字符串…

安裝cocoa pods時出現Operation not permitted - /usr/bin/xcodeproj的問題

在更新完ruby&#xff0c;更換Ruby鏡像&#xff0d;&#xff0d;淘寶的那個鏡像(https://ruby.taobao.org/ )已經不可用了。官方的需要FQ。所以我們現在用最新支持的ruby鏡像(https://gems.ruby-china.org/) 安裝cocoa pods時&#xff0c; 在命令行中輸入&#xff1a; 安裝&…

js 日期控件laydate使用

官網 http://sentsin.com/layui/laydate/ 1. 下載官網上的壓縮包,解壓后只需要復制laydate 文件夾到你的項目中; 2. 在頁面引入 <script type"text/javascript" src"js/laydate/laydate.js"></script> 3. 在頁面添加: <div class"i…

老李推薦:第8章2節《MonkeyRunner源碼剖析》MonkeyRunner啟動運行過程-解析處理命令行參數 2...

我們這一節會先去分析下monkeyrunner是如何對參數進行處理的&#xff0c;我們跳轉到MonkeyRunnerOptions這個類里面的processOptions這個方法&#xff1a; 93 public static MonkeyRunnerOptions processOptions(String[] args) 94 { 95 int index 0; 96 97 Strin…

MFC CPropertySheet 多頁面切換 實例

為了能實現在同一個頁面實現多個頁面的切換效果。CPropertySheet要與CPropertyPage一起使用。 首先 新建一個MFC工程--MFC AppWizard(exe), 取名Pagesheet, 選擇Dialog based, 然后Finish. 2. 在對話框資源中插入兩個對話框IDD_DIALOG1、IDD_DIALOG2&#xff0c;作為…

ReactiveCocoa簡單介紹

ReactiveCocoa 的簡單介紹 http://www.jianshu.com/p/87ef6720a096

游戲提高性能 游戲降幀處理

什么是降幀&為什么降幀 一般情況下我們為了提高整個游戲的體驗&#xff0c;所以我們一般會將游戲的幀數&#xff08;每秒鐘刷新多少次&#xff09;設置的比較高。一般情況下&#xff0c;我們的游戲所有的代碼都是一幀執行一次。為了讓每一幀都變成真的關鍵數據幀。不過&…

delphi 更改DBGrid 顏色技巧

1、根據條件更改某一單元格的顏色 [delphi] view plaincopy procedure TMainFrm.First_DGDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); begin if DM.FirstListStatus.AsString生產 then begin …

mfc中UpdateData的用法

http://blog.csdn.net/ddjj_1980/article/details/51452289 UpdateData(TRUE)——刷新控件的值到對應的變量。(外部輸入值交給內部變量)即&#xff1a;控件的值—>變量。UpdateData(FALSE)—— 拷貝變量值到控件顯示。(變量的最終運算結果值交給外部輸出顯示)即&#xff1a;…

動畫類的層次結構

CASpringAnimation類是CAABasicAnimation的子類 CAPropertyAnimation &#xff1a;是CAAnimation的子類&#xff0c;它支持動畫地顯示圖層的keyPath&#xff0c;一般不直接使用。 iOS9.0之后新增CASpringAnimation類&#xff0c;它實現彈簧效果的動畫&#xff0c;是CABasicAnim…

[原]小命令大作用:modprobe

調整網絡為綁定模式&#xff0c;但啟動時候會報錯&#xff0c;此時執行命令 modprobe bonding 可以解決問題。 之前在磁盤方面遇到問題也是通過modprobe命令解決的&#xff0c;又遇到這個命令&#xff0c;似曾相識。于是看下該命令&#xff1a; Linux命令&#xff1a;modprobe …

sql語句優化之not in

多表關聯想查a表中除去b表的可用not exists 效率比not in 更高 優化后的語句用時0.421秒 select john.*, (case when round((case john.sumcount when 0 then 0 else mycount * 100 / sumcount end), 2) > 100 then 100 else round((case john.sumcount when 0 then 0 else …

setup2go制作安裝程序

QT程序設計完畢時&#xff0c;我們就要發布自己的程序&#xff0c;發布程序有兩種方法&#xff1a;一是靜態編譯&#xff0c;二是制作程序安裝包。 靜態編譯好麻煩&#xff0c;我從來沒有成功過&#xff0c;所以我用了動態編譯方法&#xff0c;設計完成時&#xff0c;用release…

gson-2.2.api簡單

使用gson的tojson和fromjson實現對象和json的轉換 Gson gson new Gson(); // Or use new GsonBuilder().create(); MyType target new MyType(); String json gson.toJson(target); // serializes target to Json MyType target2 gson.fromJson(json, MyType.c…

用戶需求、己、競爭對手的關系

圖一 圖二 圖三 如第一圖所示&#xff1a;現在在市面上的產品基本上都可以歸納為這一方面&#xff0c; 如“用戶需求”是網上購物的需求&#xff0c;以“己”是京東為例子&#xff0c;“己”的…

SharePoint 入門介紹

from&#xff1a;http://www.cnblogs.com/jianyus/archive/2013/01/11/2856963.html 前言&#xff1a;接觸SharePoint兩年有余&#xff0c;從一開始的小白&#xff0c;變成現在的菜鳥&#xff0c;一路走來&#xff0c;學到很多&#xff0c;現在&#xff0c;想把自己知道的東西&…

AJAX-服務器響應

服務器響應 如需獲得來自服務器的響應&#xff0c;請使用 XMLHttpRequest 對象的 responseText 或 responseXML 屬性。 屬性 描述 responseText 獲得字符串形式的響應數據。 responseXML 獲得 XML 形式的響應數據。 responseText 屬性 如果來自服務器的響應并非 XML&#xff0c…

c#下不同命名空間的引用(一個project使用另外一個project的名稱空間)

http://bbs.csdn.net/topics/300089064 兩個命名空間在同一個項目中時&#xff0c;沒有任何問題。 若兩個命名空間不在同一個項目中&#xff0c;則變成兩個程序集之間的互相引用。 程序集之間的引用無所謂循環不循環的問題。 但如果兩個程序集要互相引用&#xff0c;并且兩個…