收到短信自动获取其中包含的验证码---工具类(Update 2017/9/26)

**

Update 2017/9/26

**
最近项目中使用过程中,发现这个类不是很完善,连续打开多个页面,在每个Activity中使用该类方法,会出现后面页面没有返回的问题。故抽了点时间重新改动了一下。
**

Code

SmsUtil.class
**

import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static android.content.Context.ACTIVITY_SERVICE;

/**
 * Synopsis     SmsUtil
 * Author		Mosr
 * Version		${VERSION}
 * Create 	    2017/8/29 10:29
 * Modify       2017/9/26
 * Email  		intimatestranger@sina.cn
 */
public class SmsUtil {
    private final int RECEIVE_SMS_PERMISSION = 0x1007;

    private Uri SMS_INBOX = Uri.parse("content://sms/");

    private static String CONTAINS_WORDS = "验证码";

    private static SmsUtil mSmsUtil;

    private List<String> mPermissionList;

    private SmsReceiver mSmsReceiver;

    private SmsObserver mSmsObserver;

    private Context mContext;

    Handler smsHandler = new Handler() {
    };

    /**
     * Receive SmsUtil instance
     *
     * @return
     */
    public static SmsUtil getInstance() {
        if (null == mSmsUtil)
            synchronized (SmsUtil.class) {
                if (null == mSmsUtil)
                    mSmsUtil = new SmsUtil();
            }
        return mSmsUtil;
    }

