If anyone else was like me and trying to find out how to do this in Kotlin, here's some code that might help in your quest:
Just a few things to note:
- You can test the try/catch by simply toggling Airplane Mode in the emulator.
- You can test a failed SMS in the emulator by composing a text that exceeds the normal SMS character limit.
- Because this is all in a try/catch block, please be aware that any exceptions that might arise due to API changes won't be highlighted in red in the Logcat window.
- Further note that Google Play has tightened requirements on apps that send SMS recently, so please be aware that if anyone intends to try to upload something like this to Google Play, they may be required to provide a lot of extra justification.
Here's the code (as heavily adapted from the US Naval Academy's site):
package com.example.texter
import android.app.Activity
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.telephony.SmsManager
import android.widget.Toast
class ClassTexter {
fun mmSendText(mvText: String, mvNumber: String, mvApplicationContext: Context): Boolean {
//Note: Because The Following Section is wrapped in a try/catch:
//Exceptions might be trickier to spot in the Logcat since they aren't highlighted red.
try {
val mvSmsManager: SmsManager =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
mvApplicationContext.getSystemService(SmsManager::class.java)
} else {
SmsManager.getDefault()
}
val mvSentIntent = PendingIntent.getBroadcast(
mvApplicationContext,
0,
Intent("SMS SENT"),
PendingIntent.FLAG_IMMUTABLE
)
val mvDelvieredIntent = PendingIntent.getBroadcast(
mvApplicationContext,
0,
Intent("SMS DELIVERED"),
PendingIntent.FLAG_IMMUTABLE
)
val mvConfirmSentBroadcastReceiver: BroadcastReceiver =
object : BroadcastReceiver() {
override fun onReceive(mvContext: Context, mvIntent: Intent) {
if (resultCode == Activity.RESULT_OK) {
Toast.makeText(
mvApplicationContext, "Text Dispatched!",
Toast.LENGTH_SHORT
).show()
mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
}
else
{
Toast.makeText(
mvApplicationContext, "Dispatch Failed!", //<-- This Part Can Be Tested By Exceeding SMS Character Limit
Toast.LENGTH_SHORT
).show()
mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
}
}
}
val mvConfirmDeliveryBroadcastReceiver: BroadcastReceiver =
object : BroadcastReceiver() {
override fun onReceive(mvContext: Context, mvIntent: Intent) {
if (resultCode == Activity.RESULT_OK) {
Toast.makeText(
mvApplicationContext, "Text Delivered!",
Toast.LENGTH_SHORT
).show()
mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
}
else
{
Toast.makeText(
mvApplicationContext, "Delivery Failed!",
Toast.LENGTH_SHORT
).show()
mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
}
}
}
val mvSentIntentFilter = IntentFilter("SMS SENT")
val mvDeliveredIntentFilter = IntentFilter("SMS DELIVERED")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
mvApplicationContext.registerReceiver(
mvConfirmSentBroadcastReceiver,
mvSentIntentFilter,
Context.RECEIVER_EXPORTED
)
mvApplicationContext.registerReceiver(
mvConfirmDeliveryBroadcastReceiver,
mvDeliveredIntentFilter,
Context.RECEIVER_EXPORTED
)
} else {
mvApplicationContext.registerReceiver(
mvConfirmSentBroadcastReceiver,
mvSentIntentFilter
)
mvApplicationContext.registerReceiver(
mvConfirmDeliveryBroadcastReceiver,
mvDeliveredIntentFilter
)
}
mvSmsManager.sendTextMessage(
mvNumber.filter { it.isDigit() },
null,
mvText,
mvSentIntent,
mvDelvieredIntent
)
//Confirm With Toast
Toast.makeText(
mvApplicationContext, "Please stand by!",
Toast.LENGTH_SHORT
).show()
return true
} catch (mvEx: Exception) {
Toast.makeText(
mvApplicationContext, "Please try again!", //<-- This Part Can Be Tested With "Airplane Mode"
Toast.LENGTH_LONG
).show()
mvEx.printStackTrace()
return false
}
}
}