79513246

Date: 2025-03-16 21:18:11
Score: 0.5
Natty:
Report link

You can do it in several ways, I want to present one of them, using the regular expect/actual mechanism in Compose Multiplatform.

expect fun parseDeepLinkUrl(url: String): DeepLinkData

also I created DeepLinkManager to handle the data and let the view model to monitor its flow

// Singleton object to hold the deeplink data
object DeepLinkManager {
    private val _deeplinkData = MutableStateFlow<DeepLinkData?>(null)
    val deeplinkData: StateFlow<DeepLinkData?> = _deeplinkData

    fun processDeeplink(data: DeepLinkData) {
        _deeplinkData.value = data
    }
}

and you can implement it in Android and iOS this way:

Android:

actual fun parseDeepLinkUrl(url: String): DeepLinkData {
    val uri = url.toUri()
    return DeepLinkData(
        username = uri.getQueryParameter("username") ?: "",
        token = uri.getQueryParameter("token") ?: "",
        email = uri.getQueryParameter("email") ?: ""
    )
}

Android Manifest:

<intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="***put your string here***" android:host="auth-success-for-example" />
            </intent-filter>

you can add the below line in activity to open the same application back, in case you called the browser from the application to do the authentication.

android:launchMode="singleTop"

in MainActivity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        onNewIntent(intent)
        setContent {
            App()
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        val url = intent.dataString ?: ""
        val data = parseDeepLinkUrl(url)
        DeepLinkManager.processDeeplink(data)
    }
}

iOS:

actual fun parseDeepLinkUrl(url: String): DeepLinkData {
    val nsUrl = NSURL.URLWithString(url) ?: return DeepLinkData("", "", "")
    val components = NSURLComponents.componentsWithURL(nsUrl, resolvingAgainstBaseURL = true)

    // This is the corrected approach - properly cast and access the query items
    val params = mutableMapOf<String, String>()
    components?.queryItems?.forEach { item ->
        val queryItem = item as NSURLQueryItem
        queryItem.value?.let { value ->
            params[queryItem.name] = value
        }
    }
    return DeepLinkData(
        username = params["username"] ?: "",
        token = params["token"] ?: "",
        email = params["email"] ?: ""
    )
}

iOS Info.plist

<key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLName</key>
            <string>org.company.name</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>***Your String here***</string>
            </array>
        </dict>
    </array>

inside iOS APP. you can take the URL, call the parser and send it to the Object to be monitored by the Viewmodel:

struct iOSApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL {
                    url in
                    let parsedData = ParseDeepLinkUrl_iosKt.parseDeepLinkUrl(url: url.absoluteString)
                    // Pass the data to the DeepLinkManager
                    DeepLinkManager.shared.processDeeplink(data: parsedData)
                }
        }
    }
}

of course you can forget about the expect/actual mechanism and implement reading the deeplink within the MainActivity and iOSApp and send the data directly to the object.

last but not least, you can read it from the view model this way:

 init {
        viewModelScope.launch {
            DeepLinkManager.deeplinkData.collect { deepLinkData ->
                deepLinkData?.let {
                    println("Got the Deeplink in Viewmodel: $it")                 
                }
            }
        }
    }

Enjoy!

Reasons:
  • RegEx Blacklisted phrase (1): I want
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Saher Al-Sous