真的很奇怪大家的复制粘贴功能,一篇自动获取手机验证码的文章各大平台争相转发,我以为很牛逼,到后来发现不能用,可能我技术不够吧,复制粘贴还不到家。

android 自动获取手机验证码好处 :① 用户不用自动输入, 方便操作
② 防止用户在别的手机上登录,保证一手机只能一个号

言归正传

先创建继承于ContentObserver的子类,用于监听信息数据库发生变化,有信息来就立马截取。

public class SMSContentObserver extends ContentObserver {private static String TAG = "SMSContentObserver";private String patternCoder = "\\d{5}";     //正则表达式private String strContent;                  //验证码内容private Context mContext  ;private Handler mHandler ;   				  //更新UI线程private String TELPHONE = "TMRTXMIN"; // 短信来源号码private String TelPHONECONTEXT ="iViralLink"; // 短信内容 特殊关键字//    8448631136public SMSContentObserver(Context context, Handler handler) {super(handler);mContext = context ;mHandler = handler ;}/*** 当所监听的Uri发生改变时,就会回调此方法** @param selfChange  此值意义不大 一般情况下该回调值false*/@Overridepublic void onChange(boolean selfChange){Log.i(TAG, "the sms table has changed");//查询收件箱里的内容Uri outSMSUri = Uri.parse("content://sms/inbox") ;Cursor c = mContext.getContentResolver().query(outSMSUri, null, null, null,"date desc");if(c != null){Log.i(TAG, "the number of send is "+c.getCount()) ;StringBuilder sb = new StringBuilder() ;c.moveToNext();String message = c.getString(c.getColumnIndex("body"));      // 短信内容String phone = c.getString(c.getColumnIndex("address"));	   //短信来源号码Log.i(TAG,"message : "+message);Log.i(TAG,"phone : "+phone);c.close();if(checkPhone(phone) &&checkString(message)){String code = patternCode(message);assert code != null;if(!TextUtils.isEmpty(code) ){strContent = code;}mHandler.obtainMessage(1, sb.toString()).sendToTarget();}}}//指定一个号码,只读取与他有关的新消息。private boolean checkPhone(String phone) {// TODO Auto-generated method stubString c_phone = TELPHONE;if(c_phone.equals(phone) )return true;return false;}//指定一关键字符串,用来确认短信内容是我们想要去提取的private boolean checkString(String message){if(TextUtils.isEmpty(message))return false;Pattern p = Pattern.compile(TelPHONECONTEXT);          //这个关键字符串可以自定义Matcher matcher = p.matcher(message);if(matcher.find())return true;return false;}//匹配短信中的数字(验证码)private String patternCode(String patternContent){if(TextUtils.isEmpty(patternContent))return null;Pattern p = Pattern.compile(patternCoder);Matcher matcher = p.matcher(patternContent);if(matcher.find())return matcher.group();return null;}public String getStrContent(){return strContent;}
}

然后自己需要的登录或者注册界面注册

  private void initRegisterContentObserver() {smsContentObserver = new SMSContentObserver(this, mHandler);Uri smsUri = Uri.parse("content://sms");getContentResolver().registerContentObserver(smsUri, true, smsContentObserver);}

有注册记得关闭

 @Overrideprotected void onDestroy() {super.onDestroy();if (getContentResolver()!=null){getContentResolver().unregisterContentObserver(smsContentObserver);}}

展示信息:

private Handler mHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case 1:String outbox = smsContentObserver.getStrContent();//(String) msg.obj;etVerificationCode.setText(outbox);break;default:break;}}};

以上内容基本上已经可以获取到验证码了,但是获取手机短信,还是需要动态读取短信的权限。
AndroidManifest.xml中加权限

 <uses-permission android:name="android.permission.RECEIVE_SMS" /><uses-permission android:name="android.permission.READ_SMS" />

在获取权限的位置动态添加权限设置

