Android Broadcast Receive廣播接收器詳解

廣播(Broadcast)是一種廣泛運用的在應(yīng)用程序之間傳輸信息的機制,在 Android 里面有各種各樣的廣播汞窗,比如電池的使用狀態(tài),電話的接收和短信的接收都會產(chǎn)生一個廣播,應(yīng)用程序也可以接受廣播并做出程序邏輯上的處理, 比如我們需要讓應(yīng)用程序開機自動啟動示启,其實就是應(yīng)用了廣播的知識。
廣播的三要素分別是:
1.廣播(Broadcast) - 用于發(fā)送廣播溯捆;
2.廣播接收器(BroadcastReceiver) - 用于接收廣播丑搔;
3.意圖(Intent)-用于保存廣播相關(guān)信息的媒介。
下面是我從網(wǎng)上搜集的一些廣播的知識點:
1.普通廣播
普通廣播是完全異步的提揍,可以在同一時刻(邏輯上)被所有廣播接收者接收到啤月,消息傳遞的效率比較高,但缺點是接收者不能將處理結(jié)果傳遞給下一個接收者劳跃,并且無法終止廣播Intent的傳播谎仲。
2.有序廣播
有序廣播是按照接收者聲明的優(yōu)先級別(聲明在intent-filter元素的android:priority屬性中,數(shù)越大優(yōu)先級別越高,取值范圍:-1000到1000刨仑。也可以調(diào)用IntentFilter對象的setPriority()進行設(shè)置)郑诺,被接收者依次接收廣播。如:A的級別高于B, B的級別高于C,那么杉武,廣播先傳給A辙诞,再傳給B,最后傳給C轻抱。A得到廣播后飞涂,可以往廣播里存入數(shù)據(jù),當(dāng)廣播傳給B時,nB可以從廣播中得到A存入的數(shù)據(jù)祈搜。
3系統(tǒng)廣播
系統(tǒng)廣播是Android內(nèi)置的廣播较店,滿足一定條件后系統(tǒng)會自動發(fā)送這個廣播,不需要我們再定義發(fā)送容燕,只需要用的時候接收就可以了梁呈,比如手機開機完成后會發(fā)出一條廣播,電池的電量發(fā)生變化會發(fā)出一 條廣播,時間或時區(qū)發(fā)生改變也會發(fā)出一條廣播,攝像頭按被按下會觸發(fā)廣播等等蘸秘。
4自定義廣播
自定義廣播是用戶可以自己定義發(fā)送一個廣播官卡,看到很多書籍都是這么講蝗茁,可以我一直在思考為什么需要自定義廣播,或者說自定義廣播在Android程序中一般是用在什么地方寻咒,因為廣播是為了給不同的組件中通信而使用的例如service 與 Activity 不同的進程中,或者不同的應(yīng)用程序中就會使用廣播機制來通信的评甜。
5本地廣播
系統(tǒng)廣播和自定義廣播都屬于全局廣播,即發(fā)出的廣播可以被其他任何 的任何應(yīng)用程序接收到, 并且我們也可以接收來自于其他任何應(yīng)用程序的廣播。這樣就很容易會引起安全性的問題, 比如說我們發(fā)送的一些攜帶關(guān)鍵性數(shù)據(jù)的廣播有可能被其他的應(yīng)用程序截獲,或者其他的程序不停地向我們的廣播接收器里發(fā)送各種垃圾廣播仔涩。
為了能夠簡單地解決廣播的安全性問題,Android 引入了一套本地廣播機制,使用這個機制發(fā)出的廣播只能夠在應(yīng)用程序的內(nèi)部進行傳遞,并且廣播接收器也只能接收來自本應(yīng)用程序發(fā)出的廣播,這樣所有的安全性問題就都不存在了忍坷。
6動態(tài)注冊廣播
動態(tài)注冊就是在程序中使用Context.registerReceiver注冊。動態(tài)注冊的廣播接收器可以自由地控制注冊與注銷,在靈活性方面有很大的優(yōu)勢,但是它也存在著一個缺點,即必須要在程序啟動之后才能接收到廣播,因為注冊的邏輯是寫在 onCreate()方法中的熔脂。
7靜態(tài)注冊廣播
在AndroidManifest.xml中注冊廣播稱之為靜態(tài)注冊佩研,靜態(tài)注冊是常駐型 ,也就是說當(dāng)應(yīng)用程序關(guān)閉后霞揉,如果有信息廣播來旬薯,程序也會被系統(tǒng)調(diào)用自動運行,所以一些系統(tǒng)級別的廣播比如開機啟動廣播就必須要用到靜態(tài)注冊的方法适秩,而有些系統(tǒng)廣播也是可以動態(tài)注冊的绊序,比如電量變化廣播等可以在程序啟動后監(jiān)聽即可。
下面我通過例子簡單的介紹一下廣播機理:
(1)首先舉一個系統(tǒng)廣播的例子秽荞,這里我們通過靜態(tài)注冊廣播的方式來完成
首先要再AndroidManifest.xml中注冊廣播接收機
<pre>
//注冊廣播接收機骤公,監(jiān)聽開機廣播
<receiver android:name=".MyBroadcastReceive">
<intent-filter>
//通過android:name來指定具體注冊哪一個廣播接收器
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</pre>
新建廣播接收機,創(chuàng)建MyBroadcastReceive.java
<pre>
public class MyBroadcastReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"開機啟動",Toast.LENGTH_LONG).show();
}
}
</pre>
運行程序候扬跋,重啟虛擬機阶捆,在開機時可以看到“開機啟動”的Toast
(2)下面我們通過靜態(tài)注冊廣播的方式完成自定義廣播
首先在AndroidManifest.xml文件中靜態(tài)注冊自定廣播接收機
<pre>
<receiver android:name=".DiyBroadReceive">
<intent-filter>
//通過android:name來指定具體注冊哪一個廣播接收器,這里可以自己任意指定name
<action android:name="linus.diyBroadReceive" />
</intent-filter>
</receiver>
</pre>
創(chuàng)建自定義廣播接收機钦听,新建DiyBroadReceive.java
<pre>
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setAction("linus.diyBroadReceive");
intent.putExtra("name", "linus");
sendBroadcast(intent);
}
});
</pre>
(3)下面我們來看一下如何動態(tài)注冊一個自定義廣播接收機
<pre>
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//實例化廣播接收器
dynamicBroadReceive = new DynamicBroadReceive();
//實例化意圖過濾器
filter = new IntentFilter();
//為過濾器添加一個定義的廣播洒试,當(dāng)然這里也可以填系統(tǒng)廣播
filter.addAction("linus.dynamicBroadReceive");

            //可以通過setPriority()設(shè)置動態(tài)廣播的優(yōu)先級,優(yōu)先級取值范圍是-1000到1000
            //注意的是的靜態(tài)注冊的廣播要快于動態(tài)注冊的廣播,不管動態(tài)注冊的優(yōu)先級設(shè)置的多高,不管靜態(tài)注冊的優(yōu)先級有多低
            filter.setPriority(1000);
            //第一步朴上,注冊廣播
            registerReceiver(dynamicBroadReceive, filter);
            
            //第二部垒棋,發(fā)送廣播
            Intent intent = new Intent();
            intent.setAction("linus.dynamicBroadReceive");
            intent.putExtra("name","linus-dynamic");
            sendBroadcast(intent);
        }
    });

