利用广播接受者监听用户短信
2016-05-29 11:56
330 查看
标签: androidservicedateobjectstringsms
2012-07-12 22:34 2906人阅读 评论(2) 收藏 举报
版权声明:本文为博主原创文章,未经博主允许不得转载。
初识广播接受者:
广播接受者用于异步接受广播intent,广播intent的发送主要有三种方式:
1.Context.sendboardcast()(发送的是普通广播,所有订阅者都有机会获得并进行处理。)
2.context.sendorderedbroadcast()(发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播,如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。对于有序广播,前面的接收者可以将处理结果存放进广播Intent,然后传给下一个接收者。)
3.Context.sendStickyBroadcast()
实现一个广播接收者的主要步骤分为如下几步:
1.第一步:继承BroadcastReceiver,并重写onReceive()方法。
public class IncomingSMSReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) { <!--广播的发送端的发送数据就被封装在intent中-->
}
}
2.第二步:订阅感兴趣的广播Intent,订阅方法有两种:
第一种:在AndroidManifest.xml文件中的节点里进行订阅:
[java] view
plain copy
<span style="font-size:12px;"><receiver android:name=".IncomingSMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver> </span>
第二种:在代码中进行注册
[java] view
plain copy
<span style="font-size:12px;">IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");//或者<span>filter.addAction(<span class="string">"android.intent.action.MY_BROADCAST"</span><span>); </span></span>
filter.setPriority(1000);
context.registerReceiver(new SmsBoradCastReciver(), filter);
</span>
广播接受者的两种类型:有序广播和无序广播(也称普通广播)。
首先对于普通广播而言,它是完全异步的(关于同步和异步小插一曲:同步指的是你的程序在执行一个操作时,一直要等到这个程序执行完,异步就是说程序在执行某一个操作时,只是发出开始的指令;由另外的并行程序执行这段代码,当完成时再通知调用者。)
普通广播:可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能传递处理结果给下一个接收者,并且无法终止广播Intent的传播。这些接受者之间并没有太大的关系,并且都能收到广播。
有序广播:逐个执行接收者——系统会按照接收者声明的优先级别(声明在intent-filter元素的Android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),按顺序逐次执行。,前后之间有很大的影响。先收到广播的接受者可以终止广播,同时也能改变广播发送的内容。后续会通过实例代码的方式对这种方式进行进一步的相关解释。
关于广播接受者需要注意的是:
在Android系统中,程序的响应收到ActivityManager以及windowManager的监听。当BroadcastReceiver在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No Response)的对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。当BroadcastReceiver在10秒内没有执行完毕,Android会认为该程序无响应。而不是使用子线程的方法来解决,因为BroadcastReceiver的生命周期很短子线程可能还没有结束它就先结束了。当然如果BroadcastReceiver结束了,它的宿主进程还在运行,子线程还会继续执行。但宿主进程此时很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。
如果我在一个广播接收器中要处理多个动作呢?那要如何去处理?
registerReceiver在Android 的接收器中onReceive 以经为我们想到的,同样的你必须在Intent-filter 里面注册该动作,可以是系统的广播动作也可以是自己需要的广播,之后你之需要在onReceive 方法中,通过intent.getAction()判断传进来的动作即可做出不同的处理,不同的动作。
同时如果我们要想要特定的广播接受者来接受广播,对于有序广播的情况,可以使用自定义的权限。就类似系统中声明的各种权限一样,用户也可以为自己的广播发送端声明权限。接受者和发送方有相同的权限,此时就可以接受广播了。
关于静态注册和动态注册:
所谓的静态注册就是在清单文件中注册,动态注册就是在代码中使用registerReciver()的方式进行注册。关于第二种注册方法需要特别注意的是;就是当用来注册的 Activity 关掉后,广播也就失效了。同时反映了静态注册的一个优势,就是无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器就是打开着的。
关于动态注册还有需要注意的就是:
registerReceiver是android.content.ContextWrapper类中的方法,Activity和Service都继承了ContextWrapper,所以可以直接调用。在实际应用中,我们在Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,记得在特定的地方执行解除注册操作:
[java] view
plain copy
package com.luochuang.sms;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
public class SmsBoradCastReciver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 通过查看源码可知,短信的发送意图为pdus
Object[] objs = (Object[]) intent.getExtras().get("pdu");
for (Object obj : objs) {
// 通过此方法可以把原始的 Pdu数据格式转换成我们可以阅读的数据格式
byte[] sms = (byte[]) obj;
SmsMessage message = SmsMessage.createFromPdu(sms);
// 短信内容
String content = message.getMessageBody();
// 发送人号码
String number = message.getOriginatingAddress();
// 发送时间
Date date = new Date(message.getTimestampMillis());
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(date);
System.out.println(content + number + time);
// 短信发送的广播是系统的有序广播,有序广播可以通过abortBroadcast()的方法来结束广播
abortBroadcast();
}
}
因为该操作侵犯到了用户权限, 所以要在清单文件中注册相关的权限。
小节:
在Android 中如果要发送一个广播必须使用sendBroadCast 向系统发送对其感兴趣的广播接收器中。
使用广播必须要有一个intent 对象必设置其action动作对象
使用广播必须在配置文件中显式的指明该广播对象
每次接收广播都会重新生成一个接收广播的对象
在BroadCast 中尽量不要处理太多逻辑问题,建议复杂的逻辑交给Activity 或者 Service 去处理
我的例子比较杂,这有一篇很好的文章,能帮助初学者准确的理解广播接受者:
2012-07-12 22:34 2906人阅读 评论(2) 收藏 举报
版权声明:本文为博主原创文章,未经博主允许不得转载。
初识广播接受者:
广播接受者用于异步接受广播intent,广播intent的发送主要有三种方式:
1.Context.sendboardcast()(发送的是普通广播,所有订阅者都有机会获得并进行处理。)
2.context.sendorderedbroadcast()(发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播,如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。对于有序广播,前面的接收者可以将处理结果存放进广播Intent,然后传给下一个接收者。)
3.Context.sendStickyBroadcast()
实现一个广播接收者的主要步骤分为如下几步:
1.第一步:继承BroadcastReceiver,并重写onReceive()方法。
public class IncomingSMSReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) { <!--广播的发送端的发送数据就被封装在intent中-->
}
}
2.第二步:订阅感兴趣的广播Intent,订阅方法有两种:
第一种:在AndroidManifest.xml文件中的节点里进行订阅:
[java] view
plain copy
<span style="font-size:12px;"><receiver android:name=".IncomingSMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver> </span>
第二种:在代码中进行注册
[java] view
plain copy
<span style="font-size:12px;">IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");//或者<span>filter.addAction(<span class="string">"android.intent.action.MY_BROADCAST"</span><span>); </span></span>
filter.setPriority(1000);
context.registerReceiver(new SmsBoradCastReciver(), filter);
</span>
广播接受者的两种类型:有序广播和无序广播(也称普通广播)。
首先对于普通广播而言,它是完全异步的(关于同步和异步小插一曲:同步指的是你的程序在执行一个操作时,一直要等到这个程序执行完,异步就是说程序在执行某一个操作时,只是发出开始的指令;由另外的并行程序执行这段代码,当完成时再通知调用者。)
普通广播:可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能传递处理结果给下一个接收者,并且无法终止广播Intent的传播。这些接受者之间并没有太大的关系,并且都能收到广播。
有序广播:逐个执行接收者——系统会按照接收者声明的优先级别(声明在intent-filter元素的Android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),按顺序逐次执行。,前后之间有很大的影响。先收到广播的接受者可以终止广播,同时也能改变广播发送的内容。后续会通过实例代码的方式对这种方式进行进一步的相关解释。
关于广播接受者需要注意的是:
在Android系统中,程序的响应收到ActivityManager以及windowManager的监听。当BroadcastReceiver在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No Response)的对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。当BroadcastReceiver在10秒内没有执行完毕,Android会认为该程序无响应。而不是使用子线程的方法来解决,因为BroadcastReceiver的生命周期很短子线程可能还没有结束它就先结束了。当然如果BroadcastReceiver结束了,它的宿主进程还在运行,子线程还会继续执行。但宿主进程此时很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。
如果我在一个广播接收器中要处理多个动作呢?那要如何去处理?
registerReceiver在Android 的接收器中onReceive 以经为我们想到的,同样的你必须在Intent-filter 里面注册该动作,可以是系统的广播动作也可以是自己需要的广播,之后你之需要在onReceive 方法中,通过intent.getAction()判断传进来的动作即可做出不同的处理,不同的动作。
同时如果我们要想要特定的广播接受者来接受广播,对于有序广播的情况,可以使用自定义的权限。就类似系统中声明的各种权限一样,用户也可以为自己的广播发送端声明权限。接受者和发送方有相同的权限,此时就可以接受广播了。
关于静态注册和动态注册:
所谓的静态注册就是在清单文件中注册,动态注册就是在代码中使用registerReciver()的方式进行注册。关于第二种注册方法需要特别注意的是;就是当用来注册的 Activity 关掉后,广播也就失效了。同时反映了静态注册的一个优势,就是无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器就是打开着的。
关于动态注册还有需要注意的就是:
registerReceiver是android.content.ContextWrapper类中的方法,Activity和Service都继承了ContextWrapper,所以可以直接调用。在实际应用中,我们在Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,记得在特定的地方执行解除注册操作:
[java] view
plain copy
package com.luochuang.sms;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
public class SmsBoradCastReciver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 通过查看源码可知,短信的发送意图为pdus
Object[] objs = (Object[]) intent.getExtras().get("pdu");
for (Object obj : objs) {
// 通过此方法可以把原始的 Pdu数据格式转换成我们可以阅读的数据格式
byte[] sms = (byte[]) obj;
SmsMessage message = SmsMessage.createFromPdu(sms);
// 短信内容
String content = message.getMessageBody();
// 发送人号码
String number = message.getOriginatingAddress();
// 发送时间
Date date = new Date(message.getTimestampMillis());
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(date);
System.out.println(content + number + time);
// 短信发送的广播是系统的有序广播,有序广播可以通过abortBroadcast()的方法来结束广播
abortBroadcast();
}
}
因为该操作侵犯到了用户权限, 所以要在清单文件中注册相关的权限。
小节:
在Android 中如果要发送一个广播必须使用sendBroadCast 向系统发送对其感兴趣的广播接收器中。
使用广播必须要有一个intent 对象必设置其action动作对象
使用广播必须在配置文件中显式的指明该广播对象
每次接收广播都会重新生成一个接收广播的对象
在BroadCast 中尽量不要处理太多逻辑问题,建议复杂的逻辑交给Activity 或者 Service 去处理
我的例子比较杂,这有一篇很好的文章,能帮助初学者准确的理解广播接受者:
相关文章推荐
- LightOJ 1214 Large Division(大整数取模)
- Android开发技术点
- CentOS 7 minimal 版本安装后网络配置
- C++基础<01>—C++初识
- 一道关于重载的例子
- POJ 1742 Coins
- 在dev环境访问self assigned的https服务器,报Trust Anchor not found for Android SSL Connection
- LightOJ 1220 Mysterious Bacteria(满足a^p = n的最大p)
- Fraction to Recurring Decimal
- 轮播图页面的倒计时
- 随笔—邀请赛前训—Wizards' Duel
- UIButton的圆角
- LightOJ 1234 Harmonic Number(调和级数求和)
- mamp环境下缓存问题
- 打开Delphi 10.1 berlin提示脚本错误的解决方法
- 取证分析的迷思
- mac 终端 svn 命令
- |NOIOJ|二分归并|7622:求排列的逆序数
- Count Color_poj2777_线段树+位运算
- 1369 - Answering Queries