Android之 BroadcastReceiver广播接收器详解

这篇具有很好参考价值的文章主要介绍了Android之 BroadcastReceiver广播接收器详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一 四大组件

1.1 Activity组件,它一个单独的窗口,程序流程都必须在Activity中运行。

1.2 service组件,用于在后台完成用户指定的操作。

1.3 content provider组件,会为所有的应用准备一个内容窗口,并且保留数据库、文件。

1.4 broadcast receiver组件,是程序之间传递信息时的一种机制,作用就是接收或者发送通知。

二 broadcast receiver简介

2.1 broadcast receiver做为四大组件之一,负责组件之间消息的传递和接收。

2.2 采用观察者模式,基于消息的发布/订阅事件模型,通过Binder机制进行消息的注册和接收。

2.3 广播中的角色:

  • 消息订阅者(广播接收者)
  • 消息发布者(广播发布者)
  • 消息中心(AMS,即Activity Manager Service)

2.4  广播的工作流程:

  • 广播接收者通过 Binder机制在AMS注册
  • 广播发送者通过 Binder 机制向AMS发送广播
  • AMS根据广播发送者要求,在已注册列表中,寻找合适的广播接收者(寻找依据:IntentFilter / Permission)
  • AMS将广播发送到合适的广播接收者相应的消息循环队列中;
  • 广播接收者通过消息循环拿到此广播,并回调 onReceive()

三 广播的注册

3.1 注册类型有两种:静态注册和动态注册

3.2 静态注册,即在清单文件中注册

第一步:创建一个广播接收器BroadcastReceiver ,广播也是通过Intent来传递数据。

public class MyReceiver extends BroadcastReceiver {
    private static final String TAG = "MyReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String msg=intent.getStringExtra("msg");
        Log.e(TAG, "onReceive: "+msg);
    }
}

第二步,清单文件注册该广播

<application
	android:allowBackup="true"
	android:icon="@mipmap/ic_launcher"
	android:label="@string/app_name"
	android:supportsRtl="true"
	android:theme="@style/Theme.MyApplication">

	<receiver android:name=".receiver.MyReceiver"
		android:exported="true"/>
	
</application>

第三步:在其它组件里面发送广播,比如Activity里面

private void buttonClick(){
	Intent intent = new Intent(this, MyReceiver.class);
	sendBroadcast(intent);
}

3.3 注意:

android 8.0以后版本对静态注册的广播做了限制,自定义的接收器会接收不到发送方发送的广播。发送方需要在intent中设定接收方的package,接收方才会接收到。如下:

Intent intent = new Intent();
intent.setAction("cn.dinghe.test");
intent.setClass(this,Class.forName("cn.dinghe.test.MyReceiver"));
sendBroadcast(intent);

3.4 动态注册:即通过 registerReceiver 注册

第一步:一样先创建广播接收器

public class MyReceiver extends BroadcastReceiver {
    private static final String TAG = "MyReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String msg=intent.getStringExtra("msg");
        Log.e(TAG, "onReceive: "+msg);
    }
}

第二步:在组件如Activity里面动态注册广播

public class MainActivity extends AppCompatActivity {
  
    MyReceiver myReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //动态注册广播
        myReceiver=new MyReceiver();
        IntentFilter intentFilter=new IntentFilter();
        intentFilter.addAction("com.dinghe.test.myAction");
        registerReceiver(myReceiver,intentFilter);
    }
}

第三步:在任意组件里面发送广播

private void buttonClick(){
	Intent intent=new Intent();
	intent.setAction("com.dinghe.test");
	intent.putExtra("mag","你好啊");
	sendBroadcast(intent);
}

第四步:取消注册,不然容易造成内存泄漏

@Override
protected void onDestroy() {
	super.onDestroy();
	if (myReceiver!=null){
		unregisterReceiver(myReceiver);
	}
}

五 有序广播

