浅谈Android BroadcastReceiver

浅谈Android BroadcastReceiver

简介

BroadcastReceiver,翻译为广播接收者,它是用来接收来自系统和应用中的广播。而在Android里面有各种各样的广播,比如电池的使用状态,电话的接收和短信的接收都会产生一个广播,应用程序开发者可以监听这些广播并做出程序逻辑的处理。
在这里插入图片描述

广播的类型

广播分为两种不同的类型:普通广播和有序广播

普通广播

  • 完全异步执行
  • 所有广播接收器几乎都会在同一时刻接收到这条广播消息, 没有任何先后顺序可言
  • 效率较高, 无法被截断

有序广播

  • 同步执行
  • 同一时刻只会有一个广播接收器能够收到这条广播消息
  • 当这个广播接收器中的逻辑执行完毕后, 广播才会继续传递。所以此时的广播接收器是有先后顺序的, 优先级高的广播接收器就可以先收到广播消息。优先级声明在intent-filter元素的Android:priority属性中,数值越大优先级越高,取值范围为-1000到1000
  • 前面的广播接收器还可以截断正在传递的广播, 这样后面的广播接收器就无法收到广播消息了

广播的发送

  • 普通广播通过调用Context.sendBroadcast()来进行发送广播
    清单文件代码如下:
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
        <intent-filter>
            <action android:name="com.example.broadcast.MyBroadcast"/>
        </intent-filter>
</receiver>

发送广播

		//获取程序中的button按钮
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
            	//创建Intent对象
                Intent intent = new Intent();
                intent.setAction("com.example.broadcast.MyBroadcast");
                intent.putExtra("msg", "简单的消息");
                //发送普通广播
                sendBroadcast(intent);
            }
        });

接收者

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override

    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context,
                "接收到的Intent的Action为"+intent.getAction()
                +"\n消息内容是:"+intent.getStringExtra("msg"),
                Toast.LENGTH_SHORT).show();
    }
}

效果图如下:
在这里插入图片描述

  • 有序广播通过调用Context.sendOrderedBroadcast()来进行发送广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者。
    清单文件的代码如下:
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
        <intent-filter android:priority="100">
            <action android:name="com.example.broadcast.MyBroadcast"/>
        </intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiver2" android:exported="true">
            <intent-filter android:priority="0">
                <action android:name="com.example.broadcast.MyBroadcast"/>
            </intent-filter>
</receiver>

发送广播

        //获取程序中的button按钮
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //创建Intent对象
                Intent intent = new Intent();
                intent.setAction("com.example.broadcast.MyBroadcast");
                intent.putExtra("msg", "简单的消息");
                //发送有序广播
                sendOrderedBroadcast(intent,null);
            }
        });

第一个接收者

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override

    public void onReceive(Context context, Intent intent) {
        System.out.println("MyReceiver called");
        Toast.makeText(context,
                "接收到的Intent的Action为"+intent.getAction()
                +"\n消息内容是:"+intent.getStringExtra("msg"),
                Toast.LENGTH_SHORT).show();
        //创建Bundle对象并存入数据
        Bundle bundle = new Bundle();
        bundle.putString("first","第一个BroadcastReceiver存入的消息");
        //将Bundle放入结果中
        setResultExtras(bundle);
    }
}

第二个接收者

public class MyBroadcastReceiver2 extends MyBroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent){
        System.out.println("MyReceiver called");
        Bundle bundle = getResultExtras(true);
        //解析前一个BroadcastReceiver所存入得到key为first的消息
        String first = bundle.getString("first");
        Toast.makeText(context,"第一个BroadcastReceiver存入的消息:"
        +first,Toast.LENGTH_LONG).show();
    }
}

效果如下:
在这里插入图片描述

Android系统当中自带的Broadcast Action

如果应用需要在系统特定时刻执行某些操作,就可以通过监听系统广播来实现。Android的大量系统事件都会对外发送标准广播。下面是Android常见的广播Action常量

  • ACTION_TIME_CHANGED:系统事件被改变
  • ACTION_DATE_CHANGED:系统日期被改变
  • ACTION_TIMEZONE_CHANGED:系统时区被改变
  • ACTION_BOOT_COMPLETED:系统启动完成
  • ACTION_PACKAGE_ADDED:系统添加包
  • ACTION_PACKAGE_CHANGED:系统的包改变
  • ACTION_PACKAGE_REMOVED:系统的包被删除
  • ACTION_PACKAGE_RESTARTED:系统的包被重启
  • ACTION_PACKAGE_DATA_CLEARED:系统的包数据被清空
  • ACTION_BATTERY_CHANGED:电池电量改变
  • ACTION_BATTERY_LOW:电池电量低
  • ACTION_POWER_CONNECTED:系统连接电源
  • ACTION_POWER_DISCONNECTED:系统与电源断开
  • ACTION_SHUTDOWN:系统被关闭

