Android獲取和讀取短信驗(yàn)證碼的實(shí)現(xiàn)方法
現(xiàn)如今,驗(yàn)證碼在Android的客戶端還是非常普遍的.通過手機(jī)賬號和驗(yàn)證碼直接去注冊應(yīng)用賬戶的信息.很多應(yīng)用都以這種方式來完成注冊.簡單的介紹一下吧.
Android獲取短信驗(yàn)證碼還是比較簡單的,通過Mob官網(wǎng)提供的ShareSDK,調(diào)用其中內(nèi)部的方法,就可以獲取到短信的驗(yàn)證碼了.提供一下Mob的官網(wǎng)地址.http://www.mob.com/#/在官網(wǎng)上注冊相關(guān)的信息之后,下載相關(guān)的jar包和.so文件就可以實(shí)現(xiàn)獲取短信驗(yàn)證碼了(2.0之前的版本都需要下載jar包和 .so文件,而現(xiàn)在的2.2版本已經(jīng)不需要下載.so文件了,通過加載SMSSDK.jar,MobCommons.jar,MobTools.jar包就可以直接使用).如何注冊我就不解釋了.


最后注冊完的樣式就是這樣的..我們來看看具體實(shí)現(xiàn)..
1.如何獲取短信驗(yàn)證碼.
i.首先需要初始化SDK,第三方這些東西首先必須要有的操作就是初始化SDK.一般都在OnCreate()函數(shù)中來完成.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
SMSSDK.initSDK(this, AppKey, APPSECRET);
EventHandler eh = new EventHandler() {
@Override
public void afterEvent(int event, int result, Object data) {
Message msg = new Message();
msg.arg1 = event;
msg.arg2 = result;
msg.obj = data;
handler.sendMessage(msg);
}
};
SMSSDK.registerEventHandler(eh);
}
這個(gè)是必須要進(jìn)行的操作,否則后續(xù)的東西都將無法完成.initSDK(Context context,String AppKey,String AppSECRET),初始化需要傳遞Context對象,以及我們申請的Key和SECRET.并且這里定義了一個(gè)EventHandler,用來進(jìn)行驗(yàn)證的時(shí)候?qū)⒁恍┫⑻峁┙o主線程的Handler,讓主線程來做一些相關(guān)的操作來通知用戶驗(yàn)證的情況到底如何.
ii.調(diào)用SMSSDK.getVerificationCode(String,String)方法
初始化SDK之后,我們就可以通過使用getVerificationCode()方法來獲取我們的驗(yàn)證碼了.
/**
* @param string 電話號碼的區(qū)號 比如說86
* @param string 具體的電話號碼
*/
SMSSDK.getVerificationCode("86", PhoneEd.getText().toString());
我們在調(diào)用方法的時(shí)候,需要傳遞我們手機(jī)號碼的區(qū)號和具體的手機(jī)號碼.由于中國國內(nèi)是86開頭.因此傳遞的區(qū)號就是86,在加上自己的電話號碼就可以通過網(wǎng)絡(luò)調(diào)用方法來獲取相關(guān)的驗(yàn)證碼了.
iii.驗(yàn)證我們輸入的驗(yàn)證碼和發(fā)送過來的驗(yàn)證碼是一致的.
當(dāng)驗(yàn)證碼發(fā)送過來的時(shí)候,客戶端一般就需要進(jìn)行輸入,但是這里需要一個(gè)驗(yàn)證的過程,判斷當(dāng)前用戶輸入的驗(yàn)證碼和發(fā)送過來的驗(yàn)證碼是否一致.
SMSSDK.submitVerificationCode("86", phone, CodeEd.getText().toString());
驗(yàn)證的方式通過調(diào)用submitVerificationCode()方法來完成.需要傳遞區(qū)號,電話號碼,以及我們輸入的驗(yàn)證碼的數(shù)值.驗(yàn)證的過程由ShareSDK幫我們完成.因此就不需要執(zhí)行太多復(fù)雜的操作.當(dāng)我們傳遞的數(shù)值和發(fā)送過來的數(shù)值是一樣的,那么就會驗(yàn)證成功,否則就會驗(yàn)證失敗.
這樣在我們的客戶端軟件上就可以通過這種驗(yàn)證方式來完成注冊功能.當(dāng)驗(yàn)證成功后,就可以進(jìn)入新的界面,如果驗(yàn)證失敗,那么就需要確認(rèn)輸入的驗(yàn)證碼.這樣就能夠完成應(yīng)用程序的驗(yàn)證碼驗(yàn)證.
一般情況下,我們只需要通過查看短信,然后提交相關(guān)的驗(yàn)證碼就可以了,但是還有一些其他的應(yīng)用更加的人性化,當(dāng)驗(yàn)證碼信息發(fā)送到手機(jī)內(nèi)部的時(shí)候直接就能夠獲取到相關(guān)的驗(yàn)證碼,然后直接添加在需要驗(yàn)證的地方,這樣非常的方便,并且還能防止用戶輸入錯(cuò)誤.那么這就涉及到讀取短信的相關(guān)內(nèi)容了.
iv.添加相關(guān)的權(quán)限
<uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
那么如何獲取短信的相關(guān)內(nèi)容呢?
2.如何獲取剛收到的短信的相關(guān)內(nèi)容.
一般而言,短信的驗(yàn)證是以新短信的方式直接發(fā)送給用戶的,那么應(yīng)用程序如果想到讀取剛收到的短息內(nèi)容,就需要有相關(guān)的監(jiān)聽事件.我通過使用ContentObserver來實(shí)現(xiàn)的.通過使用這個(gè)類可以捕捉特定的uri使數(shù)據(jù)庫改變,然后進(jìn)而作一些相關(guān)的處理.
那么我們就可以這樣去實(shí)現(xiàn),通過繼承ContentObserver類,重寫內(nèi)部的onChange方法,設(shè)置特定的Uri,使得我們的類能夠監(jiān)聽短信數(shù)據(jù)發(fā)生了變化這樣我們的應(yīng)用程序就知道什么時(shí)候短信到來了.那么短信到來之后,我們通過對短信內(nèi)容的獲取,然后讀取內(nèi)容中的驗(yàn)證碼信息就可以了.
private class SmsObserver extends ContentObserver {
public SmsObserver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
/**
*Uri.parse("content://sms/inbox")表示對收到的短信的一個(gè)監(jiān)聽的uri.
*/
@Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
StringBuilder sb = new StringBuilder();
Cursor cursor = getContentResolver().query(
Uri.parse("content://sms/inbox"), null, null, null, null);
//這里不要使用while循環(huán).我們只需要獲取當(dāng)前發(fā)送過來的短信數(shù)據(jù)就可以了.
cursor.moveToNext();
sb.append("body=" + cursor.getString(cursor.getColumnIndex("body"))); //獲取短信內(nèi)容的實(shí)體數(shù)據(jù).
Pattern pattern = Pattern.compile("[^0-9]"); //正則表達(dá)式.
Matcher matcher = pattern.matcher(sb.toString());
CodeText = matcher.replaceAll("");
CodeEd.setText(CodeText); //將輸入驗(yàn)證碼的控件內(nèi)容進(jìn)行改變.
cursor.close(); //關(guān)閉游標(biāo)指針.
super.onChange(selfChange);
}
}
實(shí)現(xiàn)類的方式如上,通過重寫OnChange方法來進(jìn)行后續(xù)的操作,這里的cursor可以對當(dāng)前的短信數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行查找,這里的cursor指針不要使用while循環(huán),因?yàn)轵?yàn)證碼這條短信是隨發(fā)即用的,我們也只需要獲取當(dāng)前發(fā)送過來的驗(yàn)證碼短信中的相關(guān)內(nèi)容,如果cursor使用了while循環(huán),那么將會讀取短信中的所有內(nèi)容.這并不是我們想要的.
當(dāng)我們獲取到了短信的具體內(nèi)容之后,我們可以通過使用正則表達(dá)式,去匹配短信內(nèi)容的數(shù)字,然后就能夠獲取到驗(yàn)證碼數(shù)據(jù)了.大體的思路就是這樣一個(gè)情況.同時(shí)我們需要添加相關(guān)用戶權(quán)限.
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
完成了上面的步驟之后,我們需要獲取ContentResolver實(shí)例,然后注冊ContentObserver。
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SmsObserver(new Handler()));
注冊我們需要傳遞相關(guān)的uri,第二個(gè)參數(shù)決定匹配uri的方式,如果設(shè)置為true的話,那么表示不精確匹配,那么也就表示,如果是一類的uri,那么都會被匹配到,如果設(shè)置為false,那么也就只能匹配到我們傳遞進(jìn)去的uri,也就是所謂的精確匹配.最后一個(gè)對象需要傳遞一個(gè)子類的實(shí)例,并且需要傳遞Handler對象.這樣我們也就可以在這個(gè)方法里去更新ui了.
當(dāng)我們不需要使用ContentObserver的時(shí)候,我們只需要注銷注冊就可以了.
相對而言,驗(yàn)證碼信息一般都是內(nèi)容比較少的,如果內(nèi)容比較復(fù)雜,然后還有其他額外的數(shù)字信息,那么我們在使用正則表達(dá)式的時(shí)候同時(shí)需要進(jìn)行相關(guān)的優(yōu)化.
最后上一個(gè)源代碼:
package com.example.sms;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONObject;
import cn.smssdk.EventHandler;
import cn.smssdk.SMSSDK;
import cn.smssdk.utils.SMSLog;
import android.app.Activity;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private Button getCode;
private Button Identity;
private EditText PhoneEd;
private EditText CodeEd;
private String AppKey = "110ee66f30b40";
private String APPSECRET = "85ec67aed1b89e3ec73f37b8b89f5142";
public String phone;
private String CodeText;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
int event = msg.arg1;
int result = msg.arg2;
Object data = msg.obj;
if (result == SMSSDK.RESULT_COMPLETE) {
if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {
Toast.makeText(getApplicationContext(), "提交驗(yàn)證碼成功",
Toast.LENGTH_SHORT).show();
} else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE) {
// 已經(jīng)驗(yàn)證
Toast.makeText(getApplicationContext(), "驗(yàn)證碼已經(jīng)發(fā)送",
Toast.LENGTH_SHORT).show();
}
} else {
int status = 0;
try {
((Throwable) data).printStackTrace();
Throwable throwable = (Throwable) data;
JSONObject object = new JSONObject(throwable.getMessage());
String des = object.optString("detail");
status = object.optInt("status");
if (!TextUtils.isEmpty(des)) {
Toast.makeText(MainActivity.this, des,
Toast.LENGTH_SHORT).show();
return;
}
} catch (Exception e) {
SMSLog.getInstance().w(e);
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
SMSSDK.initSDK(this, AppKey, APPSECRET);
EventHandler eh = new EventHandler() {
@Override
public void afterEvent(int event, int result, Object data) {
Message msg = new Message();
msg.arg1 = event;
msg.arg2 = result;
msg.obj = data;
handler.sendMessage(msg);
}
};
SMSSDK.registerEventHandler(eh);
}
private void init() {
getCode = (Button) findViewById(R.id.getCode);
Identity = (Button) findViewById(R.id.Indentity);
PhoneEd = (EditText) findViewById(R.id.PhoneEd);
CodeEd = (EditText) findViewById(R.id.Code);
getCode.setOnClickListener(this);
Identity.setOnClickListener(this);
}
private class SmsObserver extends ContentObserver {
public SmsObserver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
@Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
StringBuilder sb = new StringBuilder();
Cursor cursor = getContentResolver().query(
Uri.parse("content://sms/inbox"), null, null, null, null);
cursor.moveToNext();
sb.append("body=" + cursor.getString(cursor.getColumnIndex("body")));
System.out.println(sb.toString());
Pattern pattern = Pattern.compile("[^0-9]");
Matcher matcher = pattern.matcher(sb.toString());
CodeText = matcher.replaceAll("");
CodeEd.setText(CodeText);
cursor.close();
super.onChange(selfChange);
}
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.getCode: // 獲取驗(yàn)證碼的過程.
if (!TextUtils.isEmpty(PhoneEd.getText().toString())) {
getContentResolver().registerContentObserver(
Uri.parse("content://sms"), true,
new SmsObserver(new Handler()));
SMSSDK.getVerificationCode("86", PhoneEd.getText().toString());
phone = PhoneEd.getText().toString();
} else {
Toast.makeText(MainActivity.this, "電話號碼不能為空", Toast.LENGTH_LONG)
.show();
}
break;
case R.id.Indentity:
SMSSDK.submitVerificationCode("86", phone, CodeEd.getText()
.toString());
break;
}
}
protected void onDestroy() {
SMSSDK.unregisterAllEventHandler();
getContentResolver().unregisterContentObserver(new SmsObserver(handler));
};
}
這樣就能夠完成一個(gè)簡單的通過使用短信驗(yàn)證碼的方式來實(shí)現(xiàn)驗(yàn)證,在一般的項(xiàng)目中,我們可以根據(jù)具體的需求進(jìn)行相關(guān)的改良,總之萬變不離其宗思路基本都是一樣的.當(dāng)然在判斷是否有短信到來也可以使用BroadCaseReceiver來實(shí)現(xiàn),不過我看了網(wǎng)上的一些相關(guān)的資源,自己也試了一下,沒有實(shí)現(xiàn)出來.感覺沒有ContentObserver這么簡單方便.
以上就是Android獲取和讀取短信驗(yàn)證碼的實(shí)現(xiàn)方法,希望對大家學(xué)習(xí)Android軟件編程有所幫助。
相關(guān)文章
Android SharedPreferences四種操作模式使用詳解
這篇文章主要介紹了Android SharedPreferences四種操作模式使用詳解的相關(guān)資料,這里介紹了獲取Android SharedPreferences的兩種方法及比較,和操作模式的介紹,需要的朋友可以參考下2017-07-07
Android自定義控件實(shí)現(xiàn)九宮格解鎖功能
這篇文章主要為大家詳細(xì)介紹了Android自定義控件實(shí)現(xiàn)九宮格解鎖功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
Android Studio報(bào)錯(cuò)Manifest merger failed with multiple errors
這篇文章主要介紹了Android Studio報(bào)錯(cuò)Manifest merger failed with multiple errors2017-10-10
Android禁止EditText自動彈出軟鍵盤的方法及遇到問題
這篇文章主要介紹了Android禁止EditText自動彈出軟鍵盤的方法及遇到問題,需要的朋友可以參考下2018-07-07
android kotlin集成WorkManager實(shí)現(xiàn)定時(shí)獲取數(shù)據(jù)的步驟
在Android中使用Kotlin集成WorkManager來實(shí)現(xiàn)定時(shí)獲取數(shù)據(jù)是一個(gè)很常見的需求,下面給大家分享android kotlin集成WorkManager實(shí)現(xiàn)定時(shí)獲取數(shù)據(jù)的步驟,感興趣的朋友跟隨小編一起看看吧2024-08-08
Android實(shí)現(xiàn)搜索保存歷史記錄功能
這篇文章主要介紹了Android實(shí)現(xiàn)搜索保存歷史記錄功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
Android Studio3.6.3 當(dāng)前最新版本數(shù)據(jù)庫查找與導(dǎo)出方法(圖文詳解)
這篇文章主要介紹了Android Studio3.6.3 當(dāng)前最新版本數(shù)據(jù)庫查找與導(dǎo)出方法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04

