android: 接收系统广播
Android 内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到 各种系统的状态信息。比如手机开机完成后会发出一条广播,电池的电量发生变化会发出一 条广播,时间或时区发生改变也会发出一条广播等等。如果想要接收到这些广播,就需要使 用广播接收器,下面我们就来看一下它的具体用法。
5.2.1 动态注册监听网络变化
广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广 播接收器就能够收到该广播,并在内部处理相应的逻辑。注册广播的方式一般有两种,在代 码中注册和在 AndroidManifest.xml 中注册,其中前者也被称为动态注册,后者也被称为静态 注册。
那么该如何创建一个广播接收器呢?其实只需要新建一个类,让它继承自 BroadcastReceiver, 并重写父类的 onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行, 具体的逻辑就可以在这个方法中处理。
那我们就先通过动态注册的方式编写一个能够监听网络变化的程序,借此学习一下广播 接收器的基本用法吧。新建一个 BroadcastTest 项目,然后修改 MainActivity 中的代码,如下 所示:
public class MainActivity extends Activity {
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();
}
}
}
可以看到,我们在 MainActivity 中定义了一个内部类 NetworkChangeReceiver,这个类 是继承自 BroadcastReceiver 的,并重写了父类的 onReceive()方法。这样每当网络状态发生变 化时,onReceive()方法就会得到执行,这里只是简单地使用 Toast 提示了一段文本信息。
然后观察 onCreate()方法,首先我们创建了一个 IntentFilter 的实例,并给它添加了一个 值为 android.net.conn.CONNECTIVITY_CHANGE 的 action,为什么要添加这个值呢?因为 当网络状态发生变化时,系统发出的正是一条值为 android.net.conn.CONNECTIVITY_ CHANGE 的广播,也就是说我们的广播接收器想要监听什么广播,就在这里添加相应的 action 就行了。接下来创建了一个 NetworkChangeReceiver 的实例,然后调用 registerReceiver() 方法进行注册,将 NetworkChangeReceiver 的实例和
IntentFilter 的实例都传了进去,这样 NetworkChangeReceiver 就会收到所有值为 android.net.conn.CONNECTIVITY_CHANGE 的广 播,也就实现了监听网络变化的功能。
最后要记得,动态注册的广播接收器一定都要取消注册才行,这里我们是在 onDestroy()方法中通过调用 unregisterReceiver()方法来实现的。 整体来说,代码还是非常简单的,现在运行一下程序。首先你会在注册完成的时候收到一条广播,然后按下 Home 键回到主界面(注意不能按 Back 键,否则 onDestroy()方法会执 行),接着按下 Menu
键→System settings→Data usage 进入到数据使用详情界面,然后尝试着 开关 Mobile
Data 来启动和禁用网络,你就会看到有 Toast
提醒你网络发生了变化。
不过只是提醒网络发生了变化还不够人性化,最好是能准确地告诉用户当前是有网络还
是没有网络,因此我们还需要对上面的代码进行进一步的优化。修改 MainActivity 中的代码, 如下所示:
public class MainActivity extends
Activity {
……
class NetworkChangeReceiver extends
BroadcastReceiver {
@Override
public void onReceive(Context
context, Intent intent) {
ConnectivityManager connectionManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectionManager.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_SHORT).show();
}
}
}
}
在 onReceive()方法中,首先通过 getSystemService()方法得到了 ConnectivityManager 的 实例,这是一个系统服务类,专门用于管理网络连接的。然后调用它getActiveNetworkInfo() 方法可以得到 NetworkInfo 的实例,接着调用 NetworkInfo 的 isAvailable()方法,就可以判断 出当前是否有网络了,最后我们还是通过 Toast
的方式对用户进行提示。
另外,这里有非常重要的一点需要说明,Android 系统为了保证应用程序的安全性做了 规定,如果程序需要访问一些系统的关键性信息,必须在配置文件中声明权限才可以,否则
程 序 将 会 直 接 崩 溃 , 比 如 这 里 查 询 系 统 的 网 络 状 态 就 是 需 要 声 明 权 限 的 。 打 开 AndroidManifest.xml 文件,在里面加入如下权限就可以查询系统网络状态了:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.broadcasttest"
android:versionCode="1" android:versionName="1.0"
>
<uses-sdk
android:minSdkVersion="14" android:targetSdkVersion="19"
/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
……
</manifest>
访问 http://developer.android.com/reference/android/Manifest.permission.html可以查看 Android
系统所有可声明的权限。
现在重新运行程序,然后按下 Home 键→按下 Menu
键→System settings→Data usage 进 入到数据使用详情界面,关闭 Mobile Data 会弹出无网络可用的提示,如图 5.3 所示。

