自动获取验证码的两种方式都需要进行注册、取消注册两个步骤
记得添加权限
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
方式一:BroadcastReceiver
自定义广播
/**
* Created by weifeiyang on 2016/7/29 0029.
*/
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.telephony.SmsMessage;
import android.util.Log;
/**
* 短信监听
*
* @author
*/
public class SMSBroadcastReceiver extends BroadcastReceiver {
private static MessageListener mMessageListener;
public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";//只要注册声明权限即可收到、阻断
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(SMS_RECEIVED_ACTION)) {
//获得短信数据
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
//短信的类型, GSM与CDMA短信的解码方式不同
String format = intent.getStringExtra("format");
if (null != pdus) {
for (Object pdu : pdus) {
Log.e("pdu", "format" + format);
//23以上版本显示 createFromPdu过时,多加一个format参数即可
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu, format);
//发送号码-可以过滤需要读取的短信的发送号码
String sender = smsMessage.getDisplayOriginatingAddress();
//短信内容
String content = smsMessage.getDisplayMessageBody();
if (content.contains("你从服务器上获取到的验证码")){
mMessageListener.onReceived(content);
abortBroadcast();//中断广播的继续传递,防止优先级低的获取到
}
}
}
}
}
//回调接口
public interface MessageListener {
public void onReceived(String message);
}
public void setOnReceivedMessageListener(MessageListener messageListener) {
this.mMessageListener = messageListener;
}
}
其中关于format的解释可以参考
http://www.cnblogs.com/flyme/archive/2011/09/07/2169740.html 3GPP与3GPP2扫盲
广播有了后就可以使用了,在activity或者fragment的onCreate方法中调用initSMSBroadcastReceiver()
进行注册,在onDestroy()
中通过
取消注册
//注销短信监听广播
this.unregisterReceiver(mSMSBroadcastReceiver);
/**
* 初始化短信监听广播
*/
private void initSMSBroadcastReceiver() {
//生成广播处理
mSMSBroadcastReceiver = new SMSBroadcastReceiver(mContent);
//实例化过滤器并设置要过滤的广播
IntentFilter intentFilter = new IntentFilter(SMSBroadcastReceiver.SMS_RECEIVED_ACTION);
//优先级最高
intentFilter.setPriority(Integer.MAX_VALUE);
//注册广播
this.registerReceiver(mSMSBroadcastReceiver, intentFilter);
mSMSBroadcastReceiver.setOnReceivedMessageListener(new SMSBroadcastReceiver.MessageListener() {
@Override
public void onReceived(String message) {
TLog.error("message" + message);
String code = ReadSmsContent.getDynamicPassword(message);
seCodeEditText.setText(code);
}
});
}
方式二:ContentObserver
照旧先上ContentObserver代码
/**
* Created by weifeiyang on 2016/7/29 0029.
*/
import android.app.Activity;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.text.TextUtils;
import android.widget.EditText;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 读取短信验证码,并设置验证码
* Created by cool on 2016/1/4.
*/
public class ReadSmsContent extends ContentObserver {
private Cursor cursor = null;
private Activity mActivity;
private EditText mEditText;
public ReadSmsContent(Handler handler, Activity activity, EditText editText) {
super(handler);
this.mActivity = activity;
this.mEditText = editText;
}
@Override
public void onChange(boolean selfChange, Uri uri) {
/*
第一次回调 不是我们想要的 直接返回
目前发现每次收到新短信都会走好几次onChange(),
可以通过这个方法来使得onChange中的方法只走一次
*/
if (uri.toString().equals("content://sms/raw")) {
return;
}
/*
读取收件箱中的短信
address 发件人手机号码:
body 信息内容:
read 是否查看:
date 发送时间:
*/
cursor = mActivity.getContentResolver().query(Uri.parse("content://sms/inbox"),
new String[]{"_id", "address", "body", "read"}, null, null, "_id desc");//按降序排列
// 指定号码
// mActivity.managedQuery(Uri.parse("content://sms/inbox"),
// new String[]{"_id", "address", "body", "read"}, "address=? and read=?", new String[]{"10086", "0"}, "_id desc");
if (null != cursor && cursor.getCount() > 0) {
cursor.moveToNext();//指向首位
int smsbodyColumn = cursor.getColumnIndex("body");//body位置
String smsBody = cursor.getString(smsbodyColumn);//获取内容
String verifyCode = getDynamicPassword(smsBody);
if (TextUtils.isEmpty(verifyCode)) {
return;
}
if (mEditText == null) {
throw new RuntimeException("你传的EditText为空");
}
if (verifyCode.contains("你从服务器上获取到的验证码"))) {
mEditText.setText(verifyCode);
//EditText获取焦点,3个属性必须同时设置
mEditText.setFocusable(true);
mEditText.setFocusableInTouchMode(true);
mEditText.requestFocus();
mEditText.setSelection(verifyCode.length());//设置光标位置
}
}
if (!cursor.isClosed()) {
cursor.close();
}
}
/**
* 从字符串中截取连续4位数字
* 用于从短信中获取动态密码
*
* @param str 短信内容
* @return 截取得到的4位动态密码
*/
public static String getDynamicPassword(String str) {
Pattern continuousNumberPattern = Pattern.compile("[0-9\\.]+");
Matcher m = continuousNumberPattern.matcher(str);
String dynamicPassword = "";
while (m.find()) {
if (m.group().length() == 4) {
dynamicPassword = m.group();
}
}
return dynamicPassword;
}
}
观察者有了后就可以使用了,在activity或者fragment的onCreate方法中调用initSmSContentObserver()
进行注册,在onDestroy()
中通过
//注销内容监听者
this.getContentResolver().unregisterContentObserver(readSmsContent);
取消注册
/**
* 初始化短信监听数据库
*/
private void initSmSContentObserver() {
readSmsContent = new ReadSmsContent(new Handler(), this, seCodeEditText);
//注册短信内容监听
this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, readSmsContent);
}
上述两种方式获取到短信后,目前由于短信平台来源账号不固定,因此是通过验证码进行校验,如果有更好的办法可以联系我
邮箱:cugb_feiyang@163.com
QQ :178546852