5.1 有序广播介绍:

  • 有序广播是一种同步执行的广播,广播发出之后,优先级高的广播接收器就可以先接收到广播消息。
  • 执行完该广播接收器的逻辑后,可以选择截断正在传递的广播或者继续传递,如果广播消息被截断,之后的广播接收器则无法收到广播消息。
  • 有序广播中的“有序”是针对广播接收者而言的。有序广播的定义过程与普通广播无异,只是其发送方式变为:sendOrderedBroadcast()。
  • 有序广播的接收者们将按照事先命的优先级依次接收,数越大优先级越高(取值范围:-1000~10000)
  • 优先级可以声明在<intent-filter android:priority="100"/> 
  • 也可以调用IntentFilter对象的 setPriority() 设置
  • 调用abortBroadcast()方法即可终止,一旦终止后面接收者就无法接受广播

5.2 实战:

第一步,创建有序广播接收器

public class MyOrderBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyOrderBroadcastReceive";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action=intent.getAction();
        String msg=intent.getStringExtra("msg");

        switch (action){
            case "BROADCAST_ACTION1":
                
                break;
            case "BROADCAST_ACTION2":
                
                break;
        }
    }
}

第二步:清单文件里面注册有序广播 ,并设置优先级

<receiver 
    android:name=".MyOrderBroadcastReceiver" >

    <!-- priority优先级:数字越高优先级越高 -->
    <intent-filter android:priority="2">
        <action android:name="BROADCAST_ACTION2" />
    </intent-filter>

    <intent-filter android:priority="1">
        <action android:name="BROADCAST_ACTION1" />
    </intent-filter>
</receiver>

或者动态注册并设置广播优先级 

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("BROADCAST_ACTION2");
intentFilter.setPriority(2);
registerReceiver(mBroadcastReceiver, intentFilter);

第三步:发送广播

Intent intent = new Intent();
intent.setAction("BROADCAST_ACTION2");
intent.putExtra("msg","你好啊");
sendOrderedBroadcast(intent, null);

第四步:拦截有序广播,在接收器里面拦截abortBroadcast();

public class MyOrderBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyOrderBroadcastReceive";
    @Override
    public void onReceive(Context context, Intent intent) {
        String action=intent.getAction();
        String msg=intent.getStringExtra("msg");

        switch (action){
            case "BROADCAST_ACTION1":

                break;
            case "BROADCAST_ACTION2":
                //优先级高,先收到消息,可以拦截断开有序广播,不再执行下一广播
                abortBroadcast();
                break;
        }
    }
}

六 应用内广播(LocalBroadcast)

6.1 Android中的广播可以跨进程甚至跨App直接通信,且注册是exported对于有intent-filter的情况下默认值是true,由此将可能出现安全隐患如下:

  • 其他App可能会针对性的发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收到广播并处理;
  • 其他App可以注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。

6.2  解决款进程上面隐患方案如下:

  • 对于同一App内部发送和接收广播,将exported属性人为设置成false,使得非本App内部发出的此广播不被接收;
  • 在广播发送和接收时,都增加上相应的permission,用于权限验证;
  • 发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。

6.3  LocalBroadcastManage处理App内广播

Android v4兼容包中给出了封装好的LocalBroadcastManager类,用于统一处理App应用内的广播问题,使用方式上与通常的全局广播几乎相同,只是注册/取消注册广播接收器和发送广播时将主调context变成了LocalBroadcastManager的单一实例。使用方式如下:

//registerReceiver(mBroadcastReceiver, intentFilter);
//注册应用内广播接收器
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

//unregisterReceiver(mBroadcastReceiver);
//取消注册应用内广播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
//sendBroadcast(intent);
//发送应用内广播
localBroadcastManager.sendBroadcast(intent);

七 常用系统广播

7.1 Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广播。

7.2 当使用系统广播时,只需要在注册广播接收者时定义相关的action即可,并不需要手动发送广播,当系统有相关操作时会自动进行系统广播

7.3 每个广播都有特定的Intent - Filter(包括具体的action),Android系统广播action如下:

监听网络变化
android.net.conn.CONNECTIVITY_CHANGE

关闭或打开飞行模式
Intent.ACTION_AIRPLANE_MODE_CHANGED

