Sms BroadCastReceiver утечки памяти - PullRequest
       45

Sms BroadCastReceiver утечки памяти

0 голосов
/ 11 октября 2018

У меня есть экран регистрации с помощью мобильного телефона, когда пользователь регистрируется с использованием номера мобильного телефона, отправляется otp, и я слушаю этот otp, чтобы пользователю не приходилось вручную кормить otp, но при прослушивании этого otp я получаюутечка памяти.

Вот мой код для прослушивания смс

class SmsReceiver : BroadcastReceiver() {

    private var bundle: Bundle? = null
    private lateinit var currentSMS: SmsMessage
    private var otp: String? = null

    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action.equals("android.provider.Telephony.SMS_RECEIVED")) {
            bundle = intent?.extras
            if (bundle != null) {
                val pduObjects = bundle?.get("pdus") as Array<*>
                for (i in pduObjects) {
                    currentSMS = i?.let { getIncomingMessage(it, bundle!!) }!!
                    val sender = currentSMS.displayOriginatingAddress
                    if (sender.endsWith("VK-DICEAP") || sender.endsWith("VM-DICEAP") || sender.endsWith("ID-DICEAP")) {
                        val msgBody = currentSMS.messageBody
                        otp = msgBody.replace(("[a-zA-Z.]").toRegex(), "").trim()
                        mListener.messageReceived(otp ?: "")
                    }
                }
            }
        }
    }



    companion object {
        private lateinit var mListener: SmsListener
        fun bindListener(listener: SmsListener) {
            mListener = listener
        }
    }

    private fun getIncomingMessage(aObject: Any, bundle: Bundle): SmsMessage {
        val currentSMS: SmsMessage
        currentSMS = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val format = bundle.getString("format")
            SmsMessage.createFromPdu(aObject as ByteArray?, format)
        } else {
            SmsMessage.createFromPdu(aObject as ByteArray?)
        }
        return currentSMS
    }

}

Теперь в своей деятельности я использую следующий код

при создании проверяю ли я пользователяпредоставил разрешение или нет

private fun checkSmsPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(arrayOf(Manifest.permission.RECEIVE_SMS), RECEIVE_SMS)
            } else {
                receiveSms()
            }
        } else {
            receiveSms()
        }
    }

Если да, тогда я просто отправляю OTP на мой сервер

 private fun receiveSms() {
        SmsReceiver.bindListener(object : SmsListener {
            override fun messageReceived(messageText: String) {
               //send otp to server 
            }
        })
    }

Я создал отдельный интерфейс только для обратного вызова

interface SmsListener {
    fun messageReceived(messageText: String)
}

Теперь я искал это в stackoverflow и увидел, что вместо регистрации получателя в файле манифеста вы должны зарегистрироваться и отменить регистрацию по коду. Поэтому я попытался использовать код следующим образом

 override fun onStart() {
        super.onStart()
        smsReceiver = SmsReceiver()
        val filter = IntentFilter()
        filter.addAction("android.provider.Telephony.SMS_RECEIVED")
        registerReceiver(smsReceiver, filter)
        checkSmsPermission()
    }

    override fun onStop() {
        super.onStop()
        unregisterReceiver(smsReceiver)
    }

, но все равно получаюутечка памяти в моем приложении.Я использую LeakCanary для обнаружения утечек в моем приложении.

Вот скриншот утечки

enter image description here

1 Ответ

0 голосов
/ 11 октября 2018

Вот просочившееся mListener поле в объекте-компаньоне (поэтому оно статично).Это обычная ситуация утечки статики, поэтому лучше не использовать их вообще.Если вы можете, вы должны изменить архитектуру своих приложений.

Но вы можете просто создать другой статический метод, чтобы очистить значение mListener и вызвать его после остановки активности.Это быстрее и проще.

...