Android开发之接收系统广播消息
BroadcastReceiver除了接收用户所发送的广播消息之外。另一个重要的用途:接收系统广播。
假设应用须要在系统特定时刻运行某些操作,就能够通过监听系统广播来实现。Android的大量系统事件都会对外发送标准广播。下面是Android常见的广播Action常量(详请參考Android API文档中关于Intent的说明)。
| Action常量 | 说明 | 
| ACTION_TIME_CHANGED | 系统时间被改变。 | 
| ACTION_DATE_CHANGED | 系统日期被改变。 | 
| ACTION_TIMEZONE_CHANGED | 系统时区被改变。 | 
| ACTION_BOOT_COMPLETED | 系统启动完毕。 | 
| ACTION_PACKAGE_ADDED | 新的应用程序被安装。 | 
| ACTION_PACKAGE_CHANGED | 应用程序被改变。 | 
| ACTION_PACKAGE_REMOVED | 应用程序被卸载。 | 
| ACTION_PACKAGE_RESTARTED | 应用程序被又一次启动。 | 
| ACTION_PACKAGE_DATA_CLEARED | 应用程序数据被清理。 | 
| ACTION_BATTERY_CHANGED | 电池电量改变。 | 
| ACTION_SHUTDOWN | 系统被关闭。 | 
| ACTION_BATTRY_LOW | 电池电量低。 | 
| ACTION_POWER_CONNECTED | 外接电源被连通。 | 
| ACTION_POWER_DISCONNECTED | 外接电源被断开。 | 
| ACTION_SHUTDOWN | 系统关闭。 | 
| ACTION_NEW_OUTGOING_CALL | 播出电话。 | 
| ACTION _PHONE_STATE | 系统通话状态改变。 | 
通过 来监听特殊的广播。即能够实现应用尾随系统运行特定的某些操作。
实例一:开机自己主动执行的Service
在实际应用总往往会让一些应用尾随系统启动。比方一个黑名单来电自己主动拦截的APP,监听垃圾短信的APP... ...等等。为了让Service能尾随系统启动。我们须要让BroadcastReceiver监听Action名为:ACTION_BOOT_COMPLETED常量的Intent,然后在BroadcastReceiver启动特定的Service就可以。
程序清单:
public class LaunchWithSys extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
                   // TODO Auto-generated method stub
                   Intent launchService=new Intent(context, LaunchService.class);
                   //启动指定Service
                   context.startActivity(launchService);
         }
}  
从上面看该LaunchWithSys很easy,仅仅须要启动指定的Service就可以,接下来须要注冊用于监听系统开机广播的BroadcastReceiver:因此须要在AndroidManifest.xml注冊一个以下的接收器:
<!—注冊一个监听系统开机广播的BroadcastReceiver à
<receiver android:name=”com.jph.monitorbroadcastfromsys.LaunchWithSys”>
<intent-filter>
<action android:name=”android.intent.action.BOOT_COMPLETED”></action>
</intent-filter>
</receiver>
除此之外。为了可以让程序訪问开机启动事件。须要为程序加入例如以下的权限:
<pre name="code" class="html"><!—为程序加入訪问系统开机事件的权限 à
<uses-permission android:name=”android.permission.RECEIVE_BOOT_COMPLETED”/>
实例二:短息提醒
在Android中当系统收到短信后会发出一个有序的广播,该广播的Intent的Action为android.provider.Telephony.SMS_RECEIVED。因此仅仅须要在程序中开发一个相应的BroadcastReceiver就可以监听到系统接收到的短信。
程序清单:
public class SmsReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
                   // TODO Auto-generated method stub
                   //假设收到短信
                   if (intent.getAction().equals(“android.provider.Telephony.SMS_RECEIVED”)) {
                            //取消这条有序广播(取消后会让其他应用收不到短信)
                            abortBroadcast();
                            Bundle bundle=intent.getExtras();
                            if (bundle!=null) {//假设数据不为空
                                     //获得收到的短信数据
                                     Object[] objArray=(Object[]) bundle.get(“pdus”);
                                     //依据objArray的大小创建一个SmsMessage数组,用于封装短信内容
                                     SmsMessage []smsMessage=new SmsMessage[objArray.length];
                                     StringBuffer sb=new StringBuffer();
                                     sb.append(“时间:”+new DateFormat().format(“yyyy-MM-dd hh.mm.ss”, new Date()));
                                     //遍历smsMessage数组取出全部短信
                                     for (int i = 0; i < smsMessage.length; i++) {
                                               //将每条字节类型的短信数据转换成SmsMessage对象
                                               smsMessage[i]=SmsMessage.createFromPdu((byte[])objArray[i]);
                                               //获取短信发送地址
                                               sb.append(“发送者:”+smsMessage[i].getOriginatingAddress());
                                               //获取短信内容
                                               sb.append(“短信内容:”+smsMessage[i].getDisplayMessageBody()+”\n”);
                                     }
                                     Toast.makeText(context, sb.toString(), Toast.LENGTH_LONG).show();
                            }
                   }
         }
}
实例分析:
Ÿ 因为接收到的短信内容是以字节数组形式保存的。为了便于用这些数据,须要使用SmsMessage.createFromPdu方法将这些字节数组形式的数据转换成SmsMessage对象。
Ÿ 因为接收器可能收到多条短信,因此。通过“pdus”返回了一个短信数组(byte[])所以须要遍历这个数组取出每一条短信。
因为须要监測系统发出的接收短信的广播。所以在配置文件里须要进行例如以下配置:
<!—注冊一个BroadcastReceiver监听系统收到短信发出的广播 à
<receiver android:name=”com.jph.monitorbroadcastfromsys.SmsReceiver”>
<!—给接收器设个较高的优先级 以便能在其他程序收到广播前结束广播à
<intent-filter android:priority=”666”>
<action android:name=”android.provider.Telephony.SMS_RECEIVED”></action>
</intent-filter>
</receiver>
另外,因为程序须要接收短信。所以须要赋予程序接收短信的权限。
<!—为程序加入接收短信的权限 à
<uses-permission android:name=”android.permission.RECEIVE_SMS”/>
执行效果图:

