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基础> (五) 广播机制的更多相关文章

  1. Android 中的广播机制

    Android 中的广播机制 Android 中的广播,按照广播响应范围,可以分为应用内广播和全局广播.按照广播的接收方式,可以分为标准广播和有序广播. 广播的分类 响应范围 应用内广播:此类广播只能 ...

  2. Android中使用广播机制退出多个Activity

    谷歌百度一下,Android中退出多个Activity的方法,大家讨论的很多. 在实习的时候,看到公司的项目退出多个Activity,是采用LinkedList方法,毕业设计的时候,也参照了那种方法. ...

  3. 【Android】BroadCast广播机制应用与实例

    如何编写广播接收器 第一步:需要继承BroadcastReceiver类,覆写其中的onReceive()方法. class MyBroadcastReceiver extends Broadcast ...

  4. Android基础(五) Service全解析----看不见的Activity

    一.服务的介绍: 作为Android四大组件之中的一个,Service(服务)也常常运用于我们的日常使用中,它与Activity的差别在于:Service一直在后台执行.没实用户界面.所以绝不会到前台 ...

  5. 九、Android学习第八天——广播机制与WIFI网络操作(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 九.Android学习第八天——广播机制与WIFI网络操作 今天熟悉了An ...

  6. Android广播机制:Broadcast

    转载:Android总结篇系列:Android广播机制 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广 ...

  7. Android 中的消息传递,详解广播机制

    --------------------------------------广播机制简介--------------------------------------------- Android中的广 ...

  8. Android广播机制简介

    为什么说Android中的广播机制更加灵活呢?这是因为Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来 ...

  9. Android开发之广播

    广播是Android开发中的一个重要的功能,在Android里面有各式各样的广播,比如:电池的状态变化.信号的强弱状态.电话的接听和短信的接收等等,现在给大家简单介绍一下系统发送.监听这些广播的机制. ...

随机推荐

  1. Bootstrap-table 部分浏览器显示不出来

    一.问题 近日,写了一个ASP.Net项目,但是bootstrap-table在别人的电脑上显示不出来,在自己的电脑上能显示,有些浏览器也是能显示,但部分浏览器就是显示不出来.找了很多原因,最后有个老 ...

  2. Visual Studio 2019 RC入门

    介绍 在本文中,让我们看看如何开始使用Visual Studio 2019 RC.Microsoft现已发布Visual Studio Release Candidate,现在可以下载了.最初,Mic ...

  3. 常用Shell脚本命令(备忘)

    此处纪录一些个人常用的Shell命令,留作复用 Linux 必备软件 Tmux 终端复用神器 zsh 无比强大Shell运行环境 oh my zsh 搭配zsh食用 uGet Linux下载工具 Do ...

  4. 从 RAID 到 Hadoop Hdfs 『大数据存储的进化史』

    我们都知道现在大数据存储用的基本都是 Hadoop Hdfs ,但在 Hadoop 诞生之前,我们都是如何存储大量数据的呢?这次我们不聊技术架构什么的,而是从技术演化的角度来看看 Hadoop Hdf ...

  5. Pycharm使用技巧(转载)

    Pycharm使用技巧(转载) 转载自:http://www.cnblogs.com/cloudtj/articles/5980666.html pycharm使用技巧 https://python. ...

  6. Centos7VMware虚拟机最小化安装后,安装Tenda U12 USB无线网卡驱动

    前几天买下了Tenda U12 USB 无线网卡 ,想连接上无线玩玩,可惜买下折腾了一周才解决他它驱动问题,前后在VMware上装了十多次,测试了好几个内核版本才搞定,好了废话不多说,分享下我安装过程 ...

  7. 某jiub笔试

    一.选择题 1.下列说法正确的有()A. class中的constructor不可省略B. constructor必须与class同名,但方法不能与class同名C.constructor在一个对象被 ...

  8. Jenkins系统监测(转)

    Jenkins系统监测   Jenkins 是一个开源项目,提供了一种易于使用的持续集成系统,使开发者从繁杂的集成中解脱出来,专注于更为重要的业务逻辑实现上.同时 Jenkins 能实施监控集成中存在 ...

  9. springboot操作mongodb

    springboot操作mongodb 采用MongoRepository操作mongodb springboot版本2.1.2.RELEASE 注意的是:在运行应用程序时,会报错OSS Algori ...

  10. mac 版 Pycharm 激活

    mac 版 Pycharm 激活   获取注册码地址: http://idea.lanyus.com 输入注册码之后可能会报 this license XXXXXXXX has been cancel ...