    /**
     * Check requisite permissions
     *
     * @param mContext
     *
     * @return
     */
    public boolean checkPermission(Context mContext) {
        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.BROADCAST_SMS) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(mContext, Manifest.permission.RECEIVE_SMS) == PackageManager.PERMISSION_GRANTED)
            return true;
        else {
            if (null == mPermissionList)
                mPermissionList = new ArrayList<>();
            else if (!mPermissionList.isEmpty())
                mPermissionList.clear();

            if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.BROADCAST_SMS)
                    != PackageManager.PERMISSION_GRANTED) {
                //添加需要申请的权限
                mPermissionList.add(Manifest.permission.BROADCAST_SMS);
            }
            if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_SMS)
                    != PackageManager.PERMISSION_GRANTED) {
                //添加需要申请的权限
                mPermissionList.add(Manifest.permission.READ_SMS);
            }
            if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.RECEIVE_SMS)
                    != PackageManager.PERMISSION_GRANTED) {
                //添加需要申请的权限
                mPermissionList.add(Manifest.permission.RECEIVE_SMS);
            }
            if (null != mPermissionList && mPermissionList.size() > 0)
                //申请权限
                if (mContext instanceof Activity)
                    ActivityCompat.requestPermissions((Activity) mContext, mPermissionList.toArray(new String[mPermissionList.size()]),
                            RECEIVE_SMS_PERMISSION);
        }
        return false;
    }

    /**
     * The Permissions request call
     *
     * @param mActivity
     * @param requestCode
     * @param permissions
     * @param grantResults
     *
     * @return
     */
    public boolean onRequestPermissionsResult(Activity mActivity, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        boolean requested = false;
        switch (requestCode) {
            case RECEIVE_SMS_PERMISSION:
                if (grantResults.length >= 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.BROADCAST_SMS) == PackageManager.PERMISSION_GRANTED
                            && ContextCompat.checkSelfPermission(mActivity, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED
                            && ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECEIVE_SMS) == PackageManager.PERMISSION_GRANTED) {
                        requested = true;
                    } else {
                        //ToastUitl.showError("请允许" + mActivity.getResources().getString(R.string.app_name) + "获取相关权限");
                        //申请权限
                        checkPermission(mActivity);
                    }
                } else {
                    //ToastUitl.showError("请允许" + mActivity.getResources().getString(R.string.app_name) + "获取相关权限");
                    checkPermission(mActivity);
                }
                break;
            default:
                break;
        }
        return requested;
    }

    /**
     * one
     * <p>
     * Get  code from data base,register the contentObserver only once,but add different CodeCallBack.
     *
     * @param mContext
     *
     * @return SmsUtil instance
     */
    public SmsUtil getCodeFromDB(Context mContext, CodeCallBack mCodeCallBack) {
        if (null == mContext)
            throw new IllegalArgumentException("Context must be not null!");


        checkPermission(mContext);

        if (null == mSmsObserver) {
            this.mContext = mContext;
            mSmsObserver = new SmsObserver(mContext, smsHandler);
            mContext.getContentResolver().registerContentObserver(SMS_INBOX, true,
                    mSmsObserver);
        }
        mSmsObserver.addCallBack(mContext, mCodeCallBack);
        return mSmsUtil;
    }

    /**
     * two
     * <p>
     * Get  code from broadcast ,register the receiver only once,but add different CodeCallBack.
     * <p>
     * The broadcastReceiver use this to dynamically register
     *
     * @param mContext
     *
     * @return SmsUtil instance
     */
    public SmsUtil getCodeFromBroadcast(Context mContext, CodeCallBack mCodeCallBack) {
        if (null == mContext)
            throw new IllegalArgumentException("Context must be not null!");

        checkPermission(mContext);

        if (null == mSmsReceiver) {
            this.mContext = mContext;
            mSmsReceiver = new SmsReceiver();
            IntentFilter mIntentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
            mIntentFilter.setPriority(Integer.MAX_VALUE);
            mContext.registerReceiver(mSmsReceiver, mIntentFilter);
        }
        mSmsReceiver.addCallBack(mContext, mCodeCallBack);
        return mSmsUtil;
    }

    /**
     * Get code from broadcast and phone DB at the same time
     * This will minimize mistakes
     *
     * @param mContext
     * @param mCodeCallBack
     *
     * @return
     */
    public SmsUtil getCodeFromBroadcastAndDB(Context mContext, final CodeCallBack mCodeCallBack) {
        if (null == mContext)
            throw new IllegalArgumentException("Context must be not null!");

        getCodeFromBroadcast(mContext, new CodeCallBack() {
            @Override
            public void call(int code) {
                Log.e("mosr", "getCodeFromBroadcast " + System.currentTimeMillis());
                returnCode(code, mCodeCallBack);
            }
        });

        getCodeFromDB(mContext, new CodeCallBack() {
            @Override
            public void call(int code) {
                Log.e("mosr", "getCodeFromDB " + System.currentTimeMillis());
                returnCode(code, mCodeCallBack);
            }
        });
        return mSmsUtil;
    }

    int iRcode = -2;

    /**
     * Call back the code ,When the DB or Broadcast respond and multiple code are not the same.
     *
     * @param mCode
     * @param mCodeCallBack
     */
    private void returnCode(int mCode, CodeCallBack mCodeCallBack) {
        if (null != mCodeCallBack) {
            if (iRcode == mCode)
                return;
            mCodeCallBack.call(mCode);
            iRcode = mCode;
        }
    }

    /**
     * Get the code from text
     *
     * @param content
     *
     * @return If has code return the code ,else return empty string
     */
    public static String getNumbers(String content) {
        if (content.contains(CONTAINS_WORDS)) {
            int mStart = content.indexOf(CONTAINS_WORDS);
            Pattern pattern = Pattern.compile("\\d+");
            Matcher matcher = pattern.matcher(content.substring(mStart));
            while (matcher.find()) {
                return matcher.group(0);
            }
        }
        return "-1";
    }

    /**
     * Get the first SMS from phone data base Within three minutes,include the SMS ID , address , body and the read state.
     * Because it's within three minutes ,so it may be wrong(this SMS isn't what you need) in some special cases.
     *
     * @param mContext
     */
    public void getSmsFromPhone(Context mContext, ArrayMap<Context, CodeCallBack> mCodeCallBackMap) {
        ContentResolver mContentResolver = mContext.getContentResolver();
        String[] projection = new String[]{"_id", "address", "body", "read"};
        String where = " date >  "
                + (System.currentTimeMillis() - 3 * 60 * 1000);
        Cursor mCursor = mContentResolver.query(SMS_INBOX, projection, where, null, "date desc");
        if (null == mCursor)
            return;
        if (mCursor.moveToFirst()) {
            String _id = mCursor.getString(mCursor.getColumnIndex("_id"));//ID
            String number = mCursor.getString(mCursor.getColumnIndex("address"));//phone num
            String read = mCursor.getString(mCursor.getColumnIndex("read"));//1 read 0 unread
            String body = mCursor.getString(mCursor.getColumnIndex("body"));//messageBody
            if (TextUtils.equals(read, "0")) {
                String sCode = getNumbers(body);
                try {
                    int iCode = Integer.parseInt(sCode);
                    call(iCode, mCodeCallBackMap);
                } catch (NumberFormatException e) {
                    call(-1, mCodeCallBackMap);
                }
            }
        }
    }

    /**
     * Call back the code ,When the activity is foreground.
     *
     * @param code
     * @param mCodeCallBackMap
     */
    private void call(final int code, ArrayMap<Context, CodeCallBack> mCodeCallBackMap) {
        for (final Map.Entry<Context, SmsUtil.CodeCallBack> entry : mCodeCallBackMap.entrySet()) {
            Context mContext = entry.getKey();
            Activity mActivity = ((Activity) mContext);
            if (null != mContext
                    && null != mActivity
                    && Foreground(mContext, mActivity.getClass().getSimpleName()))
                mActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        entry.getValue().call(code);
                    }
                });

        }
    }

    /**
     * Judge the activity is in the foreground
     *
     * @param context
     * @param className
     *
     * @return true foreground false background
     */
    public static boolean Foreground(Context context, String className) {
        if (context == null || TextUtils.isEmpty(className))
            return false;
        ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> list = am.getRunningTasks(1);
        for (ActivityManager.RunningTaskInfo taskInfo : list) {
            if (taskInfo.topActivity.getShortClassName().contains(className)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Uninit
     * Release all variable
     */
    public void unInit(Context context) {
        if (null != mContext
                && null != mSmsObserver
                && null != mContext.getContentResolver()
                && mContext == context) {
            mContext.getContentResolver().unregisterContentObserver(mSmsObserver);
            mSmsObserver = null;
            smsHandler = null;
        }

        if (null != mContext
                && null != mSmsReceiver
                && mContext == context) {
            mContext.unregisterReceiver(mSmsReceiver);
            mSmsReceiver = null;
            mContext = null;
        }
    }

    /**
     * SMS observer ,when receive new SMS execute the getSmsFromPhone() method
     */
    class SmsObserver extends ContentObserver {
        private Context mContext;
        ArrayMap<Context, CodeCallBack> mCodeCallBackMap;

        /**
         * add the callBack ,if it hasn't been added yet
         *
         * @param mCodeCallBack
         */
        public void addCallBack(Context mContext, SmsUtil.CodeCallBack mCodeCallBack) {
            if (null == mContext)
                throw new IllegalArgumentException("Context must be not null!");
            if (null == this.mCodeCallBackMap)
                this.mCodeCallBackMap = new ArrayMap<>();
            if (!mCodeCallBackMap.containsKey(mContext))
                this.mCodeCallBackMap.put(mContext, mCodeCallBack);
        }


        public SmsObserver(Context context, Handler handler) {
            super(handler);
            this.mContext = context;
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            //when receive new SMS,
            getSmsFromPhone(mContext, mCodeCallBackMap);
        }
    }

    /**
     * Use to return the user, this code
     */
    public interface CodeCallBack {
        /**
         * If code equal "-1" express numberFormatException
         * else code is correct value
         *
         * @param code
         */
        void call(int code);
    }
}
SmsReceiver.class

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.util.ArrayMap;
import android.telephony.SmsMessage;

import java.util.Map;


/**
 * Synopsis     SmsReceiver
 * Author		Mosr
 * version		${VERSION}
 * Create 	    2017/8/29 10:31
 * Modify       2017/9/26
 * Email  		intimatestranger@sina.cn
 */
public class SmsReceiver extends BroadcastReceiver {
    ArrayMap<Context, SmsUtil.CodeCallBack> mCodeCallBackMap;

    /**
     * add the callBack ,if it hasn't been added yet
     *
     * @param mCodeCallBack
     */
    public void addCallBack(Context mContext, SmsUtil.CodeCallBack mCodeCallBack) {
        if (null == mContext)
            throw new IllegalArgumentException("Context must be not null!");
        if (null == this.mCodeCallBackMap)
            this.mCodeCallBackMap = new ArrayMap<>();
        if (!mCodeCallBackMap.containsKey(mContext))
            this.mCodeCallBackMap.put(mContext, mCodeCallBack);
    }


    @Override
    public void onReceive(Context context, Intent intent) {
        if (null != intent) {
            Bundle bundle = intent.getExtras();
            SmsMessage msg = null;
            if (null != bundle) {
                Object[] smsObj = (Object[]) bundle.get("pdus");
                if (null != smsObj && smsObj.length > 0)
                    for (Object object : smsObj) {
                        if (null == object)
                            return;
                        msg = SmsMessage.createFromPdu((byte[]) object);
                        if (null == msg)
                            return;
                        if ((System.currentTimeMillis() - msg.getTimestampMillis()) < 3 * 60 * 1000)//Within three minutes
                        {
                            String sCode = SmsUtil.getNumbers(msg.getDisplayMessageBody());
                            try {
                                int iCode = Integer.parseInt(sCode);
                                call(iCode);
                            } catch (NumberFormatException e) {
                                call(-1);
                            }
                        }
                    }
            }
        }
    }

    /**
     * Call back the code ,When the activity is foreground.
     *
     * @param code
     */
    void call(int code) {
        for (Map.Entry<Context, SmsUtil.CodeCallBack> entry : mCodeCallBackMap.entrySet()) {

            Context mContext = entry.getKey();
            if (SmsUtil.Foreground(mContext, ((Activity) mContext).getClass().getSimpleName()))
                entry.getValue().call(code);

        }
    }
}

用法参照章底Using,需注意unInit方法 添加Context参数改动

SmsUtil.getInstance().unInit(mContext);

**

Old 2017/8/29

**
**

Code

**

/**
 * Synopsis     ${SYNOPSIS}
 * Author		Mosr
 * Version		${VERSION}
 * Create 	    2017/8/29 10:29
 * Email  		intimatestranger@sina.cn
 */
public class SmsUtil {
    private final int RECEIVE_SMS_PERMISSION = 0x1007;

    private Uri SMS_INBOX = Uri.parse("content://sms/");

    private static String CONTAINS_WORDS = "验证码";

    private static SmsUtil mSmsUtil;

    private List<String> mPermissionList;

    private SmsReceiver mSmsReceiver;

    private SmsObserver mSmsObserver;

    private Context mContext;


    Handler smsHandler = new Handler() {
    };

    /**
     * Receive SmsUtil instance
     *
     * @return
     */
    public static SmsUtil getInstance() {
        if (null == mSmsUtil)
            synchronized (SmsUtil.class) {
                if (null == mSmsUtil)
                    mSmsUtil = new SmsUtil();
            }
        return mSmsUtil;
    }

    public boolean checkPermission(Context mContext) {
        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.BROADCAST_SMS) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(mContext, Manifest.permission.RECEIVE_SMS) == PackageManager.PERMISSION_GRANTED)
            return true;
        else {
            if (null == mPermissionList)
                mPermissionList = new ArrayList<>();
            else if (!mPermissionList.isEmpty())
                mPermissionList.clear();

            if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.BROADCAST_SMS)
                    != PackageManager.PERMISSION_GRANTED) {
                //添加需要申请的权限
                mPermissionList.add(Manifest.permission.BROADCAST_SMS);
            }
            if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_SMS)
                    != PackageManager.PERMISSION_GRANTED) {
                //添加需要申请的权限
                mPermissionList.add(Manifest.permission.READ_SMS);
            }
            if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.RECEIVE_SMS)
                    != PackageManager.PERMISSION_GRANTED) {
                //添加需要申请的权限
                mPermissionList.add(Manifest.permission.RECEIVE_SMS);
            }
            if (null != mPermissionList && mPermissionList.size() > 0)
                //申请权限
                if (mContext instanceof Activity)
                    ActivityCompat.requestPermissions((Activity) mContext, mPermissionList.toArray(new String[mPermissionList.size()]),
                            RECEIVE_SMS_PERMISSION);
        }
        return false;
    }

    public boolean onRequestPermissionsResult(Activity mActivity, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        boolean requested = false;
        switch (requestCode) {
            case RECEIVE_SMS_PERMISSION:
                if (grantResults.length >= 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.BROADCAST_SMS) == PackageManager.PERMISSION_GRANTED
                            && ContextCompat.checkSelfPermission(mActivity, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED
                            && ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECEIVE_SMS) == PackageManager.PERMISSION_GRANTED) {
                        requested = true;
                    } else {
                        ToastUitl.showError("请允许" + mActivity.getResources().getString(R.string.app_name) + "获取相关权限");
                        //申请权限
                        checkPermission(mActivity);
                    }
                } else {
                    ToastUitl.showError("请允许" + mActivity.getResources().getString(R.string.app_name) + "获取相关权限");
                    checkPermission(mActivity);
                }
                break;
            default:
                break;
        }
        return requested;
    }

    /**
     * one
     * <p>
     * Get  code from data base
     *
     * @param mContext
     *
     * @return SmsUtil instance
     */
    public SmsUtil getCodeFromDB(Context mContext, CodeCallBack mCodeCallBack) {
        if (null == mContext)
            throw new IllegalArgumentException("Context must be not null!");

        this.mContext = mContext;

        checkPermission(mContext);

        if (null == mSmsObserver)
            mSmsObserver = new SmsObserver(mContext, smsHandler, mCodeCallBack);
        mContext.getContentResolver().registerContentObserver(SMS_INBOX, true,
                mSmsObserver);
        return mSmsUtil;
    }

    /**
     * two
     * <p>
     * Get  code from broadcast
     * <p>
     * Ghe broadcastReceiver use this to dynamically register
     *
     * @param mContext
     *
     * @return SmsUtil instance
     */
    public SmsUtil getCodeFromBroadcast(Context mContext, CodeCallBack mCodeCallBack) {
        if (null == mContext)
            throw new IllegalArgumentException("Context must be not null!");

        this.mContext = mContext;

        checkPermission(mContext);

        if (null == mSmsReceiver) {
            mSmsReceiver = new SmsReceiver();
            mSmsReceiver.call(mCodeCallBack);
            IntentFilter mIntentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
            mIntentFilter.setPriority(Integer.MAX_VALUE);
            mContext.registerReceiver(mSmsReceiver, mIntentFilter);
        }
        return mSmsUtil;
    }

    int iBCcode = -1;
    int iDBcode = -1;

    /**
     * Get code from broadcast and phone DB at the same time
     * This will minimize mistakes
     *
     * @param mContext
     * @param mCodeCallBack
     *
     * @return
     */
    public SmsUtil getCodeFromBroadcastAndDB(Context mContext, final CodeCallBack mCodeCallBack) {
        if (null == mContext)
            throw new IllegalArgumentException("Context must be not null!");

        this.mContext = mContext;

        getCodeFromBroadcast(mContext, new CodeCallBack() {
            @Override
            public void call(int code) {
                Log.e("mosr", "getCodeFromBroadcast " + System.currentTimeMillis());
                iBCcode = code;
                returnCode(mCodeCallBack);
            }
        });
        getCodeFromDB(mContext, new CodeCallBack() {
            @Override
            public void call(int code) {
                Log.e("mosr", "getCodeFromDB " + System.currentTimeMillis());
                iDBcode = code;
                returnCode(mCodeCallBack);
            }
        });
        return mSmsUtil;
    }

    int iRcode = -2;

    private void returnCode(CodeCallBack mCodeCallBack) {
        if (iBCcode != -1 || iDBcode != -1) {
            if (null != mCodeCallBack) {
                int mCode = iBCcode != -1 ? iBCcode : iDBcode;
                if (iRcode == mCode)
                    return;
                mCodeCallBack.call(mCode);
                iRcode = mCode;

                iBCcode = -1;
                iDBcode = -1;
            }
        }
    }

    /**
     * Get the code from text
     *
     * @param content
     *
     * @return If has code return the code ,else return empty string
     */
    public static String getNumbers(String content) {
        if (content.contains(CONTAINS_WORDS)) {
            int mStart = content.indexOf(CONTAINS_WORDS);
            Pattern pattern = Pattern.compile("\\d+");
            Matcher matcher = pattern.matcher(content.substring(mStart));
            while (matcher.find()) {
                return matcher.group(0);
            }
        }
        return "-1";
    }

    /**
     * Get the first SMS from phone data base Within three minutes,include the SMS ID , address , body and the read state.
     * Because it's within three minutes ,so it may be wrong(this SMS isn't what you need) in some special cases.
     *
     * @param mContext
     */
    public void getSmsFromPhone(Context mContext, CodeCallBack mCodeCallBack) {
        ContentResolver mContentResolver = mContext.getContentResolver();
        String[] projection = new String[]{"_id", "address", "body", "read"};
        String where = " date >  "
                + (System.currentTimeMillis() - 3 * 60 * 1000);
        Cursor mCursor = mContentResolver.query(SMS_INBOX, projection, where, null, "date desc");
        if (null == mCursor)
            return;
        if (mCursor.moveToFirst()) {
            String _id = mCursor.getString(mCursor.getColumnIndex("_id"));//ID
            String number = mCursor.getString(mCursor.getColumnIndex("address"));//phone num
            String read = mCursor.getString(mCursor.getColumnIndex("read"));//1 read 0 unread
            String body = mCursor.getString(mCursor.getColumnIndex("body"));//messageBody
            if (TextUtils.equals(read, "0")) {
                String sCode = getNumbers(body);
                try {
                    int iCode = Integer.parseInt(sCode);
                    if (null != mCodeCallBack)
                        mCodeCallBack.call(iCode);
                } catch (NumberFormatException e) {
                    if (null != mCodeCallBack)
                        mCodeCallBack.call(-1);
                }
            }
        }
    }

    /**
     * Uninit
     * Release all variable
     */
    public void unInit() {
        if (null != mContext
                && null != mSmsObserver
                && null != mContext.getContentResolver())
            mContext.getContentResolver().unregisterContentObserver(mSmsObserver);
        mSmsObserver = null;
        smsHandler = null;

        if (null != mContext
                && null != mSmsReceiver)
            mContext.unregisterReceiver(mSmsReceiver);
        mSmsReceiver = null;

        mContext = null;
    }

    /**
     * SMS observer ,when receive new SMS execute the getSmsFromPhone() method
     */
    class SmsObserver extends ContentObserver {
        private Context mContext;
        private CodeCallBack mCodeCallBack;

        public SmsObserver(Context context, Handler handler, CodeCallBack mCodeCallBack) {
            super(handler);
            this.mContext = context;
            this.mCodeCallBack = mCodeCallBack;
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            //when receive new SMS,
            getSmsFromPhone(mContext, mCodeCallBack);
        }
    }

    /**
     * Use to return the user, this code
     */
    public interface CodeCallBack {
        /**
         * If code equal "-1" express numberFormatException
         * else code is correct value
         *
         * @param code
         */
        void call(int code);
    }
}

