目录
什么是广播
广播(Broadcast)是Android四大组件之一,用于在应用内或应用之间传递消息和通知。它允许应用程序在系统中发送事件或消息,以便其他应用程序可以接收并响应这些事件。
广播分为两个主要角色:发送者和接收者。发送者是发送广播的应用程序组件,而接收者是接收和处理广播的应用程序组件。发送者发送广播后,系统会将广播传递给与接收者匹配的组件。
Android中的广播可以分为两种类型:标准广播(Normal Broadcast)和有序广播(Ordered Broadcast):
-
标准广播(Normal Broadcast):
- 发送者发送广播后,所有匹配的接收者都会同时接收到广播。
- 接收者之间没有优先级顺序,不能中断或拦截广播。
- 应用程序无法得知广播是否被接收者接收到。
-
有序广播(Ordered Broadcast):
- 发送者发送广播后,接收者按照优先级顺序接收广播。
- 每个接收者都有机会处理广播,并可以选择终止广播的传递。
- 如果一个接收者终止了广播,后续的接收者将不再收到广播。
Android广播的使用场景包括但不限于:
- 系统事件通知:例如设备启动、网络连接状态变化、电池电量变化等。
- 自定义事件通知:应用程序内部的事件通知,例如下载完成、数据更新等。
- 跨应用通信:不同应用程序之间的消息传递。
- 与系统组件交互:与系统组件(如闹钟、电话、短信)进行交互。
在Android中,广播使用Intent来传递消息。发送者通过创建Intent对象并调用sendBroadcast()方法发送广播。接收者可以通过在AndroidManifest.xml中声明静态接收器,或者通过在代码中动态注册BroadcastReceiver来接收广播。接收者需要实现BroadcastReceiver类,并重写onReceive()方法来处理接收到的广播。
接收系统广播
示例
创建广播接收器
public class NetworkCHangeReceive extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"network changes",Toast.LENGTH_SHORT).show();
}
}
主活动(动态注册广播接收器监测网络变化)
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkCHangeReceive networkCHangeReceive;
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkCHangeReceive);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkCHangeReceive = new NetworkCHangeReceive();
registerReceiver(networkCHangeReceive,intentFilter);
}
注意:动态注册的广播接收器一定都要取消注册!
另外,程序中对于用户来说一些敏感的操作,都需要声明权限,打开AndroidManifest.xml文件:
(图片中的报错跟本篇博客无关)
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
该活动是监听网络变化的,启动活动后,点击Home(不可返回,否则活动被销毁!),进行开关网络操作,Toast就会提醒你网络发生了变化。
主活动(静态注册广播接收器实现开机启动)
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Boot Complete",Toast.LENGTH_LONG).show();
}
}
另外,静态的广播接收器一定要在AndroidManifest.xml文件中注册才可以使用,但我们使用了快捷的注册方式,AndroidStudio已经帮我们注册好了
同时还要进行权限的修改
(注意,图中报错与本文没有关系!)
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
现在运行程序,我们的程序已经可以接受开机广播了
自定义广播
发送标准广播
新建一个类
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
Toast.makeText(context,"received in MyBroadcastReceiver",Toast.LENGTH_SHORT).show();
}
在AndroidManifest.xml文件中进行修改:
<receiver android:name="com.example.broadcsdttest.MyBroadcastReceiver"
android:exported="true"
android:enabled="true" >
<intent-filter>
<action android:name="com.example.broadcsdttest.MY_BROADCAST" />
</intent-filter>
</receiver>
在主活动的布局文件添加一个按钮,这里省略
主活动
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.broadcsdttest.My_BROADCAST");
intent.setPackage(getPackageName());
sendBroadcast(intent);
}
});
}
发送有序广播
广播是一种跨进程的通信方式,我们在我们的应用发送广播,别的程序也能接受得到。我们可以再创建一个项目来进行验证:
执行完上述操作,你会发现两个程序都弹出了Toast。
在onReceive()的方法中使用了abortBrocast()方法,说明广播已被截断,后面的广播无法再接受这条广播,点击设置的Button按钮,你会发现,只有第一个程序弹出了Toast,第二个没有。
使用本地广播
public class MainActivity extends AppCompatActivity {
private LocalReceiver localReceiver;
private IntentFilter intentFilter;
private LocalBroadcastManager localBroadcastManager;
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.broadcsdttest.LocalBroadcast");
localBroadcastManager.sendBroadcast(intent);
}
});
intentFilter = new IntentFilter();
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver,intentFilter);
}
class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"receive local broadcast!",Toast.LENGTH_SHORT).show();
}
}
}
如果你尝试在第二个项目也接收这一条广播,你会发现无法接收到,因为这条广播只会在Broadcsdttest这个程序里面传播。
是不是好奇为什么不需要在AndroidManifest.xml中添加<intent-filter>?
发送本地广播时不需要在<intent-filter>
中添加对应的动作(action)声明。本地广播是应用内部使用的广播机制,不需要在AndroidManifest.xml中声明和注册。
因此,在发送本地广播时,不需要在<intent-filter>
中添加动作声明。我们只需要创建一个Intent对象,指定广播的名称(例如:"com.example.broadcsdttest.LocalBroadcast"),然后使用LocalBroadcastManager
的sendBroadcast()
方法发送广播即可。
同时,我们还可以使用LocalBroadcastManager
发送多个本地广播。LocalBroadcastManager
是为应用内部使用的广播机制,它可以在应用内部发送和接收多个本地广播。
我们可以通过创建不同的Intent
对象并指定不同的广播名称(Action)来发送多个本地广播。每个本地广播可以具有不同的目的和参数,以满足应用程序的需求。
public void onClick(View view) {
// 发送第一个本地广播
Intent intent1 = new Intent("com.example.myapp.ACTION_ONE");
localBroadcastManager.sendBroadcast(intent1);
// 发送第二个本地广播
Intent intent2 = new Intent("com.example.myapp.ACTION_TWO");
intent2.putExtra("message", "Hello");
localBroadcastManager.sendBroadcast(intent2);
}
});
我们还可以在接收广播的地方添加逻辑来处理不同的广播。当注册了一个BroadcastReceiver并接收到广播时,我们可以通过判断接收到的广播的动作(Action)或其他附加信息来区分不同的广播,并针对每种广播执行不同的逻辑。
在BroadcastReceiver的onReceive()
方法中,我们通常使用Intent
对象来获取接收到的广播信息,并根据其中的数据进行逻辑处理。
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("com.example.myapp.ACTION_ONE")) {
// 处理第一个广播
// 添加逻辑代码
// ...
} else if (action.equals("com.example.myapp.ACTION_TWO")) {
// 处理第二个广播
// 添加逻辑代码
String message = intent.getStringExtra("message");
// ...
} else {
// 处理其他广播
// 添加逻辑代码
// ...
}
}
}
(本文内容均摘抄自郭霖的《Android第一行代码》)