Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App crash after SendIntent.finish() #69

Closed
Ryner47 opened this issue Jan 26, 2023 · 14 comments
Closed

App crash after SendIntent.finish() #69

Ryner47 opened this issue Jan 26, 2023 · 14 comments

Comments

@Ryner47
Copy link

Ryner47 commented Jan 26, 2023

Describe the bug
Hello, on ionic/android I'm implementing this plugin but when I execute the recommended 'SendIntent.finish()' after intent and routing to the desired page are executed successfully, the app crashes closing itself. What could this be due to?

@carsten-klaffke
Copy link
Owner

Hello! Did you configure your intent filter in your MainActivity or in a separate activity? "finish()" closes the current activity. So if you call that, you should be in a separate activity. I recommend using a separate activity for handling intents, because otherwise it can lead to app state problems (intents might be re-executed after your activity returns after idle time).

@Ryner47
Copy link
Author

Ryner47 commented Jan 31, 2023

Hello, on ionic app side there is no 'activity' concept, so it would be useful understand in which phase of the lifecycle of the ionic components execute 'SendIntent.finish()'. Maybe in 'ngOnDestroy' function of the main component? Thanks

@carsten-klaffke
Copy link
Owner

You should call it after your share workflow is finished, whenever that is. E.g. in my app this is after a user edited the content and the save operation completed. But be aware that "finish" does close the current instance (and if it wouldn't, you would have two app instances running in parallel).

@luisleagues
Copy link

Is there a way to share a file to the already running App and not start a new instance? I want the user to stay in the App after they shared the file.

@carsten-klaffke
Copy link
Owner

Yes, you could just configure the intent-filters in your MainActivity instead of the SendIntentActivity. I think you would need to call registerPlugin(SendIntent.class); in your create-Method, but that should be it. But as I said, this can lead to some strange app state issues that can occur after idle mode (Android might re-execute the share-intent to restart the app).

@luisleagues
Copy link

That works! Can you also share a file with the App when it is already running? SendIntent.checkSendIntentReceived() works when the App is closed, but when the App is already running it doesn't received anything. This issue seems to indicate that that doesn't work: #61 (comment).

@carsten-klaffke
Copy link
Owner

carsten-klaffke commented Feb 3, 2023

You can do this with an event/listener pattern. This is the "old way" this plugin used to work (you can see it in the history of readme). But I switched to the separate activity implementation due to the state problems which weren't solvable for me (and which appears cleaner to me, because you don't steal another apps context).

Dispatch an event in your MainActivity like this:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    String action = intent.getAction();
    String type = intent.getType();
    if ((Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) && type != null) {
        bridge.getActivity().setIntent(intent);
        bridge.eval("window.dispatchEvent(new Event('sendIntentReceived'))", new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String s) {
            }
        });
    }
}

And register a listener in your app:

window.addEventListener("sendIntentReceived", () => {
   Plugins.SendIntent.checkSendIntentReceived().then((result: any) => {
        if (result) {
            // ...
        }
    });
})

@luisleagues
Copy link

Thanks again, I really appreciate it :). I'll do it this way and hope I won't get any state problems for now.

@daniandl
Copy link

Yes, you could just configure the intent-filters in your MainActivity instead of the SendIntentActivity. I think you would need to call registerPlugin(SendIntent.class); in your create-Method, but that should be it. But as I said, this can lead to some strange app state issues that can occur after idle mode (Android might re-execute the share-intent to restart the app).

So a cleaner way would be to catch the finish event and then re-open the main activity? Maybe with a deep link so we can redirect the user with context? Is this possible?

@carsten-klaffke
Copy link
Owner

Hey daniandl, using a deep link could work, but maybe that will not give you a fluid user experience. I'm sorry but I didn't find a clean solution for staying in the app after a send-intent yet. This is somewhat of an Android problem. I was even able to get Whatsapp crashing this way.

@chiraganand
Copy link

Hey daniandl, using a deep link could work, but maybe that will not give you a fluid user experience. I'm sorry but I didn't find a clean solution for staying in the app after a send-intent yet. This is somewhat of an Android problem. I was even able to get Whatsapp crashing this way.

I was having the same problem of going back to the main activity of my app after performing the action. I tried a solution which seems to work for my use case. The UX isn't really fluid mainly because of the back animation by the OS, it should have been front.

I noticed that WhatsApp does a similar thing: creating a new activity for an inward share and then probably using a deep-link to the main activity (the sharing activity is destroyed the moment you press send button). Plus, it has been able to achieve forward animation for move to the main activity even if it was already active in the background.

This is the method I added to SendIntent.java:

@PluginMethod
public void openMainActivity (PluginCall call) {
    Activity currentActivity = bridge.getActivity();
    Intent intent = currentActivity.getParentActivityIntent();
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); // doesn't seem to work
    currentActivity.startActivity(intent);
    call.resolve(new JSObject()); // not sure if this is needed?
}

AndroidManifest.xml:

<activity
    android:name="de.mindlib.sendIntent.SendIntentActivity"
    android:parentActivityName="MainActivity"
    ...
</activity>

@carsten-klaffke Thanks for creating this plugin, it is very useful. If you think the above function could be of wider use to other users then let me know I will be happy to create a PR!

@daniandl
Copy link

@PluginMethod
public void openMainActivity (PluginCall call) {
    Activity currentActivity = bridge.getActivity();
    Intent intent = currentActivity.getParentActivityIntent();
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); // doesn't seem to work
    currentActivity.startActivity(intent);
    call.resolve(new JSObject()); // not sure if this is needed?
}

Thanks for sharing. I ended up just using the capacitor AppLauncher package and launching the app before calling .finish().
This uses deep-links and verified domain association, which requires some setup.

if (this.$platform === 'android') {
  await AppLauncher.openUrl({
    url: `${CONFIG.appLaunchUrl}/bookmarks`,
  }).catch(console.error)
}

@chiraganand
Copy link

Thanks for sharing. I ended up just using the capacitor AppLauncher package and launching the app before calling .finish(). This uses deep-links and verified domain association, which requires some setup.

if (this.$platform === 'android') {
  await AppLauncher.openUrl({
    url: `${CONFIG.appLaunchUrl}/bookmarks`,
  }).catch(console.error)
}

This actually is a simpler solution than writing native code.

@carsten-klaffke
Copy link
Owner

Very nice @chiraganand and @daniandl ! I mentioned your solution in the Readme. Thank you, I think this will help many developers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants