package com.example.sendsms;import android.app.Activity;import android.database.ContentObserver;import android.database.Cursor;import android.net.Uri;import android.os.Handler;import android.os.Message;import android.telephony.SmsManager;import android.text.TextUtils;import android.util.Log;import android.widget.Toast;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * Monitor sms database * * @author Jackie */public class SmsContent extends ContentObserver {    private static final String TAG = SmsContent.class.getSimpleName();    private static final String MARKER = "YOUR_KEYWORD";    private Cursor cursor = null;    private Activity mActivity;    private String body;    private int before;    public SmsContent(Handler handler, Activity activity) {        super(handler);        this.mActivity = activity;    }    /**     * This method is called when a content change occurs.     * 

* Subclasses should override this method to handle content changes. *

* * @param selfChange True if this is a self-change notification. */ @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Log.d(TAG, "onChange(boolean selfChange). selfChange=" + selfChange); onChange(selfChange, null); } /** * Notice: onChange will be triggered twice on some devices when a sms received, * eg: samsung s7 edge(API.23) - twice * samsung note3(API.18) - once * 06-15 11:45:48.706 D/SmsContent: onChange(boolean selfChange, Uri uri). selfChange=false, uri=content://sms/raw * 06-15 11:45:49.466 D/SmsContent: onChange(boolean selfChange, Uri uri). selfChange=false, uri=content://sms/387 *

* Generally onChange will be triggered twice, first time is triggered by uri "content://sms/raw"(sms received, * but have not written into inbox), second time is triggered by uri "content://sms/387"(number is sms id) *

* Android official comments: * This method is called when a content change occurs. * Includes the changed content Uri when available. *

* Subclasses should override this method to handle content changes. * To ensure correct operation on older versions of the framework that * did not provide a Uri argument, applications should also implement * the {@link #onChange(boolean)} overload of this method whenever they * implement the {@link #onChange(boolean, Uri)} overload. *

* Example implementation: *

     * // Implement the onChange(boolean) method to delegate the change notification to     * // the onChange(boolean, Uri) method to ensure correct operation on older versions     * // of the framework that did not have the onChange(boolean, Uri) method.     * {@literal @Override}     * public void onChange(boolean selfChange) {     *     onChange(selfChange, null);     * }     *     * // Implement the onChange(boolean, Uri) method to take advantage of the new Uri argument.     * {@literal @Override}     * public void onChange(boolean selfChange, Uri uri) {     *     // Handle change.     * }     * 
*

* * @param selfChange True if this is a self-change notification. * @param uri The Uri of the changed content, or null if unknown. */ @Override public void onChange(boolean selfChange, Uri uri) { Log.d(TAG, "onChange(boolean selfChange, Uri uri). selfChange=" + selfChange + ", uri=" + uri); /** * 适配某些较旧的设备,可能只会触发onChange(boolean selfChange)方法,没有传回uri参数, * 此时只能通过"content://sms/inbox"来查询短信 */ if (uri == null) { uri = Uri.parse("content://sms/inbox"); } /** * 06-15 11:45:48.706 D/SmsContent: onChange(boolean selfChange, Uri uri). selfChange=false, uri=content://sms/raw * 06-15 11:45:49.466 D/SmsContent: onChange(boolean selfChange, Uri uri). selfChange=false, uri=content://sms/387 * * Generally onChange will be triggered twice, first time is triggered by uri "content://sms/raw"(sms received, * but have not written into inbox), second time is triggered by uri "content://sms/387"(number is sms id) */ if (uri.toString().equals("content://sms/raw")) { return; } cursor = this.mActivity.getContentResolver().query(uri, null, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { int id = cursor.getInt(cursor.getColumnIndex("_id")); int thread_id = cursor.getInt(cursor.getColumnIndex("thread_id")); body = cursor.getString(cursor.getColumnIndex("body")); Log.d(TAG, "sms id: " + id + "\nsms body: " + body); cursor.close(); // Already got sms body, do anything you want, for example: filter the verify code getVerifyCode(body); Log.e(TAG, "onChangeid: " + body); if (before != thread_id) { senSMSCode(body); } before = thread_id; } } else { Log.e(TAG, "error: cursor == null"); } } /** * Register a monitor of changing of sms */ public void register() { Log.d(TAG, "Register sms monitor"); this.mActivity.getContentResolver().registerContentObserver( Uri.parse("content://sms/"), true, this); } /** * Unregister the monitor of changing of sms */ public void unRegister() { Log.d(TAG, "Unregister sms monitor"); this.mActivity.getContentResolver().unregisterContentObserver(this); } /** * Get verify code from sms body * * @param str * @return */ public String getVerifyCode(final String str) { String verifyCode = null; if (smsContentFilter(str)) { Log.d(TAG, "sms content matched, auto-fill verify code."); verifyCode = getDynamicPassword(str); } else { // Do nothing Log.d(TAG, "sms content did not match, do nothing."); } return verifyCode; } /** * Check if str is verification-code-formatted * * @param str * @return */ private boolean smsContentFilter(String str) { Log.d(TAG, "smsContentFilter. smsBody = " + str); boolean isMatched = false; if (!TextUtils.isEmpty(str)) { // Check if str contains keyword if (str.contains(MARKER)) { Log.d(TAG, "This sms contains \"" + MARKER + "\""); // Check if str contains continuous 6 numbers Pattern continuousNumberPattern = Pattern.compile("[0-9\\.]+"); Matcher m = continuousNumberPattern.matcher(str); while (m.find()) { if (m.group().length() == 6) { Log.d(TAG, "This sms contains continuous 6 numbers : " + m.group()); isMatched = true; } } } } return isMatched; }//发送短信代码 private void senSMSCode(final String smsContent) { String content = smsContent; String phone = "183****1210"; //发送短信 if (!TextUtils.isEmpty(content) && !TextUtils.isEmpty(phone)) { SmsManager manager = SmsManager.getDefault(); manager.sendTextMessage(phone, null, content, null, null); Toast.makeText(mActivity, "发送成功", Toast.LENGTH_SHORT).show(); return; } else { Toast.makeText(mActivity, "手机号或内容不能为空", Toast.LENGTH_SHORT).show(); return; } } /** * Cut the continuous 6 numbers from str * * @param str sms content * @return verification code */ private String getDynamicPassword(String str) { Log.d(TAG, "getDynamicPassword. smsBody = " + str); Pattern continuousNumberPattern = Pattern.compile("[0-9\\.]+"); Matcher m = continuousNumberPattern.matcher(str); String dynamicPassword = ""; while (m.find()) { if (m.group().length() == 6) { Log.d(TAG, m.group()); dynamicPassword = m.group(); } } Log.d(TAG, "Verification code: " + dynamicPassword); return dynamicPassword; }}

更多相关文章

  1. Android获取验证码倒计时
  2. Android(安卓)GPS基础
  3. Android:上下拖动切换界面
  4. 在android中玩转wcf
  5. Android(安卓)Studio简单的登录界面
  6. Android(安卓)中屏幕点击事件的实现
  7. Android启动脚本init.rc
  8. 手机拨号器
  9. 初识SeekBar

随机推荐

  1. Android扫描zxing定制化界面实现扫描和图
  2. Android(安卓)studio 获取手机短信内容并
  3. android样式学习(一) 使用selector改变来动
  4. Android, App常用图标尺寸规范
  5. Android:Material Design之FloatingAction
  6. Retrofit源码解析(一)
  7. ArcGIS for Android示例解析之FeatureLay
  8. Android(安卓)GridView之实现单元格合并,
  9. 关于Android(安卓)Activity之间传递数据
  10. android studio连接手机(小米5s)