API-интерфейс SMS-ретривера: SMSBroadcastReceiver не распознает полученное сообщение.

1

Я использую SMS Retriever API, я следовал этому руководству Tutorial_Link. Я правильно выполнил все шаги. Просто чит-код, который я использовал: я отправляю и проверяю OTP SMS со стороны клиента, а не с сервера. Я получаю SMS, но мой приемник не может обнаружить SMS. Зачем?

OTP-сообщение:

 String message = "<#> otp code: "+otp+" XkvuQVe6yfP";

Пожалуйста, помогите мне, я застрял здесь в последние три дня... Вот мой код:

Forgot_Password.kt:

 class Forgot_Password : AppCompatActivity(), MySMSBroadcastReceiver.OTPReceiveListener {

    private var otpReceiver: MySMSBroadcastReceiver.OTPReceiveListener = this

    val smsBroadcast = MySMSBroadcastReceiver()


    @RequiresApi(Build.VERSION_CODES.KITKAT)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_forgot__password)

        btn_submit_mobile.setOnClickListener { v ->
                    verify_mobile_number()
            }

    }

    override fun onOTPReceived(otp: String) {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(smsBroadcast)
        ed_otp.setText("Your OTP is: $otp")
    }

    override fun onOTPTimeOut() {
        ed_otp.setText("Timeout")
        Toast.makeText(this, " SMS retriever API Timeout", Toast.LENGTH_SHORT).show()
    }

    private fun startSMSListener() {

        SmsRetriever.getClient(this).startSmsRetriever()
                .addOnSuccessListener {
                    ed_otp.setText("Waiting for OTP")
                    Toast.makeText(this, "SMS Retriever starts", Toast.LENGTH_LONG).show()
                }.addOnFailureListener {
                    ed_otp.setText("Cannot Start SMS Retriever")
                    Toast.makeText(this, "Error", Toast.LENGTH_LONG).show()
                }

        smsBroadcast.initOTPListener(this)
        val intentFilter = IntentFilter()
        intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION)

        applicationContext.registerReceiver(smsBroadcast, intentFilter)
    }

    public override fun onResume() {
        LocalBroadcastManager.getInstance(this).registerReceiver(receiver, IntentFilter("otp"))
        super.onResume()
    }

    public override fun onPause() {
        super.onPause()
        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
    }

    private fun verify_mobile_number() {

        mobile_num = ed_mobile_num.text.toString()

        //if it passes all the validations

        class Verify_mobile : AsyncTask<Void, Void, String>() {

            private val progressBar: ProgressBar? = null

            override fun doInBackground(vararg voids: Void): String {
                //creating request handler object
                val requestHandler = RequestHandler()

                val params = HashMap<String, String>()
                params["U_Mobile_Number"] = mobile_num + ""

                //returing the response
                return requestHandler.sendPostRequest(URLs.URL_VERIFY_MOBILE_NUMBER, params)
            }

            @TargetApi(Build.VERSION_CODES.KITKAT)
            @RequiresApi(Build.VERSION_CODES.KITKAT)
            override fun onPostExecute(s: String?) {
                super.onPostExecute(s)  
                try {

                    Log.i("result", "123" + s!!)

                    if (s == "") {
                        val snackbar = Snackbar
                                .make(top_layout, "Problem connecting server,try again!", Snackbar.LENGTH_LONG)
                        snackbar.show()
                    } else {
                        val obj = JSONObject(s)

                        if (!obj.getBoolean("error")) {
                            startSMSListener()

                            var signs  = AppSignatureHelper(applicationContext).appSignatures

                            Log.i("hash___", (AppSignatureHelper(applicationContext).appSignatures+"").toString())

                            for (item in signs) {
                                Log.i("hash",item)

                                val sm = sendSMS()
                                sm.sendSms(mobile_num,item+"")
                            }


                        } else {
                            val snackbar = Snackbar
                                    .make(top_layout, "Some error occurred!" + obj.getString("message"), Snackbar.LENGTH_LONG)
                            snackbar.show()
                        }
                    }

                } catch (e: Exception) {
                    e.printStackTrace()

                    val snackbar = Snackbar
                            .make(top_layout, "Problem connecting server,try again!", Snackbar.LENGTH_LONG)
                    snackbar.show()
                }

            }
        }

        //executing the async task
        val ru = Verify_mobile()
        ru.execute()
    }
}

