BroadcastReceive基礎(chǔ)知識(shí)總結(jié)
1也祠、BroadcastReceive簡(jiǎn)介
- BroadcastReceive也就是“廣播接收者”的意思懂盐,顧名思義刃榨,就是用來(lái)接收來(lái)自系統(tǒng)和應(yīng)用中的廣播
- 在Android系統(tǒng)中参淫,廣播體現(xiàn)在方方面面福稳,例如當(dāng)開(kāi)機(jī)完成后系統(tǒng)會(huì)產(chǎn)生一條廣播残拐,接收到這條廣播就能實(shí)現(xiàn)開(kāi)機(jī)啟動(dòng)服務(wù)的功能途茫,當(dāng)網(wǎng)絡(luò)狀態(tài)改變時(shí),系統(tǒng)會(huì)產(chǎn)生一條廣播溪食,接收到這條廣播囊卜,就能及時(shí)的做出提示和保存數(shù)據(jù)等操作,當(dāng)電池的電量改變的時(shí)候错沃,系統(tǒng)會(huì)產(chǎn)生一條廣播栅组,接收到這條廣播就能在電量低的時(shí)候告知用戶,及時(shí)保存進(jìn)度枢析。等等
- Android中的廣播機(jī)制設(shè)計(jì)的非常出色玉掸,很多事情原本需要開(kāi)發(fā)者親自操作的額,現(xiàn)在只需要廣播告知自己就可以了醒叁,大大的減少了開(kāi)發(fā)的工作量和開(kāi)發(fā)周期司浪,而作為應(yīng)用開(kāi)發(fā)者泊业,就需要熟練掌握Android系統(tǒng)提供的一個(gè)開(kāi)發(fā)利器,那就是BroadcastReceive啊易。
2脱吱、廣播接收器的類型
- (1)Normal broadcasts:默認(rèn)廣播
- 發(fā)送一條默認(rèn)的廣播 Context.sendBroadcast()方法,普通廣播對(duì)于多個(gè)接收者來(lái)說(shuō)是異步的认罩,通常每個(gè)接受者都無(wú)需等待即可以接收到廣播箱蝠,接受者相互之間不會(huì)有影響,對(duì)于這種廣播垦垂,接受者無(wú)法終止廣播宦搬,即無(wú)法阻止其他接受者的接收動(dòng)作
- MainActivity.java
sendNormal = (Button) findViewById(R.id.sendNormal);
sendNormal.setOnClickListener(new OnClickListener());
/**
* 自定義的內(nèi)部click
*/
class OnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sendNormal:
Intent intent = new Intent("com.wuyinlei.action.BROADCAST");
intent.putExtra("info","我們很有緣,謝謝你收到我");
MainActivity.this.sendBroadcast(intent);
break;
}
}
}
MyReceiver.java
/**
* 自定義的廣播接收器
*/
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
/**
* 接受的方法
* @param context
* @param intent
*/
@Override
public void onReceive(Context context, Intent intent) {
String info = intent.getStringExtra("info");
Toast.makeText(context, info, Toast.LENGTH_SHORT).show();
}
}
mainfest.xml
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.wuyinlei.action.BROADCAST"></action>
</intent-filter>
</receiver>
- (2)Ordered broadcasts:有序廣播
- 發(fā)送一個(gè)有序廣播使用Context.sendOrderedBroadcast()方法,有序廣播比較特殊劫拗,它每次只發(fā)死你個(gè)到優(yōu)先級(jí)較高的接受者那里间校,然后由優(yōu)先級(jí)高的接受者在傳播到優(yōu)先級(jí)別低的接受者那里,優(yōu)先級(jí)高的接受者又能力終止這個(gè)廣播
- (3)Sticky Broadcast:粘性廣播
- 當(dāng)處理完之后的Intent页慷,依然存在憔足,知道你把它去掉
3、廣播接收器的創(chuàng)建步驟
- 1酒繁、構(gòu)建Intent滓彰,使用sendBroadcast方法發(fā)送廣播
- 2、定義一個(gè)廣播接收器州袒,該廣播接收器集成BroadcastReceiver,并且覆蓋onReceive()方法來(lái)響應(yīng)事件
- 3揭绑、注冊(cè)廣播接收器,我們可以在代碼中注冊(cè)郎哭,也可以在AndroidManifest.xml配置文件中注冊(cè)
4他匪、注冊(cè)廣播接收器的兩種方式
- 靜態(tài)注冊(cè)
- 靜態(tài)注冊(cè)是在AndroidManifest.xml文件中配置
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.yinlei.action.MY_BROADCAST"></action>
</intent-filter>
</receiver>
這個(gè)時(shí)候,我們需要在Activity或者Service中這樣
Intent intent = new Intent("com.yinlei.action.MY_BROADCAST");
intent.putExtra("info","我是自定義廣播");
sendBroadcast(intent);
- 動(dòng)態(tài)注冊(cè)
- 動(dòng)態(tài)注冊(cè)需要在代碼中動(dòng)態(tài)的指定廣播地址并注冊(cè)夸研,通常我們是在Activity或者Service注冊(cè)一個(gè)廣播
MyReceiver receiver = new MyReceiver()邦蜜;
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.MY_BROADCAST");
registerReceiver(receiver,filter);
解除注冊(cè)
unregisterReceiver(receiver);
- 注意:
- 在這個(gè)方法中發(fā)來(lái)的廣播中亥至,代碼注冊(cè)方式中悼沈,接收到的廣播的先后和注明優(yōu)先級(jí)最高的他們的先后是隨機(jī)的,如果沒(méi)有優(yōu)先級(jí)抬闯,代碼注冊(cè)收到為最先井辆。
5、有序廣播
- 發(fā)送廣播
sendOrderedBroadcast();
* 在注冊(cè)廣播中的<intent-filter>中使用android:priority屬性溶握,這個(gè)屬性的范圍在-1000---1000杯缺。
* 數(shù)值越大,優(yōu)先權(quán)越高睡榆,在廣播接收者中使用setResultExtras方法將一個(gè)Bundle對(duì)象設(shè)置為結(jié)果集對(duì)象萍肆,傳遞到下一個(gè)接受者哪里袍榆,這樣優(yōu)先級(jí)低的接受者可以用getResultExtras獲取到最新的經(jīng)過(guò)處理的信息集合
* 使用sendOrderedBroadcast方法有序廣播的時(shí)候,需要一個(gè)權(quán)限參數(shù)塘揣,如果為null則表示不要求接收者聲明指定的權(quán)限包雀,如果不為null,則表示接收者要接收此廣播亲铡,需聲明指定權(quán)限才写,這樣做是從安全角度考慮的,例如系統(tǒng)的短信就是有序的廣播的形式奖蔓,一個(gè)應(yīng)用可能是具有攔截垃圾短信的功能赞草,當(dāng)短信到來(lái)的時(shí)候它可以先接收到短信,必要時(shí)候終止廣播的傳遞吆鹤,這樣的軟件就必須聲明接收短信的權(quán)限厨疙。
- 終止廣播傳遞
abortBroadcast()
* 同級(jí)別接收是先后是隨機(jī)的,在到級(jí)別低的收到廣播疑务,如果先接收到的把廣播攔截了沾凄,同級(jí)別以外的接收者是無(wú)法收到該廣播的
* 在這個(gè)方法發(fā)來(lái)的廣播(代碼注冊(cè)方式中),收到廣播先后次序?yàn)椋鹤⒚鲀?yōu)先級(jí)的知允、代碼優(yōu)先級(jí)的撒蟀、沒(méi)有優(yōu)先級(jí)的,如果都沒(méi)有優(yōu)先級(jí)廊镜,代碼注冊(cè)接收到優(yōu)先
- 創(chuàng)建的兩個(gè)有序廣播
case R.id.sendOrder:
Intent intentOrder = new Intent("com.wuyinlei.action.MY_BROADCAST");
//第一個(gè)參數(shù)是intent牙肝,第二個(gè)是接收的權(quán)限
MainActivity.this.sendOrderedBroadcast(intentOrder,null);
break;
mainfest.xml配置
<receiver
android:name=".ThreeReceiver"
android:enabled="true"
android:exported="true"
>
<intent-filter android:priority="100">
<action android:name="com.wuyinlei.action.MY_BROADCAST"></action>
</intent-filter>
</receiver>
<receiver
android:name=".FourReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="200">
<action android:name="com.wuyinlei.action.MY_BROADCAST"></action>
</intent-filter>
</receiver>
6、粘性廣播
- 發(fā)送粘性廣播使用:sendStickBroadcast(intent)
- 發(fā)送這個(gè)廣播需要權(quán)限
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
- 去掉這個(gè)removeStickyBroadcast(intent)
- sendStickyOrderedBroadcast():這個(gè)方法具有有序廣播的特性也有粘性廣播的特性嗤朴;
- 在這個(gè)方法發(fā)來(lái)的廣播中,代碼注冊(cè)方式中虫溜,收到廣播先后次序?yàn)椋鹤⒚鲀?yōu)先級(jí)的雹姊、代碼注冊(cè)的、沒(méi)有優(yōu)先級(jí)的衡楞;如果都沒(méi)有優(yōu)先級(jí)吱雏,代碼注冊(cè)的收到最先。
MainActivity.java
- 在這個(gè)方法發(fā)來(lái)的廣播中,代碼注冊(cè)方式中虫溜,收到廣播先后次序?yàn)椋鹤⒚鲀?yōu)先級(jí)的雹姊、代碼注冊(cè)的、沒(méi)有優(yōu)先級(jí)的衡楞;如果都沒(méi)有優(yōu)先級(jí)吱雏,代碼注冊(cè)的收到最先。
case R.id.sendSticky:
Intent intentSticky = new Intent("com.wuyinlei.action.MY_BROADCAST_STICKY");
MainActivity.this.sendStickyBroadcast(intentSticky);
break;
case R.id.startSticky:
startActivity(new Intent(MainActivity.this, ReceiveActivity.class));
break;
ReceiveActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_receive);
mFiveReceiver = new FiveReceiver();
}
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("com.wuyinlei.action.MY_BROADCAST_STICKY");
registerReceiver(mFiveReceiver,filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mFiveReceiver);
}
7瘾境、接收系統(tǒng)廣播
- 1歧杏、開(kāi)機(jī)啟動(dòng)廣播
- 我們經(jīng)常會(huì)有這樣的應(yīng)用場(chǎng)合,比如消息推送服務(wù)迷守,需要實(shí)現(xiàn)開(kāi)機(jī)啟動(dòng)的功能犬绒,要實(shí)現(xiàn)這個(gè)功能,我們就可以訂閱系統(tǒng)“啟動(dòng)完成”這條廣播兑凿,接收到這條廣播凯力,我們就可以啟動(dòng)自己的服務(wù)了
<intent-filter>
<!--注冊(cè)開(kāi)機(jī)廣播地址-->
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
這個(gè)開(kāi)機(jī)廣播地址茵瘾,從安全角度考慮,系統(tǒng)要求必須聲明接收開(kāi)機(jī)啟動(dòng)廣播的權(quán)限咐鹤。
<user-permission android:name="android.peimission.RECEIVE_BOOT_COMPLETE"/>
* 2拗秘、網(wǎng)絡(luò)狀態(tài)變化
* 比如用戶游覽游覽器信息的時(shí)候,網(wǎng)絡(luò)突然斷開(kāi)祈惶,我們要及時(shí)的提醒用戶網(wǎng)絡(luò)已經(jīng)斷開(kāi)雕旨,要實(shí)現(xiàn)這個(gè)功能,我們可以接受網(wǎng)絡(luò)狀態(tài)改變這樣的一條廣播捧请,當(dāng)由連接狀態(tài)變?yōu)閿嚅_(kāi)狀態(tài)時(shí)候凡涩,系統(tǒng)就會(huì)收到一條廣播,我們接收到之后血久,在通過(guò)網(wǎng)絡(luò)的狀態(tài)做出相應(yīng)的操作
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
訪問(wèn)的網(wǎng)絡(luò)狀態(tài)權(quán)限:
<user-permission android:name="android.peimission.ACCESS_NETWORK_STATE"/>
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
String typeName = info.getTypeName();//連接類型
info.getState();//連接狀態(tài)
* 3突照、電量變化
* 如果我們?cè)谑褂瞄喿x軟件,可能全屏閱讀氧吐,這個(gè)時(shí)候用戶就看不到剩余的電量了讹蘑,我們就可以為他們提供電量的信息,要想做到這一點(diǎn)筑舅,我們需要接受一條電量變化的廣播座慰,然后獲取百分比信息
* int currLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0) //當(dāng)前電量
* int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE,1)//總電量
* int percent = currLevel*100/total;
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
立即獲取電量,而不是等電量變化的廣播翠拣,可以使用:
Intent batteryIntent = getApplicationContext().registerReceiver(null,new IntentFilter(Intent.ACTION_BATTERY_CHANGED))