I was developing an app which send some receipt to a mobile phone, and I try to use using two Broadcast Receivers, like this:
enter persistSentMessageIfRequired(), mAppInfo.packageName = [******], mPersistMessage = [true] (Ask Gemini)
java.lang.Throwable at com.android.internal.telephony.SMSDispatcher$SmsTracker.persistSentMessageIfRequired(SMSDispatcher.java:1565) at com.android.internal.telephony.SMSDispatcher$SmsTracker.persistOrUpdateMessage(SMSDispatcher.java:1634)
at com.android.internal.telephony.SMSDispatcher$SmsTracker.onFailed(SMSDispatcher.java:1655)
at com.android.internal.telephony.SMSDispatcher.sendRawPdu(SMSDispatcher.java:1055)
at com.android.internal.telephony.gsm.GsmSMSDispatcher.sendText(GsmSMSDispatcher.java:424)
at com.android.internal.telephony.ImsSMSDispatcher.sendText(ImsSMSDispatcher.java:208)
at com.android.internal.telephony.IccSmsInterfaceManager.sendTextInternal(IccSmsInterfaceManager.java:466)
at com.android.internal.telephony.IccSmsInterfaceManager.sendText(IccSmsInterfaceManager.java:407)
at com.android.internal.telephony.UiccSmsController.sendTextForSubscriber(UiccSmsController.java:140)
at com.android.internal.telephony.ISms$Stub.onTransact(ISms.java:201)
at android.os.Binder.execTransact(Binder.java:723)
Here is my method sendSMS()
:
val TAG = "TRACK_SMS_STATUS"
fun sendSMS(activity: Activity, phoneNumber: String, message: String) {
val send = "SMS_SENT"
val delivered = "SMS_DELIVERED"
// Create intents
val sentIntent = Intent(send)
val deliveredIntent = Intent(delivered)
// PendingIntents for sent and delivered
val sentPI = PendingIntent.getBroadcast(activity, 0, sentIntent, 0)
val deliveredPI = PendingIntent.getBroadcast(activity, 0, deliveredIntent, 0)
// Create BroadcastReceiver for sent messages
val sentReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (resultCode) {
AppCompatActivity.RESULT_OK -> {
Log.d(TAG, "SMS sent")
toast("SMS sent")
}
SmsManager.RESULT_ERROR_GENERIC_FAILURE -> {
Log.d(TAG, "Generic failure")
toast("Generic failure")
}
SmsManager.RESULT_ERROR_NO_SERVICE -> {
Log.d(TAG, "No service")
toast("No service")
}
SmsManager.RESULT_ERROR_NULL_PDU -> {
Log.d(TAG, "Null PDU")
toast("Null PDU")
}
SmsManager.RESULT_ERROR_RADIO_OFF -> {
Log.d(TAG, "Radio off")
toast("Radio off")
}
}
}
}
// Create BroadcastReceiver for delivered messages
val deliveredReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (resultCode) {
AppCompatActivity.RESULT_OK -> {
Log.d(TAG, "SMS delivered")
toast("SMS delivered")
}
AppCompatActivity.RESULT_CANCELED -> {
Log.d(TAG, "SMS not delivered")
toast("SMS not delivered")
}
}
}
}
// Register the broadcast receivers
// The constant asked to be added doesn't exist under api levels below 33
activity.registerReceiver(sentReceiver, IntentFilter(send))
activity.registerReceiver(deliveredReceiver, IntentFilter(delivered))
// Send the SMS
val smsManager = SmsManager.getDefault()
smsManager.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI)
// Unregister the receivers after a delay to ensure they catch the broadcasts
activity.window.decorView.postDelayed({
activity.unregisterReceiver(sentReceiver)
activity.unregisterReceiver(deliveredReceiver)
}, 5000) // Adjust delay as necessary for your context
}
In the lines where I register the receivers I’m getting this warning:
sentReceiver is missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag for unprotected broadcasts registered for SMS_SENT
So to protect the broadcast receivers I create a custom permission in my manifest:
<permission
android:name="******.SEND_SMS"
android:protectionLevel="signature" />
It’s weird due to when I using a custom server the sms is sent without issue, but using the receivers rise this error.