图 5.3
然后重新打开 Mobile
Data 又会弹出网络可用的提示,如图 5.4 所示。

图 5.4
5.2.2 静态注册实现开机启动
动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大的优势,但是 它也存在着一个缺点,即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在 onCreate()方法中的。那么有没有什么办法可以让程序在未启动的情况下就能接收到广播 呢?这就需要使用静态注册的方式了。
这里我们准备让程序接收一条开机广播,当收到这条广播时就可以在 onReceive()方法里 执行相应的逻辑,从而实现开机启动的功能。新建一个 BootCompleteReceiver 继承自 BroadcastReceiver,代码如下所示:
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) { Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}
可以看到,这里不再使用内部类的方式来定义广播接收器,因为稍后我们需要在 AndroidManifest.xml 中将这个广播接收器的类名注册进去。在 onReceive()方法中,还是简单 地使用 Toast 弹出一段提示信息。
然后修改 AndroidManifest.xml 文件,代码如下所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.broadcasttest"
android:versionCode="1" android:versionName="1.0" >
……
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >
……
<receiver android:name=".BootCompleteReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
终于,<application>标签内出现了一个新的标签<receiver>,所有静态注册的广播接收器
都是在这里进行注册的。它的用法其实和<activity>标签非常相似,首先通过 android:name 来指定具体注册哪一个广播接收器,然后在<intent-filter>标签里加入想要接收的广播就行了, 由于 Android 系统启动完成后会发出一条值为 android.intent.action.BOOT_COMPLETED 的广 播,因此我们在这里添加了相应的 action。
另外,监听系统开机广播也是需要声明权限的,可以看到,我们使用<uses-permission>标签又加入了一条 android.permission.RECEIVE_BOOT_COMPLETED 权限。 现在重新运行程序后,我们的程序就已经可以接收开机广播了,首先打开到应用程序管理界面来查看一下当前程序所拥有的权限。在桌面按下 Menu 键→System settings→Apps,然 后点击 BroadcastTest,如图 5.5
所示。

图 5.5
可以看到,我们的程序目前拥有访问网络状态和开机自动启动的权限。然后将模拟器关
闭并重新启动,在启动完成之后就会收到开机广播了,如图 5.6 所示。

