一般用戶喜歡用手機(jī)號(hào)作為用戶名注冊(cè)APP賬號(hào),常常通過(guò)手機(jī)驗(yàn)證碼的方式進(jìn)行驗(yàn)證,下面我們就研究一個(gè)非常實(shí)用的方法,通過(guò)監(jiān)聽(tīng)短信-實(shí)現(xiàn)短信驗(yàn)證碼的自動(dòng)填入,提高用戶體驗(yàn)。 首先看一下如何監(jiān)聽(tīng)手機(jī)短信。
1.新建一個(gè)SMSBroadcastReceiver:
package com.example.messagecut;
//省略導(dǎo)入包
/**
* 配置廣播接收者:
* <receiver android:name=".SMSBroadcastReceiver">
* <intent-filter android:priority="1000">
* <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
* </intent-filter>
* </receiver>
*
* 注意:
* <intent-filter android:priority="1000">表示:
* 設(shè)置此廣播接收者的級(jí)別為最高
*/
public class SMSBroadcastReceiver extends BroadcastReceiver {
private static MessageListener mMessageListener;
public SMSBroadcastReceiver() {
super();
}
@Override
public void onReceive(Context context, Intent intent) {
Object [] pdus= (Object[]) intent.getExtras().get("pdus");
for(Object pdu:pdus){
SmsMessage smsMessage=SmsMessage.createFromPdu((byte [])pdu);
String sender=smsMessage.getDisplayOriginatingAddress();
String content=smsMessage.getMessageBody();
long date=smsMessage.getTimestampMillis();
Date timeDate=new Date(date);
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time=simpleDateFormat.format(timeDate);
System.out.println("短信來(lái)自:"+sender);
System.out.println("短信內(nèi)容:"+content);
System.out.println("短信時(shí)間:"+time);
mMessageListener.OnReceived(content);
//如果短信來(lái)自5556,不再往下傳遞,一般此號(hào)碼可以作為短信平臺(tái)的號(hào)碼。
if("5556".equals(sender)){
System.out.println(" abort ");
abortBroadcast();
}
}
}
// 回調(diào)接口
public interface MessageListener {
public void OnReceived(String message);
}
public void setOnReceivedMessageListener(MessageListener messageListener) {
this.mMessageListener=messageListener;
}
}
SMSBroadcastReceiver 繼承自BroadcastReceiver,覆寫(xiě)了onReceive方法,通過(guò)Object [] pdus= (Object[]) intent.getExtras().get("pdus");獲取短信內(nèi)容,將對(duì)象集合遍歷,獲取所需的內(nèi)容,通過(guò)回調(diào)接口將內(nèi)容傳遞到Activity中。
2.配置AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.messagecut"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".SMSBroadcastReceiver">
<intent-filter >
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
</manifest>
設(shè)置了接收和讀取短信的權(quán)限
3.創(chuàng)建MainActivity.java-用于接收顯示短信信息內(nèi)容:
package com.example.messagecut;
import android.os.Bundle;
import android.widget.TextView;
import com.example.messagecut.SMSBroadcastReceiver.MessageListener;
import android.app.Activity;
/**
* Demo描述:
* 利用BroadcastReceiver實(shí)現(xiàn)監(jiān)聽(tīng)短信
* 注意權(quán)限:
* <uses-permission android:name="android.permission.RECEIVE_SMS"/>
*/
public class MainActivity extends Activity{
private TextView mTextView;
private SMSBroadcastReceiver mSMSBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init(){
mTextView=(TextView) findViewById(R.id.textView);
mSMSBroadcastReceiver=new SMSBroadcastReceiver();
mSMSBroadcastReceiver.setOnReceivedMessageListener(new MessageListener() {
public void OnReceived(String message) {
mTextView.setText(message);
}
});
}
}
項(xiàng)目運(yùn)行在真機(jī)上進(jìn)行測(cè)試,用另一臺(tái)手機(jī)發(fā)送短信給本機(jī),得到如下:
成功獲取短信內(nèi)容,打印出來(lái)。
上面實(shí)現(xiàn)了截取短信全部?jī)?nèi)容,下面看一下如何截取有效信息–驗(yàn)證碼。原理很簡(jiǎn)單,就是在字符串中截取部分字符串。 算法即:
/**
* 從字符串中截取連續(xù)6位數(shù)字組合 ([0-9]{" + 6 + "})截取六位數(shù)字 進(jìn)行前后斷言不能出現(xiàn)數(shù)字 用于從短信中獲取動(dòng)態(tài)密碼
* @param str
* 短信內(nèi)容
* @return 截取得到的6位動(dòng)態(tài)密碼
*/
public String getDynamicPassword(String str) {
// 6是驗(yàn)證碼的位數(shù)一般為六位
Pattern continuousNumberPattern = Pattern.compile("(?<![0-9])([0-9]{"
+ 6 + "})(?![0-9])");
Matcher m = continuousNumberPattern.matcher(str);
String dynamicPassword = "";
while (m.find()) {
System.out.print(m.group());
dynamicPassword = m.group();
}
return dynamicPassword;
}
getDynamicPassword方法可以將參數(shù)str中的特定字符串截取出來(lái),這里用到了正則匹配,將上面的算法添加到MainActivity中:
package com.example.messagecut;
//省略import
/**
* Demo描述:
* 利用BroadcastReceiver實(shí)現(xiàn)監(jiān)聽(tīng)短信
* 注意權(quán)限:
* <uses-permission android:name="android.permission.RECEIVE_SMS"/>
*/
public class MainActivity extends Activity{
private EditText mCode;
private SMSBroadcastReceiver mSMSBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init(){
mCode=(EditText) findViewById(R.id.et_code);
mSMSBroadcastReceiver=new SMSBroadcastReceiver();
mSMSBroadcastReceiver.setOnReceivedMessageListener(new MessageListener() {
public void OnReceived(String message) {
mCode.setText(getDynamicPassword(message));//截取6位驗(yàn)證碼
}
});
}
/**
* 從字符串中截取連續(xù)6位數(shù)字組合 ([0-9]{" + 6 + "})截取六位數(shù)字 進(jìn)行前后斷言不能出現(xiàn)數(shù)字 用于從短信中獲取動(dòng)態(tài)密碼
*
* @param str
* 短信內(nèi)容
* @return 截取得到的6位動(dòng)態(tài)密碼
*/
public String getDynamicPassword(String str) {
// 6是驗(yàn)證碼的位數(shù)一般為六位
Pattern continuousNumberPattern = Pattern.compile("(?<![0-9])([0-9]{"
+ 6 + "})(?![0-9])");
Matcher m = continuousNumberPattern.matcher(str);
String dynamicPassword = "";
while (m.find()) {
System.out.print(m.group());
dynamicPassword = m.group();
}
return dynamicPassword;
}
}
這里我們也修改了activity_main.xml文件,將TextView改成了EditText,因?yàn)閍ndroid手機(jī)用戶可能會(huì)禁止應(yīng)用訪問(wèn)短信的權(quán)限,這時(shí)應(yīng)該支持手動(dòng)填寫(xiě)。
在真機(jī)上測(cè)試,發(fā)送:
接收:
超實(shí)用的功能,趕快引入到你的項(xiàng)目中去吧,會(huì)大大提高用戶體驗(yàn)!