目录
广播的分类:
按照发送方式分类:
- 标准广播
是一个完全异步执行的广播,几乎同时的接收器会收到这个广播,效率比较高,无法截断;
2. 有序广播
是同步执行,同一时刻只有一个接受器才能接受到消息,优先级高的接收器先接受到,同时也可以进行截断
3. 本地广播
应用内广播,不会被其他应用接收到,更安全,不会泄露信息,但只能用于同一个 app 内部通信。
4. 粘性广播
广播发送后会一直保留,即使接收器之后才注册也能收到最近的一条广播,但可能造成数据泄露、资源占用;
但如果按照注册方式分类,可以分为静态注册和动态注册:我们先来看看动态注册:
动态注册
我们来对过程做一个解析:
自定义一个网络接收器的类:继承BroadcastReceiver;
注册:new一个intentfilter对象,通过对象的addAction方法,可以将我们所要接受的广播进行添加;最后获得网络接收器的实例,通过方法registerReceiver(),有两个参数,第一个参数是网络接收器的对象,第二个参数是intentfilter的对象;
因为是动态在Oncreat里面注册的对象,所以还需要在onDestory的时候进行销毁:调用unregisterReceiver(网络接收器的对象);
我们还需要判断是否有网络进行具体的提示:
通过方法getSystemService方法得到服务类ConnectiVITYManager的实例,参数是Context.CONNECTIVITY_SERVICE,然后通过实例的getActiveNetWorkInfo()方法,得到networkinfo的对象,通过isAvailable方法的判断;
上面这段是判断有无网络的提示,如果您只是单纯想学习广播的话,可以不用看,但最好完成这个案例;代码如下:
public class MainActivity extends AppCompatActivity {
private NetworkChangeReceiver ncr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
IntentFilter intentfilter = new IntentFilter();
intentfilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
ncr = new NetworkChangeReceiver();
registerReceiver(ncr,intentfilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(ncr);
}
class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
if(activeNetworkInfo!=null && activeNetworkInfo.isAvailable()){
Toast.makeText(context,"uesablae",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(context,"unuseable",Toast.LENGTH_SHORT).show();
}
}
}
为了大家理解,我把重点的代码贴到这里:
IntentFilter intentfilter = new IntentFilter();
intentfilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
ncr = new NetworkChangeReceiver();
registerReceiver(ncr,intentfilter);
静态注册:
不是所有的都允许静态注册,要根据最新的文档来确定:
要点如下:
不用打开app,也能实现注册;
步骤是:在包下创建一个接收器,在接收器的onrecive方法中,弹出提示消息,作为我们的成果演示;
添加intentfilter标签,同时也需要得到许可:user-permisssion
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
//许可
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
以上都是在androidmanifest,xml文件中进行的;
pay attention to!!!
不建议添加过多的逻辑,因为不允许开启线程,当有onreceive方法耗时操作时,程序就会报错 ;
显示广播和隐式广播的区别:
显示广播:指明确了我要发的组件,通过intent.setpackage()参数是getPackageName();
通过方法指定了广播目标所属的包名,只会发给app中具有对应action的接收器
隐式广播: 不指定接收器,只指定action,所有注册action的接收器选择谁来接收
Android8.0以后静态注册只接受显示广播,除了系统广播;
那么有人要问了,我在这里为什么要强调显示广播和隐式广播的区别呢?
是因为:
从 Android 8.0 开始,系统对静态注册的隐式广播进行了限制,以减少后台资源消耗、提升性能;
被系统限制的隐式广播只支持显式广播的方式发送;
标准广播和有序广播的发送:
发送有序广播
1. 通过Intent对象,参数是广播的值,跟注册接受广播器的action是一致的,都包括包名.名字;
-
通过方法:sendBoradcast(intent对象)来发送信息;
发送无序广播
可以通过在XML文件中的广播组件中,利用android:priority来设置优先级;
-
通过sendOrderedbroadcase(intent,null)来发送
因为两者代码只有一处不一样,所以这里就贴出一段代码:
Intent a = new Intent("com.example.broadcasttest.MY_M ES");
a.setPackage(getPackageName());
sendOrderedBroadcast(a,null);
使用本地广播:
只需要在类中定义成员变量: 通过LocalBroadcastManager对广播进行管理,并提供了注册和发送广播的方法;
获取实例:LocalBroadcastManager.getINstance(this)方法
通过实例对象可以registerReceiver和sendBroadcast(intent)
注意事项: 只能通过动态注册的方式,静态注册主要是想让我们没打开程序时也能收到广播,但是发送广播时,程序肯定启动,就没必要使用静态注册
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private NetworkChangeReceiver nevt;
private LocalBroadcastManager lbm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
lbm = LocalBroadcastManager.getInstance(this);
IntentFilter iff= new IntentFilter();
iff.addAction("android.intent.action.pp");
nevt = new NetworkChangeReceiver();
lbm.registerReceiver(nevt,iff);
@SuppressLint({"MissingInflatedId", "LocalSuppress"}) View view = findViewById(R.id.button);
view.setOnClickListener(this);
}
实例总结:
如果有提示牌,记得用show来调用;
在配置xml文件中,主活动必须设置为可以由外部应用来调用
android:exported="true"
总体的思路:先化个登录界面的ui,然后写登录界面的活动:从文本框里获取字符串比较,如果成功的话就跳转到下一个活动,再写主活动,在主活动中,设置按钮,发送广播;在定义广播接收器,BasicActivity:因为必须要让所有的活动都可以接受到,这个一开始就先写,因为效果是关闭,所以ActivityCollector也必须先写;
以上的实例总结是我个人的学习总结,各位可用于知识点的复习,如果不需要可跳过;
好啦,就到这里!