</pre>
創(chuàng)建自定義廣播,新建DynamicBroadReceive.java
<pre>
public class DynamicBroadReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//第三部痪宰,接收廣播
String name = intent.getExtras().getString("name");
Toast.makeText(context,"動態(tài)注冊廣播后叼架,接收到的名字是"+name,Toast.LENGTH_SHORT).show();
}
}
</pre>
動態(tài)注冊廣播,在結(jié)束時必須注銷廣播
<pre>
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(dynamicBroadReceive);
}
</pre>
(4)下面在舉例說明一下本地廣播酵镜,本地廣播無法通過靜態(tài)注冊完成廣播注冊碉碉。因為當(dāng)廣播到來時柴钻,應(yīng)用一定時啟動的淮韭。本地廣播一般時通過LocalBroadcastManager進行管理的
<pre>
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
localBroadcastManager = LocalBroadcastManager.getInstance(getBaseContext());
localBroadReceive = new LocalBroadReceive();
filter = new IntentFilter();
filter.addAction("linus.localBroadReceive");
localBroadcastManager.registerReceiver(localBroadReceive,filter);

            Intent intent = new Intent();
            intent.setAction("linus.localBroadReceive");
            intent.putExtra("name","linus-local");
            localBroadcastManager.sendBroadcast(intent);
        }
    });