充电时或电量发生变化
Intent.ACTION_BATTERY_CHANGED

电池电量低
Intent.ACTION_BATTERY_LOW

电池电量
Intent.ACTION_BATTERY_OKAY

系统启动完成后(仅广播一次)
Intent.ACTION_BOOT_COMPLETED

按下照相时的拍照按键(硬件按键)时
Intent.ACTION_CAMERA_BUTTON

屏幕锁屏
Intent.ACTION_CLOSE_SYSTEM_DIALOGS

设备当前设置被改变时(界面语言、设备方向等)
Intent.ACTION_CONFIGURATION_CHANGED

插入耳机时
Intent.ACTION_HEADSET_PLUG

未正确移除SD卡但已取出来时(正确移除方法:设置--SD卡和设备内存--卸载SD卡)
Intent.ACTION_MEDIA_BAD_REMOVAL

插入外部储存装置(如SD卡)
Intent.ACTION_MEDIA_CHECKING

成功安装APK
Intent.ACTION_PACKAGE_ADDED

成功删除APK
Intent.ACTION_PACKAGE_REMOVED

重启设备
Intent.ACTION_REBOOT

屏幕被关闭
Intent.ACTION_SCREEN_OFF

屏幕被打开
Intent.ACTION_SCREEN_ON

关闭系统时
Intent.ACTION_SHUTDOWN

重启设备
Intent.ACTION_REBOOT

7.4 示例,比如监听事件分钟变化

 第一步:创建时间变化监听器

/**
 * 时间更新监听
 */
BroadcastReceiver mTimeUpdateReceiver = new BroadcastReceiver() {
	@Override
	public void onReceive(Context context, Intent intent) {
		if (intent == null) {
			return;
		}
		String action = intent.getAction();
		if (action == null || action.isEmpty()) {
			return;
		}

		if (action.equals(Intent.ACTION_TIME_TICK)) {
			//system every 1 min send broadcast
			
			Log.e(TAG, "onReceive: " + Config.FOOTPRINTTIME);
		}
	}
};

第二步:注册系统监听

/**
 * 注册时间监听
 */
private void registerUpdateTimeReceiver() {
	//register time update
	IntentFilter filter = new IntentFilter();
	filter.addAction(Intent.ACTION_TIME_TICK);
	registerReceiver(mTimeUpdateReceiver, filter);
}

 第三步:取消系统时间监听

/**
 * 注销时间监听
 */
private void unRegisterUpdateTimeReceiver() {
	if (mTimeUpdateReceiver != null) {
		unregisterReceiver(mTimeUpdateReceiver);
	}
}

八 广播的其它方式

8.1 广播的作用就是会主动监听并接收数据变化,但广播是系统组件,需要传上下文,使用不规范可能会造成内存泄漏。而且系统的更新可能会限制广播的某些功能使用,于是也出现了基于发布/订阅模式的其它框架,比如使用非常广泛的EventBus。

8.2 EventBus 优点:

  • 调度灵活,不依赖于 Context,使用时无需像广播一样关注 Context 的注入与传递。
  • 父类对于通知的监听和处理可以继承给子类,这对于简化代码至关重要。
  • 通知的优先级,能够保证 Subscriber 关注最重要的通知。
  • 粘滞事件 (sticky events) 能够保证通知不会因 Subscriber 的不在场而忽略

8.3 当然使用广播和EventBus都能达到监听消息的机制,可以根据自己情况选择。还有其它类似的发送/接收机制的框架,比如配合网络请求使用的RxJava,LiveData等。文章来源地址https://www.toymoban.com/news/detail-742309.html

