android - Sms BroadCastReceiver 泄漏内存

标签 android memory-leaks kotlin broadcastreceiver leakcanary

我有一个使用手机的注册屏幕,当用户使用手机号码注册时,会发送一个 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
    }

}

现在在我的 Activity 中我使用如下代码

在创建时检查用户是否授予了权限

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)

interface SmsListener {
    fun messageReceived(messageText: String)
}

现在我在 stackoverflow 上搜索了这个,我看到不是在 Manifest 文件中注册接收器,而是应该通过代码注册和注销 所以我尝试使用如下代码

 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

最佳答案

这里是伴随对象中泄漏的 mListener 字段(因此它是静态的)。这是泄漏静电的常见情况,所以最好不要使用它们。如果可以,您应该更改您的应用架构。

但是您可以创建另一个静态方法来清除 mListener 值并在 Activity 停止后调用它。它更快、更容易。

关于android - Sms BroadCastReceiver 泄漏内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52752780/

相关文章:

c# - xamarin 广播接收器访问 View 模型

java - 显示收到的推送通知

android - "PowerManger.FULL_WAKE_LOCK is deprecated"是什么意思?

javascript - NodeJS 警告 : possible event emitter leak. 11 添加了开放监听器

kotlin - 如何确定某些 Kotlin 标准库类型是否可序列化?

android - 无法使用Kotlin以编程方式检索资源

java - 来自 BroadcastReceiver 的 SmsManager.sendTextMessage 在 CDMA 手机上不执行任何操作

c++ - openCV 将 IplImage 与 cv::Mat 混合

ios5 - 如何在iphone sdk中的XCODE中检查崩溃日志

android - MobileAds.initialize(this) 崩溃致命信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR)