Android实现短信验证码获取自动填写功能(详细版)

Android实现短信验证码获取自动填写功能(详细版),第1张

概述现在的应用在注册登录或者修改密码中都用到了短信验证码,那在android中是如何实现获取短信验证码并自动填写的呢?

现在的应用在注册登录或者修改密码中都用到了短信验证码,那在androID中是如何实现获取短信验证码并自动填写的呢?

首先,需要要在manifest中注册接收和读取短信的权限: 

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

实现一个广播SMSbroadcastReceiver来监听短信:

package com.example.receive;import java.text.SimpleDateFormat;import java.util.Date;import androID.content.broadcastReceiver;import androID.content.Context;import androID.content.Intent;import androID.telephony.SmsMessage;/** * 短信监听 * @author  * */public class SMSbroadcastReceiver extends broadcastReceiver {  private static MessageListener mMessageListener; public static final String SMS_RECEIVED_ACTION = "androID.provIDer.Telephony.SMS_RECEIVED";  public SMSbroadcastReceiver() {  super(); } @OverrIDe public voID onReceive(Context context,Intent intent) {   if (intent.getAction().equals(SMS_RECEIVED_ACTION)) {    Object[] pdus = (Object[]) intent.getExtras().get("pdus");    for(Object pdu:pdus) {     SmsMessage smsMessage = SmsMessage.createFromPdu((byte [])pdu);     String sender = smsMessage.getdisplayOriginatingAddress();     //短信内容     String content = smsMessage.getdisplayMessageBody();     long date = smsMessage.getTimestampMillis();     Date tIEmDate = new Date(date);     SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     String time = simpleDateFormat.format(tIEmDate);     //过滤不需要读取的短信的发送号码     if ("+8613450214963".equals(sender)) {      mMessageListener.onReceived(content);      abortbroadcast();     }    }   }   }  //回调接口 public interface MessageListener {  public voID onReceived(String message); }  public voID setonReceivedMessageListener(MessageListener messageListener) {  this.mMessageListener = messageListener; }}

在需要填写验证码的Activity中,生产SMSbroadcastReceiver的实例,实现onReceived的回调接口。为了节约系统资源,我们使用动态注册注销广播的方法。 

package com.example.smstest;import com.example.receive.SMSbroadcastReceiver;import androID.os.Bundle;import androID.app.Activity;import androID.content.IntentFilter;import androID.vIEw.Menu;import androID.Widget.EditText;public class MainActivity extends Activity {  private EditText edtPassword; private SMSbroadcastReceiver mSMSbroadcastReceiver;  private static final String ACTION = "androID.provIDer.Telephony.SMS_RECEIVED"; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); edtPassword = (EditText) findVIEwByID(R.ID.password); }  @OverrIDe protected voID onStart() {  super.onStart();  //生成广播处理  mSMSbroadcastReceiver = new SMSbroadcastReceiver();  //实例化过滤器并设置要过滤的广播  IntentFilter intentFilter = new IntentFilter(ACTION);  intentFilter.setPriority(Integer.MAX_VALUE);  //注册广播  this.registerReceiver(mSMSbroadcastReceiver,intentFilter);  mSMSbroadcastReceiver.setonReceivedMessageListener(new SMSbroadcastReceiver.MessageListener() {   @OverrIDe   public voID onReceived(String message) {    edtPassword.setText(message);   }  }); }  @OverrIDe protected voID onDestroy() { super.onDestroy(); //注销短信监听广播  this.unregisterReceiver(mSMSbroadcastReceiver); }}

上面提供了一种获取短信息验证码并自动填写的实现方式,就是直接通过短信广播监听短信。但是,这种方式有它的缺陷:当你的手机安装了其他一些短信应用(例如QQ通讯录)或者手机本身限制了权限的情况下,这种方式有可能会不起作用,无法做到自动填写,而且就算把优先级设高,也不能保证不会被别的应用“抢先”。

后来查资料知道,可以通过监听短信数据库的方式实现。监听短信数据库主要是通过ContentObserver这个类来完成。ContentObserver主要是通过Uri来监测特定的Databases的表,当ContentObserver所观察的Uri发生变化时,便会触发它。思路就是监听短信数据库中特定号码的未读短信。我们可以通过百度找到许多demo,但是我发现很多demo中存在着BUG,在接收到短信后引起崩溃。还有一种情况,当真机连接着电脑,电脑装有类似豌豆荚之类的软件的时候,手机收到短信后,豌豆荚之类的可能会把该短信的状态改成“已读”,这样也会导致崩溃。

通过调试,终于把BUG修复了,布局和短信权限就不再赘述。在MainActivity中增加一个内部类SmsContent。

  /**  * 监听短信数据库  */ class SmsContent extends ContentObserver {  private Cursor cursor = null;  public SmsContent(Handler handler) {   super(handler);  }  @OverrIDe  public voID onChange(boolean selfChange) {   super.onChange(selfChange);   //读取收件箱中指定号码的短信   cursor = managedquery(Uri.parse("content://sms/in@R_419_6951@"),new String[]{"_ID","address","read","body"}," address=? and read=?",new String[]{"1065811201","0"},"_ID desc");//按ID排序,如果按date排序的话,修改手机时间后,读取的短信就不准了   MyLog.l("cursor.isBeforeFirst() " + cursor.isBeforeFirst() + " cursor.getCount() " + cursor.getCount());   if (cursor != null && cursor.getCount() > 0) {    ContentValues values = new ContentValues();    values.put("read","1");  //修改短信为已读模式    cursor.movetoNext();    int smsbodyColumn = cursor.getColumnIndex("body");    String smsBody = cursor.getString(smsbodyColumn);    MyLog.v("smsBody = " + smsBody);    edtPassword.setText(MatchesUtil.getDynamicPassword(smsBody));   }   //在用managedquery的时候,不能主动调用close()方法, 否则在AndroID 4.0+的系统上, 会发生崩溃   if(Build.VERSION.SDK_INT < 14) {    cursor.close();   }  } } 

记得在onCreate中注册短信变化监听 

SmsContent content = new SmsContent(new Handler());  //注册短信变化监听  this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"),true,content); 

记得注销监听
 this.getContentResolver().unregisterContentObserver(content);

其中,下发的验证码短信一般都是一个字符串,其中包含6位数字,我们需要把这6位数字提取出来,我们可以用正则表达式写一个静态方法。 

 /**  * 从字符串中截取连续6位数字  * 用于从短信中获取动态密码  * @param str 短信内容  * @return 截取得到的6位动态密码  */ public static String getDynamicPassword(String str) {  Pattern continuousNumberPattern = Pattern.compile("[0-9\.]+");  Matcher m = continuousNumberPattern.matcher(str);  String dynamicPassword = "";  while(m.find()){   if(m.group().length() == 6) {    System.out.print(m.group());    dynamicPassword = m.group();   }  }  return dynamicPassword; }

至此,androID获取短信验证码并自动填写的功能就实现了。

补充:对于上面短信数据库监听中有个直接关闭游标的 *** 作(现在已经更正):cursor.close();  
但是,如果这样直接关闭的话,会引起崩溃。例如,当获取了短信密码,自动填写上了之后,按home键返回桌面,然后再进入应用,会引起应用崩溃。报的错是:

androID.database.StaleDataException: Attempted to access a cursor after it has been closed

后来通过查资料得知,是用managedquery的时候, 不能主动调用close()方法, 否则在AndroID 4.0+的系统上, 会发生崩溃。对版本进行一个判断再执行关闭游标的 *** 作。 

//在用managedquery的时候,不能主动调用close()方法, 否则在AndroID 4.0+的系统上, 会发生崩溃   if(Build.VERSION.SDK_INT < 14) {    cursor.close();   }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android实现短信验证码获取自动填写功能(详细版)全部内容,希望文章能够帮你解决Android实现短信验证码获取自动填写功能(详细版)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1141522.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存