private void getReadPermissions() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {if (ActivityCompat.shouldShowRequestPermissionRationale(RegisterActivity.this, Manifest.permission.RECEIVE_SMS)) {//是否请求过该权限ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS,Manifest.permission.READ_SMS
//                                    , Manifest.permission.SEND_SMS},10001);} else {//没有则请求获取权限,示例权限是:相机权限和定位权限,需要其他权限请更改或者替换ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS,Manifest.permission.READ_SMS},10001);}} else {        //如果已经获取到了权限则直接进行下一步操作Log.e(TAG, "onRequestPermissionsResult");}}}

设置请求权限的回调

/*** 一个或多个权限请求结果回调** @param requestCode* @param permissions* @param grantResults*///当点击了不在询问,但是想要实现某个功能,必须要用到权限,可以提示用户,引导用户去设置@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode) {case 10001:for (int i = 0; i < grantResults.length; i++) {
//                   如果拒绝获取权限if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {//判断是否勾选禁止后不再询问boolean flag= ActivityCompat.shouldShowRequestPermissionRationale(RegisterActivity.this, permissions[i]);if (flag) {getReadPermissions();return;//用户权限是一个一个的请求的,只要有拒绝,剩下的请求就可以停止,再次请求打开权限了} else { // 勾选不再询问,并拒绝Toast.makeText(RegisterActivity.this, "Please go to Settings to get user permissions",Toast.LENGTH_LONG).show();return;}}}Toast.makeText(RegisterActivity.this, " go to school",Toast.LENGTH_LONG).show();break;default:break;}}

完整获取验证码代码如下:

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;import static android.content.ContentValues.TAG;public class RegisterActivity extends Activity {private SMSContentObserver smsContentObserver;private EditText etVerificationCode;private Handler mHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case 1:String outbox = smsContentObserver.getstrContent();//(String) msg.obj;etVerificationCode.setText(outbox);break;default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);etVerificationCode = findViewById(R.id.ed_code);getReadPermissions();initRegisterContentObserver();}private void initRegisterContentObserver() {smsContentObserver = new SMSContentObserver(this, mHandler);Uri smsUri = Uri.parse("content://sms");getContentResolver().registerContentObserver(smsUri, true, smsContentObserver);}private void getReadPermissions() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {if (ActivityCompat.shouldShowRequestPermissionRationale(RegisterActivity.this, Manifest.permission.RECEIVE_SMS)) {//是否请求过该权限ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS,Manifest.permission.READ_SMS},10001);} else {//没有则请求获取权限,示例权限是:相机权限和定位权限,需要其他权限请更改或者替换ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECEIVE_SMS,Manifest.permission.READ_SMS},10001);}} else {        //如果已经获取到了权限则直接进行下一步操作Log.e(TAG, "onRequestPermissionsResult");}}}/*** 一个或多个权限请求结果回调** @param requestCode* @param permissions* @param grantResults*///当点击了不在询问,但是想要实现某个功能,必须要用到权限,可以提示用户,引导用户去设置@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode) {case 10001:
//               一次请求多个权限时,可以循环设置,单独一个可以不用写了for (int i = 0; i < grantResults.length; i++) {
//                   如果拒绝获取权限if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {//判断是否勾选禁止后不再询问boolean flag= ActivityCompat.shouldShowRequestPermissionRationale(RegisterActivity.this, permissions[i]);if (flag) {getReadPermissions();return;//用户权限是一个一个的请求的,只要有拒绝,剩下的请求就可以停止,再次请求打开权限了} else { // 勾选不再询问,并拒绝Toast.makeText(RegisterActivity.this, "Please go to Settings to get user permissions",Toast.LENGTH_LONG).show();return;}}}Toast.makeText(RegisterActivity.this, " go to school",Toast.LENGTH_LONG).show();break;default:break;}}@Overrideprotected void onDestroy() {super.onDestroy();if (getContentResolver()!=null){getContentResolver().unregisterContentObserver(smsContentObserver);}}
}