【四大组件之BroadcastReceiver】


一、BroadcastReceiver是什么?

BroadcastReceiver:广播接收者。我们常说听广播,那么什么是收听广播呢?打开收音机,调频就可以收到对应的广播节目了。其实在Android开发中也有类似的概念,所以就称之为广播了。
广播包括发广播和广播接收者,这就类似于广播发射塔和收音机。因些在Android开发中,我们主要研究的就是发广播和接收广播。

二、广播的注册方式

1、静态注册

例子:监听开机广播
在AndroidManifext.xml中注册广播并添加权限

<receiver
	android:name=".BootCompleteReceiver"
    android:enabled="true"
    android:exported="true">
		<intent-filter>
			<action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
public class BootCompleteReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "开机完成!", Toast.LENGTH_SHORT).show();
    }
}

例子:监听应用的安装与卸载

<receiver
	android:name=".AppStateChangeReceiver"
    android:enabled="true"
	android:exported="true">
		<intent-filter>
			<action android:name="android.intent.action.PACKAGE_ADDED" />
			<action android:name="android.intent.action.PACKAGE_REMOVED" />
			<data android:scheme="package" />
        </intent-filter>
</receiver>
public class AppStateChangeReceiver extends BroadcastReceiver {
    private final String TAG = "AppStateChangeReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG, "action:");
        if (action.equals(Intent.ACTION_PACKAGE_ADDED)) {
            Log.d(TAG, "安装了应用!");
        } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
            Log.d(TAG, "卸载了应用!");
        }
    }
}

应用场景:Launcher监听应用的安装与卸载;大型公司为了收集用户使用习惯或是用于分析未来市场。
注意事项:Android8.0以后需要动态注册监听。详见:监听App安装、卸载的系统广播

2、动态注册

例子:监听电量、充电变化的广播

public class MainActivity extends AppCompatActivity {
    private BatteryReceiver mBatteryReceiver;
    private final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter intentFilter = new IntentFilter();
        //监听电量变化 设置action
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
        intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
        mBatteryReceiver = new BatteryReceiver();
        //注册广播
        this.registerReceiver(mBatteryReceiver, intentFilter);
    }

    //创建广播
    public class BatteryReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, "action: " + action);
            switch (action) {
                case Intent.ACTION_BATTERY_CHANGED:
                    //获取当前电量
                    int batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
                    Toast.makeText(MainActivity.this, "电量: " + batteryLevel, Toast.LENGTH_SHORT).show();
                    break;
                case Intent.ACTION_POWER_CONNECTED:
                    Toast.makeText(MainActivity.this, "USB线已连接", Toast.LENGTH_SHORT).show();
                    break;
                case Intent.ACTION_POWER_DISCONNECTED:
                    Toast.makeText(MainActivity.this, "USB线已断开", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy");
        super.onDestroy();
        //取消广播注册 否则造成内存泄露
        if (mBatteryReceiver != null) {
            this.unregisterReceiver(mBatteryReceiver);
        }
    }
}

在AndroidManifest.xml添加权限

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

3、两种方式的区别

1、静态注册可以长期监听,即使应用没有起来也可以监听,所以耗资源;

2、静态注册的广播优先级高于动态注册的广播;

3、动态注册的优点就是省资源,需要的时候才监听,不需要的时候需要取消注册。

不可以静态注册的广播

android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
android.intent.action.BATTERY_CHANGED
android.intent.action.CONFIGURATION_CHANGED
android.intent.action.TIME_TICK

为什么不能静态注册?

如果不是必须一直监听着的广播,一直监听的话会消耗资源,所以静态注册会提高系统的效率。而动态注册的话需要释放资源取消注册,否则会报错的。这样子有利于提高系统的速度。

三、发送广播

例子:自定义一个广播

public class SendBroadCastActivity extends AppCompatActivity {
    private EditText mEtSendContent;
    private Button mBtSend;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_send_broad_cast);
        initView();
        initListener();
    }

    private void initView() {
        mEtSendContent = findViewById(R.id.et_sendContent);
        mBtSend = findViewById(R.id.bt_send);
    }

    private void initListener() {
        mBtSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction(Constants.ACTION_SEND_MESSAGE);
                String content = mEtSendContent.getText().toString();
                intent.putExtra(Constants.CONTENT, content);
                intent.setComponent(new ComponentName("com.wj.broadcastdemo","com.wj.broadcastdemo.MessageReceiver"));
                //发送广播
                sendBroadcast(intent);
            }
        });
    }
}
public class Constants {
    public static final String ACTION_SEND_MESSAGE = "com.wj.broadcastdemo.SEND_MESSAGE";
    public static final String CONTENT = "content";
}
public class MessageReceiver extends BroadcastReceiver {
    private final String TAG = "MessageReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG, "action: " + action);
        String content = intent.getStringExtra(Constants.CONTENT);
        Log.d(TAG, "content: " + content);
        Toast.makeText(context, "收到了一条广播: " + content, Toast.LENGTH_SHORT).show();
    }
}
<?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"
    android:orientation="vertical"
    android:padding="20dp"
    tools:context=".SendBroadCastActivity">

    <EditText
        android:id="@+id/et_sendContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入要发送的广播内容" />

    <Button
        android:id="@+id/bt_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送广播" />
</LinearLayout>

在这里插入图片描述
打印Log

2022-12-10 18:39:51.094  5275-5275  MessageReceiver         com.wj.broadcastdemo                 D  action: com.wj.broadcastdemo.SEND_MESSAGE
2022-12-10 18:39:51.094  5275-5275  MessageReceiver         com.wj.broadcastdemo                 D  content: 放假回家过年了

四、广播的类型

1、有序广播

注意事项:Android8.0以后发送有序广播需要动态注册 详见:解决安卓8.0版本之后有序广播的接收问题

public class SendOrderedBroadCastActivity extends AppCompatActivity {
    private Button mBtSend;
    private HighLevelReceiver mHighLevelReceiver;
    private DefaultLevelReceiver mDefaultLevelReceiver;
    private LowLevelReceiver mLowLevelReceiver;
    private final String TAG = "SendOrderedBroadCast";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_send_ordered_broad_cast);
        initView();
        initListener();
        handleSendOrderBroadcast();
    }

    private void handleSendOrderBroadcast() {
        Log.d(TAG, "handleSendOrderBroadcast");
        IntentFilter filter1 = new IntentFilter();
        filter1.addAction(Constants.ACTION_SEND_ORDERED);
        filter1.setPriority(1000);
        mHighLevelReceiver = new HighLevelReceiver();
        this.registerReceiver(mHighLevelReceiver, filter1);
        IntentFilter filter2 = new IntentFilter();
        filter2.addAction(Constants.ACTION_SEND_ORDERED);
        filter2.setPriority(0);
        mDefaultLevelReceiver = new DefaultLevelReceiver();
        this.registerReceiver(mDefaultLevelReceiver, filter2);
        IntentFilter filter3 = new IntentFilter();
        filter3.addAction(Constants.ACTION_SEND_ORDERED);
        filter3.setPriority(-1000);
        mLowLevelReceiver = new LowLevelReceiver();
        this.registerReceiver(mLowLevelReceiver, filter3);
    }

    private void initView() {
        mBtSend = findViewById(R.id.bt_send);
    }

    private void initListener() {
        mBtSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction(Constants.ACTION_SEND_ORDERED);
                //发送一个有序广播
                //sendOrderedBroadcast(Intent intent,  //发送广播的意图对象(可以携带数据)
                //          String receiverPermission, //接收权限(如果为空,则不需要权限)
                //          BroadcastReceiver resultReceiver, //广播接收者对象(自己创建的最终的广播接收者,可以无须在清单文件中配置,也会接收到广播 )
                //          Handler scheduler,         //若传null,则默认是在主线程中
                //          int initialCode,           //初始化的一个值。可默认:Activity.RESULT_OK
                //          String initialData,        //可发送的初始化数据(相当于一条广播数据)。可为null
                //          Bundle initialExtras)      //可绑定数据传递(Intent对象也可以,所以可为null)
                sendOrderedBroadcast(intent, null, null, null, Activity.RESULT_OK, "国家发放补贴1000", null);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mHighLevelReceiver != null) {
            this.unregisterReceiver(mHighLevelReceiver);
        }
        if (mDefaultLevelReceiver != null) {
            this.unregisterReceiver(mDefaultLevelReceiver);
        }
        if (mLowLevelReceiver != null) {
            this.unregisterReceiver(mLowLevelReceiver);
        }
    }
}
public class HighLevelReceiver extends BroadcastReceiver {
    private final String TAG = "HighLevelReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        //终止往下传达
        //abortBroadcast();
        Log.d(TAG, "HighLevelReceiver action: " + intent.getAction());
        String resultData = getResultData();
        setResultData("国家发放补贴800");
        Toast.makeText(context, "省接收:" + resultData, Toast.LENGTH_SHORT).show();
    }
}
public class DefaultLevelReceiver extends BroadcastReceiver {
    private final String TAG = "DefaultLevelReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "DefaultLevelReceiver action: " + intent.getAction());
        String resultData = getResultData();
        setResultData("国家发放补贴600");
        Toast.makeText(context, "市接收:" + resultData, Toast.LENGTH_SHORT).show();
    }
}
public class LowLevelReceiver extends BroadcastReceiver {
    private final String TAG = "LowLevelReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "LowLevelReceiver action: " + intent.getAction());
        String resultData = getResultData();
        Toast.makeText(context, "县接收:" + resultData, Toast.LENGTH_SHORT).show();
    }
}
<?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"
    android:orientation="vertical"
    android:padding="20dp"
    tools:context=".SendBroadCastActivity">

    <Button
        android:id="@+id/bt_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送一条有序广播" />
</LinearLayout>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
打印Log

2022-12-10 21:15:36.264 21188-21188 HighLevelReceiver       com.wj.broadcastdemo                 D  HighLevelReceiver action: com.wj.broadcastdemo.SEND_ORDERED
2022-12-10 21:15:36.300 21188-21188 DefaultLevelReceiver    com.wj.broadcastdemo                 D  DefaultLevelReceiver action: com.wj.broadcastdemo.SEND_ORDERED
2022-12-10 21:15:36.343 21188-21188 LowLevelReceiver        com.wj.broadcastdemo                 D  LowLevelReceiver action: com.wj.broadcastdemo.SEND_ORDERED

2、无序广播

之前的例子都是无序广播。

3、广播的权限

谁可以接受我的广播

在发送的AndroidManifest.xml中定义权限

<permission android:name="com.wj.broadcastdemo.ORDER_PERMISSION" />
sendOrderedBroadcast(intent, Manifest.permission.ORDER_PERMISSION, null, null, Activity.RESULT_OK, null, null);

在接收的AndroidManifest.xml中申明权限

<uses-permission android:name="com.wj.broadcastdemo.ORDER_PERMISSION"/>

谁有权限给我发广播

同理需要在节点添加permission属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值