How to Open System Settings in Compose Multiplatform
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 🙌