深入Android中BroadcastReceiver的兩種注冊方式(靜態(tài)和動態(tài))詳解
今天我們一起來探討下安卓中BroadcastReceiver組件以及詳細分析下它的兩種注冊方式。
BroadcastReceiver也就是“廣播接收者”的意思,顧名思義,它就是用來接收來自系統(tǒng)和應用中的廣播。在Android系統(tǒng)中,廣播體現(xiàn)在方方面面,例如當開機完成后系統(tǒng)會產(chǎn)生一條廣播,接收到這條廣播就能實現(xiàn)開機啟動服務的功能;當網(wǎng)絡狀態(tài)改變時系統(tǒng)會產(chǎn)生一條廣播,接收到這條廣播就能及時地做出提示和保存數(shù)據(jù)等操作;當電池電量改變時,系統(tǒng)會產(chǎn)生一條廣播,接收到這條廣播就能在電量低時告知用戶及時保存進度等等。Android中的廣播機制設(shè)計的非常出色,很多事情原本需要開發(fā)者親自操作的,現(xiàn)在只需等待廣播告知自己就可以了,大大減少了開發(fā)的工作量和開發(fā)周期。而作為應用開發(fā)者,就需要數(shù)練掌握Android系統(tǒng)提供的一個開發(fā)利器,那就是BroadcastReceiver。
在我們詳細分析創(chuàng)建BroadcastReceiver的兩種注冊方式前,我們先羅列本次分析的大綱:
(1)對靜態(tài)和動態(tài)兩種注冊方式進行概念闡述以及演示實現(xiàn)步驟
(2)簡述兩種BroadcastReceiver的類型(為后續(xù)注冊方式的對比做準備)
(3)在默認廣播類型下設(shè)置優(yōu)先級和無優(yōu)先級情況下兩種注冊方式的比較
(4)在有序廣播類型下兩種注冊方式的比較
(5)通過接受打電話的廣播,在程序(Activity)運行時和終止運行時,對兩種注冊方式的比較
(6)總結(jié)兩種方式的特點
第一步:靜態(tài)和動態(tài)注冊方式基本概念以及實現(xiàn)步驟
構(gòu)建Intent,使用sendBroadcast方法發(fā)出廣播定義一個廣播接收器,該廣播接收器繼承BroadcastReceiver,并且覆蓋onReceive()方法來響應事件注冊該廣播接收器,我們可以在代碼中注冊(動態(tài)注冊),也可以AndroidManifest.xml配置文件中注冊(靜態(tài)注冊)。
動態(tài)注冊:
效果如下圖:

這里就不演示點擊按鈕布局的實現(xiàn)了,MainActivity.java中實現(xiàn)代碼如下:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
DynamicReceiver dynamicReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//實例化IntentFilter對象
IntentFilter filter = new IntentFilter();
filter.addAction("panhouye");
dynamicReceiver = new DynamicReceiver();
//注冊廣播接收
registerReceiver(dynamicReceiver,filter);
}
//按鈕點擊事件
public void send2(View v){
Intent intent = new Intent();
intent.setAction("panhouye");
intent.putExtra("sele","潘侯爺");
sendBroadcast(intent);
}
/*動態(tài)注冊需在Acticity生命周期onPause通過
*unregisterReceiver()方法移除廣播接收器,
* 優(yōu)化內(nèi)存空間,避免內(nèi)存溢出
*/
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(new MyReceiver());
}
//通過繼承 BroadcastReceiver建立動態(tài)廣播接收器
class DynamicReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//通過土司驗證接收到廣播
Toast t = Toast.makeText(context,"動態(tài)廣播:"+ intent.getStringExtra("sele"), Toast.LENGTH_SHORT);
t.setGravity(Gravity.TOP,0,0);//方便錄屏,將土司設(shè)置在屏幕頂端
t.show();
}
}
}
建立方法代碼中做了詳細注釋,有不明白的地方請留言討論。
靜態(tài)注冊:
效果如下:

靜態(tài)注冊建立第一步,新建BroadcastReceiver,見下圖:

通過以上步驟,生成MyReceiver.java文件:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.view.Gravity;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
Toast t = Toast.makeText(context,"靜態(tài)廣播:"+intent.getStringExtra("info"), Toast.LENGTH_SHORT);
t.setGravity(Gravity.TOP,0,0);
t.show();
}
}
生成MyReceiver.java的同時,修改AndroidMainfest.xml配置文件中的代碼:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.administrator.day19">
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<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>
//生成的receiver配置文件
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
//自定義Action
<action android:name="MLY" />
</intent-filter>
</receiver>
</application>
</manifest>
最后在MainActivity.java文件中添加按鈕點擊事件,如下:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
DynamicReceiver dynamicReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//靜態(tài)廣播點擊
public void send(View v){
Intent intent = new Intent();
intent.setAction("MLY");
intent.putExtra("info","panhouye");
sendBroadcast(intent);
}
}
至此,兩種注冊方式的實現(xiàn)代碼演示完畢,歡迎探討。
第二步:為方便后續(xù)分析,這里插入BroadcastReceiver的兩種常用類型
(1)Normalbroadcasts:默認廣播
發(fā)送一個默認廣播使用Context.sendBroadcast()方法,普通廣播對于多個接收者來說是完全異步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對于這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。
(2)orderedbroadcasts:有序廣播
發(fā)送一個有序廣播使用Context.sendorderedBroadcast()方法,有序廣播比較特殊,它每次只發(fā)送到優(yōu)先級較高的接收者那里,然后由優(yōu)先級高的接受者再傳播到優(yōu)先級低的接收者那里,優(yōu)先級高的接收者有能力終止這個廣播。
發(fā)送有序廣播:sendorderedBroadCast()
在注冊廣播中的<intent-filter>中使用android:priority屬性。這個屬性的范圍在-1000到1000,數(shù)值越大,優(yōu)先級越高。在廣播接收器中使用setResultExtras方法將一個Bundle對象設(shè)置為結(jié)果集對象,傳遞到下一個接收者那里,這樣優(yōu)先級低的接收者可以用getResuttExtras獲取到最新的經(jīng)過處理的信息集合。使用sendorderedBroadcast方法發(fā)送有序廣播時,需要一個權(quán)限參數(shù),如果為null則表示不要求接收者聲明指定的權(quán)限,如果不為null則表示接收者若要接收此廣播,需聲明指定權(quán)限。這樣做是從安全角度考慮的,例如系統(tǒng)的短信就是有序廣播的形式,一個應用可能是具有攔截垃圾短信的功能,當短信到來時它可以先接受到短信廣播,必要時終止廣播傳遞,這樣的軟件就必須聲明接收短信的權(quán)限。
第三步:在默認廣播下兩種注冊方式的比較
(1)兩種注冊方式均不設(shè)置優(yōu)先級
這里將動態(tài)與靜態(tài)兩種注冊的廣播觸發(fā)集中在一個按鈕上,顯示效果如下(未設(shè)置優(yōu)先級的情況下,先動態(tài)后靜態(tài)):

這里同樣不演示按鈕布局文件,以及靜態(tài)注冊涉及AndroidMainfest.xml和MyReceiver.java文件。直接展示MainActicity.java的實現(xiàn)代碼:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
DynamicReceiver dynamicReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction("panhouye");
dynamicReceiver = new DynamicReceiver();
registerReceiver(dynamicReceiver,filter);
}
//靜態(tài)廣播點擊
public void send(View v){
Intent intent = new Intent();
//設(shè)置與動態(tài)相同的Action,方便同時觸發(fā)靜態(tài)與動態(tài)
intent.setAction("panhouye");
intent.putExtra("info","潘侯爺");
sendBroadcast(intent);//默認廣播
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(new MyReceiver());
}
class DynamicReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast t = Toast.makeText(context,"動態(tài)廣播:"+ intent.getStringExtra("info"), Toast.LENGTH_SHORT);
t.setGravity(Gravity.TOP,0,0);
t.show();
}
}
}
(2)將動態(tài)優(yōu)先級設(shè)置為最低-1000,靜態(tài)優(yōu)先級設(shè)置為最高1000
顯示效果如下(動態(tài)仍先于靜態(tài)被接收到):

