一般用戶喜歡用手機(jī)號作為用戶名注冊APP賬號,常常通過手機(jī)驗證碼的方式進(jìn)行驗證,下面我們就研究一個非常實用的方法,通過監(jiān)聽短信-實現(xiàn)短信驗證碼的自動填入,提高用戶體驗。 首先看一下如何監(jiān)聽手機(jī)短信。
1.新建一個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è)置此廣播接收者的級別為最高
*/
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("短信來自:"+sender);
System.out.println("短信內(nèi)容:"+content);
System.out.println("短信時間:"+time);
mMessageListener.OnReceived(content);
//如果短信來自5556,不再往下傳遞,一般此號碼可以作為短信平臺的號碼。
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,覆寫了onReceive方法,通過Object [] pdus= (Object[]) intent.getExtras().get("pdus");獲取短信內(nèi)容,將對象集合遍歷,獲取所需的內(nèi)容,通過回調(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實現(xiàn)監(jiān)聽短信
* 注意權(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);
}
});
}
}
項目運(yùn)行在真機(jī)上進(jìn)行測試,用另一臺手機(jī)發(fā)送短信給本機(jī),得到如下:
成功獲取短信內(nèi)容,打印出來。
上面實現(xiàn)了截取短信全部內(nèi)容,下面看一下如何截取有效信息–驗證碼。原理很簡單,就是在字符串中截取部分字符串。 算法即:
/**
* 從字符串中截取連續(xù)6位數(shù)字組合 ([0-9]{" + 6 + "})截取六位數(shù)字 進(jìn)行前后斷言不能出現(xiàn)數(shù)字 用于從短信中獲取動態(tài)密碼
* @param str
* 短信內(nèi)容
* @return 截取得到的6位動態(tài)密碼
*/
public String getDynamicPassword(String str) {
// 6是驗證碼的位數(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中的特定字符串截取出來,這里用到了正則匹配,將上面的算法添加到MainActivity中:
package com.example.messagecut;
//省略import
/**
* Demo描述:
* 利用BroadcastReceiver實現(xiàn)監(jiān)聽短信
* 注意權(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位驗證碼
}
});
}
/**
* 從字符串中截取連續(xù)6位數(shù)字組合 ([0-9]{" + 6 + "})截取六位數(shù)字 進(jìn)行前后斷言不能出現(xiàn)數(shù)字 用于從短信中獲取動態(tài)密碼
*
* @param str
* 短信內(nèi)容
* @return 截取得到的6位動態(tài)密碼
*/
public String getDynamicPassword(String str) {
// 6是驗證碼的位數(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,因為android手機(jī)用戶可能會禁止應(yīng)用訪問短信的權(quán)限,這時應(yīng)該支持手動填寫。
在真機(jī)上測試,發(fā)送:
接收:
超實用的功能,趕快引入到你的項目中去吧,會大大提高用戶體驗!