安卓学习笔记35:广播接收者
零、学习目标
- 知道广播接收者的作用
- 掌握如何创建并注册自定义广播接收者
- 掌握如何利用广播接收者实现组件之间的通信
一、广播接收者概述
(一)广播分类
1、标准广播
标准广播( Normal Broadcasts) 是一种完全异步执行的广播,在广播发出之后,所有的广播接收者几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。标准广播也叫无序广播,无序广播不能设置优先级,没有abortBroadcast()方法。
2、有序广播
有序广播( Ordered Broadcasts) 则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收者能够收到这条广播消息,当这个广播接收者中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收者是有先后顺序的,优先级高的广播接收者就可以先 收到广播消息,并且前面的广播接收者还可以截断正在传递的广播,这样后面的广播接收者就无法收到广播消息了。有序广播可以设置优先级, 有 abortBroadcast() 方法。
(二)广播接收者作用
- 广播接收者可以实现组件之间的通信。安卓系统会发生一些事件的改变,比如,电量变低,收发短信,拨打电话,屏幕解锁系统会发送广播,只要应用程序接收到这条广播,就知道系统发生了什么事件,从而执行相应的代码,使用广播接受者,就可以接收广播。
(三)广播接收者继承关系图
(四)使用广播接收者
1、创建广播接收者
- 新建一个类,让它继承自BroadcastReceiver,并重写父类的 onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行,具体的逻辑就可以在这个方法中处理。
2、注册广播接收者
– 动态注册广播接收者(在Java代码里)
– 静态注册广播接收者(在项目清单文件里)
3、通过意图发送广播
– 利用sendBroadcast(Intent inten)发送广播
二、案例演示 - 发送与接收广播
(一)运行效果
(二)涉及知识点
- 线性布局(LinearLayout)
- 编辑框(EditText)
- 按钮(Button)
- 广播接收者(BroadcastReceiver)
(三)实现步骤
1、创建安卓应用【SendReceiveBroadcast】
2、将背景图片拷贝到drawable目录
3、主布局资源文件activity_main.xml
<?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:background="@drawable/background"
android:gravity="center"
android:orientation="vertical"
android:padding="20dp"
tools:context=".MainActivity">
<EditText
android:id="@+id/edtMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/input_message"
android:singleLine="true"
android:textSize="20sp" />
<Button
android:id="@+id/btnSendBroadcast"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doSendBroadcast"
android:text="@string/send_broadcast"
android:textSize="20sp" />
</LinearLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
4、字符串资源文件strings.xml
<resources>
<string name="app_name">发送与接收广播</string>
<string name="input_message">请输入要广播的消息</string>
<string name="send_broadcast">发送广播的消息</string>
</resources>
- 1
- 2
- 3
- 4
- 5
5、创建自定义广播接收者
- 继承BroadcastReceiver类,创建自定义广播接收者类CustomReceiver
package net.hw.send_receive_broadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* 功能:自定义广播接收者
* 作者:华卫
* 日期:2020年12月30日
*/
public class CustomReceiver extends BroadcastReceiver {
private final String TAG = "send_receive_broadcast"; // 标记
private final String INTENT_ACTION_SEND_MESSAGE = "net.hw.intent.action.SEND_MESSAGE"; // 广播频道
@Override
public void onReceive(Context context, Intent intent) {
// 按照频道获取广播信息
if (intent.getAction().equals(INTENT_ACTION_SEND_MESSAGE)) {
// 获取广播信息
String message = intent.getStringExtra("message");
// 输出广播信息
Log.d(TAG, message);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
6、在项目清单文件里注册广播接收者
- 采用静态方式注册自定义广播接收者
7、主界面类 - MainActivity
- 定义常量与变量
- 通过资源标识符获取控件实例
- 编写代码发送广播的信息
- 查看主界面类完整源代码
package net.hw.send_receive_broadcast;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private final String TAG = "send_receive_broadcast"; // 标记
private final String INTENT_ACTION_SEND_MESSAGE = "net.hw.intent.action.SEND_MESSAGE"; // 广播频道
private EditText edtMessage; // 消息编辑框
private int broadcastCount; // 发送广播次数
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 利用布局资源文件设置用户界面
setContentView(R.layout.activity_main);
// 通过资源标识符获取控件实例
edtMessage = findViewById(R.id.edtMessage);
}
/**
* 发送广播
*
* @param view
*/
public void doSendBroadcast(View view) {
// 统计发送广播次数
broadcastCount++;
// 获取用户输入要广播的信息
String message = edtMessage.getText().toString();
// 创建意图
Intent intent = new Intent();
// 设置意图动作(广播频道)
intent.setAction(INTENT_ACTION_SEND_MESSAGE);
// 设置意图携带的附加内容
intent.putExtra("message", "第" + broadcastCount + "次广播信息:" + message);
// 按照意图发送广播
sendBroadcast(intent);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
8、启动应用,查看效果
9、采用动态方式注册广播接收者
(1)修改项目清单文件对广播接收者的注册
(2)在主界面类里动态注册广播接收者
(3)启动应用,查看效果
三、案例演示 - 显示播放进度
- 本案例演示如何通过广播实现窗口与服务之间的通信
(一)运行效果
(二)涉及知识点
- 活动窗口(Activity)
- 服务(Service)
- 广播接收者(BroadcastReceiver)
- 标签(TextView)
- 进度条(ProgressBar)
- 按钮(Button)
- 线性布局(LinearLayout)
- 线程(Thread)
(三)实现步骤
1、创建安卓应用【DisplayProgress】
2、将背景图片拷贝到drwawable目录
3、主布局资源文件activity_main.xml
<?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:background="@drawable/background"
android:gravity="center"
android:orientation="vertical"
android:padding="20dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/tvProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0%"
android:textColor="#0000ff"
android:textSize="50sp" />
<ProgressBar
android:id="@+id/pbPlay"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btnStart"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:onClick="doStart"
android:text="@string/start"
android:textSize="20sp" />
<Button
android:id="@+id/btnStop"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:onClick="doStop"
android:text="@string/stop"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
4、字符串资源文件strings.xml
<resources>
<string name="app_name">显示播放进度</string>
<string name="start">开始</string>
<string name="stop">停止</string>
</resources>
- 1
- 2
- 3
- 4
- 5
5、创建应用程序常量接口 - AppConstants
package net.hw.display_progress;
/**
* 功能:应用程序常量接口
* 作者:华卫
* 日期:2020年12月30日
*/
public interface AppConstants {
String TAG = "net.hw.display_progress"; // 应用程序标记
String INTENT_ACTION_START = "net.hw.display_progress.intent.action.START"; // 开始进度广播频道
String INTENT_ACTION_STOP = "net.hw.display_progress.intent.action.STOP"; // 停止进度广播频道
String INTENT_ACTION_UPDATE_PROGRESS = "net.hw.display_progress.intent.action.UPDATE_PROGRESS"; // 更新进度广播频道
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
6、创建进度服务类 - ProgressService
- 继承Service类,实现AppConstants接口
- 创建内部广播接收者 - InnerBroadcastReceiver (功能代码暂时空着)
- 声明变量
- 在创建回调方法里创建并注册内部广播接收者
- 创建启动更新线程的方法 - startUpdateThread()
- 编写销毁更新线程的方法
- 在销毁回调方法里注销内部广播接收者
- 编写内部广播接收者代码
- 查看进度服务类完整源代码
package net.hw.display_progress;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
/**
* 功能:进度服务类
* 作者:华卫
* 日期:2020年12月30日
*/
public class ProgressService extends Service implements AppConstants {
private InnerBroadcastReceiver receiver; // 内部广播接收者
private IntentFilter filter; // 意图过滤器
private Thread thread; // 线程
private boolean isRunning; // 线程循环控制变量
private int progressValue; // 进度值
/**
* 创建回调方法
*/
@Override
public void onCreate() {
super.onCreate();
// 创建内部广播接收者
receiver = new InnerBroadcastReceiver();
// 创建意图过滤器
filter = new IntentFilter();
// 添加意图动作(广播频道)
filter.addAction(INTENT_ACTION_START);
filter.addAction(INTENT_ACTION_STOP);
// 动态注册内部广播接收者
registerReceiver(receiver, filter);
}
/**
* 启动更新线程
*/
private void startUpdateThread() {
// 设置线程循环控制变量为真
isRunning = true;
// 创建更新进度值的线程
thread = new Thread(new Runnable() {
@Override
public void run() {
// 线程循环
while (isRunning) {
// 更新进度值
progressValue = ++progressValue % 101;
// 输出调试信息
Log.d(TAG, "当前进度值:" + progressValue + "%");
// 创建意图
Intent intent = new Intent();
// 设置意图动作(广播频道)
intent.setAction(INTENT_ACTION_UPDATE_PROGRESS);
// 设置意图携带的附加数据
intent.putExtra("progressValue", progressValue);
// 按意图发送广播
sendBroadcast(intent);
try {
// 让线程睡眠500毫秒
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
// 启动线程
thread.start();
}
/**
* 销毁更新线程
*/
private void destroyUpdateThread() {
// 设置县城循环控制变量为假
isRunning = false;
// 销毁更新进度的线程
thread = null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 销毁回调方法
*/
@Override
public void onDestroy() {
super.onDestroy();
// 注销内部广播接收者
unregisterReceiver(receiver);
}
/**
* 内部广播接收者
*/
private class InnerBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
// 根据广播频道进行不同操作
switch (intent.getAction()) {
case INTENT_ACTION_START:
// 启动更新线程
startUpdateThread();
Log.d(TAG, "收到启动进度的广播!");
break;
case INTENT_ACTION_STOP:
// 销毁更新线程
destroyUpdateThread();
Log.d(TAG, "收到停止进度的广播!");
break;
}
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
7、在项目清单文件里注册进度服务类
8、主界面类 - MainActivity
-
创建内部广播接收者(功能代码暂时空着)
-
声明变量
-
实现AppConstants接口
-
通过资源标识符获取控件实例
-
启动进度服务
-
创建并注册内部广播接收者
-
编写内部广播接收者代码
-
编写开始按钮单击事件处理方法
-
编写停止按钮单击事件处理方法
-
在销毁回调方法里停止服务,注销内部广播接收者
-
查看主界面类完整源代码
package net.hw.display_progress;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity implements AppConstants {
private TextView tvProgress; // 显示进度值的标签
private ProgressBar pbPlay; // 播放进度条
private Intent intent; // 意图
private IntentFilter filter; // 意图过滤器
private InnerBroadcastReceiver receiver; // 内部广播接受者
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 利用布局资源文件设置用户界面
setContentView(R.layout.activity_main);
// 通过资源标识符获取控件实例
tvProgress = findViewById(R.id.tvProgress);
pbPlay = findViewById(R.id.pbPlay);
// 创建启动服务的意图
intent = new Intent(this, ProgressService.class);
// 启动进度服务
startService(intent);
// 创建内部广播接收者
receiver = new InnerBroadcastReceiver();
// 创建意图过滤器
filter = new IntentFilter();
// 添加意图动作(广播频道)
filter.addAction(INTENT_ACTION_UPDATE_PROGRESS);
// 动态注册内部广播接受者
registerReceiver(receiver, filter);
}
/**
* 内部广播接收者
*/
private class InnerBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
// 收到来自进度服务所发送的广播
if (INTENT_ACTION_UPDATE_PROGRESS.equals(intent.getAction())) {
// 获取广播传递过来的进度值
int progressValue = intent.getIntExtra("progressValue", 0);
// 用更新后的进度值去设置进度标签
tvProgress.setText(progressValue + "%");
// 用更新后的进度值去设置进度条
pbPlay.setProgress(progressValue);
}
}
}
}
/**
* 开始按钮单击事件处理方法
*
* @param view
*/
public void doStart(View view) {
// 创建意图
Intent intent = new Intent();
// 设置动作(广播频道)
intent.setAction(INTENT_ACTION_START);
// 按意图发送广播
sendBroadcast(intent);
}
/**
* 停止按钮单击事件处理方法
*
* @param view
*/
public void doStop(View view) {
// 创建意图
Intent intent = new Intent();
// 设置动作(广播频道)
intent.setAction(INTENT_ACTION_STOP);
// 按意图发送广播
sendBroadcast(intent);
}
/**
* 销毁回调方法
*/
@Override
protected void onDestroy() {
super.onDestroy();
// 停止服务
stopService(intent);
// 注销广播接收者
unregisterReceiver(receiver);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
9、启动应用,查看效果
文章来源: howard2005.blog.csdn.net,作者:howard2005,版权归原作者所有,如需转载,请联系作者。
原文链接:howard2005.blog.csdn.net/article/details/111941533
- 点赞
- 收藏
- 关注作者
评论(0)