</pre>
創(chuàng)建本地廣播接收機,創(chuàng)建LocalBroadReceive.java
<pre>
public class LocalBroadReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getExtras().getString("name");
Toast.makeText(context,"本地廣播接收到的name是"+name,Toast.LENGTH_SHORT).show();
}
}
</pre>
本地廣播在結(jié)束時贴届,也是需要注銷廣播的靠粪。
<pre>
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localBroadReceive);
}
</pre>
(5)有序廣播就是按照廣播的優(yōu)先級進行廣播蜡吧,不同的應(yīng)用接收到廣播的先后順序不同。同時先接收到廣播的應(yīng)用可以向后接收到的廣播傳遞數(shù)據(jù)占键。這里就不舉例說明了昔善。
為了方面大家實踐測試,我將整個demo的源碼分享一下畔乙。
MainActivity.java
<pre>
package linuszhao.js.one.jsbroadcast;

import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

private Button btn1, btn2,btn3;
//定義意圖過濾器
private IntentFilter filter;
//定義廣播接收器
DynamicBroadReceive dynamicBroadReceive;

LocalBroadReceive localBroadReceive;
private LocalBroadcastManager localBroadcastManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btn1 = (Button) findViewById(R.id.btn1);
    btn2 = (Button) findViewById(R.id.btn2);
    btn3 = (Button) findViewById(R.id.btn3);
    btn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent();
            intent.setAction("linus.diyBroadReceive");
            intent.putExtra("name", "linus");
            sendBroadcast(intent);
        }
    });
    btn2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //實例化廣播接收器
            dynamicBroadReceive = new DynamicBroadReceive();
            //實例化意圖過濾器
            filter = new IntentFilter();
            //為過濾器添加一個定義的廣播君仆,當(dāng)然這里也可以填系統(tǒng)廣播
            filter.addAction("linus.dynamicBroadReceive");

            //可以通過setPriority()設(shè)置動態(tài)廣播的優(yōu)先級,優(yōu)先級取值范圍是-1000到1000
            //注意的是的靜態(tài)注冊的廣播要快于動態(tài)注冊的廣播,不管動態(tài)注冊的優(yōu)先級設(shè)置的多高,不管靜態(tài)注冊的優(yōu)先級有多低
            filter.setPriority(1000);
            //注冊廣播
            registerReceiver(dynamicBroadReceive, filter);

            Intent intent = new Intent();
            intent.setAction("linus.dynamicBroadReceive");
            intent.putExtra("name","linus-dynamic");
            sendBroadcast(intent);
        }
    });

    btn3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            localBroadcastManager = LocalBroadcastManager.getInstance(getBaseContext());
            localBroadReceive = new LocalBroadReceive();
            filter = new IntentFilter();
            filter.addAction("linus.localBroadReceive");
            localBroadcastManager.registerReceiver(localBroadReceive,filter);

            Intent intent = new Intent();
            intent.setAction("linus.localBroadReceive");
            intent.putExtra("name","linus-local");
            localBroadcastManager.sendBroadcast(intent);
        }
    });

}

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(dynamicBroadReceive);
    localBroadcastManager.unregisterReceiver(localBroadReceive);
}

}
</pre>
activity_main.xml
<pre>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="linuszhao.js.one.jsbroadcast.MainActivity"
android:orientation="vertical">

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn1"
    android:text="發(fā)起自定義廣播"/>
<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn2"
    android:text="動態(tài)發(fā)送廣播"/>
<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn3"
    android:text="發(fā)起本地廣播"/>

</LinearLayout>
</pre>
Androidmanifest.xml
<pre>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="linuszhao.js.one.jsbroadcast">

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    //注冊廣播接收機牲距,監(jiān)聽開機廣播
    <receiver android:name=".MyBroadcastReceive">
        <intent-filter>
            //通過android:name來指定具體注冊哪一個廣播接收器
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    //注冊廣播接收機
    <receiver android:name=".DiyBroadReceive">
        <intent-filter>
            //通過android:name來指定具體注冊哪一個廣播接收器返咱,這里可以自己任意指定name
            <action android:name="linus.diyBroadReceive" />
        </intent-filter>
    </receiver>

</application>

</manifest>
</pre>
DiyBroadReceive.java
<pre>
package linuszhao.js.one.jsbroadcast;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

/**

  • Created by linus on 2017/3/5.
    */
    public class DiyBroadReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    Toast.makeText(context,"自定義廣播接收機接收到的名字是"+name,Toast.LENGTH_SHORT).show();
    }
    }

</pre>
MyBroadcastReceive.java
<pre>
package linuszhao.js.one.jsbroadcast;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

/**

  • Created by linus on 2017/3/5.
    */
    public class MyBroadcastReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    Toast.makeText(context,"開機啟動",Toast.LENGTH_LONG).show();
    }
    }
    </pre>
    DynamicBroadReceive.java
    <pre>
    package linuszhao.js.one.jsbroadcast;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

/**

  • Created by linus on 2017/3/5.
    */
    public class DynamicBroadReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    Toast.makeText(context,"動態(tài)注冊廣播后,接收到的名字是"+name,Toast.LENGTH_SHORT).show();
    }
    }

</pre>
LocalBroadReceive.java
<pre>
package linuszhao.js.one.jsbroadcast;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

/**

  • Created by linus on 2017/3/5.
    */
    public class LocalBroadReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    Toast.makeText(context,"本地廣播接收到的name是"+name,Toast.LENGTH_SHORT).show();
    }
    }

</pre>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牍鞠,一起剝皮案震驚了整個濱河市咖摹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌难述,老刑警劉巖萤晴,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異胁后,居然都是意外死亡店读,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門攀芯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來两入,“玉大人,你說我怎么就攤上這事敲才」桑” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵紧武,是天一觀的道長剃氧。 經(jīng)常有香客問我,道長阻星,這世上最難降的妖魔是什么朋鞍? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮妥箕,結(jié)果婚禮上滥酥,老公的妹妹穿的比我還像新娘。我一直安慰自己畦幢,他們只是感情好坎吻,可當(dāng)我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宇葱,像睡著了一般瘦真。 火紅的嫁衣襯著肌膚如雪刊头。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天诸尽,我揣著相機與錄音原杂,去河邊找鬼。 笑死您机,一個胖子當(dāng)著我的面吹牛穿肄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播际看,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼被碗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了仿村?” 一聲冷哼從身側(cè)響起锐朴,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蔼囊,沒想到半個月后焚志,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡畏鼓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年酱酬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片云矫。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡膳沽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出让禀,到底是詐尸還是另有隱情挑社,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布巡揍,位于F島的核電站痛阻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏腮敌。R本人自食惡果不足惜阱当,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望糜工。 院中可真熱鬧弊添,春花似錦、人聲如沸捌木。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至免钻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崔拥,已是汗流浹背极舔。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留链瓦,地道東北人拆魏。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像慈俯,于是被迫代替她去往敵國和親渤刃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,761評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理贴膘,服務(wù)發(fā)現(xiàn)卖子,斷路器,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • 案例最后效果: 廣播的類型: 標準廣播 標準廣播是完全異步的廣播刑峡, 也就是當(dāng)廣播發(fā)出之后洋闽, 所有的廣播接收器機會都...
    史慧君閱讀 3,118評論 2 50
  • 廣播接收器 是Android的四大組件之一,可見廣播在Android中的重要性突梦; 1. 什么是廣播诫舅? 廣播(Bro...
    Lost_Robot閱讀 1,939評論 2 10
  • 我真的老了,最近我的腿疼得厲害宫患,連下地走路都很困難了刊懈,這都是年輕時候落下的病根。年輕的時候不懂得保養(yǎng)自己娃闲,現(xiàn)在渾身...
    安人閱讀 921評論 3 12