实例三:手机电量提醒
当手机电量发生变化是系统会发出,Intent的Action名为ACTION_BATTERY_CHANGED的广播,当手机电量过低时系统会发出Intent的Action名为ACTION_BATTRY_LOW的广播。所以,仅仅需监測相应Intent的BroadcastReceiver便可实现手机低电量提醒的应用。
程序清单:
public class MianActivity extends Activity {
         TextView show;
         @Override
         protected void onCreate(Bundle savedInstanceState) {
                   super.onCreate(savedInstanceState);
                   setContentView(R.layout.mian);
                   show=(TextView)findViewById(R.id.show);
                   ShowPowerReceiver showPowerReceiver=new ShowPowerReceiver();
                   IntentFilter filter=new IntentFilter();
                   filter.addAction(Intent.ACTION_BATTERY_CHANGED);
                   //注冊showPowerReceiver
                   registerReceiver(showPowerReceiver, filter);
         }
         /**
          * Describe:</br>
          * 手机电量提醒
          * */
         class ShowPowerReceiver extends BroadcastReceiver {
                   @Override
                   public void onReceive(Context context, Intent intent) {
                            // TODO Auto-generated method stub
                            //推断接收到的是否为电量变化的BroadCast Action
                            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
                                     //当前电量
                                     int level=intent.getIntExtra("level", 0);
                                     //总电量
                                     int scale=intent.getIntExtra("scale", 100);
                                     int current=level*100/scale;
                                     show.setText("当前电量:"+current+"%");
                            }
                   }
         }
}
程序执行效果图:
实例四:来去电提醒
当通话状态改变时候系统会发出,Intent的Action名为ACTION _PHONE_STAT的广播。当手机播出电话时系统会发出Intent的Action名为ACTION_NEW_OUTGOING_CALL的广播。
所以,仅仅需监測相应Intent的BroadcastReceiver便可实现来去电提醒的应用。
程序清单:
来电提醒
public class InCallReceiver extends BroadcastReceiver
{
private static Object obj;
/**
* 创建一个永不关闭的Toast
* @param context Context context上下文
* @param msg String msg 消息提示信息
* */
public static void showToast(Context context, String msg)
{
//创建一个Toast对象
Toast toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
//设置Toast的显示位置
toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);
try
{
//从toast对象中获取mTN对象
Field field = toast.getClass().getDeclaredField("mTN");
field.setAccessible(true);
obj = field.get(toast);
//从TN对象中获得show方法
Method method = obj.getClass().getDeclaredMethod("show", null);
//调用TN对象的show方法来显示Toast信息提示框
method.invoke(obj, null);
}
catch (Exception e)
{
}
}
/**
* 关闭Toast
* */
public static void closeToast()
{
if (obj != null)
{
try
{
Method method = obj.getClass().getDeclaredMethod("hide", null);
method.invoke(obj, null);
}
catch (Exception e)
{
}
}
}
@Override
public void onReceive(final Context context, final Intent intent)
{
//获取电话管理服务
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Service.TELEPHONY_SERVICE); switch (tm.getCallState())
{
case TelephonyManager.CALL_STATE_RINGING://响铃
String incomingNumber = intent
.getStringExtra("incoming_number");
showToast(context, incomingNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK://接听电话
Log.d("call_state", "offhook");
break; case TelephonyManager.CALL_STATE_IDLE://挂断电话
closeToast();
}
}
} //去电提醒
public class OutCallReceiver extends BroadcastReceiver
{ @Override
public void onReceive(Context context, Intent intent)
{
//获取去电的电话号码
String outcomingNumber = intent
.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
InCallReceiver.showToast(context, outcomingNumber);
} }
配置文件:AndroidManifest.xml
<!-- 为程序加入訪问电话状态的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 为程序加入同意程序监视,改动或放弃播出电话 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <!-- 注冊一个BroadcastReceiver监听系发出的电话状态的广播 -->
<receiver android:name=".InCallReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<!-- 注冊一个BroadcastReceiver监听系统发出的新来电的广播 -->
<receiver android:name=".OutCallReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
程序执行效果图:

       最后:因为在接收广播的时候。系统会为每一次接收广播单独创建一个广播接收器。即使是同一个广播的多次接收。因此,当电话处于不同的通话状态时,实际上是在不同的接收器对象中发生的,所以须要使用静态变量来保存Toast对象,不然closeTost我无法获取在上一个状态创建的Toast对象。也就无法关闭Toast信息框了。
