android - Why am I getting duplicate activity instances when I click on a deeplink - Stack Overflow

admin2025-04-17  2

I have a very simple single activity compose app utilising compose navigation:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=";
    xmlns:tools=";>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.MyApplication">
            <intent-filter>
                <data android:scheme="myscheme" android:host="app" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        enableEdgeToEdge()

        Log.d("Blah", "onCreate!!!")

        setContent {
            MyApplicationTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    val navController = rememberNavController()

                    NavHost(
                        navController = navController,
                        startDestination = "screen-1"
                    ) {
                        composable(
                            "screen-1",
                            deepLinks = listOf(
                                navDeepLink {
                                    uriPattern = "myscheme://app/screen-1"
                                    action = Intent.ACTION_VIEW
                                }
                            )
                        ) {
                            Text("Screen 1", Modifier.padding(innerPadding))
                        }
                        composable(
                            "screen-2",
                            deepLinks = listOf(
                                navDeepLink {
                                    uriPattern = "myscheme://app/screen-2"
                                    action = Intent.ACTION_VIEW
                                }
                            )
                        ) {
                            Text("Screen 2", Modifier.padding(innerPadding))
                        }
                    }
                }
            }
        }
    }
}

When I trigger a deep link (via the command line or browser) I get duplicate instances of the activity (the log message in onCreate appears twice). This even happens when the deep link triggers a fresh launch of the app (app is not already present in the background). I am using the latest versions of everything. I have tried changing the launch mode and task affinity to no avail. Any ideas?

Thanks!

I have a very simple single activity compose app utilising compose navigation:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.MyApplication">
            <intent-filter>
                <data android:scheme="myscheme" android:host="app" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        enableEdgeToEdge()

        Log.d("Blah", "onCreate!!!")

        setContent {
            MyApplicationTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    val navController = rememberNavController()

                    NavHost(
                        navController = navController,
                        startDestination = "screen-1"
                    ) {
                        composable(
                            "screen-1",
                            deepLinks = listOf(
                                navDeepLink {
                                    uriPattern = "myscheme://app/screen-1"
                                    action = Intent.ACTION_VIEW
                                }
                            )
                        ) {
                            Text("Screen 1", Modifier.padding(innerPadding))
                        }
                        composable(
                            "screen-2",
                            deepLinks = listOf(
                                navDeepLink {
                                    uriPattern = "myscheme://app/screen-2"
                                    action = Intent.ACTION_VIEW
                                }
                            )
                        ) {
                            Text("Screen 2", Modifier.padding(innerPadding))
                        }
                    }
                }
            }
        }
    }
}

When I trigger a deep link (via the command line or browser) I get duplicate instances of the activity (the log message in onCreate appears twice). This even happens when the deep link triggers a fresh launch of the app (app is not already present in the background). I am using the latest versions of everything. I have tried changing the launch mode and task affinity to no avail. Any ideas?

Thanks!

Share Improve this question asked Jan 31 at 11:56 user648462user648462 6659 silver badges23 bronze badges 9
  • Hi, did you try to use android:launchMode="singleTask" for the <activity>? – Yurii Commented Jan 31 at 12:26
  • Yes, it made no difference. I would understand the need to alter the launch mode for cases where the activity is already running in the background and you want the deep link to re-use that activity instance rather than launch another. However, the issue I am experiencing happens even when the deep link triggers a completely fresh launch of the app. – user648462 Commented Jan 31 at 12:36
  • hm, ok, next step, is to try override the public override fun onNewIntent(intent: Intent) { and handle the deeplink from Intent. – Yurii Commented Jan 31 at 12:41
  • onNewIntent doesn't get called, onCreate is called multiple times. – user648462 Commented Jan 31 at 12:43
  • btw, does it correctly handle the uriPattern ? I mean for the both url cases? – Yurii Commented Jan 31 at 12:47
 |  Show 4 more comments

1 Answer 1

Reset to default 0

You have to define launchMode for MainActivity

<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTop "
android:theme="@style/Theme.MyApplication">

You can use either "singleTask" or "singleTop" depending on your specific requirements. Here's cases of when to use each:

Use singleTop if you need to preserve the back stack and avoid clearing it.

This is useful when you want to ensure that only one instance of the activity exists at the top of the back stack, but you don't want to clear the rest of the stack.

Use singleTask if you need to guarantee that the activity will be the only one in its task and clear the back stack.

Here is a documentation about start mode documentation about start mode

转载请注明原文地址:http://anycun.com/QandA/1744863753a88689.html