編輯:Android編程入門
PS:最近很多事情都拖拖拉拉的..都什麼辦事效率啊!!! 還得吐槽一下移動運營商,驗證碼超過五次的時候,直接把我的手機號封閉.真是受夠了.
學習筆記:
1.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包就可以直接使用).如何注冊我就不解釋了.
最後注冊完的樣式就是這樣的..我們來看看具體實現..
1.如何獲取短信驗證碼.
i.首先需要初始化SDK,第三方這些東西首先必須要有的操作就是初始化SDK.一般都在OnCreate()函數中來完成.
@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
今天把公司閒置的一台Mac-mini重裝了下系統感覺用著速度還不錯,平時上班用的機器USB有些問題,所以打算用這台Mac。以往開發用Intellij Idea就夠用,但是
現在的換膚基本都是切換主題了,畢竟md是主流。先說說切換主題的思路:事先在theme資源文件中准備好各種主流的主題樣式。寫一個工具類,具體功能:sharePreferen
1.什麼是ToggleButtonToggleButton有兩種狀態:選中和未選中狀態並且需要為不同的狀態設置不同的顯示文本2.ToggleButton屬性android
一、在這裡我會先說明兩個基本概念,Broadcast(廣播)和BroadcastReceiver(廣播接收器) 1、Broadcast:是運用在