监听系统短信这个只能作为一个技术点来研究下,读者可能在工作中可能不会哦涉及到,一般的应用软件也不会有这个需求

但是作为程序员呢,多了解一下也是好的。


Android 监听系统短信有什么用?

1、对系统接收到的短信进行识别,是广告或者是诈骗等

2、对短信内容进行过滤或者是对内容进行提取,比如验证码提取

3、对系统短信进行拦截,连系统自己都不让收到了(不会出现在系统数据里面,也不会有系统短信的通知栏提示)

  

监听系统短信广播有什么坑?

1、系统短信广播为有序广播,要拦截的话,需要在注册广播的时候设置广播优先级为最大,不过这种也有风险,如果被其他的应用先拦截了,那么我们将不再收到,使用时需注意。

2、要接到系统短信广播,那么应用必须具备短信读取权限,这对使用者来说可能是一个限制

3、除了短信读取权限,有些手机需要同时具备彩信读取权限(小米手机),这个就有点苛刻了

4、如果不能够接受第3点,那么要使用另外一种方式获取短信内容了,那就是:通过监听系统短信数据库数据变化,这个单独写了一篇文章介绍http://www.cnblogs.com/popfisher/p/5455980.html

5、系统短信数据库也是通过监听短信广播的方式得到短信内容数据的,只是系统自己的东西它有默认权限允许,不担心因为权限问题收不到短信广播

第5点可以这样验证:自己写一个短信广播的接收者,把短信广播给拦截了,会发现系统自己也收不到短信内容了。

如果是上面几种场景你都可是通过监听系统短信广播,然后解析出系统短信的内容, 进而对短信内容进行其他相关处理

监听系统短信广播代码如下

private static class SmsReceiver extends BroadcastReceiver {
SmsReceiverProcessor mSmsReceiverProcessor; SmsReceiver() {
mSmsReceiverProcessor = new SmsReceiverProcessor();
} @Override
public void onReceive(Context context, Intent intent) {
if (intent == null) {
return;
}
String action = intent.getAction();
if (SmsReceiverProcessor.ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED.equals(action)
|| SmsReceiverProcessor.ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED2.equals(action)
|| SmsReceiverProcessor.ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED_2.equals(action)
|| SmsReceiverProcessor.ANDROID_PROVIDER_TELEPHONY_GSM_SMS_RECEIVED.equals(action)){
mSmsReceiverProcessor.handleSms(intent);
} // 如果需要拦截广播,调用下面语句
abortBroadcast();
}
} public class SmsReceiverProcessor {
public static final String ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
public static final String ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED2 = "android.provider.Telephony.SMS_RECEIVED2";
public static final String ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED_2 = "android.provider.Telephony.SMS_RECEIVED_2";
public static final String ANDROID_PROVIDER_TELEPHONY_GSM_SMS_RECEIVED = "android.provider.Telephony.GSM_SMS_RECEIVED";
public SmsReceiverProcessor() {
} public void handleSms(Intent intent) {
SmsMessage[] smss = SmsUtils.getMessagesFromIntent(intent);
if (smss != null && smss.length >= 1) {
StringBuilder bodyBuf = new StringBuilder();
String phoneNumber = ""; // 电话号码
long time = 0;
for (SmsMessage msg : smss) {
try {
bodyBuf.append(msg.getDisplayMessageBody());
phoneNumber
= msg.getDisplayOriginatingAddress();
time = msg.getTimestampMillis();
} catch (Exception e) {
e.printStackTrace();
continue;
}
}
final String smsContent = bodyBuf.toString(); // 短信内容
if (TextUtils.isEmpty(phoneNumber) || TextUtils.isEmpty(smsContent)) {
return;
}
// 获得短信号码和内容之后可以进行相关处理
System.out.println("phoneNumber: " + phoneNumber + " smsContent: " + smsContent);
}
}
} // SmsUtils.java代码
public class SmsUtils {
public static SmsMessage[] getMessagesFromIntent(Intent intent) {
// moto的双模手机
if (isMotoTwoMode()) {
return getMessagesFromIntentInMotoXT800(intent);
} Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
if (messages == null) {
return null;
}
final int pduCount = messages.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
try {
for (int i = 0; i < pduCount; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) messages[i]);
}
} catch (Throwable e) {
return null;
} return msgs;
} private static SmsMessage[] getMessagesFromIntentInMotoXT800(Intent intent) {
String strFrom = intent.getStringExtra("from");
boolean bCDMA; if (strFrom == null)
return null; if (strFrom.equals("GSM")) {
bCDMA = false;
} else if (strFrom.equals("CDMA")) {
bCDMA = true;
} else {
return null;
} Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
byte[][] pduObjs = new byte[messages.length][]; for (int i = 0; i < messages.length; i++) {
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++) {
pdus[i] = pduObjs[i];
SmsMessageBase obj = XT800CreateFromPdu(pdus[i], bCDMA); try {
msgs[i] = SmsMessage.class.newInstance();
Field f = SmsMessage.class.getField("mWrappedSmsMessage");
f.set(msgs[i], obj);
} catch (Exception e) {
e.printStackTrace();
}
}
return msgs;
} // MOTO xt800上面的短信解析 private static SmsMessageBase XT800CreateFromPdu(byte[] pdu, boolean bCDMA) {
SmsMessageBase wrappedMessage = null;
if (bCDMA) {
wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
} else {
wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
}
return wrappedMessage;
} // 判断是否是摩托的双模手机
public static boolean isMotoTwoMode() {
final String strXT800 = "XT800";
final String strXT800plus = "XT800+";
final String strXT806 = "XT806";
final String strXT882 = "XT882"; String model = Build.MODEL; if (model != null) {
String upper = model.toUpperCase();
if (upper.equals(strXT800) || upper.equals(strXT800plus)
|| upper.equals(strXT806) || upper.equals(strXT882)) { return true;
}
} return false;
}
}
上面的代码需要导入两个类如下:
import android.telephony.SmsMessage;
import com.android.internal.telephony.SmsMessageBase;

