Android 短信监听及用途分析
监听系统短信这个只能作为一个技术点来研究下,读者可能在工作中可能不会哦涉及到,一般的应用软件也不会有这个需求
但是作为程序员呢,多了解一下也是好的。
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 短信监听及用途分析的更多相关文章
- Android短信监听软件
本案例是在android手机中运行,是一个没有界面的短信监听软件.主要是用BroadcastReceiver来接受短信广播,当接收到短信后就跳转到service中来转发短信.哈哈,不是用来干坏事的.这 ...
- Android短信监听(二)——利用ContentObserver实现短信监听
MainActivity例如以下: package cc.testsmslistener; import cc.testsmslistener.SMSContentObserver.MessageLi ...
- wemall app商城源码Android短信监听接收器
wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...
- Android短信监听实现,及Android4.4之后短信机制变更
前阵子公司有一个项目,简单的监听短信应用,功能只有如下两个: 1.监听短信并获取短信内容上传服务器: 2.从服务器获取短信内容,发送出去 按照传统的思路,监听短信我们有两种方式:第一种是使用广播 ...
- Android实战简易教程-第四十枪(窃听风云之短信监听)
近期在做监听验证码短信自己主动填入的功能,无意间想到了一个短信监听的办法. 免责声明:短信监听本身是一种违法行为,这里仅仅是技术描写叙述.请大家学习技术就可以.(哈哈) 本实例是基于bmob提供的后台 ...
- Android 编程下短信监听在小米手机中失效的解决办法
相信很多人写的短信监听应用在小米手机上是拦截不到短信的,这是因为小米对短信的处置权优先分给了系统.我们可以在短信的[设置]→[高级设置]→[系统短信优先]中发现短信的优先处理权默认是分给系统的,只要关 ...
- Android实现短信监听并且转发到指定的手机号,转发后不留痕
转载:http://blog.csdn.net/swqqcs/article/details/7252419 通过这些代码也可以对远程手机实现短信控制.有兴趣的可以自己改一下,说一下简单的原理,要实现 ...
- 赵雅智_BroadcastReceiver短信监听
AndroidManifest.xml 注冊广播接收者 加入权限 <?xml version="1.0" encoding="utf-8"?> &l ...
- Android短信收到,语音播报
发送短信功能界面 /** * 发送短信Demo * * @description: * @author ldm * @date 2016-4-22 上午9:07:53 */ public class ...
随机推荐
- IntelliJ IDEA 15 激活码 正版 可离线激活
43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...
- Mysql的用户名密码设置方法
方法如下: 1, 关闭mysql服务 /etc/init.d/mysqld stop 2,使用 –skip-grant-tables选项启动mysql服务,可以修 改/etc/inin.d/mysql ...
- Base64 转换 %2B 变 空格 解决
//此方法转换会转换出错 deString.ServerUrlDecode().Replace(" ", "+") //换此方法完美解决 HttpUtility ...
- jquery.ajax
var params = {};//定义一个数组 var USERNAME= $("#USERNAME").val(); params["USERNAME"]= ...
- Mac 软件篇
对于美好事务的追求无论何时都不算晚. ** 文章内容来着我整理的fetool,以下内容可能更新不及时 ** Mac 下的软件那么多,又是免费又是付费,应该怎么选呢?我来分享下我的推荐列表,推荐的优先级 ...
- Git Shell 基本命令(官网脱水版)
用户信息 当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址. 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改: $ git conf ...
- 使用border做三角形
网站上经常会使用一些三角形,除了图片的方式,实际上利用border我们可以做出纯CSS的三角形.我们知道border是个边抖可以单独设置,当四个边相交的时候他们是什么时候改变的? .t0{ margi ...
- linux java so 历险
一开始 -bash-4.1# java -cp "/usr/linkapp/bin/tomcat-master/webapps/ROOT/WEB-INF/lib/*":" ...
- 模拟淘宝购物,运用cookie,记录登录账号信息,并且记住购物车内所选的商品
1.登录界面 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEn ...
- [译]libev和libevent的设计差异
本文译自what's the difference between libev and libevent? 作者是libev作者 [问]两个库都是为异步io调度而设计,在Linux上都是使用epoll ...