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/inbox"), 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();
   }

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

(0)

相关推荐

  • Android实现短信验证码自动拦截读取功能

    知识准备:  1.观察者模式的理解[文章稍后来到~~]  2.Android的Cursor使用[Android基础]  3.正则表达式使用[Java基础]  4.Handler使用[Android基础] 代码整理: MainActivity.java import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.suppo

  • Android实现短信验证码自动填写功能

    本实例为大家分享了Android实现短信验证码自动填写功能,供大家参考,具体内容如下 实现思路很简单: 1.在需要输入验证码的Activity代码注册监听短信的广播 2.拦截短信,获取其中的验证码 3.回写到EditText private SmsReciver smsReciver = new SmsReciver(); /** 收到短信Action **/ String ACTION_SMS_RECIVER = "android.provider.Telephony.SMS_RECEIVED

  • Android如何通过手机自动获取短信验证码

    本文实例为大家分享了Android实现手机自动获取短信验证码功能,供大家参考,具体内容如下 1.短信监听广播 2.读取短信内容 3.截取短信内容[可以 reg截取] 4.填写至相应控件 PS:DevStore测试没有获取到验证码 源码片段 public class MainActivity extends Activity { private BroadcastReceiver smsReceiver; private IntentFilter filter2; private Handler

  • 关于Android短信验证码的获取的示例

    最近突然想起App里面的登录模块,有可以使用手机号码注册的功能,感觉此功能在大多款App里面都比较常见,因此在此做一个记录,顺便将之前踩过得坑在此记录一下,之前一直没有在简书上面写过文章,感觉慌慌哒.好了,下面开始记录下我的过程. 先放上最终的效果图: 我去,这上传的效果也不是太好,各位看官请见谅,不过基本的功能还是有了的,不妨碍后面的阅读. 下面我将一步步介绍如何实现这个功能的. 首先我使用的是容联云平台的短信验证,做这个之前需要先注册一个开发者账号,然后下载里面的一个demo,可以它的看看介

  • Android获取和读取短信验证码的实现方法

    现如今,验证码在Android的客户端还是非常普遍的.通过手机账号和验证码直接去注册应用账户的信息.很多应用都以这种方式来完成注册.简单的介绍一下吧. Android获取短信验证码还是比较简单的,通过Mob官网提供的ShareSDK,调用其中内部的方法,就可以获取到短信的验证码了.提供一下Mob的官网地址.http://www.mob.com/#/在官网上注册相关的信息之后,下载相关的jar包和.so文件就可以实现获取短信验证码了(2.0之前的版本都需要下载jar包和 .so文件,而现在的2.2

  • Android​短信验证码倒计时验证的2种常用方式

    前言 ​本文主要介绍的是短信验证码功能,这里总结了两种常用的方式,可以直接拿来使用. 看图 计时器 说明:这里的及时从10开始,是为了演示的时间不要等太长而修改的. 方法如下 1.第一种方式:Timer /** * Description:自定义Timer * <p> * Created by Mjj on 2016/12/4. */ public class TimeCount extends CountDownTimer { private Button button; //参数依次为总时

  • Android实现自动提取短信验证码功能

    本文实例讲解了Android自动提取短信验证码解决方案,分享给大家供大家参考,具体内容如下 主要功能及优点 1.收到验证码短信后,自动提取短信中的验证码填写到相应输入框 2.可指定一个号码,只读取与他有关短信,避免提取来源错误 3.利用正则表达式,可匹配各种类型验证码 模块集成关键步骤     将auto_getcode_demo中src包里的SMSContentObserver类复制到你的项目src包中 在SMSContentObserver中:    修改正则表达式内容来匹配自己想要获取的字

  • Android获取短信验证码的实现方法

    先给大家展示下效果图,如果感觉不错,请参考实现思路详解 Android开发中关于短息验证码的设计层出不穷,越来越多的应用为了更好的提高软件的安全性,开始使用通过服务器向用户发送验证码的方式,来保护用户个人信息的安全性.无论是用户注册时的信息验证还是当用户发出找回密码请求时的短信验证,他们的工作原理大致上是一致的,因为项目的需要研究了一下关于这方面的知识,本篇我将带领大家一起实现这一当下流行的设计方案. 众所周知,短信验证需要服务器端生成一个验证码,然后发送到用户输入的手机上,这个过程需要服务器主

  • Android用 Mob 实现发送短信验证码实例

    和室友参加的互联网大赛要做一个 APP,涉及到用户的登录注册,于是上网找了许多资料,其中有阿里大于,网易云等等,阿里大于的客服给我说他们不支持 Android,网易云还要拍手持身份证的照片,而且这两个都收费,还麻烦,于是找了一个既简单有免费的,叫做 Mob,官网如下 Mob 官网 官方文档看了很多,还是觉得写的不好,于是自己写一篇. 注册账号 在 Mob 官网右上角点击注册,依次填入信息,其中公司一栏可以随便填 添加应用 登录后,点击 SecurityCodeSDK - 立即使用,Mob 会提示

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

    现在的应用在注册登录或者修改密码中都用到了短信验证码,那在android中是如何实现获取短信验证码并自动填写的呢? 首先,需要要在manifest中注册接收和读取短信的权限: <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> <uses-permission android:name="android.permission.READ_

  • Android实现获取短信验证码并自动填写功能

    本文实例为大家分享了Android短信验证码获取并自动填写功能的具体代码,供大家参考,具体内容如下 代码如下: MainActivity public class MainActivity extends AppCompatActivity { public static TextView mText; private SmsContent content; @Override protected void onCreate(Bundle savedInstanceState) { super.

  • Flutter之Timer实现短信验证码获取60s倒计时功能的代码

    先看下效果: 两种需求场景: 1.广告页3s后跳转到首页 2.短信验证码60s倒计时 第一种的话,根据需求我们可以知道,我们想要的效果就是3s结束做出一个动作. factory Timer(Duration duration, void callback()) { if (Zone.current == Zone.root) { // No need to bind the callback. We know that the root's timer will // be invoked in

  • Android实现短信验证码自动填写

    android应用经常会涉及到注册登录功能,而许多的注册登录或修改密码功能常常需要输入短信验证码,通常,用户收到短信需要最小化应用去查看短信再填入验证码,必然比较麻烦,因此有必要能够自动获得下发的短信验证码,方便了用户的操作,用户体验更好. 原理讲解: 主要就是实时获取短信信息.涉及到ContentObserver类的使用.使用ContentProvider来监听短信数据库的变化,在自定义的ContentObserver当中实现onChange的方法进行监听特定手机号的短信,然后进行信息截取在填

  • Android实现短信验证码输入框

    本文实例为大家分享了Android实现短信验证码输入框的具体代码,供大家参考,具体内容如下 其实用官方自定的那个inputEditText默认带下划线的,然后自己再实行焦点和输入框弹出等操作也可以. 写这个自定义View主要是为了练习. /** * 实现了粘贴事件监听回调的 EditText */ open class ListenPasteEditTextTest : AppCompatEditText { constructor(context: Context): super(contex

  • Android自定义短信验证码组件

    Android自定义短信验证码组件,供大家参考,具体内容如下 效果图 1.布局实现 因为要禁用光标,所以我用TextView代替了EditText,每一行显示的验证码个数由用户决定,所以我这里用线性布局的权重,对TextView进行控制宽度等分,然后设置选中和未选中当前TextView的底部边框,设置高亮颜色背景 2.接受用户输入 我这里使用了TextView,但是怎么接受用户输入的值呢.这里我直接继承了RelativeLayout,然后添加了一个透明的EditText,覆盖在这几个TextVi

  • 基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)

    相关阅读: 基于jQuery实现发送短信验证码后的倒计时功能(无视页面关闭) 下面一段代码是小编给大家带来的js发送短信验证码后实现倒计时功能,代码简单易懂. 具体代码如下所示: <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="Generator" content="EditPlus

  • 基于jQuery实现发送短信验证码后的倒计时功能(无视页面关闭)

    相关阅读: 基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能) 今天测试提了一个bug,发送短信倒计时功能,要求关闭页面也要进行倒计时.这想到了,当年我参与的周杰伦演唱会的先付先抢功能.与之类似,只不过,那个项目的时间都是服务器时间,本人目前有点偷懒,就用客户端的时间了. 一下是完整的代码,只不过在客户端的效率不是很好. <!doctype html> <html lang="en"> <head> <meta

  • java短信验证码获取次数限制实例

    现在不管什么项目,用到短信验证功能,都会在程序上设计一个短信验证码的获取次数限制,这样主要是避免短信验证码接口被刷. 前一段正好做一个项目的用户短信验证码登录功能,就研究了以下,下面贴出来分享一下. 这里涉及到的短信接口,用的第三方短信接口-动力思维思维乐信的(http://www.lx598.com/),如果想了解短信接口接入,可以到他们官网,查看下短信接口API文档说明,参考下面的代码应该就能弄明白. 用户注册部分,主要代码如下: //主要js方法: //获取手机验证码: function

随机推荐