MainActivity中動態(tài)優(yōu)先級設(shè)置如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction("panhouye");
filter.setPriority(-1000);//設(shè)置動態(tài)優(yōu)先級
dynamicReceiver = new DynamicReceiver();
registerReceiver(dynamicReceiver,filter);
}
AndroidMainfest.xml中靜態(tài)優(yōu)先級設(shè)置如下:
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
//設(shè)置靜態(tài)優(yōu)先級
<intent-filter android:priority="1000">
<action android:name="panhouye" />
</intent-filter>
</receiver>
第四步:在有序廣播下兩種注冊方式比較
靜態(tài)廣播1(優(yōu)先級為200),靜態(tài)廣播2(優(yōu)先級為300),靜態(tài)廣播3(優(yōu)先級為400),靜態(tài)廣播優(yōu)先級為(-100),動態(tài)廣播優(yōu)先級為0。顯示效果如下:

出現(xiàn)順序由優(yōu)先級決定,由高到低分別為靜態(tài)3-靜態(tài)2-靜態(tài)1-動-靜態(tài)。(這里參照前文代碼)
第五步:接受打電話的廣播,比較程序運行中與結(jié)束運行時,兩種注冊方式的比較
本次比較采用比對Log的方式對兩種注冊方式進行比較,在MainActivity.java中會插入Activity全部生命周期用于檢測Log分析。
AndroidMainfest.xml配置文件代碼如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.administrator.test19">
//添加撥打電話權(quán)限
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<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>
<receiver
android:name=".StaticReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
//設(shè)置打電話對應的action
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
</application>
</manifest>
MainActivity.java中實現(xiàn)代碼:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
DynamicReceiver dynamicReceiver;//聲明動態(tài)注冊廣播接收
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
dynamicReceiver = new DynamicReceiver();
registerReceiver(dynamicReceiver,filter);
Log.i("Tag","Activity-onCreate");
}
@Override
protected void onStart() {
super.onStart();
Log.i("Tag","Activity-onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.i("Tag","Activity-onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.i("Tag","Activity-onPause");
}
@Override
protected void onStop() {
super.onPause();
Log.i("Tag","Activity-onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i("Tag","Activity-onDestroy");
unregisterReceiver(dynamicReceiver);
}
class DynamicReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Log.i("Tag","動態(tài)注冊廣播接收到您正在撥打電話"+getResultData());
}
}
}
StaticReceiver.java中實現(xiàn)代碼:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class StaticReceiver extends BroadcastReceiver {
public StaticReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
Log.i("Tag","靜態(tài)注冊廣播接收到您正在撥打電話"+getResultData());
}
}
(1)在未退出Activity時,撥打電話,Log如下:

由Log可知在未退出Activity是,兩種方式均可接受到廣播。
(2)在退出Activity時,撥打電話,Log如下:

在退出程序(Activity)時,只有靜態(tài)注冊方式可以接受到廣播。
第六步:總結(jié)兩種注冊方式特點
廣播接收器注冊一共有兩種形式:靜態(tài)注冊和動態(tài)注冊.
兩者及其接收廣播的區(qū)別:
(1)動態(tài)注冊廣播不是常駐型廣播,也就是說廣播跟隨Activity的生命周期。注意在Activity結(jié)束前,移除廣播接收器。
靜態(tài)注冊是常駐型,也就是說當應用程序關(guān)閉后,如果有信息廣播來,程序也會被系統(tǒng)調(diào)用自動運行。
(2)當廣播為有序廣播時:優(yōu)先級高的先接收(不分靜態(tài)和動態(tài))。同優(yōu)先級的廣播接收器,動態(tài)優(yōu)先于靜態(tài)
(3)同優(yōu)先級的同類廣播接收器,靜態(tài):先掃描的優(yōu)先于后掃描的,動態(tài):先注冊的優(yōu)先于后注冊的。
(4)當廣播為默認廣播時:無視優(yōu)先級,動態(tài)廣播接收器優(yōu)先于靜態(tài)廣播接收器。同優(yōu)先級的同類廣播接收器,靜態(tài):先掃描的優(yōu)先于后掃描的,動態(tài):先注冊的優(yōu)先于后冊的。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android在ubuntu上過濾多條關(guān)鍵字日志
今天小編就為大家分享一篇關(guān)于Android在ubuntu上過濾多條關(guān)鍵字日志,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04

