<Android基础> (五) 广播机制
1)接收系统广播:a.动态注册监听网络变化
b.静态注册实现开机启动
2)发送自定义广播:a.发送标准广播
b.发送有序广播
3)使用本地广播
第五章
5.1 广播机制
Android中的每个程序都可以对自己感兴趣的广播进行注册。发送广播的方法借助Intent,接收广播的方法则为广播接收器(Broadcast Receiver)。
广播可分为两种。
1.标准广播 (Normal broadcasts):完全异步执行的广播,在广播发出之后,所有广播几乎会在同一时刻接收到这条广播信息,没有任何先后顺序。这种广播传播效率比较高,同时使无法被截断的。
2.有序广播(Ordered broadcasts):同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播,当当前的广播接收器中的逻辑执行完毕后,广播才会继续传递,所以此时的广播接收器是有先后顺序的,优先级高的广播接收器可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后边的广播接收器就无法收到广播信息了。
5.2 接收系统广播
注册广播的方式有两种。
1.动态注册:在代码中注册。
2.静态注册:在AndroidManifest.xml中注册。
5.2.1 动态注册监听网络变化
新建类继承BroadcastReceiver类,并重写onReceive()方法,当有广播来时,onReceiver就会得到执行。
新建一个BroadCastTest项目,修改MainActivity.java中的方法
public class MainActivity extends AppCompatActivity { private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter);
} @Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
} class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
}
}
}
a.在MainActivity中定义一个内部类NetworkChangeReceiver,继承BroadcastReceiver类,并重写onReceive()方法,当网络状态变化时显示Toast
b.创建IntentFilter实例,并添加了android.net.conn.CONNECTIVITY_CHANGE的action,意思为当系统的网络发生变化时,及发送该条广播
c.创建NetworkChangeReceiver实例,最后调用registerReceiver()方法传入两个实例进行注册
d.最后,动态广播的广播接收器一定要取消注册,在onDestroy()方法中调用unrigisterReceiver()来实现
运行程序,当网络发生变化时,显示Toast。
优化设计:直接告诉用户是否有网络
修改onReceive()方法
class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isAvailable()){
Toast.makeText(context, "network is available",
Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context, "network is unavailable",
Toast.LENGTH_LONG).show();
}
}
}
a.ConnectivityManager为一个系统服务类,专门用于管理网络连接,通过getSystemService()方法得到
b.调用ConnectivityManager的getActiveNetworkInfo()方法来判断当前是否有网络
c.最后判断显示的Toast
Android为了保护用户的隐私和安全,做了严格的规定:如果程序需要进行对一些用户来说敏感的操作,就必须在配置文件中声明权限才可以,否则程序会崩溃。
打开AndroidManifest.xml文件,加入访问系统网络的权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.song.broadcasttest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
运行程序:
5.2.2 静态注册实现开机启动
动态注册的广播接收器可以自由地控制注册与注销,在灵活方面有很大优势,但是必须要在程序启动之后才能接收广播。
在程序未启动的情况下接收广播,就需要用到静态注册的方式。
a.右击包com.example.song.broadcasttext——>New——>Other——>Broadcast Receiver 创建名为BootCompleteReceiver
修改onReceive()中的方法
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show();
}
b.在AndroidManifest.xml文件中发现静态广播就已经被注册了
<receiver
android:name=".BootCompleteReciver"
android:enabled="true"
android:exported="true">
</receiver>
c.添加新权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.song.broadcasttest"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
d.系统启动完成后会发出一条值为android.intent.action.BOOT_COMPLETED的广播
<receiver
android:name=".BootCompleteReciver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
在<intent-filter>中添加了相应的action
重启模拟器,即可在启动完成后收到开机广播
不要在onReceiver()方法中添加过多的逻辑或者进行任何耗时的操作,当onReceiver()方法运行了较长时间而没有结束时,程序就会报错。
5.3 发送自定义广播
5.3.1 发送标准广播
a.新建类MyBroadcastReceiver,设置显示Toast
public class MyBroadcastReceiver extends BroadcastReceiver {
public MyBroadcastReceiver() {
} @Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, " received in MyBroadcastReciver", Toast.LENGTH_SHORT).show();
}
}
b.在AndroidManifest.xml中对这个广播接收器进行修改
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.song.broadcasttest.MY_BROADCAST"/>
</intent-filter> </receiver>
c.在activity_main.xml中加入一个Button
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"> <Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send Broadcast"/>
</LinearLayout>
d.在MainAcitivity.java中为Button注册事件
@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 v) {
Intent intent = new
Intent("com.example.song.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);
}
});
}
构建一个Intent对象,并把发送的广播的值传入,然后调用Context的sendBroadCast方法将广播发送出去。所有监听com.example.song.broadcasttest.MY_BROADCAST这条广播的广播接收器都会收到消息。
运行程序:
5.3.2 发送有序广播
广播是一种可以跨进程的通信方式,在当前应用程序内发出的广播在其他的应用程序里也是可以收到的。
1.发送标准广播
a.新建一个BroadcastTest2项目,新建AnotherBroadcastReceiver类
public class AnotherBroadcastReceiver extends BroadcastReceiver {
public AnotherBroadcastReceiver() {
} @Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in AnotherBroadcastReceiver",
Toast.LENGTH_SHORT).show();
}
}
当接收到广播弹出Toast
b.在AndroidManifest.xml中对这个广播接收器进行修改
<receiver
android:name=".AnotherBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.song.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
同样接收的是com.example.song.broadcasttest.MY_BROADCAST这条广播
运行BroadcastTest项目的程序,点击Send Broadcast按钮,分别弹出两次提示信息
2.发送有序广播
a.修改BroadcastTest项目中的MainActivity代码
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new
Intent("com.example.song.broadcasttest.MY_BROADCAST");
sendBroadcast(intent, null);
}
});
sendBroadcast()多传入了一个参数null,第一个为Intent,第二个是与权限相关的字符串,传入null
b.设定先后顺序,在AndroidManifest.xml中修改,设定了优先级别为100,以保证它一定会在AnotherBroadcastReceiveer之前收到广播
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.example.song.broadcasttest.MY_BROADCAST"/>
</intent-filter> </receiver>
运行程序与原来效果一样,但实际设定了顺序。
c.可以在MyBroadcastReceiver中设定中断下一步传播
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, " received in MyBroadcastReciver", Toast.LENGTH_SHORT).show();
abortBroadcast();
}
加一句abortBroadcast()即可截断后面的广播接收器无法再接收到这条广播。
只有MyBroadcastReciver中的Toast信息能够弹出,这条广播经过MyBroadcastReceiver之后中止传递。
5.4 使用本地广播
之前发送的和接收的广播全部属于系统全局广播,即发出的广播可以被其他任何应用程序接收到,并且也可以接受来自其他任何应用程序的广播。
为了能够简单的解决广播的安全性问题,引入本地广播机制,使发出的广播只能够在应用程序内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播。
主要用LocalBroadcastManager来对广播进行管理,并提供了发送和注册广播接收器的方法。
通过LoaclBroadcastManager的getInstance()方法得到一个实例,然后在注册广播接收器的时候调用LocalBroadcastManager的registerReceiver()方法,在发送广播的时候调用LocalBroadcastManager的sendBroadcast()方法。
public class MainActivity extends AppCompatActivity { private IntentFilter intentFilter; private LocalReceiver localReceiver; private LocalBroadcastManager localBroadcastManager; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
localBroadcastManager = LocalBroadcastManager.getInstance(this); Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new
Intent("com.example.song.broadcasttest.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent);
}
}); intentFilter = new IntentFilter();
intentFilter.addAction("com.example.song.broadcasttest.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
} @Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
} class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received local broadcast", Toast.LENGTH_SHORT).show();
}
} }
本地广播是无法通过静态注册的方式来接收的。
本地广播的优势:
1.可以明确地知道正在发送地广播不会离开当前的程序,不必担心机密数据泄露。
2.其他地程序无法将广播发送到当前程序的内部,不必担心会有安全漏洞的隐患。
3.发送本地广播比发送系统全局广播将会更加高效。
<Android基础> (五) 广播机制的更多相关文章
- Android 中的广播机制
Android 中的广播机制 Android 中的广播,按照广播响应范围,可以分为应用内广播和全局广播.按照广播的接收方式,可以分为标准广播和有序广播. 广播的分类 响应范围 应用内广播:此类广播只能 ...
- Android中使用广播机制退出多个Activity
谷歌百度一下,Android中退出多个Activity的方法,大家讨论的很多. 在实习的时候,看到公司的项目退出多个Activity,是采用LinkedList方法,毕业设计的时候,也参照了那种方法. ...
- 【Android】BroadCast广播机制应用与实例
如何编写广播接收器 第一步:需要继承BroadcastReceiver类,覆写其中的onReceive()方法. class MyBroadcastReceiver extends Broadcast ...
- Android基础(五) Service全解析----看不见的Activity
一.服务的介绍: 作为Android四大组件之中的一个,Service(服务)也常常运用于我们的日常使用中,它与Activity的差别在于:Service一直在后台执行.没实用户界面.所以绝不会到前台 ...
- 九、Android学习第八天——广播机制与WIFI网络操作(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 九.Android学习第八天——广播机制与WIFI网络操作 今天熟悉了An ...
- Android广播机制:Broadcast
转载:Android总结篇系列:Android广播机制 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广 ...
- Android 中的消息传递,详解广播机制
--------------------------------------广播机制简介--------------------------------------------- Android中的广 ...
- Android广播机制简介
为什么说Android中的广播机制更加灵活呢?这是因为Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来 ...
- Android开发之广播
广播是Android开发中的一个重要的功能,在Android里面有各式各样的广播,比如:电池的状态变化.信号的强弱状态.电话的接听和短信的接收等等,现在给大家简单介绍一下系统发送.监听这些广播的机制. ...
随机推荐
- MongoDB 如何实现备份压缩
背景及原理 数据库的备份是灾难恢复的最后一道屏障,不管什么类型的数据库都需要设置数据库备份,MongoDB也不例外.MongoDB 3.0 后 ,数据库可以采用Wiredtiger存储引擎后(3.2 ...
- SQL Server -- 回忆笔记(三):ADO.NET之C#操作数据库
SQL Server知识点回忆篇(三):ADO.NET之C#操作数据库 1.连接数据库 (1)创建连接字符串: 使用windows身份验证时的连接字符串: private string conStr= ...
- 小小白搭建nextcloud云盘
我是一名linux的小小白,今天就利用自己的所学搭建属于自己的云盘——nextcloud. 本人学生狗,普通的云盘也要几十块钱,既然我们只是拿来搭建巩固自己知识并不做为生产力,我们就用VMware W ...
- HTML,CSS---问题记录
1,,登录框input和标签垂直方向对不齐,咋解决? 给input框外套一层span标签,给span标签设置宽高,让它和左边或右边的标签对齐. 不要直接给input设置宽高,这样是对不齐的 2,套没有 ...
- 函数rand,randn,randi
1,rand 生成均匀分布的伪随机数.分布在(0~1)之间主要语法:rand(m,n)生成m行n列的均匀分布的伪随机数rand(m,n,‘double’)生成指定精度的均匀分布的伪随机数,参数还可以是 ...
- Django学习笔记之表单验证
表单概述 HTML中的表单 单纯从前端的html来说,表单是用来提交数据给服务器的,不管后台的服务器用的是Django还是PHP语言还是其他语言.只要把input标签放在form标签中,然后再添加一个 ...
- Luogu P1852 BZOJ 2144 [国家集训队]跳跳棋
qwq 这题一看就不会,如果不是gg让做我是坚决不会做的 画图模拟,因为一次只能跳过一个棋子,所以对于一种情况只有三种移动方式: 中间向左跳 中间向右跳 左或右(距中间近的那个)向中间跳 发现,除了跳 ...
- Mongo字符串类型的数值查询---$Where查询介绍
在Mongo中都知道字符串类型大小比较都是以ASCII进行比较的,所以无法真实比较字符串类型的数值大小 比如查询age大于3的: db.getCollection(&q ...
- ELK原理与简介
为什么用到ELK: 一般我们需要进行日志分析场景:直接在日志文件中 grep.awk 就可以获得自己想要的信息.但在规模较大的场景中,此方法效率低下,面临问题包括日志量太大如何归档.文本搜索太慢怎么办 ...
- 细述:nginx http内核模块提供的变量和解释
导读 ngx_http_core_module模块在处理请求时,会有大量的变量,这些变量可以通过访问日志来记录下来,也可以用于其它nginx模块. 在我们对请求做策略如改写等等都会使用到一些变量,顺便 ...