Android开发之接收系统广播消息的更多相关文章
- android开发 socket接收图片并保存
		逻辑:接收到socket之后需要将socket发送的图片数据保存下来并通知handler更新界面 关键代码: public void readImage(Socket socket) { try { ... 
- JAVA微信公众号网页开发——将接收的消息转发到微信自带的客服系统
		如果公众号处于开发模式,普通微信用户向公众号发消息时,微信服务器会先将消息POST到开发者填写的url上,无法直接推送给微信自带的客服功能.如果需要把用户推送的普通消息推送到客服功能中,就需要进行代码 ... 
- BroadcastReceiver接收系统广播消息
		Android常用的广播Action常量: ACTION_TIME_CHANGED:系统时间被改变. ACTION_DATE_CHANGED:系统日期被改变. ACTION_TIMEZONE_CHAN ... 
- Android开发学习清单
		目录: 第1章 Android应用与开发环境1.1 Android的发展和历史1.1.1 Android的发展和简介1.1.2 Android平台架构及特性1.2 搭建Android开发环境1.2.1 ... 
- Android开发——Android的消息机制详解
		)子线程默认是没有Looper的,Handler创建前,必须手动创建,否则会报错.通过Looper.prepare()即可为当前线程创建一个Looper,并通过Looper.loop()来开启消息循环 ... 
- C#微信公众号开发系列教程四(接收普通消息)
		微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ... 
- Android开发之漫漫长途 ⅥI——Android消息机制(Looper Handler MessageQueue Message)
		该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ... 
- 《android开发艺术探索》读书笔记(十)--Android的消息机制
		接上篇<android开发艺术探索>读书笔记(九)--四大组件 No1: 消息队列MessageQueue的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表,因为单链表 ... 
- Android开发之漫漫长途 Ⅶ——Android消息机制(Looper Handler MessageQueue Message)
		该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ... 
随机推荐
- 用1天快速上手org-mode(windows系统)
			Table of Contents 1. 选择Emacs的理由--Org-mode 1.1. 现状(基于本人现有软件的使用) 1.2. 理念(够用才好) 1.3. 学习过程(少走弯路) 2. 快速安装 ... 
- 笔试算法题(11):Josephus环 & Fibonacci序列
			出题:Josephus Cycle,约瑟夫环问题.k个数字连成一个环,第一个数字为1.首先从1开始计数删除第m个数字:然后从上次被删除的数字的下一个数字开始计数,删除第m个数字:重复进行第二步直到只剩 ... 
- mysql主从同步,主库宕机解决方案
			链接:https://blog.csdn.net/zfl589778/article/details/51441719 
- 【笔记】搭建OpenWrt编译环境
			参考书目<B智能路由开发指南> 目标:搭建一个OpenWrt编译环境,可以同时在家里和公司使用. [2018-09-13] 刚开始想用自己的电脑共享远程桌面,但不知道什么原因搞不定,所以干 ... 
- mysql常用命令用法
			Mysql帮助文档地址:http://dev.mysql.com/doc/ 1.创建数据库: create database database_name; 2.选择数据库: use database_ ... 
- 【转】SQLServer连接字符串配置:MultipleActiveResultSets
			ADO.NET 1.x 利用SqlDataReader读取数据,针对每个结果集需要一个独立的连接.当然,你还必须管理这些连接并且要付出相应的内存和潜在的应用程序中的高度拥挤的瓶颈代价-特别是在数据集中 ... 
- 怎样签发SSL证书
			最近在做怎样让网站有SSL,搞了一天,现在总结一下 首先要安装OPENSSL和 Java的 keytool 先用OPENSSL生成私钥和CSR openssl req -newkey rsa:2048 ... 
- Git Cheat Sheet 中文版
			Git Cheat Sheet 中文版 索引 配置 配置文件 创建 本地修改 搜索 提交历史 分支与标签 更新与发布 合并与重置 撤销 Git Flow 配置 列出当前配置: $ git config ... 
- 在 Windows 10 64 下安装 Memcached,安装 PHP 7.0.22 的 Memcache 扩展
			1.之前写过一篇在 PHP 5.6.27 下的博客:http://www.shuijingwanwq.com/2017/09/11/1892/ ,此次是 PHP 7.0.22 下的,如图1 图1 2. ... 
- Jquery为DIV添加点击事件,Jquery为a标签超链接添加点击事件
			<div>1</div> <div>2</div> <div>3</div> <div>4</div> ... 