SmsReceiver.class

/**
 * Synopsis     ${SYNOPSIS}
 * Author		Mosr
 * version		${VERSION}
 * Create 	    2017/8/29 10:31
 * Email  		intimatestranger@sina.cn
 */
public class SmsReceiver extends BroadcastReceiver {
    SmsUtil.CodeCallBack mCodeCallBack;

    public void call(SmsUtil.CodeCallBack mCodeCallBack) {
        this.mCodeCallBack = mCodeCallBack;
    }


    @Override
    public void onReceive(Context context, Intent intent) {
        if (null != intent) {
            Bundle bundle = intent.getExtras();
            SmsMessage msg = null;
            if (null != bundle) {
                Object[] smsObj = (Object[]) bundle.get("pdus");
                if (null != smsObj && smsObj.length > 0)
                    for (Object object : smsObj) {
                        if (null == object)
                            return;
                        msg = SmsMessage.createFromPdu((byte[]) object);
                        if (null == msg)
                            return;
                        if ((System.currentTimeMillis() - msg.getTimestampMillis()) < 3 * 60 * 1000)//Within three minutes
                        {
                            String sCode = SmsUtil.getNumbers(msg.getDisplayMessageBody());
                            try {
                                int iCode = Integer.parseInt(sCode);
                                if (null != mCodeCallBack)
                                    mCodeCallBack.call(iCode);
                            } catch (NumberFormatException e) {
                                if (null != mCodeCallBack)
                                    mCodeCallBack.call(-1);
                            }
                        }
                    }
            }
        }
    }
}

**

Using

**
从广播中获取验证码;


        SmsUtil.getInstance().getCodeFromBroadcast(getActivity(), new SmsUtil.CodeCallBack() {
            @Override
            public void call(int code) {
                
            }
        });

从手机数据库中获取验证码:


        SmsUtil.getInstance().getCodeFromDB(getActivity(), new SmsUtil.CodeCallBack() {
            @Override
            public void call(int code) {

            }
        });

双重获取(推荐)


        SmsUtil.getInstance().getCodeFromBroadcastAndDB(getActivity(), new SmsUtil.CodeCallBack() {
            @Override
            public void call(int code) {

            }
        });

因为许多安卓手机对权限管理严格,有甚者不允许第三方应用获取短信广播,或者短信数据库数据读取,所以推荐同时使用获取广播和读取数据库,能最大限度的保证工具类的可用性。

Android 6.0 权限获取


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
       boolean requested= SmsUtil.getInstance().onRequestPermissionsResult(getActivity(), requestCode, permissions, grantResults);
        if (requested){
            
        }
    }

销毁


    @Override
    public void onDestroy() {
        SmsUtil.getInstance().unInit();
        super.onDestroy();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值