1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Android开发 亲测可用--多种方式获取手机短信验证码自动填入

Android开发 亲测可用--多种方式获取手机短信验证码自动填入

时间:2024-02-13 10:25:10

相关推荐

Android开发 亲测可用--多种方式获取手机短信验证码自动填入

Android开发 静态注册、动态注册、短信中心库监控获取手机验证码,自动复制到剪切板或或填入输入框。

友情提醒初学者:这是广播接收器的类,写在xml中静态注册或写在启动类的Oncreate方法下动态注册即可!有新短信通知就会触发。若使用正常的验证码填入功能,请处理完毕后在界面销毁处注销监听。

第一种方式:广播接收者 静/动注册监听短信广播 获取验证码

第二种方式:内容观察者 观察短信库的变化,根据日期获取最新短信,并解决onChange回调多次的情况。

一.通过广播接收者监控获取验证码

1.SMSReceiver.java 类代码 - -静态、动态都可用

import android.content.BroadcastReceiver;import android.content.ClipData;import android.content.ClipboardManager;import android.content.Context;import android.content.Intent;import android.telephony.SmsMessage;import android.util.Log;import android.widget.Toast;import java.util.regex.Matcher;import java.util.regex.Pattern;public class SMSReceiver extends BroadcastReceiver {private static final String TAG = "SMSReceiver";@Overridepublic void onReceive(Context context, Intent intent) {//调用短信内容获取类getMsg(context, intent);}/*** 短信内容的获取* @param context* @param intent*/private void getMsg(Context context, Intent intent) {//解析短信内容 pdus短信单位pduif (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {Object[] pdus = (Object[]) intent.getExtras().get("pdus");assert pdus != null;for (Object pdu : pdus) {//封装短信参数的对象SmsMessage sms = SmsMessage.createFromPdu((byte[]) pdu);String number = sms.getOriginatingAddress(); //获取发送短信的手机号String body = sms.getMessageBody(); //获取接收短信手机号的完整信息System.out.println("发短信的手机号:"+number+" "+"监听到的短信息:" + body);//写处理逻辑 可以加线程new Thread(new Runnable() {@Overridepublic void run() {try {//在这里写线程相关的处理逻辑} catch (Exception e) {e.printStackTrace();}}}).start();//写处理逻辑,调用相关类 匹配获取验证码并复制到剪贴板getCode(context, body);}}}/*** 匹配出验证码并复制到剪贴板* @param context* @param body*/private void getCode(Context context, String body) {//获取剪贴板管理器:ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);Pattern pattern1 = pile("(\\d{4,6})");//正则匹配4-6位数字Matcher matcher1 = pattern1.matcher(body);//进行匹配if (matcher1.find()) {//匹配成功String code = matcher1.group(0);// 创建普通字符型ClipDataClipData mClipData = ClipData.newPlainText("Label", code);// 将mClipData内容放到手机系统剪贴板cm.setPrimaryClip(mClipData);Toast.makeText(context, "验证码复制成功,请粘贴", Toast.LENGTH_SHORT).show();Log.d(TAG, "onReceive: " + code);} else {Toast.makeText(context, "未检测到验证码,请手动输入", Toast.LENGTH_SHORT).show();Log.d(TAG, "onReceive: " + "未检测到验证码");}}}

2.动态申请权限的相关类

在项目代码中的目标获取验证码处,动态申请读取短信相关权限的代码,也可在进入软件后界面的Oncreate下搞代码,动态申请权限。强制用户同意存储及短信权限。

2.1XML中添加存储读写及短信权限

<!-- 修改或删除您的USB存储设备中的内容 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!--发送及接收读取短信的权限--><uses-permission android:name="android.permission.SEND_SMS" /><uses-permission android:name="android.permission.RECEIVE_SMS" /><uses-permission android:name="android.permission.READ_SMS" />

2.2在合适/启动界面申请获取权限

public class LoginActivity extends Activity {//日志打印常量private String TAG;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//在onCreate方法这里调用来动态获取存储权限以及短信权限getReadPermissions();}/*** 权限的验证及处理,相关方法*/private void getReadPermissions() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED| ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECEIVE_SMS) | ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {//是否请求过该权限ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS,Manifest.permission.READ_SMS,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 10001);} else {//没有则请求获取权限,示例权限是:存储权限和短信权限,需要其他权限请更改或者替换ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS,Manifest.permission.READ_SMS,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}, 10001);}} else {//如果已经获取到了权限则直接进行下一步操作Log.e(TAG, "onRequestPermissionsResult");}}}/*** 一个或多个权限请求结果回调* 当点击了不在询问,但是想要实现某个功能,必须要用到权限,可以提示用户,引导用户去设置*/@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(this, permissions[i]);if (flag) {getReadPermissions();return;//用户权限是一个一个的请求的,只要有拒绝,剩下的请求就可以停止,再次请求打开权限了} else {// 勾选不再询问,并拒绝Toast.makeText(this, "请到设置中打开权限", Toast.LENGTH_LONG).show();return;}}}//Toast.makeText(LoginActivity.this, "权限开启完成",Toast.LENGTH_LONG).show();break;default:break;}}

3.静态注册广播接收者

3.1AndroidManifest.xml添加权限及广播服务

<!--发送接收读取短信的权限 都加上吧--><uses-permission android:name="android.permission.SEND_SMS" /><uses-permission android:name="android.permission.RECEIVE_SMS" /><uses-permission android:name="android.permission.READ_SMS" /><applicationandroid:allowBackup="true"android:hardwareAccelerated="false"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:largeHeap="true"android:theme="@style/AppTheme">。。。。。。。。<receiverandroid:name=".SMSReceiver这里是静态注册写法,写广播类所在的位置"><intent-filter android:priority="1000"><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>。。。。。。。。</application>

4.动态注册广播接收者

4.1在启动界面动态注册

public class LoginActivity extends Activity {//日志打印常量private String TAG;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//动态注册广播接收者且设置为最大优先级IntentFilter filter = new IntentFilter();filter.addAction("android.provider.Telephony.SMS_RECEIVED" );filter.setPriority(Integer.MAX_VALUE);//设置动态优先级为最大,1000应该不是最大SMSReceiver receiver = new SMSReceiver();registerReceiver(receiver,filter);}

二.通过内容监控者读取短信库获取验证码

1.SMSobserver.java 类代码

解决SMSobserver的onChang回调或获取短信不是最新,以及获取重复短信问题。

import android.content.ClipboardManager;import android.content.Context;import android.database.ContentObserver;import android.database.Cursor;import .Uri;import android.os.Handler;import android.util.Log;import android.widget.Toast;import java.text.SimpleDateFormat;import java.util.Date;import java.util.regex.Matcher;import java.util.regex.Pattern;public class SMSobserver extends ContentObserver {private Context mContext;private Handler mHandler;private String TAG;private static int id=0; //这里必须用静态的,防止程序多次意外初始化情况public SMSobserver(Context context, Handler handler) {super(handler);mContext = context;mHandler = handler;}@Overridepublic void onChange(boolean selfChange, Uri uri) {super.onChange(selfChange, uri);//过滤可能界面调用初始化两次的情况if (uri.toString().contains("content://sms/raw")) {return;}Uri inboxUri = Uri.parse("content://sms/inbox");Cursor cursor = mContext.getContentResolver().query(inboxUri, null, null, null, "date desc");if (cursor != null) {if (cursor.moveToFirst()) {String _id = cursor.getString(cursor.getColumnIndex("_id"));//比较id 解决重复问题if (id < Integer.parseInt(_id)) {id = Integer.parseInt(_id);//将获取到的当前id记录,防止重复String address = cursor.getString(cursor.getColumnIndex("address"));String body = cursor.getString(cursor.getColumnIndex("body"));String date = cursor.getString(cursor.getColumnIndex("date"));SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");String time1 = dateFormat.format(new Date(Long.parseLong(date)));//写自己的处理逻辑,我这里是复制验证码到剪切板if(body.contains("短信中包含某字符才匹配复制到剪切板")) {Pattern pattern = pile("(\\d{4,6})");Matcher matcher = pattern.matcher(body);if (matcher.find()) {String code = matcher.group(0);System.out.println("验证码:" + code);ClipboardManager cmb = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);cmb.setText(code);Toast.makeText(mContext.getApplicationContext(), "复制成功" + code, Toast.LENGTH_SHORT).show();}}}}cursor.close();}}}

2.调用注册内容监控者

public class LoginActivity extends Activity {//回调显示private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg.what == 1) {String code = (String) msg.obj;editname.setText(code);//要显示验证码的控件id}}};//防止多次初始化private SMSobserver smsobserver = new SMSobserver(this, mHandler);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//调用注册内容监控者getContentResolver().registerContentObserver(Uri.parse("content://sms"),true, smsobserver);}

参考文章:全网文章。查了全网基本都没有解决回调和筛选重复的问题,我这个请参考。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。