图 5.6
到目前为止,我们在广播接收器的 onReceive()方法中都只是简单地使用 Toast 提示了一 段文本信息,当你真正在项目中使用到它的时候,就可以在里面编写自己的逻辑。需要注意 的是,不要在 onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收 器中是不允许开启线程的,当 onReceive()方法运行了较长时间而没有结束时,程序就会报错。
因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如创建一条状态栏通知,或
者启动一个服务等.
android: 接收系统广播的更多相关文章
- Android 接收系统广播(动态和静态)
1.标准广播:是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎会在同一时刻接收到这条广播信息,它们之间没有先后顺序.效率高.无法被截断. 2.有序广播:是一种同步执行的广播,在广播发出后 ...
- Android接收系统广播
Android内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到各种系统的状态信息.比如手机开机完成后会发出一条广播,电池的电量发生变化会发出一条广播,时间或时区发生改变也会发出一条 ...
- Android开发之接收系统广播消息
BroadcastReceiver除了接收用户所发送的广播消息之外.另一个重要的用途:接收系统广播. 假设应用须要在系统特定时刻运行某些操作,就能够通过监听系统广播来实现.Android的大量系统事件 ...
- android接收短信——framework处理流程(android 5.1)
modem层不懂,所以直接从RIL.java开始.以电信卡接收短信为例 modem通知RIL.java中的 RILReceiver处理接收信息 class RILReceiver implements ...
- Android接收短信
Android收到短信时会广播android.provider.Telephony.SMS_RECEIVED消息,因此只要定义一个Receiver,收听该消息,就能接收短信. <receiver ...
- android: 接收和发送短信
8.2 接收和发送短信 收发短信应该是每个手机最基本的功能之一了,即使是许多年前的老手机也都会具备这 项功能,而 Android 作为出色的智能手机操作系统,自然也少不了在这方面的支持.每个 A ...
- Android常用系统广播
关于Intent的使用,可参阅前章:http://www.cnblogs.com/caidupingblogs/p/5101669.html //关闭或打开飞行模式时的广播 Intent.ACTION ...
- Android 接收短信
启动程序时启动一个service,在service里注册接收短信的广播,当手机收到短信里,打印出短信内容跟电话号码. package com.lmy.SmsListener; import andro ...
- Android接收wifi路由器发送过来的一组字节数据
1.字节数组转换为字符串 byte[] byBuffer = new byte[20];... ...String strRead = new String(byBuffer);strRead = S ...
随机推荐
- 来自工程师的8项Web性能提升建议
在互联网盛行的今天,越来越多的在线用户希望得到安全可靠并且快速的访问体验.针对Web网页过于膨胀以及第三脚本蚕食流量等问题,Radware向网站运营人员提出以下改进建议,帮助他们为用户提供最快最优质的 ...
- 将eclipse的maven项目导入到intellij idea中
最近项目中需要用到idea,需要将原来的eclipse项目进行转移.捣鼓了半天终于成功了,在这里和大家分享下,希望对大家有所帮助,如有错误,欢迎指正. idea的确是一款很智能的开发工具,真的是爱不释 ...
- SpringMVC MongoDB之“基本文档查询(Query、BasicQuery)”
一.简介 spring Data MongoDB提供了org.springframework.data.mongodb.core.MongoTemplate对MongoDB的CRUD的操作,上一篇我 ...
- Kotlin 喧嚣过后,谈谈 Java 程序员未来的出路
http://blog.jobbole.com/111422 Java 生态圈 Java 的生态环境开放.自由,在Sun/Oracle.Google.Apache.Eclipse基金会等各大厂商,还有 ...
- [转] 插件兼容CommonJS, AMD, CMD 和 原生 JS
模块标准 CommonJS CommonJS 有三个全局变量 module.exports 和 require.但是由于 AMD 也有 require 这个全局变量,故不使用这个变量来进行检测. 如果 ...
- java12小时制的时间转换为24小时制
Java中将12小时制的时间转换为24小时制的方式如下: import java.text.SimpleDateFormat; import java.util.Date; public class ...
- IE下script标签的readyState属性
在做加载器时遇到一个常见问题,如何判定一个脚本已经执行完毕. "uninitialized" – 原始状态 "loading" – 下载数据中 "lo ...
- Codeforces 498B Name That Tune 概率dp (看题解)
Name That Tune 刚开始我用前缀积优化dp, 精度炸炸的. 我们可以用f[ i ][ j ] 来推出f[ i ][ j + 1 ], 记得加加减减仔细一些... #include<b ...
- BZOJ1202 [HNOI2005]狡猾的商人 spfa
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1202 题意概括 有一个数列,共n个数字. 告诉你m个区间和,问是否矛盾. 数据组数<=100 ...
- 【noip模拟赛9】123法典
描述 很久很久以前,有个叫123的国家,这个国家的国王很喜欢颁布各种法令,并把这些法令记录在一部<123法典>中.最近这部法典终于被发掘了出来,专家们经过研究发现法典中的法令是按颁布的时间 ...