學習筆記:java
1.Android之如何獲取短信驗證碼.android
2.如何讀取剛收到的短信的相關內容.正則表達式
現現在,驗證碼在Android的客戶端仍是很是廣泛的.經過手機帳號和驗證碼直接去註冊應用帳戶的信息.不少應用都以這種方式來完成註冊.簡單的介紹一下吧.數據庫
Android獲取短信驗證碼仍是比較簡單的,經過Mob官網提供的ShareSDK,調用其中內部的方法,就能夠獲取到短信的驗證碼了.提供一下Mob的官網地址.http://www.mob.com/#/在官網上註冊相關的信息以後,下載相關的jar包和.so文件就能夠實現獲取短信驗證碼了(2.0以前的版本都須要下載jar包和 .so文件,而如今的2.2版本已經不須要下載.so文件了,經過加載SMSSDK.jar,MobCommons.jar,MobTools.jar包就能夠直接使用).如何註冊我就不解釋了.json
最後註冊完的樣式就是這樣的..咱們來看看具體實現..網絡
1.如何獲取短信驗證碼.app
i.首先須要初始化SDK,第三方這些東西首先必需要有的操做就是初始化SDK.通常都在OnCreate()函數中來完成.ide
@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); }
這個是必需要進行的操做,不然後續的東西都將沒法完成.initSDK(Context context,String AppKey,String AppSECRET),初始化須要傳遞Context對象,以及咱們申請的Key和SECRET.而且這裏定義了一個EventHandler,用來進行驗證的時候將一些消息提供給主線程的Handler,讓主線程來作一些相關的操做來通知用戶驗證的狀況到底如何.
函數
ii.調用SMSSDK.getVerificationCode(String,String)方法學習
初始化SDK以後,咱們就能夠經過使用getVerificationCode()方法來獲取咱們的驗證碼了.
/** * @param string 電話號碼的區號 好比說86 * @param string 具體的電話號碼 */ SMSSDK.getVerificationCode("86", PhoneEd.getText().toString());
咱們在調用方法的時候,須要傳遞咱們手機號碼的區號和具體的手機號碼.因爲中國國內是86開頭.所以傳遞的區號就是86,在加上本身的電話號碼就能夠經過網絡調用方法來獲取相關的驗證碼了.
iii.驗證咱們輸入的驗證碼和發送過來的驗證碼是一致的.
當驗證碼發送過來的時候,客戶端通常就須要進行輸入,可是這裏須要一個驗證的過程,判斷當前用戶輸入的驗證碼和發送過來的驗證碼是否一致.
SMSSDK.submitVerificationCode("86", phone, CodeEd.getText().toString());
驗證的方式經過調用submitVerificationCode()方法來完成.須要傳遞區號,電話號碼,以及咱們輸入的驗證碼的數值.驗證的過程由ShareSDK幫咱們完成.所以就不須要執行太多複雜的操做.當咱們傳遞的數值和發送過來的數值是同樣的,那麼就會驗證成功,不然就會驗證失敗.
這樣在咱們的客戶端軟件上就能夠經過這種驗證方式來完成註冊功能.當驗證成功後,就能夠進入新的界面,若是驗證失敗,那麼就須要確認輸入的驗證碼.這樣就可以完成應用程序的驗證碼驗證.
通常狀況下,咱們只須要經過查看短信,而後提交相關的驗證碼就能夠了,可是還有一些其餘的應用更加的人性化,當驗證碼信息發送到手機內部的時候直接就可以獲取到相關的驗證碼,而後直接添加在須要驗證的地方,這樣很是的方便,而且還能防止用戶輸入錯誤.那麼這就涉及到讀取短信的相關內容了.
iv.添加相關的權限
<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" />
那麼如何獲取短信的相關內容呢?
2.如何獲取剛收到的短信的相關內容.
通常而言,短信的驗證是以新短信的方式直接發送給用戶的,那麼應用程序若是想到讀取剛收到的短息內容,就須要有相關的監聽事件.我經過使用ContentObserver來實現的.經過使用這個類能夠捕捉特定的uri使數據庫改變,而後進而做一些相關的處理.
那麼咱們就能夠這樣去實現,經過繼承ContentObserver類,重寫內部的onChange方法,設置特定的Uri,使得咱們的類可以監聽短信數據發生了變化這樣咱們的應用程序就知道何時短信到來了.那麼短信到來以後,咱們經過對短信內容的獲取,而後讀取內容中的驗證碼信息就能夠了.
private class SmsObserver extends ContentObserver { public SmsObserver(Handler handler) { super(handler); // TODO Auto-generated constructor stub } /** *Uri.parse("content://sms/inbox")表示對收到的短信的一個監聽的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循環.咱們只須要獲取當前發送過來的短信數據就能夠了. cursor.moveToNext(); sb.append("body=" + cursor.getString(cursor.getColumnIndex("body"))); //獲取短信內容的實體數據. Pattern pattern = Pattern.compile("[^0-9]"); //正則表達式. Matcher matcher = pattern.matcher(sb.toString()); CodeText = matcher.replaceAll(""); CodeEd.setText(CodeText); //將輸入驗證碼的控件內容進行改變. cursor.close(); //關閉遊標指針. super.onChange(selfChange); } }
實現類的方式如上,經過重寫OnChange方法來進行後續的操做,這裏的cursor能夠對當前的短信數據庫中的數據進行查找,這裏的cursor指針不要使用while循環,由於驗證碼這條短信是隨發即用的,咱們也只須要獲取當前發送過來的驗證碼短信中的相關內容,若是cursor使用了while循環,那麼將會讀取短信中的全部內容.這並非咱們想要的.
當咱們獲取到了短信的具體內容以後,咱們能夠經過使用正則表達式,去匹配短信內容的數字,而後就可以獲取到驗證碼數據了.大致的思路就是這樣一個狀況.同時咱們須要添加相關用戶權限.
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
完成了上面的步驟以後,咱們須要獲取ContentResolver實例,而後註冊ContentObserver。
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SmsObserver(new Handler()));
註冊咱們須要傳遞相關的uri,第二個參數決定匹配uri的方式,若是設置爲true的話,那麼表示不精確匹配,那麼也就表示,若是是一類的uri,那麼都會被匹配到,若是設置爲false,那麼也就只能匹配到咱們傳遞進去的uri,也就是所謂的精確匹配.最後一個對象須要傳遞一個子類的實例,而且須要傳遞Handler對象.這樣咱們也就能夠在這個方法裏去更新ui了.
當咱們不須要使用ContentObserver的時候,咱們只須要註銷註冊就能夠了.
相對而言,驗證碼信息通常都是內容比較少的,若是內容比較複雜,而後還有其餘額外的數字信息,那麼咱們在使用正則表達式的時候同時須要進行相關的優化.
最後上一個源代碼:
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(), "提交驗證碼成功", Toast.LENGTH_SHORT).show(); } else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE) { // 已經驗證 Toast.makeText(getApplicationContext(), "驗證碼已經發送", 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: // 獲取驗證碼的過程. 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)); }; }
這樣就可以完成一個簡單的經過使用短信驗證碼的方式來實現驗證,在通常的項目中,咱們能夠根據具體的需求進行相關的改良,總之萬變不離其宗思路基本都是同樣的.固然在判斷是否有短信到來也可使用BroadCaseReceiver來實現,不過我看了網上的一些相關的資源,本身也試了一下,沒有實現出來.感受沒有ContentObserver這麼簡單方便.
最後提供一個源代碼下載:http://files.cnblogs.com/files/RGogoing/SMS.rar