监听短信:
ContentObserver:监听短信数据库的变化
BroadCastReceiver:通过广播接收器来实现监听

拦截垃圾短信:用广播,如果用ContentObserver,垃圾短信已经存到收件箱了 用广播要考虑优先级不如第三方软件会被拦截
监 听 短 信:用ContentObserver,用广播如果短信长会被切割成多条

第一种方式:广播

SMSBroadcastReceiver:

package com.ddgl.ddlx.BroadcastReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by 27c1 on 2016/12/27.
 */

public class SMSBroadcastReceiver extends BroadcastReceiver {

    private static final String TAG = "smsreceiver";
    private String ss;
    private static MessageListener mMessageListener;

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "onReceive: " + "收到短信广播");

        Bundle bundle = intent.getExtras();
        SmsMessage msg = null;
        if (null != bundle) {
            Object[] smsObj = (Object[]) bundle.get("pdus");
            for (Object object : smsObj) {
                msg = SmsMessage.createFromPdu((byte[]) object);
                Date date = new Date(msg.getTimestampMillis());//时间
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String receiveTime = format.format(date);
                Log.i(TAG, "onReceive:===="+"number:" + msg.getOriginatingAddress()
                        + "   body:" + msg.getDisplayMessageBody() + "  time:"
                        + msg.getTimestampMillis());

                if (msg.getDisplayMessageBody().substring(0,9).equals("【丁丁旅行】验证码")){
                    ss = msg.getDisplayMessageBody().substring(9, 15);
                    Log.i(TAG, "onReceive: 截取的为==="+ ss);

                    if (ss.length()==6){
                        mMessageListener.onReceived(ss);
                        abortBroadcast();
                    }
                }
            }
        }
    }

    //回调接口
    public interface MessageListener {
        public void onReceived(String message);
    }

    public void setOnReceivedMessageListener(MessageListener messageListener) {
        this.mMessageListener = messageListener;
    }
}
MainActiivty:动态注册广播并修改edittext内容

@Override
    public void onStart() {
        super.onStart();
        receiver = new SMSBroadcastReceiver();
        IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
        filter.setPriority(Integer.MAX_VALUE);
        getActivity().registerReceiver(receiver, filter);
        receiver.setOnReceivedMessageListener(new SMSBroadcastReceiver.MessageListener() {
            @Override
            public void onReceived(String message) {
                etLoginName.setText(message);
            }
        });
    }

    //注销短信监听广播
    @Override
    public void onDestroy() {
        super.onDestroy();
        getActivity().unregisterReceiver(receiver);
    }
短信权限:

<!--短信权限-->
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS" />
但是这个方法Android 5.1系统魅族手机可以 Android4.3系统oppo手机不可以

第二种方法:数据库读取短信记录:

MainActivity:

private SMSObserver observer;

//点击完获取验证码就开始读取数据库
observer = new SMSObserver(getActivity(), smsHandler);
getActivity().getContentResolver().registerContentObserver(SMS_INBOX, true, observer);

//读取短信内容handler
private Handler smsHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
    super.handleMessage(msg);
    Log.i(TAG, "handleMessage: msg===" + msg.obj);
    String autoCode = (String) msg.obj;
    etLoginName.setText(autoCode);
    }
};

@Override
public void onDestroy() {
    super.onDestroy();
    getActivity().getContentResolver().unregisterContentObserver(observer);
}
SMSObserver:

package com.ddgl.ddlx.ContentObserver;

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.ddgl.ddlx.fragment.LoginNoPassFragment.getCodeTime;

/**
 * Created by 27c1 on 2016/12/29.
 */

public class SMSObserver extends ContentObserver {

    private static final String TAG = "smsobserver";
    private Context context;
    public static Uri SMS_INBOX = Uri.parse("content://sms/");
    private Handler handler = new Handler();

    /**
     * Creates a content observer.
     *
     * @param handler The handler to run {@link #onChange} on, or null if none.
     */
    public SMSObserver(Context context, Handler handler) {
        super(handler);
        this.context = context;
        this.handler = handler;
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        //每当有新短信到来时,使用我们获取短消息的方法
        getSmsFromPhone();
    }