接下来是注册广播,这里使用动态注册的方式,广播的注册与反注册结合Activity或者Service的生命周期来使用,具体不再详述。

广播的使用

private static BroadcastReceiver mSmsReceiver = null;
private static void registerSmsReceiver(ContextWrapper contextWrapper) {
try {
mSmsReceiver = new SmsReceiver();
IntentFilter filter = new IntentFilter(SmsReceiverProcessor.ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED);
filter.addAction(SmsReceiverProcessor.ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED2);
filter.addAction(SmsReceiverProcessor.ANDROID_PROVIDER_TELEPHONY_SMS_RECEIVED_2);
filter.addAction(SmsReceiverProcessor.ANDROID_PROVIDER_TELEPHONY_GSM_SMS_RECEIVED);
filter.setPriority(Integer.MAX_VALUE); // 这里虽然这是为整数最大值,但是实际上应该不允许超过系统运行的最大值1000,没验证
contextWrapper.registerReceiver(mSmsReceiver, filter, Manifest.permission.BROADCAST_SMS, null);
} catch(Throwable e) { }
} private static void unregisterSmsReceiver(ContextWrapper contextWrapper) {
try {
contextWrapper.unregisterReceiver(mSmsReceiver);
} catch(Exception e) { }
}

如果是简单的一点应用,使用上面的方式获取短信内容能够满足需求,但是如果对覆盖率要求高一点的需求可能就不行了,特别是对彩信权限或者其他权限的依赖会很不方便,所以多数时候使用监听系统短信数据库内容变化的方式来获取短信内容。

