為了減少用戶的操作步驟,在獲得短信驗證碼的時候,我們可以監聽特殊手機號碼的短信,截取信息當中的短信驗證碼(其實有很多應用都監聽短信例如360短信,一些信用卡或者是記賬類的應用)。
原理:可以使用一個自定義的BroadcastReceiver來監聽短信,在監聽結果當中過濾手機號,在需要回填的activity當中實現實例化廣播並且實現其回調接口,在接口當中進行回填驗證碼,在銷毀activity時銷毀鏈接。但是這樣操作會出現一些問題,由於一些其他的應用也會使用廣播監聽手機例如QQ通訊錄或者是360通訊錄等有的時候會被其攔截,即使你修改優先級也會出現不能進行回填的問題。所有這里可以采用另外一種的解決方法:使用ContentProvider來監聽短信數據庫的變化,在自定義的ContentObserver當中實現onChange的方法進行監聽特定手機號的短信,然后進行信息截取在填充到需要填充的位置。
1,在AndroidManifest當中需要的權限:
01.<!-- 發送短信--> 02. <uses-permission android:name="android.permission.SEND_SMS" /> 03. <!-- 閱讀消息 --> 04. <uses-permission android:name="android.permission.READ_SMS" /> 05. <!-- 寫入消息 --> 06. <uses-permission android:name="android.permission.WRITE_SMS" /> 07. <!-- 接收消息 --> 08. <uses-permission android:name="android.permission.RECEIVE_SMS" /> 復制代碼
2,在oncreate()方法中注冊短信庫的監聽:
1 content = new SmsContent(new Handler()); 2 //注冊短信變化監聽 3 this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, content); 4 復制代碼
3,SmsContent自定義的ContentObserver:
/* 02. * 監聽短信數據庫 03. */ 04. class SmsContent extends ContentObserver { 05. private Cursor cursor = null; 06. 07. public SmsContent(Handler handler) { 08. super(handler); 09. // TODO Auto-generated constructor stub 10. } 11. 12. @SuppressWarnings("deprecation") 13. @Override 14. public void onChange(boolean selfChange) { 15. // TODO Auto-generated method stub 16. super.onChange(selfChange); 17. // 讀取收件箱中指定號碼的短信 18. cursor = managedQuery(Uri.parse("content://sms/inbox"), 19. new String[] { "_id", "address", "read", "body" }, 20. " address=? and read=?", 21. new String[] { "監聽的號碼", "0" }, "_id desc"); 22. // 按id排序,如果按date排序的話,修改手機時間后,讀取的短信就不准了 23. if (cursor != null && cursor.getCount() > 0) { 24. ContentValues values = new ContentValues(); 25. values.put("read", "1"); // 修改短信為已讀模式 26. cursor.moveToNext(); 27. int smsbodyColumn = cursor.getColumnIndex("body"); 28. String smsBody = cursor.getString(smsbodyColumn); 29. edit1.setText(getDynamicPassword(smsBody)); 30. 31. } 32. // 在用managedQuery的時候,不能主動調用close()方法, 否則在Android 4.0+的系統上, 會發生崩潰 33. if (Build.VERSION.SDK_INT < 14) { 34. cursor.close(); 35. } 36. } 37. 38. } 復制代碼
4,getDynamicPassword(smsBody)截取短信中六位數字驗證碼的方法
/** 02. * 從字符串中截取連續6位數字組合 ([0-9]{" + 6 + "})截取六位數字 進行前后斷言不能出現數字 用於從短信中獲取動態密碼 03. * 04. * @param str 05. * 短信內容 06. * @return 截取得到的6位動態密碼 07. */ 08. public static String getDynamicPassword(String str) { 09. // 6是驗證碼的位數一般為六位 10. Pattern continuousNumberPattern = Pattern.compile("(?<![0-9])([0-9]{" 11. + 6 + "})(?![0-9])"); 12. Matcher m = continuousNumberPattern.matcher(str); 13. String dynamicPassword = ""; 14. while (m.find()) { 15. System.out.print(m.group()); 16. dynamicPassword = m.group(); 17. } 18. 19. return dynamicPassword; 20. } 復制代碼
如果驗證碼的位數變化只要將6修改為想要的位數,過驗證不只為數字直接修改正則為想要的內容即可。
5,在Activity銷毀的時候要記得關閉數據庫監聽:
@Override 02. protected void onDestroy() { 03. // TODO Auto-generated method stub 04. super.onDestroy(); 05. this.getContentResolver().unregisterContentObserver(content); 06. } 復制代碼
這樣既可以實現短信監聽自動回填,在回填的位置一般使用EditText不要使用TextView,因為android手機用戶可能會禁止應用訪問短信的權限應該支持手動填寫。