到了这里,关于Android之 BroadcastReceiver广播接收器详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 罗技鼠标使用接收器和电脑重新配对

    罗技的鼠标出厂的时候,默认的是将通道一设置为接收器配对,在后面如果把通道一改为了蓝牙配对,那之前的接收器配对的连接就断开了。如果后面再想改为接手机配对的话,就需要借助罗技官方的软件进行手动配对了 到这里下载Unifying软件 support.logi.com/hc/zh cn/articles/360

    2024年02月03日
    浏览(25)
  • stm32---用外部中断实现红外接收器

    红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传 输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是 家用电器广泛采用,并越来越多的应用到计算机系统中。 红外遥控通信系统一般由红外发射装置和红外接收设备两大部分组成 (1) 红

    2024年02月10日
    浏览(19)
  • 小技巧:罗技一个接收器连接多个鼠标或键盘

    安装Logitech Unifying™ 优联软件: 最多可以将六个罗技 Unifying™ 优联无线鼠标或键盘连接至一只小巧又节省空间的 Unifying 优联 USB 接收器。 Unifying Software – Logitech 支持 + 下载 Unifying Software More https://support.logi.com/hc/zh-cn/articles/360025297913

    2024年02月11日
    浏览(186)
  • ikbc键盘2.4G接收器丢失,重新对码

    我的键盘:ikbc W200 1.键盘关掉重开; 2.新接收器插在电脑上; 3.电脑上打开软件,点开始对码,一会就连接上了。 对码软件放在这里:  我用夸克网盘分享了「IKBC 对码.rar」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。 链

    2024年02月16日
    浏览(132)
  • 罗技m330更换接收器(通过重新对码的方式)

    下载安装SetPoint驱动:https://support.logi.com/hc/zh-cn/articles/360025141274 在罗技setpoint驱动的安装目录里找到Connectutility.exe 将鼠标的开关关闭,再打开,完成配对。 本文方法来源: 无线鼠标更换接收器后怎样才能使用,需要对码吗?具体步骤是怎样的? - 知乎

    2024年02月11日
    浏览(31)
  • 罗技MX Keys从蓝牙连接切换为优联(无线接收器)连接

    不知道什么原因用最近MX Keys蓝牙连接mac怪卡的,按一个键按四五下电脑上才有反应。于是还是想用无线接收器连接来控制电脑。 按照壳子上按 fn+o 来切换好像不太管用。。。 于是试了很久,最后用罗技自家的键盘管理软件切换上了。 先下一个Logi Options+。 下载链接:https:

    2024年02月11日
    浏览(40)
  • 普通人也能看懂WiFi接收器怎么用的使用手册

    一般家庭或者办公场合中,仅配备一到两个的WiFi网络,就有可能造成与距离区域的人在使用wifi的时候出现网速较慢,加载卡顿的现象。WiFi接收器能够帮助原有是WiFi信号扩大他的覆盖范围,还能够提高网络速度。 如何将WiFi接收器连接到电脑: 首先,将WiFi接收器连接到电脑

    2024年02月04日
    浏览(43)
  • 用FPGA实现四通道、全频率 GNSS RF 接收器-用于卫星的精确定位

    全球导航卫星系统(英文:Global Navigation Satellite System,GNSS ),又称全球卫星导航系统,是能在地球表面或近地空间的任何地点为用户提供全天候的3维坐标和速度以及时间信息的空基无线电导航定位系统。其包括一个或多个卫星星座及其支持特定工作所需的增强系统。 全球

    2024年02月04日
    浏览(30)
  • 无线键盘有几种连接方式?(USB接收器连接(无线2.4g)、蓝牙连接、wi-fi连接、红外线连接)

    无线键盘有以下几种连接方式: 通过USB接收器连接(无线2.4g):无线键盘通过USB接收器与电脑连接,一般需要插入电脑的USB接口,然后通过无线信号与键盘进行通信。 蓝牙连接:无线键盘通过蓝牙与电脑或其他设备连接,需要在电脑或设备上开启蓝牙功能,并进行配对。

    2024年02月08日
    浏览(40)
  • Android广播BroadcastReceiver

    BroadcastReceiver组件 BroadcastReceiver 是Android中的一个组件,用于接收和处理系统广播或应用内广播。它可以监听系统事件或应用内自定义的广播,并在接收到广播时执行相应的操作。 广播是一种用于在应用组件之间传递消息的机制。通过发送广播,一个应用组件可以通知其他组

    2024年02月06日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包