MySMSBroadcastReceiver.kt:

class MySMSBroadcastReceiver : BroadcastReceiver() {

    private var otpReceiver: OTPReceiveListener? = null

    fun initOTPListener(receiver: OTPReceiveListener) {
        this.otpReceiver = receiver
    }

    override fun onReceive(context: Context, intent: Intent) {

        if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {

            val extras = intent.extras
            val status = extras!!.get(SmsRetriever.EXTRA_STATUS) as Status

            when (status.statusCode) {
                CommonStatusCodes.SUCCESS -> {

                    // Get SMS message contents
                    var otp: String = extras.get(SmsRetriever.EXTRA_SMS_MESSAGE) as String

                    val pattern = Pattern.compile("(\\d{4})")
                    val matcher = pattern.matcher(otp)

                    // Extract one-time code from the message and complete verification
                    var value = ""
                    if (matcher.find()) {
                        System.out.println(matcher.group(1))
                        value = matcher.group(1)
                    }

                    println("message : $value")
                    otpReceiver?.onOTPReceived(value)
                }

                CommonStatusCodes.TIMEOUT ->
                    // Waiting for SMS timed out (5 minutes)
                    otpReceiver?.onOTPTimeOut()
            }
        }
    }

    interface OTPReceiveListener {

        fun onOTPReceived(otp: String)

        fun onOTPTimeOut()
    }
}

AppSignatureHelper.java:

public class AppSignatureHelper extends ContextWrapper {

    public static final String TAG = AppSignatureHelper.class.getSimpleName();

    private static final String HASH_TYPE = "SHA-256";
    public static final int NUM_HASHED_BYTES = 9;
    public static final int NUM_BASE64_CHAR = 11;

    public AppSignatureHelper(Context context) {
        super(context);
    }

    /**
     * Get all the app signatures for the current package
     *
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public ArrayList<String> getAppSignatures() {
        ArrayList<String> appCodes = new ArrayList<>();

        try {
            // Get all package signatures for the current package
            String packageName = getPackageName();
            PackageManager packageManager = getPackageManager();
            Signature[] signatures = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures;

            // For each signature create a compatible hash
            for (Signature signature : signatures) {
                String hash = hash(packageName, signature.toCharsString());
                if (hash != null) appCodes.add(String.format("%s", hash));

            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Unable to find package to obtain hash.", e);
        }
        return appCodes;
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private static String hash(String packageName, String signature) {
        String appInfo = packageName + " " + signature;
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(HASH_TYPE);
            messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));
            byte[] hashSignature = messageDigest.digest();

            // truncated into NUM_HASHED_BYTES
            hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);

            // encode into Base64
            String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);
            base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);

            Log.e(TAG, String.format("pkg: %s -- hash: %s", packageName, base64Hash));
            return base64Hash;

        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG, "hash:NoSuchAlgorithm", e);
        }
        return null;
    }
}

Androidmanifest.xml:

  <receiver android:name="threedpower.com.babynamesapp.SMS_Retrival_API.SMS_Broadcast" android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
            </intent-filter>
        </receiver>
Теги:
kotlin
one-time-password

1 ответ

0

Попробуйте добавить экспортированное поле в широковещательный приемник в манифест

  <receiver
    android:name="threedpower.com.babynamesapp.SMS_Retrival_API.SMS_Broadcast"
    android:exported="true">
      <intent-filter>
       <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
      </intent-filter>
  </receiver>

Более того, я думаю, что в вашем коде вместо matcher.group(1) это должно быть matcher.group(0).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню