Android短信驗證碼自動填充
在我們的Android開發中會經常用到短信驗證的功能,這個時候如果再讓用戶就查看短信.然后再回到界面進行短信的填寫,難免有多少有些不方便,為了提高用戶體驗,我也就自己來實現驗證碼的自動填寫功能
一、簡介
之前筆者見過一些人的實現思路是這樣的:
創建一個廣播接收器,接受短信變化的廣播,然后在收到廣播的時候,再把驗證碼提取出來發送給我們的需要填充驗證碼的地方就行了。 但是,這種方式有它的缺陷:當你的手機安裝了其他一些短信應用(例如QQ通訊錄)或者手機本身限制了權限的情況下,這種方式有可能會不起作用,無法做到自動填寫,而且就算把優先級設高,也不能保證不會被別的應用“搶先”。 所以,通過查閱資料,發現了這種方式: 可以通過監聽短信數據庫的方式實現。監聽短信數據庫主要是通過ContentObserver這個類來完成。ContentObserver主要是通過Uri來監測特定的Databases的表,當ContentObserver所觀察的Uri發生變化時,便會觸發它。
二、短信驗證碼自動填充的工具類
/**
* 短信驗證碼自動填充
*
* @author 周旭
*/
public class SMSContentObserver extends ContentObserver {
private Context mContext; // 上下文
private Handler mHandler; // 更新UI線程
private String code; // 驗證碼
public SMSContentObserver(Context context, Handler handler) {
super(handler);
mContext = context;
mHandler = handler;
}
/**
* 回調函數, 當所監聽的Uri發生改變時,就會回調此方法
* <p>
* 注意當收到短信的時候會回調兩次
* 收到短信一般來說都是執行了兩次onchange方法.第一次一般都是raw的這個.
* 這個時候雖然收到了短信.但是短信還沒有寫入到收件箱里面
* 然后才是另外一個,后面的數字是該短信在收件箱中的位置
*
* @param selfChange 此值意義不大 一般情況下該回調值false
*/
@Override
public void onChange(boolean selfChange, Uri uri) {
Log.e("tag", uri.toString());
// 第一次回調 不是我們想要的 直接返回
if (uri.toString().equals("content://sms/raw")) {
return;
}
// 第二次回調 查詢收件箱里的內容
Uri inboxUri = Uri.parse("content://sms/inbox");
// 按時間順序排序短信數據庫
Cursor c = mContext.getContentResolver().query(inboxUri, null, null,
null, "date desc");
if (c != null) {
if (c.moveToFirst()) {
// 獲取短信提供商的手機號
String address = c.getString(c.getColumnIndex("address"));
// 獲取短信內容
String body = c.getString(c.getColumnIndex("body"));
Log.i("tag", "body------->" + body);
// 判斷手機號是否為目標號碼(短信提供商的號碼)
// 在這里我們的短信提供商的號碼如果是固定的話.我們可以再加一個判斷,這樣就不會受到別的短信應用的驗證碼的影響了
// 不然的話就在我們的正則表達式中,加一些自己的判斷,例如短信中含有自己應用名字啊什么的...
/*if (!address.equals("13342290623"))
{
Log.i("tag","------->沒有讀取到內容");
return;
}*/
// 正則表達式截取短信中的6位驗證碼
Pattern pattern = Pattern.compile("(\\d{6})");
Matcher matcher = pattern.matcher(body);
// 利用handler將得到的驗證碼發送給主線程
if (matcher.find()) {
code = matcher.group(0);
//mHandler.obtainMessage(1, code).sendToTarget();
Message msg = Message.obtain();
msg.what = MainActivity.MSG_RECEIVE_CODE;
msg.obj = code;
mHandler.sendMessage(msg);
}
}
c.close();
}
}
}
調用的Activity:
/**
* 短信驗證碼自動填寫功能的實現
*/
public class MainActivity extends AppCompatActivity {
public static final int MSG_RECEIVE_CODE = 1; //收到短信的驗證碼
private EditText codeEdt; //短信驗證碼的輸入框
private SMSContentObserver smsContentObserver;
//回調接口
@SuppressLint("HandlerLeak")
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_RECEIVE_CODE) {
codeEdt.setText(msg.obj.toString()); //設置讀取到的內容
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
codeEdt = (EditText) findViewById(R.id.smsCode);
findViewById(R.id.send_sms_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
senSMSCode();
}
});
smsContentObserver = new SMSContentObserver(
MainActivity.this, handler);
//ContentObserver注冊
getContentResolver().registerContentObserver(
Uri.parse("content://sms/"), true, smsContentObserver);
}
/**
* 取消注冊
*/
@Override
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(smsContentObserver);
}
//使用Bmob云的短信驗證功能來發送短信
private void senSMSCode() {
BmobSMS.requestSMSCode("13342290623", "知么網絡", new QueryListener<Integer>() {
@Override
public void done(Integer smsId, BmobException ex) {
if (ex == null) {//驗證碼發送成功
Log.i("smile", "短信id:" + smsId);//用于后續的查詢本次短信發送狀態
Toast.makeText(MainActivity.this, "發送驗證碼成功", Toast.LENGTH_SHORT).show();
}
}
});
}
}
添加權限
<!--讀取短信的權限-->
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS" />
三、短信的Uri共有一下幾種:
content://sms/inbox 收件箱
content://sms/sent 已發送
content://sms/draft 草稿
content://sms/outbox 發件箱 (正在發送的信息)
content://sms/failed 發送失敗
content://sms/queued 待發送列表 (比如開啟飛行模式后,該短信就在待發送列表里)
本文由用戶 egret0502 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!