Android 短信监听及用途分析的更多相关文章

  1. Android短信监听软件

    本案例是在android手机中运行,是一个没有界面的短信监听软件.主要是用BroadcastReceiver来接受短信广播,当接收到短信后就跳转到service中来转发短信.哈哈,不是用来干坏事的.这 ...

  2. Android短信监听(二)——利用ContentObserver实现短信监听

    MainActivity例如以下: package cc.testsmslistener; import cc.testsmslistener.SMSContentObserver.MessageLi ...

  3. wemall app商城源码Android短信监听接收器

    wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...

  4. Android短信监听实现,及Android4.4之后短信机制变更

    前阵子公司有一个项目,简单的监听短信应用,功能只有如下两个: 1.监听短信并获取短信内容上传服务器: 2.从服务器获取短信内容,发送出去    按照传统的思路,监听短信我们有两种方式:第一种是使用广播 ...

  5. Android实战简易教程-第四十枪(窃听风云之短信监听)

    近期在做监听验证码短信自己主动填入的功能,无意间想到了一个短信监听的办法. 免责声明:短信监听本身是一种违法行为,这里仅仅是技术描写叙述.请大家学习技术就可以.(哈哈) 本实例是基于bmob提供的后台 ...

  6. Android 编程下短信监听在小米手机中失效的解决办法

    相信很多人写的短信监听应用在小米手机上是拦截不到短信的,这是因为小米对短信的处置权优先分给了系统.我们可以在短信的[设置]→[高级设置]→[系统短信优先]中发现短信的优先处理权默认是分给系统的,只要关 ...

  7. Android实现短信监听并且转发到指定的手机号,转发后不留痕

    转载:http://blog.csdn.net/swqqcs/article/details/7252419 通过这些代码也可以对远程手机实现短信控制.有兴趣的可以自己改一下,说一下简单的原理,要实现 ...

  8. 赵雅智_BroadcastReceiver短信监听

    AndroidManifest.xml 注冊广播接收者 加入权限 <?xml version="1.0" encoding="utf-8"?> &l ...

  9. Android短信收到,语音播报

    发送短信功能界面 /** * 发送短信Demo * * @description: * @author ldm * @date 2016-4-22 上午9:07:53 */ public class ...

随机推荐

  1. 安卓动态调试七种武器之离别钩 – Hooking(上)

    安卓动态调试七种武器之离别钩 – Hooking(上) 作者:蒸米@阿里聚安全 0x00 序 随着移动安全越来越火,各种调试工具也都层出不穷,但因为环境和需求的不同,并没有工具是万能的.另外工具是死的 ...

  2. 不要对外公开泛型List成员

    最近在阅读Framework Design Guidelines,本着现学现用的原则,于是就用FxCop工具对代码进行规范性检查时,发现了很多问题,其中包括命名以及一些设计上的规范. 其中,Do no ...

  3. Got the Best Employee of the year 2015 Star Award

    Got "The Best Employee of the year 2015 Star Award" from the company, thanks to all that h ...

  4. ajax的post方式和get方式比较,以及需要注意的地方

    说明:测试所用的js框架为kissy,后端语言为php 写在前面 目前我们可以将ajax请求的情形按照不同的类型进行分类,比如页面编码:utf-8 or gbk; ajax 传参方式 post or ...

  5. 有一个团队协同工具,叫Worktile

    项目管理,本是一个老生常谈的话题,曾几何时大碗云集在这个市场,其中不乏出现像微软.SAP.IBM.用友这样的名字.复杂而又冗繁的流程控制,让人们划分成两类人,一类是会使用这些工具和系统的人,另一类是不 ...

  6. C语言 · 前缀表达式

    问题描述 编写一个程序,以字符串方式输入一个前缀表达式,然后计算它的值.输入格式为:"运算符 对象1 对象2",其中,运算符为"+"(加法)."-&q ...

  7. JS实战 · 表格行颜色间隔显示,并在鼠标指定行上高亮显示

    思路: 1.获取所有行对象,将需要间隔颜色显示的行对象进行动态的className属性指定:      前提是:先定义好类选择器,就是说给行对象赋予name. 2.高亮用到两个事件:onmouseov ...

  8. [大数据之Spark]——Transformations转换入门经典实例

    Spark相比于Mapreduce的一大优势就是提供了很多的方法,可以直接使用:另一个优势就是执行速度快,这要得益于DAG的调度,想要理解这个调度规则,还要理解函数之间的依赖关系. 本篇就着重描述下S ...

  9. KnockoutJS 3.X API 第七章 其他技术(8) 异步错误处理

    注意:本文档适用于Knockout 3.4.0及更高版本. ko.onError Knockout包装内部异步调用,并在抛出原始错误之前查找可选的ko.onError回调以执行(如果遇到异常). 这使 ...

  10. PHP SESSION机制,从存储到读取

    PHP中,如果要获取SESSION数据,必须要有对应的session_id,session_id的获取方式有两种 1.基于客户端的cookie 2.基于url 先说第一种情况,基于客户端的cookie ...