通过使用BroadcastReceiver来监听特殊的广播,即可让应用随系统执行特定的操作。

使用广播接收器的一般步骤

1.实现一个广播接收器,继承自BroadcastReceiver类,重写onReceive()方法

注意不要在onReceive() 方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的, 如果BroadcastReceiver的onReceiver()方法不能在10秒内执行完成,Android会认为该程序无响应,会弹出ANR(Application No Response)对话框。

如果确实需要根据Broadcast来完成一项比较耗时的操作,则可以考虑通过Intent启动一个Service来完成该操作。

2.注册广播接收器

广播接收器的注册方法有两种:静态注册和动态注册

静态注册

在清单配置文件中声明,即使进程被杀死,该广播仍然运行。

<receiver android:name=".MyBroadcastReceiver" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
</receiver>

可惜的是在清单文件进行静态注册这种方式在Android8.0,API26以后已经不能使用了。

动态注册

在代码中注册,受activity生命周期的影响。
在这里稍微说一下,在Context这个类当中提供了如下两个函数:

  • registerReceiver(receiver,filter);
    这个函数的作用就是将一个BroadcastReceiver注册到应用程序当中,这个函数接收两个参数,第一个参数是需要注册的BroadcastReceiver对象,第二个是一个IntentFilter。第一个参数是非常容易理解的,第二个参数的作用是定义了哪些Intent才能触发这个注册的BroadcastReceiver对象。
  • unregisterReceiver(receiver);
    这个方法就非常简单了,用于解除BroadcastReceiver的绑定状态。一旦解除完成,响应的BroadcastReceiver就不会再接收系统所广播的Intent了。
public class MainActivity extends AppCompatActivity {
    private MyBroadcastReceiver receiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //动态注册
        IntentFilter filter = new IntentFilter();
        //广播接收器想要监听什么广播, 就在这里add相应的action
        filter.addAction("android.intent.action.BOOT_COMPLETED");
        receiver = new MyBroadcastReceiver();
        //注册
        registerReceiver(receiver,filter);
    }
    @Override
    //当Activity不可见或者销毁时,解除注册
    protected void onStop(){
        super.onStop();
        unregisterReceiver(receiver);
    }
}

实例介绍(动态注册——监听网络变化)

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private NetWorkChangeReceiver receiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        receiver = new NetWorkChangeReceiver();
        registerReceiver(receiver,filter);
    }
    @Override
    protected void onStop(){
        super.onStop();
        unregisterReceiver(receiver);
    }
}

NetWorkChangeReceiver.java

public class NetWorkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent){
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo!=null&&networkInfo.isAvailable()){
            Toast.makeText(context,"网络可用", Toast.LENGTH_SHORT).show();
        }else {
            Toast.makeText(context,"网络不可用",Toast.LENGTH_SHORT).show();
        }
    }
}

最后在AndroidManifest.xml清单文件中添加权限

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

效果如下:
在这里插入图片描述

广播接收者静态注册方式与静态注册方式差异

  • 静态注册方法可以保证在应用程序安装之后,BroadcastReceiver始终处于活动状态,通常用于监听系统状态的改变,比如说手机的电量,WiFi网卡的状态(当然,监视这些东西也是取决于软件的需求)。对于这样的BroadcastReceiver,通常是在产生某个特定的系统事件之后,进行相应的操作,比如说WiFi网卡打开时,给用户一个提示。
  • 动态注册方法相对于静态注册要灵活的多,这样注册的BroadcastReceiver通常用于更新UI的状态。一般来说,都是在一个Activity启动的时候使用这样的方法注册BroadcastReceiver,一旦接收到广播的事件,就可以在onReceiver方法当中更新当前的这个Activity当中的控件。但是需要注意的是如果这个Activity不可见了,就应该调用unregisterReceiver方法来解除注册。

作者:沈东源
原文地址:https://blog.csdn.net/qq_41491927/article/details/106616020

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值