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

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


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短信拦截和电话拦截

    MainActivity: package com.wyl.bctest; import android.support.v7.app.ActionBarActivity; import androi ...

  2. android 短信拦截

    android 4+版本需要用户主动添加broadReceiver 1.清单文件 <manifest xmlns:android="http://schemas.android.com ...

  3. android短信拦截

    广播分2种,无序广播和有序广播.可以理解为散列和队列广播. 首先无序广播,不能中断,分发机制有点类似散列发送.这种广播的的发送为:context.sendBroadcast这种广播是不能中断的,请看A ...

  4. android之短信拦截器

    下面通过短信拦截器来介绍短信中的广播 布局文件 在布局文件中可以设置需要拦截的号码 <?xml version="1.0" encoding="utf-8" ...

  5. Android的BroadcastReceiver 广播 短信拦截

    如何去理解BroadcastReceiver(广播)?其实可以这样想,首先我们要有一个发送广播的"媒体",在这个例子中,我们暂且用activity组件作为这个媒体,当然以后会用到s ...

  6. [android] 手机卫士黑名单功能(短信拦截)

    前面我们把需要拦截的手机号都存储和展示出来了,接下来是使用广播接收者拦截短信了,这个广播接收者需要和一个服务绑定,服务开启的时候,接收者存在,服务停掉时,接收者关闭 在service包下定义一个类Ca ...

  7. Android -- 怎么发出和接收广播, Broadcast, 电话拨号拦截,短信拦截

    1. 发送广播 使用以下三个API可以发送广播 public void click(View view){ Intent intent = new Intent(); intent.setAction ...

  8. Android应用源码安卓短信拦截木马项目源码

    温馨提示:本资源由源码天堂整理提供下载转载时请留下链接说明:http://code.662p.com/view/9174.html安卓短信拦截木马源码主要功能就是开机后台启动,拦截本机收到的短信并且转 ...

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

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

随机推荐

  1. bzoj3114 LCM Pair Sum

    题意:以质因数分解的方式给定n,求所有满足:lcm(a, b) = n的无序数对的价值和.其中(a, b)的价值为a + b 解: 定义首项为a,公比为q,项数为n的等比数列的和为getQ(a, q, ...

  2. WebService注解总结

    @WebService 1.serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service.缺省值为 Java 类的简单名称 + Service.(字符 ...

  3. ServiceStack.Redis 之 IRedisTypedClient<第四篇>

    IRedisTypedClient IRedisTypedClient类相当于IRedicClient的强类型版,其方法与属性大多数与IRedisClient类似. 它支持在Redis中使用Linq查 ...

  4. HDU 2255 KM算法 二分图最大权值匹配

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  5. java基础基础总结----- RunTime

  6. Java远程访问接口的几种方式

    一.Java访问远程url接口并获取结果 1.原生JavaAPI获取 package com.util; import java.io.DataOutputStream; import java.io ...

  7. oracle 工作笔记,不定期更新

    此博客为工作时,所见技术问题的解决方案笔记,欢迎大家转载,转载请注明出处,谢谢~ 更新时间: 2017-07-12 1. clob字段值读取时,借用extractvalue或extract函数读取节点 ...

  8. spring中set注入的一些小细节错误

    这是小白偶尔一直null指针的错误,调试了好久,原来是自己对spring注入的不够了解 我相信有很多跟我差不多的初学者会遇上,所以特地写出来,防止有人跟我一样.哈哈,也写上去,以防自己下次还犯这样的错 ...

  9. scala 基础知识总结

    在最开始处引入 log 相关的 包 import org.apache.log4j.{Logger,Level} 在需要屏蔽日志输出的地方加上这两行代码 // 屏蔽不必要的日志显示在终端上 Logge ...

  10. Bower使用笔记

    全局安装bower $ npm install -g bower 检测成功 $ bower help 在项目根目录下进行安装(最新版本),会自动生成一个bower_components文件夹(如果在c ...