Matcher赢得了与Android中的模式匹配

时间:2016-08-26 18:22:22

标签: java android regex pattern-matching

我正在尝试开发一个自动从来电短信中读取一次性密码的应用。我有一个名为SMS的类,其中我存储了当前读取的消息,还有一个名为SMSRule的类,其中包含有关可能的OTP发送者的信息。

SMSRule还包含一个Pattern变量,该变量应与消息匹配,以查看它是否确实是OTP的正确发送方。

除了从消息中提取OTP之外,一切都很顺利。我的短信包含该消息,但当我尝试将Pattern与消息匹配时,我的match.find()返回false。

以下是我的档案:

OTPAutoRead.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import auro.widget.OTP.SMS.SMS;
import auro.widget.OTP.SMS.SMSRule;

/**
 * Created on 26/8/16.
 * @author Auro
 * @since 1.0
 */

public class OTPAutoRead extends BroadcastReceiver {

    private static final String LOG_TAG = OTPAutoRead.class.getCanonicalName();

    private static final String mReadPermission = "android.permission.READ_SMS";
    private static final String mReceivePermission = "android.permission.RECEIVE_SMS";

    private List<SMSRule> smsRules;
    private Context context;
    private String OTP;

    public OTPAutoRead() {throw new InstantiationError("Empty Constructor");}

    public OTPAutoRead(@NonNull Context context, final List<SMSRule> smsRules) {

        if (smsRules == null || smsRules.size() == 0) {

            throw new AuroMissingRulesException("No SMS Rules Found");
        }

        this.smsRules = smsRules;
        this.context = context;
        CheckSMSReadPermission();

        IntentFilter itf = new IntentFilter();
        itf.addAction("android.provider.Telephony.SMS_RECEIVED");
        itf.setPriority(999);
        context.registerReceiver(this,itf);

    }


    private void CheckSMSReadPermission() {

        PackageManager packageManager = context.getPackageManager();
        String packageName = context.getPackageName();

        int readPermission = packageManager.checkPermission(mReadPermission,packageName);
        int receivePermission = packageManager.checkPermission(mReceivePermission, packageName);

        boolean canRead = (readPermission == PackageManager.PERMISSION_GRANTED);

        if (!canRead)
            Toast.makeText(context,"Please enable SMS read permission for auto OTP read", Toast.LENGTH_SHORT).show();
    }


    @Override
    public void onReceive(Context context, Intent intent) {

        try {
            if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED"))
                tryReceiveMessage(intent);
        }   catch (Exception e) {
            Log.i(LOG_TAG, "Failed to read SMS", e);
        }
    }


    private void tryReceiveMessage(Intent intent) {

        Bundle bundle = intent.getExtras();

        SmsMessage[] messages = null;

        if (bundle != null) {

            Object[] pdus = (Object[]) bundle.get("pdus");

            if (pdus != null) {
                messages = new SmsMessage[pdus.length];

                for (int i = 0; i < messages.length; i++) {

                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                    String messageFrom = messages[i].getOriginatingAddress().toUpperCase();
                    String messageBody = messages[i].getMessageBody().toUpperCase();

                    Log.d(LOG_TAG, "Message is from: " + messageFrom + " and its content is: " + messageBody);

                    SMS sms = new SMS();
                    sms.setMessage(messageBody).setAddress(messageFrom);

                    processOTP(sms);
                }
            }
        }
    }


    private void processOTP(SMS sms) {

        int i;

        for (i = 0; i < smsRules.size(); i ++) {

            if (sms.getAddress().toUpperCase().contains(smsRules.get(i).getSender().toUpperCase())) {

                Pattern pattern = smsRules.get(i).getOTPPattern();

                System.out.println(pattern.pattern());
                System.out.println(sms.getMessage());

                Matcher matcher = pattern.matcher(sms.getMessage().toUpperCase());

                if (matcher.find()) {

                    OTP = matcher.group(1);
                    Log.i(LOG_TAG,"Extracted OTP is: " + OTP);
                    Toast.makeText(context,"OTP RECEIVED IS: " + OTP,Toast.LENGTH_SHORT).show();
                    return;
                } else
                    Log.d(LOG_TAG,"Failed to extract OTP");
            }
        }
    }

    public String getOTP() {
        return OTP;
    }

}

SMS.java

import android.support.annotation.NonNull;

/**
 * Created on 26/8/16.
 * @author Auro
 * @since 1.0
 */
public class SMS {

    private String mID;
    private String mAddress;
    private String mMessage;
    private boolean isRead = false;
    private String mTime;

    public String getID() {

        return mID;
    }

    public SMS setID(@NonNull final String ID) {

        mID = ID;
        return this;
    }

    public String getAddress() {

        return mAddress;
    }

    public SMS setAddress(@NonNull final String Address) {

        mAddress = Address;
        return this;
    }

    public String getMessage() {
        return mMessage;
    }

    public SMS setMessage(@NonNull final String Message) {

        mMessage = Message;
        return this;
    }

    public boolean isRead() {

        return isRead;
    }

    public SMS setReadState(boolean ReadState) {

        isRead = ReadState;
        return this;
    }

    public String getTime() {

        return mTime;
    }

    public SMS setTime(@NonNull String Time) {

        mTime = Time;
        return this;
    }
}

SMSRule.java

import java.util.regex.Pattern;

/**
 * Created on 26/8/16.
 * @author Auro
 * @since 1.0
 */
public class SMSRule {

    private String mSender;
    private String mGroupID;
    private Pattern mOTPPattern;


    private SMS sms;

    public String getSender() {

        return mSender;
    }

    public SMSRule setSender(final String sender) {

        mSender = sender;
        return this;
    }

    public String getGroupID() {

        return mGroupID;
    }

    public SMSRule setGroupID(final String groupID) {

        mGroupID = groupID;
        return this;

    }


    public Pattern getOTPPattern() {

        return mOTPPattern;
    }

    public SMSRule setOTPPattern(final Pattern otpPattern) {

        mOTPPattern = otpPattern;
        return this;
    }

}

MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.EditText;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import auro.widget.OTP.OTPAutoRead;
import auro.juspay.widget.OTP.SMS.SMSRule;


public class MainActivity extends AppCompatActivity {


    private EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = (EditText) findViewById(R.id.editText);

        SMSRule rule = new SMSRule();
        Pattern pattern = Pattern.compile("One Time Password is (\\d{6})".toUpperCase());

        rule.setSender("BANK-XYZ");
        rule.setOTPPattern(pattern);

        List<SMSRule> smsRules = new ArrayList<>();
        smsRules.add(rule);

        OTPAutoRead otpAutoRead = new OTPAutoRead(this,smsRules);

        String OTP = otpAutoRead.getOTP();

        if (OTP != null)
        {
            editText.setText(OTP);
        }
    }

}

问题,当我在Debug模式下运行时,我得到matchFound = false。我也尝试将regex更改为

Pattern pattern = Pattern.compile("One Time Password is \d{6}".toUpperCase());

它不会起作用

以下是截图: -

enter image description here

1 个答案:

答案 0 :(得分:1)

Pattern.compile("One Time Password is (\\d{6})".toUpperCase())中将模式字符串转换为大写时,\d(匹配一个数字)变为\D(匹配非数字)。

使用[0-9]代替\d,以便模式表示相同,或者只删除toUpperCase()并编写确切模式,或使用模式区分大小写标记。