Deep link is causing multiple instances of the app to open
Asked Answered
I

3

8

This issue has been addressed in similar posts, however, my situation is a little different. I have only ONE activity, and multiple fragments. I am not deeplinking into specific fragments, I am launching my one activity and then redirecting to the different fragments. The issue I am running into is that multiple instances of the app is opening when clicking on the deep link and when preventing multiple instances of the app from opening I lose the data in my intent for deep linking.

I have prevented multiple instances a couple of ways. One was was by adding singleTop to my manifest

android:launchMode="singleTop"

This prevents multiple instances, however, the static data from my original app instance gets lost. Another way I have also tried the below way as well

   // finishes activity if its not the root activity
    if (!FrameworkUtils.checkIfNull(getIntent().getExtras())) {
        if (!isTaskRoot()) {
            finish();
        }
    }

With this code, I maintain the original instance of the app, but the intent data I need from the deep link is gone because the new instance of the app (which I need) gets closed.

How can I resolve this situation without having to create additional Activities to launch and then doing something like

    Intent intent = getIntent();
    String intentUrl = intent.getDataString();
    Intent newIntent = new Intent(this, MainActivity.class);
    newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
    newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    newIntent.putExtra("intentUrl",intentUrl);
    newIntent.setAction(Long.toString(System.currentTimeMillis()));
    startActivity(newIntent);
    finish();

Or rather, how can I remove the original instance of the app and keep the new instance of the app after the user clicks on the deep link? Thanks in advance

Isomorph answered 9/3, 2017 at 0:6 Comment(8)
What do you mean 'the new instance of the app (which I need) gets closed'? That's not what singleTop does. Where do you override onNewIntent?Mattah
I meant that the original instance of the app gets closed. Sorry typo. The new instance of the app gets closed the second way. But there are issues either way, because the new instance of the app doesn't have the data from my static objects. And in the converse, if the new instance of the app gets closed, then the original instance doesn't have the data from the push notification.Isomorph
Your process can always be removed at anytime (it'll happen all the time on low end devices as users switch from your app to other apps). You need to be able to recover from that in any case.Mattah
Yes, this is true. But I do not have a solution for ideal case, still. I understand that there are still other potential issues with user closing the app, for exampleIsomorph
What do you mean by "multiple instances of the app". Please be more specific. Are new instances of your Activity being created? How do you know?Hattiehatton
Please also show an example of your "deep link"Hattiehatton
Multiple instances of the app is specific. It means when pressing the back button, the new instance Activity removes and then you can still see the same Activity under it. Pressing the back button again, closes that instance of the app. And the deep link is a URL link. Just a schema and host.Isomorph
You do not have "multiple instances of the app". You have multiple instances of an Activity. That's what I mean about "being more specific". An "app" is not an Activity.Hattiehatton
I
8

Please find below the activity code which will have only one instance and also you can send your data and process it. Let me know if you have any doubts.

    package example.raghavpai;

    import android.app.Activity;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;

    /**
     * Created by RaghavPai on 09-03-2017.
     */

    public class MyActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            processDataFromIntent();
        }

        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            setIntent(intent);
            processDataFromIntent();
        }

        private void processDataFromIntent() {
            Intent intent = getIntent();
            if (intent != null) {
                Bundle extras = intent.getExtras();
                if (extras != null) {
                    String message = extras.getString("data_key");
                }
            }
        }

        public static void startMyActivity(Context context, String data) {
            Intent intent = new Intent(context, MyActivity.class);
            intent.putExtra("data_key", data);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }

Manifest code for the same

    <activity
        android:name=".MyActivity"
        android:launchMode="singleTask"
        android:screenOrientation="portrait"
        android:theme="@android:style/Theme.Holo.Light.NoActionBar.Fullscreen"></activity>

Use the public static API startMyActivity from any of your activities.

Indeterminable answered 9/3, 2017 at 4:9 Comment(2)
Yes, I understand how to have 1 instance of the app. That is what you have described. But this does not quite answer my question about how to keep the original static objects before the deep link is clicked.Isomorph
For you to understand what I mean, keep your same code but create a counter that increments. Upon pressing your CTA that triggers the deep link from an email (for example), increment that counter to 1. Now minimize the app, and when you press the email deep link and get redirected back into your app, you will notice that the counter is reset back to 0. Yes, you have one instance of the app, but you have kept the new instance and destroyed the original. That is the issue.Isomorph
V
0

In xamarin forms or Xamarin Android, the best way to prevent this behavior is set 'LaunchMode = LaunchMode.SingleInstance'

    [Activity(Label = "My App Name", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = false, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, LaunchMode = LaunchMode.SingleInstance)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    ...
}
Vanwinkle answered 12/7, 2022 at 0:43 Comment(0)
A
-3

I found a simple solution that is working better for me

just add this

if (!isTaskRoot()) {
        finish();
    }
Algoid answered 10/4, 2021 at 18:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.