Skip to content

Instantly share code, notes, and snippets.

@KovshefulCoder
Last active April 26, 2025 18:10
Show Gist options
  • Save KovshefulCoder/77dde3f271931f6bb16dc617138a4d63 to your computer and use it in GitHub Desktop.
Save KovshefulCoder/77dde3f271931f6bb16dc617138a4d63 to your computer and use it in GitHub Desktop.
KMP Android/iOS UI Alert (Toast/Alert dialog). Does not require Compose. Uses androidx.startup on Android, but this can be avoided by manually accessing Context or by marking the function as @composable and using LocalContext.current
<application
...
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="<package-name>.AndroidApplicationContextInitializer"
android:value="androidx.startup"/>
</provider>
</application>
import kotlin.properties.Delegates
import android.app.Application
import android.content.Context
import android.widget.Toast
import androidx.startup.Initializer
actual fun showUIAlert(message: String) {
Toast.makeText(
AndroidApplicationContext.application,
message,
Toast.LENGTH_SHORT,
).show()
}
internal class AndroidApplicationContextInitializer : Initializer<Context> {
override fun create(context: Context): Application {
AndroidApplicationContext.setUp(context.applicationContext as Application)
return AndroidApplicationContext.application
}
override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
}
internal object AndroidApplicationContext {
var application by Delegates.notNull<Application>()
private set
fun setUp(application: Application) {
this.application = application
}
}
expect fun showUIAlert(message: String)
import platform.Foundation.NSLog
import platform.Foundation.NSTimer
import platform.UIKit.UIAlertAction
import platform.UIKit.UIAlertActionStyleDefault
import platform.UIKit.UIAlertController
import platform.UIKit.UIAlertControllerStyleAlert
import platform.UIKit.UIApplication
import platform.UIKit.UIDevice
import platform.darwin.dispatch_async
import platform.darwin.dispatch_get_main_queue
actual fun showUIAlert(message: String) {
val viewController = UIApplication.sharedApplication.keyWindow?.rootViewController
if (viewController != null) {
val alertController = UIAlertController.alertControllerWithTitle(
title = UIDevice.currentDevice.systemName,
message = message,
preferredStyle = UIAlertControllerStyleAlert,
)
alertController.addAction(
UIAlertAction.actionWithTitle(
"OK",
style = UIAlertActionStyleDefault,
handler = null,
),
)
dispatch_async(dispatch_get_main_queue()) {
viewController.presentViewController(
viewControllerToPresent = alertController,
animated = true,
completion = {
val delay = 1.5
NSTimer.scheduledTimerWithTimeInterval(delay, repeats = false) {
alertController.dismissViewControllerAnimated(true, completion = null)
}
},
)
}
} else {
NSLog("Error: rootViewController is null")
}
}
Placeholder to fix gist name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment