四大组件之广播
Posted 春招进大厂的梦想家
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四大组件之广播相关的知识,希望对你有一定的参考价值。
四大组件之广播
用途:
- 在安卓开发中,当我们需要接收系统发出或者别的程序发出来的消息的时候,就需要用到广播接收器。或者我们需要在应用之中传递一些数据时,我们也可以用本地广播来发送和接收这些消息;
- 广播在android开发中的使用十分广泛,其功能由发送者和接收者两部分组成,与现实中的广播类似,广播台通过信号塔发射广播信号(发送广播),用户通过收音机(广播接收者)来接收广播内容。
一、Android 广播机制的概述
Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器)。广播作为Android组件间的通信方式,可以使用的场景如下:
- 同一app内部的同一组件内的消息通信(单个或多个线程之间);
- 同一app内部的不同组件之间的消息通信(单个进程);
- 同一app具有多个进程的不同组件之间的消息通信;
- 不同app之间的组件之间消息通信;
- Android系统在特定情况下与App之间的消息通信。
从实现原理看上,Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型。因此,从实现的角度来看,Android中的广播将广播的发送者和接受者极大程度上解耦,使得系统能够方便集成,更易扩展。具体实现流程要点粗略概括如下:
- 广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;
- .广播发送者通过binder机制向AMS发送广播;
- AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;
- 消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。
二、监听电量变化的广播(例子)
1.创建一个新的活动,命名为Broadcast_learning
2.首先在manifest文件下添加用户权限
<!--添加状态改变的权限-->
<uses-permission android:name="android.permission.BATTERY_STATS"
tools:ignore="ProtectedPermissions" />
3.在.java文件下编辑代码
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//第二步:我们要收听的频道是:电量变化
IntentFilter intentFilter = new IntentFilter();
//第三步:然后设置频道,这里设置的频道就是电量的变化
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
//第四部:实例化对象
BatterLevelRecever batterLevelRecever = new BatterLevelRecever();
//第五步:注册广播
this.registerReceiver(batterLevelRecever, intentFilter);
}
//第一步,首先创建一个广播接收器,继承自BroadcastReceiver,然后覆写onReceive方法
private class BatterLevelRecever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "收到了状态改变的广播" + action);
}
}
}
个人理解就是,首先创建一个类,让其继承自BroadcastReceiver,并重写父类的onReceive()方法。当广播来临时,onReceive()就会得到调用,具体的逻辑就可以在这个方法里面处理。
4.点击运行之后,在locat中就可以看到打印出的结果
D/MainActivity: 收到了状态改变的广播android.intent.action.BATTERY_CHANGED
至此,一个监听电量变化的广播就创建好了
三、通过广播接收者显示电池电量
1.代码实现:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView batterLevelText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定控件
initView();
RegisterBatterReveiver();
}
//找到控件
public void initView(){
batterLevelText = this.findViewById(R.id.battery_level);
}
//注册广播的方法
private void RegisterBatterReveiver() {
//我们要收听的频道是:电量变化
IntentFilter intentFilter = new IntentFilter();
//然后设置频道,这里设置的频道就是电量的变化
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
//实例化对象
BatterLevelRecever batterLevelRecever = new BatterLevelRecever();
//注册广播
this.registerReceiver(batterLevelRecever, intentFilter);
}
//第一步,首先创建一个广播接收器,继承自BroadcastReceiver,然后覆写onReceive方法
private class BatterLevelRecever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "收到了状态改变的广播" + action);
//显示电池当前电量
Log.d(TAG, "当前电量:"+intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0));
//首先必须进行判空,因为如果注册广播的代码在准备控件的代码之前,就会出现异常
if (batterLevelText != null) {
batterLevelText.setText("当前电量:"+intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0));
}
}
}
}
2.效果图展示:
3.代码优化升级
1.设置两个TextView用来显示当前电量和当前电量百分比;
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/battery_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="30dp"
android:id="@+id/battery_percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/battery_level" />
</RelativeLayout>
2.编辑代码
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView batterLevelText;
private TextView batterPercentText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定控件
initView();
RegisterBatterReveiver();
}
//找到控件
public void initView() {
batterLevelText = this.findViewById(R.id.battery_level);
batterPercentText = findViewById(R.id.battery_percent);
}
//注册广播的方法
private void RegisterBatterReveiver() {
//我们要收听的频道是:电量变化
IntentFilter intentFilter = new IntentFilter();
//然后设置频道,这里设置的频道就是电量的变化
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
//实例化对象
BatterLevelRecever batterLevelRecever = new BatterLevelRecever();
//注册广播
this.registerReceiver(batterLevelRecever, intentFilter);
}
//第一步,首先创建一个广播接收器,继承自BroadcastReceiver,然后覆写onReceive方法
private class BatterLevelRecever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
Log.d(TAG, "收到了状态改变的广播" + action);
//显示电池当前电量
Log.d(TAG, "当前电量:" + intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0));
int currentlevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
//首先必须进行判空,因为如果注册广播的代码在准备控件的代码之前,就会出现异常
if (batterLevelText != null) {
batterLevelText.setText("当前电量:" + intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0));
}
int maxlevel = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
//拿到当前电量后再除以最大值
float percent = currentlevel * 1.0f / maxlevel * 100;
Log.d(TAG, "当前电量百分比是:" + percent + "%");
if (batterPercentText != null) {
batterPercentText.setText("百分比:" + percent + "%");
}
}
}
}
}
四、监听USB线拔出及插入
1.设置频道(USB连接成功和连接失败两个频道)
//这个频道为连接USB
intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
//这个频道为顿开USB
intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
2.USB连接或者断开,将结果打印出来
else if(Intent.ACTION_POWER_CONNECTED.equals(action)){
Log.d(TAG, "usb连接成功");
}else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)){
Log.d(TAG, "usb断开");
}
3.全部代码
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView batterLevelText;
private TextView batterPercentText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定控件
initView();
RegisterBatterReveiver();
}
//找到控件
public void initView() {
batterLevelText = this.findViewById(R.id.battery_level);
batterPercentText = findViewById(R.id.battery_percent);
}
//注册广播的方法
private void RegisterBatterReveiver() {
//我们要收听的频道是:电量变化
IntentFilter intentFilter = new IntentFilter();
//然后设置频道,这里设置的频道就是电量的变化
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
//这个频道为连接USB
intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
//这个频道为顿开USB
intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
//实例化对象
BatterLevelRecever batterLevelRecever = new BatterLevelRecever();
//注册广播
this.registerReceiver(batterLevelRecever, intentFilter);
}
//第一步,首先创建一个广播接收器,继承自BroadcastReceiver,然后覆写onReceive方法
private class BatterLevelRecever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
Log.d(TAG, "收到了状态改变的广播" + action);
//显示电池当前电量
Log.d(TAG, "当前电量:" + intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0));
int currentlevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
//首先必须进行判空,因为如果注册广播的代码在准备控件的代码之前,就会出现异常
if (batterLevelText != null) {
batterLevelText.setText("当前电量:" + intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0));
}
int maxlevel = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
//拿到当前电量后再除以最大值
float percent = currentlevel * 1.0f / maxlevel * 100;
Log.d(TAG, "当前电量百分比是:" + percent + "%");
if (batterPercentText != null) {
batterPercentText.setText("百分比:" + percent + "%");
}
}else if(Intent.ACTION_POWER_CONNECTED.equals(action)){
Log.d(TAG, "usb连接成功");
}else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)){
Log.d(TAG, "usb断开");
}
}
}
}
五、广播的动态注册
1.首先创建一个广播接收器类,继承自BroadcastReceiver,然后重写父类中onReceive()方法
2.实例化IntentFilter类;
3.设置频道,使用intentFilter.addAction()方法;
4.实例化广播接收器类;
5.注册广播,使用this.registerReceiver();
6.必须要销毁该广播接收器
//取消广播注册
@Override
protected void onDestroy() {
super.onDestroy();
//取消广播注册,否则会导致内存泄露
if (batterLevelRecever != null) {
this.unregisterReceiver(batterLevelRecever);
}
}
六、以实现开机监听的例子实现静态注册广播
1.新建一个类,继承BroadcastReceiver类
public class BootCompleteReceiver extends BroadcastReceiver {
private static final String TAG = "BootCompleteReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action is == " + action);
Log.d(TAG, "开机完成");
Toast.makeText(context, "收到开机完成的广播", Toast.LENGTH_LONG).show();
}
}
2.在manifest文件下添加一个
<!--第二步,跟动态设置action是一样的-->
<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
</application>
在标签下面要添加一个i标签,在标签里面在添加一个标签。
相当于动态注册时的这两部分
IntentFilter intentFilter = new IntentFilter(); //然后设置频道,这里设置的频道就是电量的变化 intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
3.在manifest文件下添加用户权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
静态和动态最大的区别就是,静态注册一旦完成不可终止,会一直保持监听状态。但是动态可以随时注册,随时销毁,可以和activity保持相同的生命周期
七、发送自定义广播和接收
1.新建一个活动,用来当做广播发射器
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SendBroadcastActivity"
android:orientation="vertical">
<EditText
android:id="@+id/be_sent_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入发送内容"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送一条广播通知"
android:onClick="SendBroadCast"
tools:ignore="OnClick" />
四大组件之广播