现在的很多软件都要接收短信验证码,每次接收验证码都得打开邮箱再输入到程序中去,这样比较麻烦,所以现在的安卓程序都有一个自动读取最新接收的短信验证码的功能。

 

实现这个功能要用到的知识点也不多:数据库观察者类ContentObserve,数据接收类,正则表达式

 

先写一个观察者类的子类,在这个类里实现对邮箱的观察,当接收到新的短信时把短信内容读取出来,并且把其中的验证码匹配出来发送给Activity。

package com.contentprovide.liuliu.test_9_12_02;

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 java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by liuliu on 2018/9/12.
 */

/*
写一个内容观察者的类,用于监视手机数据库中uri的变化
        原理:
        当没有特定uri数据引起手机数据库变化时程序不执行操作,如果接受到新的短信,
        uri会引起数据库,当监视到数据库的变化时对短信内容
        进行操作,进而实现获取到最新短信验证码的功能*/
public class Mycontent extends ContentObserver {

    Cursor cursor;
    Context mcontext;
    Handler mhandler;

    /*
    重写一个构造方法,因为当数据库变化时要通知程序进行下一步操作,
    所以需要传入Handler对象*/
    public Mycontent(Context context,Handler handler) {
        super(handler);
        mcontext = context;
        mhandler = handler;
    }


    /*
    重写内容观察者类的onChange方法,当数据库uri变化时读取短信内容,
    并通过Handler将短信内容传递给界面进行显示*/
    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange, uri);


        if (uri.toString().equals("content://sms/raw")) {
            return;
        } else {
            cursor = mcontext.getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);

            if (cursor.moveToFirst()) {

//                读取短信内容
                String body = cursor.getString(cursor.getColumnIndex("body"));

//                取出短信内容后通过正则表达式匹配出其中的验证码内容
                Pattern p = Pattern.compile("[0-9]{6}");
                Matcher m = p.matcher(body);

//                如果匹配到了验证码内容,发送给界面
                if (m.find()) {
                    String re = m.group(0).toString();
                    Message message = mhandler.obtainMessage(1, re);
                    mhandler.sendMessage(message);
                }


            }
        }
    }
}


接下来是主类中的代码实现,这里主要是调用观察类的实例对象并且把接收到的内容显示到控件上

package com.contentprovide.liuliu.test_9_12_02;

import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    Cursor cursor;

    TextView te;

    String body;

    Mycontent mycontent;

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1) {
                te.setText("最新接收的验证码是:" + msg.obj.toString());
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        te = (TextView) findViewById(R.id.te);

//        实例化内容观察者类
        mycontent = new Mycontent(this, handler);

        /*
        第一个参数是需要观察的uri,第二个参数true表示可以同时匹配这个uri的派生uri、false表示只可以
                精确匹配当前的uri.第三个参数是当检测到uri引起数据库变化时需要回调的观察类的实例对象*/
        getContentResolver().registerContentObserver(Uri.parse("content://sms"), true,mycontent);
    }


}