通过监听短信和正则表达式实现自动填写短信验证码
实现短信监听要用到广播,这里我在Service里面注册这个广播
在activity里面启动service
intent = new Intent(MainActivity.this, SmsService.class); intent.putExtra("cmd", 1); startService(intent);
接下来看 service
在service的onCreate方法中 通过startForeground 让服务前台运行
在 onStartCommand方法中 接受到 activity 启动监听的指令,注册接收者
要注意优先级要尽量设高, Action为
android.provider.Telephony.SMS_RECEIVED
在广播接受者的 onReceive方法 9-19行 取出需要的短信信息
拿到短信内容后,就可以进行验证码匹配
举两个验证码短信例子
【百度】您在百度开发者中心进行的手机验证的验证码为:313253,请输入后进行验证,谢谢![百度开发者中心]
【哔哩哔哩】951422 为你的手机绑定验证码,请在5分钟内完成手机绑定。如非本人操作,请忽略或回复T退订。
通常手机接受到的验证码都是 4位或者6位的纯数字
可以用 \d{4,6}(?!\d) , 红色部分 表示 4到6位的数字,粉色表示后面不能为数字,其实这个可有可无
如果遇到的是 数字字母混合的
可以用 [A-Za-z0-9]{4,}(?![A-Za-z0-9]) 红色部分表示符合 A到Z a到z 0到9的这个类型 的字符,粉色表示四位以上 ,后面同上
没有使用\w 是因为\w 还可以代表汉字
^((https|http)?:\/\/)[^\s]+[jpg]
图片地址例子
对于不同的短信验证码模板,肯定有不同的方法,我写的只是一种思路,不可能所有都适用,如果收到一条国外的验证码短信,就不是上面那么简单了
1 public class SmsService extends Service { 2 3 private NotificationManager manger; 4 public static NotificationCompat.Builder builder; 5 private BroadcastReceiver receiver = new BroadcastReceiver() { 6 @Override 7 public void onReceive(Context context, Intent intent) { 8 9 SmsMessage msg = null; 10 Bundle bundle = intent.getExtras(); 11 if (bundle != null) { 12 Object[] pdusObj = (Object[]) bundle.get("pdus"); 13 for (Object p : pdusObj) { 14 msg = SmsMessage.createFromPdu((byte[]) p); 15 String msgTxt = msg.getMessageBody();//得到消息的内容 16 Date date = new Date(msg.getTimestampMillis());//时间 17 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 18 String receiveTime = format.format(date); 19 String senderNumber = msg.getOriginatingAddress(); 20 //Toast.makeText(context, "发送人:" + senderNumber + " 短信内容:" + msgTxt + "接受时间:" + receiveTime, Toast.LENGTH_LONG).show(); 21 22 23 // \d{4,6}(?!\d) 24 // [A-Za-z0-9]{4,}(?![A-Za-z0-9]) 25 Pattern pattern=Pattern.compile("[A-Za-z0-9]{4,}(?![A-Za-z0-9])"); 26 Matcher matcher=pattern.matcher(msgTxt); 27 if (matcher.find()){ 28 String code=matcher.group(0); 29 Toast.makeText(context,"验证码是 "+code,Toast.LENGTH_LONG).show(); 30 context.sendBroadcast(new Intent().setAction("yzm").putExtra("code",code)); 31 createNotification(code); 32 } 33 return; 34 } 35 return; 36 } 37 } 38 }; 39 40 private void createNotification(String code) { 41 NotificationCompat.Builder builder=new NotificationCompat.Builder(this); 42 builder.setSmallIcon(R.mipmap.ic_launcher); 43 builder.setAutoCancel(true); 44 builder.setContentTitle("收到验证码 "+code); 45 46 Intent[] intents = new Intent[2]; 47 intents[0]=Intent.makeRestartActivityTask(new ComponentName(this,MainActivity.class)); 48 intents[1]=new Intent(this,CodeActivity.class); 49 intents[1].putExtra("code",code); 50 51 PendingIntent pendingIntent = PendingIntent.getActivities(this, 0, intents, PendingIntent.FLAG_UPDATE_CURRENT); 52 builder.setContentIntent(pendingIntent); 53 54 Notification notification = builder.build(); 55 manger.notify(666, notification); 56 } 57 58 59 @Nullable 60 @Override 61 public IBinder onBind(Intent intent) { 62 return null; 63 } 64 65 @Override 66 public void onCreate() { 67 super.onCreate(); 68 manger = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 69 builder = new NotificationCompat.Builder(this); 70 71 builder.setSmallIcon(R.mipmap.ic_launcher); 72 builder.setAutoCancel(true); 73 builder.setContentTitle("sms listening"); 74 75 Intent intent = new Intent(this, MainActivity.class); 76 PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); 77 builder.setContentIntent(pendingIntent); 78 79 Notification notification = builder.build(); 80 //manger.notify(333, notification); 81 startForeground(333, notification); 82 83 } 84 85 @Override 86 public int onStartCommand(Intent intent, int flags, int startId) { 87 int i = intent.getExtras().getInt("cmd"); 88 if (1 == i) { 89 initReceiver(); 90 } else { 91 stopForeground(true); 92 } 93 return super.onStartCommand(intent, flags, startId); 94 } 95 96 97 private void initReceiver() { 98 IntentFilter intentFilter = new IntentFilter(); 99 intentFilter.setPriority(1000); 100 intentFilter.addAction("android.provider.Telephony.SMS_RECEIVED"); 101 registerReceiver(receiver, intentFilter); 102 } 103 104 @Override 105 public void onDestroy() { 106 super.onDestroy(); 107 unregisterReceiver(receiver); 108 stopForeground(true); 109 } 110 }
最后拿到验证码之后,从service里面发送广播,activity里面注册接收者,拿到验证码,填充给 EditText,当然也可以用EventBus
private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case "yzm": editText.setText(intent.getExtras().getString("code")); break; } } };
如果想停止service,应该在service的onDestroy方法中
unregisterReceiver 注销短信接收者
stopForeground 停止服务前台运行