最近做的项目里要监听手机的短消息内容,这个东西好像在最初学的时候都做过,不过现在早忘记了,现在写下来,记住了。
前提–权限:
-
<uses-permission android:name=
“android.permission.RECEIVE_SMS”
> - </uses-permission>
-
<uses-permission android:name=
“android.permission.READ_SMS”
> - </uses-permission>
方式一:通过广播监听短信消息
(注意:这种方式只对新收到的短消息有效,运行代码,并不会读取收件箱中已读或未读的消息,只有当收到新来的短消息时,才会执行onChange方法)
注册一个广播:
-
<receiver android:name=
“com.dbjtech.acbxt.waiqin.SmsReciver”
> -
<intent-filter android:priority=
“999”
> -
<action android:name=
“android.provider.Telephony.SMS_RECEIVED”
/> - </intent-filter>
- </receiver>
SmsReceiver.java
-
public
class
SmsReciver
extends
BroadcastReceiver { -
@Override
-
public
void
onReceive(Context context, Intent intent) { - Bundle bundle = intent.getExtras();
-
SmsMessage msg =
null
; -
if
(
null
!= bundle) { -
Object[] smsObj = (Object[]) bundle.get(
“pdus”
); -
for
(Object object : smsObj) { -
msg = SmsMessage.createFromPdu((
byte
[]) object); -
Date date =
new
Date(msg.getTimestampMillis());
//时间
-
SimpleDateFormat format =
new
SimpleDateFormat(
“yyyy-MM-dd HH:mm:ss”
); - String receiveTime = format.format(date);
-
System.out.println(
“number:”
+ msg.getOriginatingAddress() -
+
” body:”
+ msg.getDisplayMessageBody() +
” time:”
- + msg.getTimestampMillis());
-
//在这里写自己的逻辑
-
if
(msg.getOriginatingAddress().equals(
“10086”
)) { -
//TODO
- }
- }
- }
- }
- }
系统的这个广播是有序广播,就是当别的程序先获取到了这个广播再传递给你,当然它也可以干掉这个广播,让你接收不到,这样你的程序肯定是接收不到这个广播的了。我们发现,通过设置priority的数值,其实有时是不管用的,现在在一些定制的系统或是有安全软件的情况下,往往短消息都被截取到,并被干掉。
那么,我们只能使用方法二,监听短信数据库的变化,这种方式比方法一稍微复杂一些,不过使用起来也很方便,不受其它程序干扰~
方式二:通过短信数据库获取短信内容
(注意:这种方式可以获取手机上所有的短信,包括已读未读的短信,是不是很赞)
-
private
Uri SMS_INBOX = Uri.parse(
“content://sms/”
); -
public
void
getSmsFromPhone() { - ContentResolver cr = getContentResolver();
-
String[] projection =
new
String[] {
“body”
};
//”_id”, “address”, “person”,, “date”, “type
-
String where =
” address = ‘1066321332’ AND date > ”
-
+ (System.currentTimeMillis() –
10
*
60
*
1000
); -
Cursor cur = cr.query(SMS_INBOX, projection, where,
null
,
“date desc”
); -
if
(
null
== cur) -
return
; -
if
(cur.moveToNext()) { -
String number = cur.getString(cur.getColumnIndex(
“address”
));
//手机号
-
String name = cur.getString(cur.getColumnIndex(
“person”
));
//联系人姓名列表
-
String body = cur.getString(cur.getColumnIndex(
“body”
)); -
//这里我是要获取自己短信服务号码中的验证码~~
-
Pattern pattern = Pattern.compile(
” [a-zA-Z0-9]{10}”
); - Matcher matcher = pattern.matcher(body);
-
if
(matcher.find()) { -
String res = matcher.group().substring(
1
,
11
); - mobileText.setText(res);
- }
- }
- }
sms主要结构:
_id:短信序号,如100
thread_id:对话的序号,如100,与同一个手机号互发的短信,其序号是相同的
address:发件人地址,即手机号,如+86138138000
person:发件人,如果发件人在通讯录中则为具体姓名,陌生人为null
date:日期,long型,如1346988516,可以对日期显示格式进行设置
protocol:协议0SMS_RPOTO短信,1MMS_PROTO彩信
read:是否阅读0未读,1已读
status:短信状态-1接收,0complete,64pending,128failed
type:短信类型1是接收到的,2是已发出
body:短信具体内容
service_center:短信服务中心号码编号,如+8613800755500
通过方式二,我们就能获取手机中所有的短消息了,可是还有一个问题,如果来了新的短消息呢?我们总不能写个线程,每隔多少秒,去读取一下短信数据库吧?其实我们可以把方式二换个方式写:
-
private
SmsObserver smsObserver; -
protected
void
onCreate(Bundle savedInstanceState) { -
super
.onCreate(savedInstanceState); - setContentView(R.layout.app_login);
-
smsObserver =
new
SmsObserver(
this
, smsHandler); -
getContentResolver().registerContentObserver(SMS_INBOX,
true
, - smsObserver);
- }
-
public
Handler smsHandler =
new
Handler() { -
//这里可以进行回调的操作
-
//TODO
- };
-
class
SmsObserver
extends
ContentObserver { -
public
SmsObserver(Context context, Handler handler) { -
super
(handler); - }
-
@Override
-
public
void
onChange(
boolean
selfChange) { -
super
.onChange(selfChange); -
//每当有新短信到来时,使用我们获取短消息的方法
- getSmsFromPhone();
- }
- }
效果: