17.Android开发笔记:广播(一)
1.广播的分类
-
标准广播
所有广播接收器可同时收到 -
有序广播
一个时刻只能有一个广播接收器收到广播,且可决定可否截断
2.接收系统广播
Android内置了很多系统级的广播,比如:开机,电量变化,时间或时区
3.广播接收器
要想接收到广播,需要注册广播接收器,注册方式有两种:
-
动态注册:代码注册
- 主要是使用方法:
registerReceiver(广播接收器,intentFilter)
- 主要是使用方法:
-
静态注册:
AndroidMannifest.xml
中注册- 主要代码
<application> .... <receiver android:name=".MyBrodcastReceiver" android:enabled="true" android:exported="false"> <intent-filter> <action android:name="com.example.mybroadcastDemo.MY_BROADCAST"/> </intent-filter> </receiver>
- 主要代码
如何创建广播接收器
- 创建继承
BroadcastReciever
- 重写方法
onRecieve
3.1 动态注册
示例:动态监听网络变化
public class MainActivity extends AppCompatActivity {
private NetWorkChangeReciever netWorkChangeReciever;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter();
//当网络变化时系统发送该广播
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//注册广播接收器
netWorkChangeReciever = new NetWorkChangeReciever();
registerReceiver(netWorkChangeReciever, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//注销广播接收器
unregisterReceiver(netWorkChangeReciever);
}
class NetWorkChangeReciever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
Log.d("network", "network changes");
}
}
}
关闭模拟器网络:
显示更详细的网络状态信息:
class NetWorkChangeReciever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
Log.d("network", "network changes");
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable()){
Toast.makeText(context, "网络已连接", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context, "网络不可用", Toast.LENGTH_SHORT).show();
}
}
}
访问网络状态需要申请权限,在AndroidMannifest.xml
文件中添加(Android Studio 有智能提示):
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
![](https://img2020.cnblogs.com/blog/380433/202003/380433-20200327155216304-790898560.png)
3.2 静态注册
静态注册广播被禁用:
-
1.创建接收器:右键本程序包节点->New Other->Broadcast Reciever, 命名为
BootCompleteReciever
,- 勾选【Export】:表示广播接收器接收本程序以为的广播
- 勾选【Enable】: 表示广播接收器可用
-
2.
BroadcastReceiver
修改onReceive
public class BootCompleteReciever extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
Log.d("reciever", "this is boot complete reciever");
Toast.makeText(context, "系统启动了", Toast.LENGTH_LONG).show();
}
}
- 3.添加权限
申请监听系统开机系统广播的权限,在AndroidMannifest.xml
文件中添加
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcastdemo">
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
...
- 4.在
AndroidMannifest.xml
文件中
receiver(BootCompleteReciever)的节点添加intent-filter
标签:android.intent.action.BOOT_COMPLETED
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<receiver
android:name=".BootCompleteReciever"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
...
注意:
不要在onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的,
当onReceive()方法运行了较长时间而没有结束时,程序就会报错。
因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如
创建一条状态栏通知,或者启动一个服务等,
4.发送自定义广播
4.1 发送标准广播
使用方法`sendBroadcast(intent)`;
- 定义广播接收器
MyBrodcastReceiver
:
public class MyBrodcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "收到自定义广播 ", Toast.LENGTH_LONG).show();
}
}
- 在
AndroidMannifest.xml
文件中注册广播接收器MyBrodcastReceiver
:
<receiver android:name=".MyBrodcastReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.example.mybroadcastDemo.MY_BROADCAST"/>
</intent-filter>
</receiver>
-
发起自定义消息
在MainActivity中的创建一个按钮,点击它发送指定义广播
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<Button
android:id="@+id/btn_send_my_broadcast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:text="发送自定义广播 MY_BROADCAST"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_send_my_broadcast = findViewById(R.id.btn_send_my_broadcast);
btn_send_my_broadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.mybroadcastDemo.MY_BROADCAST");
sendBroadcast(intent); //发送自定义标准广播
}
});
}
}
点击按钮,接收程序内部自定义广播
![](https://img2020.cnblogs.com/blog/380433/202003/380433-20200327192020970-1056336990.png)
-
其它程序接收自定义广播
com.example.mybroadcastDemo.MY_BROADCAST
:
创建一个新的工程:【MybroadcastReciever2】(1)创建广播接收器
RecieveAntherAppBroadcast
:
public class RecieveAntherAppBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"mybroadcastreciever2:收到其它程序的广播(com.example.mybroadcastDemo.MY_BROADCAST)", Toast.LENGTH_SHORT).show();
}
}
(2) 在AndroidMannifest.xml
文件中注册广播接收器RecieveAntherAppBroadcast
<receiver android:name=".RecieveAntherAppBroadcast"
android:exported="true"
android:enabled="true" >
<intent-filter>
<action android:name="com.example.mybroadcastDemo.MY_BROADCAST"/>
</intent-filter>
</receiver>
-
在程序【MyBrodcastReceiver】中点击按钮【发送自定义广播 MY_BROADCAST】,
程序【MyBrodcastReceiver2】会受到广播:
![](https://img2020.cnblogs.com/blog/380433/202003/380433-20200327191020525-30387705.png)
4.2 发送有序广播
在项目【MyBrodcastReceiver】中
- 在
AndroidMannifest.xml
文件中注册广播接收器MyBrodcastReceiver
的优先级:
<intent-filter android:priority="100"
数字越大,优先级越高
...
<receiver android:name=".MyBrodcastReceiver"
android:enabled="true"
android:exported="false">
<intent-filter android:priority="100">
<action android:name="com.example.mybroadcastDemo.MY_BROADCAST"/>
</intent-filter>
</receiver>
...
- 点击按钮时,使用有序广播
sendOrderedBroadcast(intent, null);
Button btn_send_my_broadcast = findViewById(R.id.btn_send_my_broadcast);
btn_send_my_broadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.mybroadcastDemo.MY_BROADCAST");
//发起标准广播
//sendBroadcast(intent);
//发起有序广播,sendOrderedBroadcast()方法接收两个参数,
// 第一个参数仍然是Intent,
// 第二个参数是一个与权限相关的字符串,这里传入null就行
sendOrderedBroadcast(intent, null);
}
});
-
截断广播:
广播接收器
MyBrodcastReceiver
使用abortBroadcast();
截断广播;
public class MyBrodcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "收到自定义广播 ", Toast.LENGTH_LONG).show();
abortBroadcast(); //截断广播,优先级的广播器将无法收到广播
}
}
这样项目【MyBrodcastReceiver2】的App将无法收到广播(com.example.mybroadcastDemo.MY_BROADCAST
)。
5.本地广播
程序为了避免:
(1)广播被其它程序截获,
(2)其它程序不断地给程序发送垃圾广播
Android引入本地广播机制
本地广播主要就是使用了一个LocalBroadcastManager
来对广播进行管理,并提供了发送广播和注册广播接收器的方法
另外还有一点需要说明,本地广播是无法通过静态注册的方式来接收的。其实这也完全可以理解,因为静态注册主要就是为了让程序在未启动的情况下也能收到广播,
而发送本地广播时,我们的程序肯定是已经启动了,因此也完全不需要使用静态注册的功能。
创建一个新的项目【LocalBroadcastDemo】
- 1.创建广播接收器
LocalReceiver
public class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "本地广播", Toast.LENGTH_SHORT).show();
}
}
- 2.注册广播接收器
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
public class MainActivity extends AppCompatActivity {
private LocalBroadcastManager localBroadcastManager;
private LocalReceiver localReceiver;
private final String localBrodcastName = "com.example.localbroadcastdemo.LOCAL_BROADCAST";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
localBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(localBrodcastName);
localReceiver = new LocalReceiver();
//注册本地广播接收器
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
...
}
}
- 3.发送本地广播
发送本地广播 localBroadcastManager.sendBroadcast(intent);
Button btn_send_loacl_broadcast = findViewById(R.id.btn_send_loacl_broadcast);
btn_send_loacl_broadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(localBrodcastName);
//发送本地广播
localBroadcastManager.sendBroadcast(intent);
}
});