Sms BroadCastReceiver 泄漏内存
Sms BroadCastReceiver Leaks Memory
我有一个使用手机的注册屏幕,当用户使用手机号码注册时,会发送一个 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 SmsListener {
fun messageReceived(messageText: String)
}
现在我在 Whosebug 上搜索了这个,我看到你应该通过代码注册和取消注册,而不是在清单文件中注册接收器
所以我尝试使用如下代码
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 来检测我的应用程序中的泄漏。
这是泄漏的屏幕截图
这是伴随对象中泄露的 mListener
字段(因此它是静态的)。这是泄漏静电的常见情况,所以最好不要使用它们。如果可以,您应该更改您的应用架构。
但是您可以创建另一个静态方法来清除 mListener
值并在 activity 停止后调用它。它更快更容易。
我有一个使用手机的注册屏幕,当用户使用手机号码注册时,会发送一个 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 SmsListener {
fun messageReceived(messageText: String)
}
现在我在 Whosebug 上搜索了这个,我看到你应该通过代码注册和取消注册,而不是在清单文件中注册接收器 所以我尝试使用如下代码
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 来检测我的应用程序中的泄漏。
这是泄漏的屏幕截图
这是伴随对象中泄露的 mListener
字段(因此它是静态的)。这是泄漏静电的常见情况,所以最好不要使用它们。如果可以,您应该更改您的应用架构。
但是您可以创建另一个静态方法来清除 mListener
值并在 activity 停止后调用它。它更快更容易。