    private void getSmsFromPhone() {
        ContentResolver cr = context.getContentResolver();
        String[] projection = new String[]{"body"};//"_id", "address", "person",, "date", "type
        String where = "  date >  " + getCodeTime;
        Cursor cursor = cr.query(SMS_INBOX, projection, where, null, "date desc");
        if (cursor != null) {
            if (cursor.moveToNext()) {
                String body = cursor.getString(cursor.getColumnIndex("body"));
                Log.i(TAG, "getSmsFromPhone:短信内容===" + body);
                if (body.contains("XXX验证码")) {
                    //这里我是要获取自己短信服务号码中的验证码~~
                    String regEx = "[^0-9]";
                    Pattern p = Pattern.compile(regEx);
                    Matcher m = p.matcher(body);
                    String num = m.replaceAll("").trim().toString();
                    Log.i(TAG, "getSmsFromPhone: num===" + num);
                    if (num != null) {
                        Message message = new Message();
                        message.obj = num;
                        handler.sendMessage(message);
                    }
                } else {
                    Log.i(TAG, "getSmsFromPhone: " + "没有收到XXX的短信");
                }
            }
        } else {
            return;
        }
    }
}

动态注册广播:写一个SMSBroadcastReceiver类

SMSBroadcastReceiver receiver = new SMSBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");
        filter.setPriority(Integer.MAX_VALUE);
        getActivity().registerReceiver(receiver, filter);
静态注册广播:
<receiver
            android:name=".BroadcastReceiver.SMSBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="1000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
数据库读取短信:
用ManageQuery还是不行 Android5.1系统魅族手机通知类短信读不到验证码
Android 6.0小米系统所有通知类短信都读不到

代码:

package com.miapsoft.intercept_mmsdemo.activity;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.example.intercept_mmsdemo.R;

import android.app.Activity;
import android.content.ContentValues;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.widget.EditText;

public class MainActivity extends Activity{

	EditText ed_mmscode;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		ed_mmscode=(EditText) findViewById(R.id.ed_mms);
		SmsContent content = new SmsContent(new Handler());
        //注册短信变化监听
        this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, content);
	}

	/**
     * 监听短信数据库
     */
    class SmsContent extends ContentObserver {
        private Cursor cursor = null;
        public SmsContent(Handler handler) {
            super(handler);
        }
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            //读取收件箱中指定号码的短信
            cursor = managedQuery(Uri.parse("content://sms/inbox"), new String[]{"_id", "address", "read", "body"}, " address=? and read=?", new String[]{"10658464", "0"}, "_id desc");//按id排序,如果按date排序的话,修改手机时间后,读取的短信就不准了
            if (cursor != null && cursor.getCount() > 0) {
                ContentValues values = new ContentValues();
                values.put("read", "1");        //修改短信为已读模式
                cursor.moveToNext();
                int smsbodyColumn = cursor.getColumnIndex("body");
                String smsBody = cursor.getString(smsbodyColumn);
                ed_mmscode.setText(getDynamicPassword(smsBody));
            }
            //在用managedQuery的时候,不能主动调用close()方法, 否则在Android 4.0+的系统上, 会发生崩溃
            if(Build.VERSION.SDK_INT < 14) {
                cursor.close();
            }
        }
    }

    /**
     * 从字符串中截取连续6位数字
     * 用于从短信中获取动态密码
     * @param str 短信内容
     * @return 截取得到的6位动态密码
     */
    public static String getDynamicPassword(String str) {
        Pattern  continuousNumberPattern = Pattern.compile("[0-9\\.]+");
        Matcher m = continuousNumberPattern.matcher(str);
        String dynamicPassword = "";
        while(m.find()){
            if(m.group().length() == 6) {
                System.out.print(m.group());
                dynamicPassword = m.group();
            }
        }
        return dynamicPassword;
    }
}








更多相关文章

  1. android之发送短信的方法研究
  2. 【Android 开发教程】通过编码实现发送短信
  3. Android短彩信源码解析-短信发送流程(三)
  4. 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案

随机推荐

  1. LibGDX制作android动态壁纸
  2. 第一章 andrid visdio 安装
  3. Run Android on Your Netbook or Desktop
  4. Android(安卓)断点续传的原理剖析与实例
  5. android系统自带的主题与样式(theme and
  6. Android 之EditText InputType说明
  7. android Application Component研究之Ser
  8. Android用户界面UI组件--AdapterView及其
  9. Android 存储选项之 ContentProvider 启
  10. [置顶] Android(安卓)实现 WheelView