I have a registration screen using mobile, when user signs up using mobile number, an otp is send and i listen to that otp so that user don't have to manually feed the otp But when listening to that otp i get an memory leak.
Here is my code for listening to sms
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
}
}
Now in my activity i am using the code as follows
in on create i check whether user has granted the permission or not
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()
}
}
If yes then i just send the otp to my server
private fun receiveSms() {
SmsReceiver.bindListener(object : SmsListener {
override fun messageReceived(messageText: String) {
//send otp to server
}
})
}
I have created a separate interface just for callback
interface SmsListener {
fun messageReceived(messageText: String)
}
Now i searched for this on stackoverflow and i saw that instead of registering the receiver in Manifest file , you should register and unregister by code So i tried using code as follows
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)
}
but i still get leak memory in my app. Iam using LeakCanary for detecting leaks in my app.
Here is a screenshot of the leak