广播BroadcastReceiver(1)
广播可以理解为是一种通信的模式,即1个发送方,若干个接收方,
例如: 1个电视台与若干个电视台,1个老师与若干个学生,1个数据发送方与若干个接收方
在广播的通信模式中,广播表现为两种方式:发送方,接收方
在广播的通信模式中,接收方的数量是若干个,广播的发送方会在需要发送
广播的时候即发出广播,并不关心接收方的数量跟状态。
在Android系统中,使用广播机制可以实现线程之间、组件之间、进程之间的通信,如:
同一个进程中主线程与子线程之间的通信,使用主线程和子线程中的任何一个作为广播的发送方,而
其他的线程作为广播的接收方;
同一个应用程序中Activity与Service之间的通信,使用Activity和Service中的任意一个作为广播的发送方,
另一个作为广播的接收方;
使用A应用程序的组件发送广播,而在B应用程序中接收广播;
从实现原理上看,Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型,一旦广播的接收方完成订阅,
当广播发出时,接收方即可收到该广播。
跟收音机接收广播需要一个“频道号”类似,Android系统中的广播机制中也存在类似的概念,它通常表现为
使用IntentFilter对Intent进行过滤,或声明权限(Permission)进行过滤。
Android系统本身也大量的使用了广播机制,在许多特定的情境下都会发送特定的广播,
以使得对应的处理程序可以做出响应,开发人员也可以接收这些广播,以完成一些特定的任务。
Android系统会发出的广播例子:
开机完成、屏幕打开/关闭、新的呼出电话、接收到短信等。
在Android系统中,广播大致区分为:
普通广播/无需广播:广播的接收者们在接收广播时,没有先后之分,任何一个接收者都有可能是第1个
接收到广播的,也可能是最后1个接收到广播的;
有序广播:广播的接收者们会根据一定的顺序先后接收到广播,且先接收到广播的接收者可以阻止广播继续向其他的接收者发送,也可以向其他的接收者传递数据,或
修改前一个接收者中向后传递的数据;
粘性广播:在Android5.0(API 21)中已经声明为不推荐继续使用(Deprecated)。
在ContextWrapper类中定义了发送广播的方法,常用的有:
public void sendBroadcast(Intent intent)
public void sendBroadcast(Intent intent,String receiverPermission)
public void sendOrderBroadcast(Intent intent,String receiverPermission)
在Android系统中,广播接收者(BroadcastReceiver)是核心系统组件之一,当开发人员需要定义广播接收者时,
则需要自定义类继承BroadcastReceiver类。
广播接收者可以在AndroidMainfest.xml文件对BroadcastReceiver类进行注册,也可以使用ContextWrapper类
中定义的registerReceiver()方法注册,前者被称之为静态注册的方式,而后者被称之为动态注册的方式。
总的来说,广播是一种发送与接受数据的通信机制;
使用广播可以实现线程间、组件间、进程间的通信;
BroadcastReceiver是Android系统的核心组件之一,其注册方式可区分为动态注册和静态注册。
Android系统中的广播区分为普通广播(无序广播)和有序广播;
开发人员可以自定义BroadcastReceiver接收系统广播,以处理一些特定的业务;
发送广播与接收广播
发送广播的方法:
public void sendBroadcast(Intent intent)
在一般情况下,广播的发送方与接收方的匹配通过IntentFilter与Intent实现过滤,因此
发送广播时,Intent中应该携带过滤/匹配时需要的属性,例如Action
当在AndroidMainfest.xml文件中注册BroadcastReceiver时,须在<application>节点下添加
<receiver>节点以注册BroadcastReceiver,并且在<receiver>节点下配置<intent-filter>,
以确定接收哪些广播。
实例:
MainActivity:
TestBroadcastReceiver:
在AndroidMainfest.xml中配置:
动态注册广播接收者:
当通过ContextWrapper类中定义的registerReceiver()方法注册
BroadcastReceiver时,需要手动的创建IntentFilter类的对象,作为该方法的参数:
public Intent registerReceiver(BroadcastReceiver receiver,IntentFilter filter)
使用动态注册时,应该及时取消注册,例如在Activity的onCreate()方法中注册,
则在同一个Activity的onDestroy()方法中取消注册,否则会抛出异常,取消注册的方法为:
public void unregisterReceiver(BroadcastReceiver receiver)
实例,布局与上面一样:
静态注册与动态注册BroadcastReceiver的区别通常表现为:
静态注册的BroadcastReceiver是常驻型,当其所属的应用程序安装到设备中时,
该BroadcastReceiver即完成注册,无论应用程序是否处于运行状态,都可以正常接收到广播;
动态注册的BroadcastReceiver仅当调用了registerReceiver()方法后才完成注册,
且当调用了unregistereReceiver()方法后即停止工作
在接收有序广播时,动态注册的BroadcastReceiver的优先级高于静态注册的BroadcastReceiver;
某些广播只有动态注册的BroadcastReceiver才可以接收。
使用广播更新音乐播放
实例:
MainActivity:
PlayMusicService:
配置信息:
布局:
使用广播监听短信
当新的短信到来时,系统会发出如下的广播:
android.provider.Telephony.SMS_RECEIVED
实例:
SmsReceiverService:
不要忘了注册Service和添加权限,这里不再一一介绍了
例如: 1个电视台与若干个电视台,1个老师与若干个学生,1个数据发送方与若干个接收方
在广播的通信模式中,广播表现为两种方式:发送方,接收方
在广播的通信模式中,接收方的数量是若干个,广播的发送方会在需要发送
广播的时候即发出广播,并不关心接收方的数量跟状态。
在Android系统中,使用广播机制可以实现线程之间、组件之间、进程之间的通信,如:
同一个进程中主线程与子线程之间的通信,使用主线程和子线程中的任何一个作为广播的发送方,而
其他的线程作为广播的接收方;
同一个应用程序中Activity与Service之间的通信,使用Activity和Service中的任意一个作为广播的发送方,
另一个作为广播的接收方;
使用A应用程序的组件发送广播,而在B应用程序中接收广播;
从实现原理上看,Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型,一旦广播的接收方完成订阅,
当广播发出时,接收方即可收到该广播。
跟收音机接收广播需要一个“频道号”类似,Android系统中的广播机制中也存在类似的概念,它通常表现为
使用IntentFilter对Intent进行过滤,或声明权限(Permission)进行过滤。
Android系统本身也大量的使用了广播机制,在许多特定的情境下都会发送特定的广播,
以使得对应的处理程序可以做出响应,开发人员也可以接收这些广播,以完成一些特定的任务。
Android系统会发出的广播例子:
开机完成、屏幕打开/关闭、新的呼出电话、接收到短信等。
在Android系统中,广播大致区分为:
普通广播/无需广播:广播的接收者们在接收广播时,没有先后之分,任何一个接收者都有可能是第1个
接收到广播的,也可能是最后1个接收到广播的;
有序广播:广播的接收者们会根据一定的顺序先后接收到广播,且先接收到广播的接收者可以阻止广播继续向其他的接收者发送,也可以向其他的接收者传递数据,或
修改前一个接收者中向后传递的数据;
粘性广播:在Android5.0(API 21)中已经声明为不推荐继续使用(Deprecated)。
在ContextWrapper类中定义了发送广播的方法,常用的有:
public void sendBroadcast(Intent intent)
public void sendBroadcast(Intent intent,String receiverPermission)
public void sendOrderBroadcast(Intent intent,String receiverPermission)
在Android系统中,广播接收者(BroadcastReceiver)是核心系统组件之一,当开发人员需要定义广播接收者时,
则需要自定义类继承BroadcastReceiver类。
广播接收者可以在AndroidMainfest.xml文件对BroadcastReceiver类进行注册,也可以使用ContextWrapper类
中定义的registerReceiver()方法注册,前者被称之为静态注册的方式,而后者被称之为动态注册的方式。
总的来说,广播是一种发送与接受数据的通信机制;
使用广播可以实现线程间、组件间、进程间的通信;
BroadcastReceiver是Android系统的核心组件之一,其注册方式可区分为动态注册和静态注册。
Android系统中的广播区分为普通广播(无序广播)和有序广播;
开发人员可以自定义BroadcastReceiver接收系统广播,以处理一些特定的业务;
发送广播与接收广播
发送广播的方法:
public void sendBroadcast(Intent intent)
在一般情况下,广播的发送方与接收方的匹配通过IntentFilter与Intent实现过滤,因此
发送广播时,Intent中应该携带过滤/匹配时需要的属性,例如Action
当在AndroidMainfest.xml文件中注册BroadcastReceiver时,须在<application>节点下添加
<receiver>节点以注册BroadcastReceiver,并且在<receiver>节点下配置<intent-filter>,
以确定接收哪些广播。
实例:
布局,在布局中添加一个简单的按钮:
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="doSendBroadcast"
android:text="发送普通广播" />
MainActivity:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void doSendBroadcast(View view){
Intent intent = new Intent();
intent.putExtra("data", "data = " + new Date());
intent.setAction("ACTION_TEST_BROADCAST");
sendBroadcast(intent);
}
}
TestBroadcastReceiver:
public class TestBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println(intent.getStringExtra("data"));
}
}
在AndroidMainfest.xml中配置:
<receiver
android:name="com.example.lianxi.TestBroadcastReceiver">
<intent-filter >
<action android:name="ACTION_TEST_BROADCAST"/>
</intent-filter>
</receiver>
动态注册广播接收者:
当通过ContextWrapper类中定义的registerReceiver()方法注册
BroadcastReceiver时,需要手动的创建IntentFilter类的对象,作为该方法的参数:
public Intent registerReceiver(BroadcastReceiver receiver,IntentFilter filter)
使用动态注册时,应该及时取消注册,例如在Activity的onCreate()方法中注册,
则在同一个Activity的onDestroy()方法中取消注册,否则会抛出异常,取消注册的方法为:
public void unregisterReceiver(BroadcastReceiver receiver)
实例,布局与上面一样:
public class MainActivity extends Activity {
private BroadcastReceiver receiver = new InnerBroadcastReceiver();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction("ACTION_TEST_BROADCAST");
registerReceiver(receiver, filter);
}
private class InnerBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println( "InnerBroadcastReceiver" + intent.getStringExtra("data"));
}
}
public void doSendBroadcast(View view){
Intent intent = new Intent();
intent.putExtra("data", "data = " + new Date());
intent.setAction("ACTION_TEST_BROADCAST");
sendBroadcast(intent);
}
//要取消注册,否则的话logcat会报错
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unregisterReceiver(receiver);
super.onDestroy();
}
}
静态注册与动态注册BroadcastReceiver的区别通常表现为:
静态注册的BroadcastReceiver是常驻型,当其所属的应用程序安装到设备中时,
该BroadcastReceiver即完成注册,无论应用程序是否处于运行状态,都可以正常接收到广播;
动态注册的BroadcastReceiver仅当调用了registerReceiver()方法后才完成注册,
且当调用了unregistereReceiver()方法后即停止工作
在接收有序广播时,动态注册的BroadcastReceiver的优先级高于静态注册的BroadcastReceiver;
某些广播只有动态注册的BroadcastReceiver才可以接收。
使用广播更新音乐播放
实例:
MainActivity:
package com.example.lianxi;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.app.Activity;
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.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
private ImageButton play_Button;
private ProgressBar progressbar;
private TextView start_Time, end_Time;
private BroadcastReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play_Button = (ImageButton) findViewById(R.id.play);
progressbar = (ProgressBar) findViewById(R.id.music_seek);
start_Time = (TextView) findViewById(R.id.start_time);
end_Time = (TextView) findViewById(R.id.end_time);
play_Button.setOnClickListener(new InnerOnClickListener());
startService(new Intent(this, PlayMusicService.class));
receiver = new InnerBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.edu.hpu.intent.action.UPDATE_PROGRESS");
filter.addAction("com.edu.hpu.SET PAUSE_BUTTON");
filter.addAction("com.edu.hpu.SET PLAY_BUTTON");
registerReceiver(receiver, filter);
}
private class InnerOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent("com.edu.hpu.intent.action.PLAY_MUSIC");
sendBroadcast(intent);
}
}
private class InnerBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if("com.edu.hpu.SET PAUSE_BUTTON".equals(intent.getAction())){
play_Button.setImageResource(android.R.drawable.ic_media_pause);
}else if("com.edu.hpu.SET PLAY_BUTTON".equals(intent.getAction())){
play_Button.setImageResource(android.R.drawable.ic_media_play);
}
else if("com.edu.hpu.intent.action.UPDATE_PROGRESS".equals(intent.getAction())){
int currentPosition = intent.getIntExtra("current_position", 0);
int duration = intent.getIntExtra("duration", 0);
int progress = currentPosition * 100 / duration;
start_Time.setText(getFormattedTime(currentPosition));
end_Time.setText(getFormattedTime(duration));
progressbar.setProgress(progress);
}
}
}
private String getFormattedTime(long date) {
return new SimpleDateFormat("mm:ss", Locale.CHINA)
.format(new Date(date));
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unregisterReceiver(receiver);
stopService(new Intent(this,PlayMusicService.class));
super.onDestroy();
}
}
PlayMusicService:
package com.example.lianxi;
import java.io.IOException;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.Environment;
import android.os.IBinder;
public class PlayMusicService extends Service {
private MediaPlayer player;
private String musicPath;
private int currentPosition;
private BroadcastReceiver receiver;
private boolean isRunning;
@Override
public void onCreate() {
player = new MediaPlayer();
player.setOnPreparedListener(new InnerPreparedListener());
musicPath = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MUSIC).toString()
+ "/number1.mp3";
IntentFilter filter = new IntentFilter();
filter.addAction("com.edu.hpu.intent.action.PLAY_MUSIC");
receiver = new InnerBroadcastReceiver();
registerReceiver(receiver, filter);
isRunning = true;
new UpdateProgressThread().start();
}
// 子线程发送广播
private class UpdateProgressThread extends Thread {
@Override
public void run() {
while (isRunning) {
if (player.isPlaying()) {
Intent intent = new Intent(
"com.edu.hpu.intent.action.UPDATE_PROGRESS");
intent.putExtra("current_position",
player.getCurrentPosition());
intent.putExtra("duration", player.getDuration());
sendBroadcast(intent);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private class InnerBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent it = new Intent();
if (player.isPlaying()) {
pause();
it = new Intent("com.edu.hpu.SET PLAY_BUTTON");
sendBroadcast(it);
} else {
play();
it = new Intent("com.edu.hpu.SET PAUSE_BUTTON");
sendBroadcast(it);
}
}
}
private void play() {
try {
player.reset();
player.setDataSource(musicPath);
player.prepareAsync();
// player.start();
} catch (IllegalArgumentException e) {
// TODO: handle exception
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void pause() {
if (player.isPlaying()) {
currentPosition = player.getCurrentPosition();
player.pause();
}
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
private class InnerPreparedListener implements
MediaPlayer.OnPreparedListener {
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
if (currentPosition != 0) {
mp.seekTo(currentPosition);
}
mp.start();
currentPosition = 0;
}
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
player.release();
player = null;
isRunning = false;
unregisterReceiver(receiver);
super.onDestroy();
}
}
配置信息:
<service
android:name="com.example.lianxi.PlayMusicService"></service>
布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageButton
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@android:drawable/ic_media_play" />
<ProgressBar
android:id="@+id/music_seek"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal" >
<TextView
android:id="@+id/start_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:gravity="left"
android:text="00:00" />
<TextView
android:id="@+id/end_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:gravity="right"
android:text="00:00" />
</RelativeLayout>
</LinearLayout>
使用广播监听短信
当新的短信到来时,系统会发出如下的广播:
android.provider.Telephony.SMS_RECEIVED
实例:
MainActivity:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this,SmsReceiverService.class));
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
stopService(new Intent(this,SmsReceiverService.class));
super.onDestroy();
}
}
SmsReceiverService:
public class SmsReceiverService extends Service{
private BroadcastReceiver receiver;
@Override
public void onCreate() {
// TODO Auto-generated method stub
receiver = new InnerBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(receiver, filter);
}
private class InnerBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Object[] pdus = (Object[])intent.getExtras().get("pdus");
SmsMessage message;
byte[] pdu;
for (int i = 0; i < pdus.length; i++) {
pdu = (byte[]) pdus[i];
message = SmsMessage.createFromPdu(pdu);
String body = message.getMessageBody();
String address = message.getOriginatingAddress();
long time = message.getTimestampMillis();
System.out.println(address);
System.out.println("信息="+body);
System.out.println(new Date(time).toString());
}
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
}
不要忘了注册Service和添加权限,这里不再一一介绍了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理