转载请注明:http://blog.youkuaiyun.com/binbinqq86/article/details/47154117
关于短信的获取已经是个老话题了,最近项目中需要用到这个功能,就是在用户注册的时候,当获取验证码后能自动填入输入框,网上找了一大堆,无非都是注册短信到达的广播,这种方式在虚拟机上是没有问题的,可是一到真机上,是根本行不通的。网上一搜,大把大把的这种方式,都是重复内容,为什么就不自己跑一遍呢???
经过自己的研究,解决了这个问题,主要思路就是通过反射,来调用系统的获取短信的方法,下面看代码:
Cursor cur = null;
try {
clazz = Class.forName("android.provider.Telephony$Sms");
// Object object = clazz.newInstance();
Method[] ms=clazz.getMethods();
Method me=clazz.getMethod("query", ContentResolver.class,String[].class,String.class,String.class);
cur=(Cursor) me.invoke(null, getContentResolver(),null,"type=1 and protocol=0","date desc");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (null == cur)
return;
while (cur.moveToNext()) {
Msg msg=new Msg();
String number = cur.getString(cur.getColumnIndex("address"));//手机号
String date = cur.getString(cur.getColumnIndex("date"));
String body = cur.getString(cur.getColumnIndex("body"));
msg.body=body;
msg.date=date;
msg.num=number;
}
看着很简单吧,
android.provider.Telephony$Sms这个内部类下的query方法被置为hide标记,所以无法调用,通过反射就能很简单的获取系统的短信,那么当短信到达时怎么能立刻得知呢?这里就要用到内容观察者ContentObserver这个类,下面看代码:
class SmsObserver extends ContentObserver {
public SmsObserver(Context context, Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
//每当有新短信到来时,会触发这个方法,可以在这里处理自己的逻辑,比如读取短信内容,自动填入验证码到输入框
}
}
注意:此时想要获得自己需要的短信的话,查询语句需要加些条件,具体短信数据库的主要字段的含义如下:
content://sms/inbox 收件箱
content://sms/sent 已发送
content://sms/draft 草稿
content://sms/outbox 发件中
content://sms/failed 失败
content://sms/queued 待发送
数据库中sms相关的字段如下:
_id primary key integer 与words表内的source_id关联
thread_id 会话id,一个联系人的会话一个id,与threads表内的_id关联 integer
address 对方号码 text
person 联系人id integer
date 发件日期 integer
protocol 通信协议,判断是短信还是彩信 integer 0:SMS_RPOTO, 1:MMS_PROTO
read 是否阅读 integer default 0 0:未读, 1:已读
status 状态 integer default-1 -1:接收,
0:complete,
64: pending,
128: failed
type 短信类型 integer 1:inbox
2:sent
3:draft56
4:outbox
5:failed
6:queued
body 内容
service_center 服务中心号码
subject 主题
reply_path_present
locked
error_code
seen 是否在通知栏显示通知 integer 0:显示,1:不显示
如果需要过滤特定的短信,只需要加上号码和未读条件即可。。。
注册下这个观察者:
smsObserver = new SmsObserver(this, smsHandler);
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, smsObserver);
到此,我们在一开始的那个问题就完美的解决了,心里那个酸爽~
想要完整代码的朋友可以留下邮箱,当然,主要核心代码就那么几行,相信大家自己也能写出来,最后不要忘记在mainfest中加入读取短信的权限。