自动获取短信中的验证码

本文介绍了如何通过分析短信内容并利用正则表达式来提取验证码。通常验证码是6位数字,前后可能伴随中文字符或其他信息。利用零宽断言定位验证码,正则表达式为(?<!\d)\d{6}(?!\d),在Java中需要注意转义字符。

获取短信内容中的验证码:

1)分析短息内容:

一般包含验证码的短信可能为“您的短信验证码为123456.”

格式为“中文字符” + "数字验证码" + “其他字符”。

2)使用正则表达式表述验证码:

\d匹配0-9的数字,\d{6}表示匹配6位0-9的数字——这是验证码本体

使用零宽断言查找验证码的位置,(?<!\d)表示匹配前面不是0-9数字的位置,(?!\d)表示匹配后面不是0-9数字的位置

所以完整的正则表达时应该为(?<!\d)\d{6}(?!\d)

注意:Java中由于转义的问题,所以反斜杠需要再加一个反斜杠,\\表示\,所以程序中的表达式实际为(?<!\\d)\\d{6}(?!\\d)


剩下的都是代码了:

首先当然是layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <EditText
            android:id="@+id/phone_num_edit_text"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:inputType="phone"
            android:hint="请输入您的手机号码"/>
        <Button
            android:id="@+id/send_ver_code_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击发送验证码"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <EditText
            android:id="@+id/ver_code_edit_text"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:hint="请输入收到的验证码"/>
        <Button
            android:id="@+id/confirm_button"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="点击确认验证码"/>
    </LinearLayout>

</LinearLayout>


然后就是activity代码,其实完全可以简化成broadcast:


public class MainActivity extends AppCompatActivity {

    private EditText phoneNumEditText,verificationCodeEditText;
    //两个按键用于网络交互
    private Button sendButton,confirmButton;
    private Handler handler;
    private String verCode;
    private BroadcastReceiver broadcastReceiver;

    //匹配验证码
    private String patternCode(String patternContent){
        if(TextUtils.isEmpty(patternContent)){
            return null;
        }
        //将正则表达式赋予生成的Pattern类
        Pattern pattern = Pattern.compile("(?<!\\d)\\d{6}(?!\\d)");
        //将要匹配的内容赋予生成的Matcher类
        Matcher matcher = pattern.matcher(patternContent);
        //尝试在目标字符串里查找下一个匹配字符串
        if(matcher.find()){
            //返回当前查找而获得的与组匹配的所有字符串内容
            return matcher.group();
        }
        return null;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        phoneNumEditText = (EditText) findViewById(R.id.phone_num_edit_text);
        verificationCodeEditText = (EditText) findViewById(R.id.ver_code_edit_text);
        sendButton = (Button) findViewById(R.id.send_ver_code_button);
        confirmButton =(Button) findViewById(R.id.confirm_button);
        //获取本机号码目前没有比较方便的方法,较简单的是读取sim卡,较成功的是发短信给服务商来读取发送号码
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        phoneNumEditText.setText(telephonyManager.getLine1Number());
        //刷新UI要用到handler传送消息
        handler = new Handler() {
            public void handleMessage(Message message){
                verificationCodeEditText.setText(verCode);
            }
        };
        //创建一个意图过滤器,接收收到短信时的广播
        IntentFilter intentFilter = new IntentFilter();
        //只有用于过滤广播的IntentFilter可以在代码中创建,其他的IntentFilter必须在manifest文件中声明
        intentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
        //设置优先级,由于参数必须为整数,所以简单的设置为Integer.MAX_VALUE——最大整数
        //事实上,这里可以衍生开去,进行短信的拦截等操作,和之前的电话录音配合,基本上能完成一部手机的基本监听需求
        intentFilter.setPriority(Integer.MAX_VALUE);
        //定制广播接收器
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                //生成一个数组将短信内容赋值进去
                //intent.getExtras()方法就是从过滤后的意图中获取携带的数据,这里携带的是以"pdus"为key、短信内容为value的键值对
                //Android设备接收到的SMS是以pdu形式的(protocol description unit)
                Object[] pdus = (Object[]) intent.getExtras().get("pdus") ;
                /*这里for循环也可以用
                for(int i = 0; i < pdus.length; i++){
                    byte[] pdu[i] = (byte[]) pdus[i];
                    do something
                }
                */
                //遍历pdus数组,将每一次访问得到的数据放入object中
                for(Object object : pdus){
                    byte[] pdu = (byte[]) object;
                    /*
                    6.0系统开始不建议使用createFromPdu(byte[])方法,只能使用createFromPdu(byte[],String format)方法
                    String format = intent.getExtras().getString("format");
                    SmsMessage smsMessage = SmsMessage.createFromPdu(pdu,format);
                    */
                    //获取短信
                    SmsMessage smsMessage = SmsMessage.createFromPdu(pdu);
                    //获取短信体,即内容
                    String messageBody = smsMessage.getMessageBody();
                    //获取短信发送方地址
                    String originationAddress = smsMessage.getOriginatingAddress();
                    //如果短信发送地址不为空,这里也可以使用equals限定短信发送方
                    if(!TextUtils.isEmpty(originationAddress)){
                        //解析短信体
                        String code = patternCode(messageBody);
                        if(!TextUtils.isEmpty(code)){
                            verCode = code;
                            //sendEmptyMessage(int what)方法是发送指定的消息,该方法为仅仅只是传递一个int值来表示发送的消息类型
                            handler.sendEmptyMessage(1);
                        }
                    }
                }
            }
        };
        //注册广播接收器
        registerReceiver(broadcastReceiver,intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //动态注册就不能忘记取消注册
        unregisterReceiver(broadcastReceiver);
    }
}


最后不能忘了在manifest文件中声明获取权限

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

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值