dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.06k stars 1.73k forks source link

Deeplinking on Android causes crash #11684

Open edgiardina opened 1 year ago

edgiardina commented 1 year ago

Description

Creating a MAUI app with Deep Linking intents, then firing those intents causes a java crash

image

Steps to Reproduce

  1. Create File -> New MAUI App
  2. Add to the MainActivity an Intent Filter to allow deep linking / opening our Maui app from a URL
    [IntentFilter(new[] { Intent.ActionView },
          Categories = new[] {
              Intent.CategoryDefault,
              Intent.CategoryBrowsable
          },
          DataSchemes = new string[] { "http", "https" },
          DataHost = "www.deeplink.com",
          DataPaths = new string[] { "/player.php", "/tournaments/view.php" },
          AutoVerify = true)]
  3. Build and run the app
  4. While the app is open, or isn't open, use ADB to simulate a deep link request .\adb shell am start -W -a android.intent.action.VIEW -d "https://www.deeplink.com/player.php?p=16927"
  5. In the Android Emulator, choose our MAUI app when presented with the bottom drawer choice about how to open the link
  6. Witness a crash like the description says

Link to public reproduction project repository

https://github.com/edgiardina/MauiBug_DeepLinkCrash

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 13 Pixel 5

Did you find any workaround?

No response

Relevant log output

0xFFFFFFFFFFFFFFFF in Android.Runtime.JNIEnv.monodroid_debugger_unhandled_exception
0x59 in Android.Runtime.JNIEnv.PropagateUncaughtException at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNIEnv.cs:308,5
ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

logikonline commented 1 year ago

This is a deeper issue around the Shell. Push Notifications will also cause the TabBar to become unresponsive. At first, I thought this was only linked to Maui, but I painstakingly recreated my entire project in XF, which also appears to occur. Only upon using the FlyoutPage method did it solve the issue.

edgiardina commented 1 year ago

@logikonline Hmm. Strange. I launched deep linking in my XF version of my app and didn't see it.

logikonline commented 1 year ago

The issue with the TabBar and the Shell, is only created with the Push Notification. The FlyoutPage or obsolete MasterDetail page will not do it. I suspect it is to do with the GotoAsync method since the PushAsync will still work but I bet the TabBar uses that GotoAsync since the route is used for those too.

edgiardina commented 1 year ago

@logikonline what's strange is that this exception happens before OnAppLinkRequestReceived fires in my App class. So the exception happens when the Intent brings the Shell App / tabbar to the front, and not when my app is asked to GoToAsync the target URL of the applinkrequest.

logikonline commented 1 year ago

I understand, the issue I found is that the Shell is likely executing the same GotoAsync code behind the scenes prior to our interaction. I only call this out because that is what breaks when I try to interact with the app when I do have control.

moljac commented 1 year ago

Running repro sample I was not able to reproduce.

Command

adb \
    shell am start \
        -W \
        -a android.intent.action.VIEW \
        -d "https://www.deeplink.com/player.php?p=16927"

Output

Starting: Intent { act=android.intent.action.VIEW dat=https://www.deeplink.com/... }
Status: ok
LaunchState: UNKNOWN (0)
Activity: com.android.chrome/org.chromium.chrome.browser.document.ChromeLauncherActivity
WaitTime: 1074
Complete

Result

www.deeplink.com refused to connect

Screenshot_1679751796

edgiardina commented 1 year ago

That your intent fired off the web browser is suspicious. did you receive a selection dialog on whether to open the fired intent in app or in browser?

edit: I just opened up the repro project and am not getting that specific error in android anymore. However, I am also not reaching the breakpoint I set on line 16 of App.xaml.cs when debugging and firing the intent, so I am pretty sure AppLinks / Deep Linking is still not functioning.

justintemplar commented 1 year ago

In the correct setup can confirm this is still a bug. Can reproduce.

justintemplar commented 1 year ago

Does anyone have a work around for this issue?

Using Tabs as main UI.

moljac commented 1 year ago

That your intent fired off the web browser is suspicious.

This would indicate that DeepLink URL was not intercepted by OS.

did you receive a selection dialog on whether to open the fired intent in app or in browser?

edit: I just opened up the repro project and am not getting that specific error in android anymore. However, I am also not reaching the breakpoint I set on line 16 of App.xaml.cs when debugging and firing the intent, so I am pretty sure AppLinks / Deep Linking is still not functioning.

OK. I will take a look again. Thanks for the feedback.

homeyf commented 1 year ago

Verified this issue with Visual Studio Enterprise 17.7.0 Preview 3.0(.Net 8). But deploying to android emulator does not have the link to exist. https://github.com/edgiardina/MauiBug_DeepLinkCrash image

angelru commented 1 year ago

the same issue...

alexsmi-noveo commented 10 months ago

Also for me. The same issue. Android 13, net7.0

timdinh commented 3 weeks ago

I ask GitHub Copilot and it suggested 2 solutions as per below

Prompt: lauch a url via deep link cause this exception An unhandled exception of type 'System.InvalidOperationException' occurred in Mono.Android.Runtime.dll: 'This window is already associated with an active Activity (LntApp.MainActivity). Please override CreateWindow on LntApp.App to add support for multiple activities https://aka.ms/maui-docs-create-window or set the LaunchMode to SingleTop on LntApp.MainActivity.' at Android.Runtime.RuntimeNativeMethods.monodroid_debugger_unhandled_exception(Exception e) at Android.Runtime.JNINativeWrapper._unhandled_exception(Exception e) at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(_JniMarshal_PPL_V callback, IntPtr jnienv, IntPtr klazz, IntPtr p0) at Microsoft.Maui.Platform.ApplicationExtensions.CreatePlatformWindow(Activity activity, IApplication application, Bundle savedInstanceState) at Microsoft.Maui.MauiAppCompatActivity.OnCreate(Bundle savedInstanceState) at LntApp.MainActivity.OnCreate(Bundle savedInstanceState) in /Users/tiendinh/Projects/holistic/App/LntApp/Platforms/Android/MainActivity.cs:line 28. how to resolve

GitHub Copilot: To resolve the System.InvalidOperationException related to launching a URL via a deep link, you need to either override the CreateWindow method in your App class to support multiple activities or set the LaunchMode to SingleTop in your [MainActivity].

Here are the steps to set the LaunchMode to SingleTop:

  1. Open your AndroidManifest.xml file.
  2. Locate the <activity> tag for your MainActivity
  3. Add the android:launchMode="singleTop" attribute to the <activity> tag.

Here is an example of how your AndroidManifest.xml should look:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.companyname.lntapp">
    <application android:allowBackup="true" android:label="LntApp" android:theme="@style/MainTheme">
        <activity android:name=".MainActivity"
                  android:exported="true"
                  android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Alternatively, if you need to support multiple activities, you can override the CreateWindow method in your App class. Here is an example:

  1. Open your App.xaml.cs file.
  2. Override the CreateWindow method.
using Microsoft.Maui.Controls;

namespace LntApp
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new MainPage();
        }

        protected override Window CreateWindow(IActivationState activationState)
        {
            return new Window(new MainPage());
        }
    }
}

Choose the approach that best fits your application's requirements.

I went with option 1 and it is not crashing anymore but it still launch the web browser rather than the app so may be my configuration.