How to Open System Settings in Compose Multiplatform

Raed Ghazal
2 min read5 days ago

--

Sometimes, we need to redirect users from our app to the application system settings — when permission is denied for example, and we can’t request it again. This guide will show you how to implement a solution in Compose Multiplatform (CMP) to easily open the application’s system settings on both Android and iOS.

Here is how the final result will look like:

@Composable
fun Foo() {
val settingsState = rememberSettingsController()
Button(
onClick = { settingsState.open() }
) {
Text("Open settings")
}
}

Let’s get right into writing code:

First, we need to set up the SettingsController composable function

1. commonMain implementation:

And the SettingsState class that will allow us to easily call open to open the settings instead of handling the boolean state ourselves


class SettingsState {
internal var open by mutableStateOf(false)

fun open() {
open = true
}
}

@Composable
internal expect fun SettingsController(state: SettingsState)

2. androidMain actual implementation

Once the state changes to true it will recompose triggering the code inside the condition to open the app’s settings, then we set the state to false, so it doesn’t reopen the settings again and again on each recomposition

import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat.startActivity

@Composable
actual fun SettingsController(state: SettingsState) {
if (state.open) {
val context = LocalContext.current
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri: Uri = Uri.fromParts("package", context.packageName, null)
intent.data = uri
startActivity(context, intent, null)

state.open = false
}
}

3. iosMain actual implementation

Similar to the android’s explanation above

import androidx.compose.runtime.Composable
import platform.Foundation.NSURL
import platform.UIKit.UIApplication
import platform.UIKit.UIApplicationOpenSettingsURLString

@Composable
actual fun SettingsController(state: SettingsState) {
if (state.open) {
val settingsUrl = NSURL.URLWithString(UIApplicationOpenSettingsURLString)

if (settingsUrl != null && UIApplication.sharedApplication.canOpenURL(settingsUrl)) {
UIApplication.sharedApplication.openURL(settingsUrl, emptyMap<Any?,Any>(), {})
}

state.open = false
}
}

Once we are done with the above implementation, we should be ready to test, but to make it even easier to use we can create this helper function

@Composable
fun rememberSettingsController(): SettingsState {
val settingsState = remember { SettingsState() }
SettingsController(settingsState)
return settingsState
}

which initiates the state and the controller for us, and returns the state so we can call open from our code directly like this:

@Composable
fun Foo() {
val settingsState = rememberSettingsController()
Button(
onClick = { settingsState.open() }
) {
Text("Open settings")
}
}

With this implementation, you now have a reusable way to open system settings in Compose Multiplatform apps, ensuring smooth functionality across Android and iOS. Happy coding! 🚀

Show support

If you enjoyed the article, support me by leaving some claps 👏, and if you have any questions please let me know in the comments.

Follow me for more 🙌

Social media

LinkedIn, Twitter, GitHub

--

--

Raed Ghazal
Raed Ghazal

Written by Raed Ghazal

Lead Android Engineer at Jodel, passionate about the mobile development industry and all the new things that come with it!

No responses yet