In modern Android development, Jetpack Compose has become the preferred toolkit for building UI. Although Compose focuses primarily on UI elements, we can still integrate system-level functionalities, like listening for incoming SMS events, into Compose-based applications. In this tutorial, we’ll walk through how to listen for SMS received events using Jetpack Compose, and also demonstrate how to create a unit test to verify the functionality.

Adding Permissions to the Manifest

To listen for incoming SMS messages, your app needs permission to receive and read SMS. Start by adding the following permissions to your AndroidManifest.xml:

<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />

Note: Runtime permissions need to be requested for these permissions if targeting Android 6.0 (API level 23) or higher.

Creating the SMSReceiver Class

First, create a BroadcastReceiver class that will listen for incoming SMS messages:

class SmsReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == "android.provider.Telephony.SMS_RECEIVED") {
            val bundle = intent.extras
            if (bundle != null) {
                val pdus = bundle.get("pdus") as Array<*>
                pdus.forEach { pdu ->
                    val smsMessage = SmsMessage.createFromPdu(pdu as ByteArray)
                    val messageBody = smsMessage.messageBody
                    val sender = smsMessage.originatingAddress
                    // Here, we could trigger a callback or an event
                    Log.d("SmsReceiver", "Received SMS from: $sender, Message: $messageBody")
                }
            }
        }
    }
}

Registering the Receiver in the Manifest

Next, register the SmsReceiver in the AndroidManifest.xml to listen for SMS messages even when the app is in the background:

<receiver android:name=".SmsReceiver">
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

Using Jetpack Compose to Handle Permissions

With Jetpack Compose, handling runtime permissions can be managed inside the Composable function. Here’s how you can request and check for SMS permissions using Compose:

@Composable
fun SmsPermissionHandler(onPermissionGranted: () -> Unit) {
    val context = LocalContext.current
    val permissionState = rememberPermissionState(android.Manifest.permission.RECEIVE_SMS)

    LaunchedEffect(permissionState.hasPermission) {
        if (permissionState.hasPermission) {
            onPermissionGranted()
        } else {
            permissionState.launchPermissionRequest()
        }
    }

    if (!permissionState.hasPermission) {
        Text("Permission to receive SMS is required for this app.")
    }
}

In this code, rememberPermissionState from the accompanist-permissions library is used to handle permission requests in a declarative Compose-friendly way.

Displaying Received SMS in Compose

Now that we can receive SMS and have permission handling, let’s update our Composable function to display the received SMS messages. We can create a ViewModel to hold the received message:

class SmsViewModel : ViewModel() {
    private val _smsMessage = MutableLiveData()
    val smsMessage: LiveData = _smsMessage

    fun updateMessage(newMessage: String) {
        _smsMessage.value = newMessage
    }
}

In your Composable function, observe the SMS message and display it:

@Composable
fun SmsReceiverScreen(viewModel: SmsViewModel) {
    val smsMessage by viewModel.smsMessage.observeAsState("Waiting for SMS...")

    Column(
        modifier = Modifier.fillMaxSize().padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = smsMessage)
    }
}

Make sure to connect the BroadcastReceiver with the ViewModel, so the received SMS message can be updated in real-time.

Conclusion

In this tutorial, we walked through how to implement SMS reception in an Android app using Jetpack Compose. We covered how to manage permissions, receive and display SMS messages, and wrote unit tests to verify the functionality. With this knowledge, you can integrate SMS-based features such as OTP verification or messaging apps into your Compose projects.

Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *