android – .NET MAUI App Hyperlinks not opening app, as an alternative opening browser

0
17
android – .NET MAUI App Hyperlinks not opening app, as an alternative opening browser


I’m attempting to arrange deep linking/common linking for my .NET MAUI app. All the pieces seems on the floor to be arrange in line with the MS documentation, nevertheless when accessing hyperlinks it merely makes use of the browser. This occurs in each Android and Google.

The specified behaviour is in order that any visitors to https://app.rackemapp.com (which can sometimes be by a QR code) will set off the app to open.

In Android I examined it with a customized scheme of rackemapp:// which labored, so I do know the bottom logic works, I simply can’t get the gadgets to know that app.rackemapp.com visitors ought to open the app.

The curl testing to succeed in my AASA file works okay (no redirects or 40x errors) and the diagnostics device on the system detects it as a legitimate common hyperlink.

How do I make it open my app?

MauiProgram.cs

public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp()
                .UseMauiCommunityToolkit()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Common.ttf", "OpenSansRegular");
                    fonts.AddFont("bootstrap-icons.ttf", "Bootstrap");
                })
                .ConfigureLifecycleEvents(lifecycle =>
                {
#if IOS
                    lifecycle.AddiOS(ios =>
                    {
                        // Common hyperlink delivered to FinishedLaunching after app launch.
                        ios.FinishedLaunching((app, knowledge) => HandleAppLink(app.UserActivity));

                        // Common hyperlink delivered to ContinueUserActivity when the app is working or suspended.
                        ios.ContinueUserActivity((app, userActivity, handler) => HandleAppLink(userActivity));

                        // Solely required if utilizing Scenes for multi-window help.
                        if (OperatingSystem.IsIOSVersionAtLeast(13) || OperatingSystem.IsMacCatalystVersionAtLeast(13))
                        {
                            // Common hyperlink delivered to SceneWillConnect after app launch
                            ios.SceneWillConnect((scene, sceneSession, sceneConnectionOptions)
                                => HandleAppLink(sceneConnectionOptions.UserActivities.ToArray()
                                    .FirstOrDefault(a => a.ActivityType == Basis.NSUserActivityType.BrowsingWeb)));

                            // Common hyperlink delivered to SceneContinueUserActivity when the app is working or suspended
                            ios.SceneContinueUserActivity((scene, userActivity) => HandleAppLink(userActivity));
                        }
                    });
#endif
#if ANDROID
                    lifecycle.AddAndroid(android =>
                    {
                        android.OnCreate((exercise, bundle) =>
                        {
                            var motion = exercise.Intent?.Motion;
                            var knowledge = exercise.Intent?.Knowledge?.ToString();

                            if (motion == Android.Content material.Intent.ActionView && knowledge isn't null)
                            {
                                Process.Run(() => HandleAppLink(knowledge));
                            }
                        });
                    });
#endif

                });

            //Pointless code omitted

            var app = builder.Construct();

            ServiceHelper.Initialize(app.Providers);

            return app;
        }

#if IOS
        static bool HandleAppLink(Basis.NSUserActivity? userActivity)
        {
            if (userActivity isn't null && userActivity.ActivityType == Basis.NSUserActivityType.BrowsingWeb && userActivity.WebPageUrl isn't null)
            {
                HandleAppLink(userActivity.WebPageUrl.ToString());
                return true;
            }
            return false;
        }
#endif

        static void HandleAppLink(string url)
        {
            if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out var uri))
                App.Present?.SendOnAppLinkRequestReceived(uri);
        }

App.xaml.cs

public App()
        {

            InitializeComponent();           

            MainPage = new MainPage();
        }

        protected override async void OnAppLinkRequestReceived(Uri uri)
        {
            base.OnAppLinkRequestReceived(uri);

            var theurl = uri.ToString();

            // Present an alert to check that the app hyperlink was obtained.
            await Dispatcher.DispatchAsync(async () =>
            {
                //await Home windows[0].Web page!.DisplayAlert("App hyperlink obtained", uri.ToString(), "OK");
                var encodedString = theurl.Break up("/")[4];

                byte[] knowledge = Convert.FromBase64String(encodedString);
                string decodedString = System.Textual content.Encoding.UTF8.GetString(knowledge);

                var api = "https://mobileapi.rackemapp.com";
#if DEBUG
                api = "https://g7c7crrc-44357.uks1.devtunnels.ms";
#endif
                var shopper = new RestClient(api);
                var request = new RestRequest("/cellular/getmatchfromtable/" + decodedString, Methodology.Get);

                var execute = shopper.Execute(request);

                string rawResponse = execute.Content material;
                var choices = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };

                var response = new TableMatchResponse();

                if (rawResponse == null || rawResponse == "")
                {
                    response.MatchCode = "OFFLINE";
                }
                else
                {
                    response = System.Textual content.Json.JsonSerializer.Deserialize(rawResponse, choices);
                }

                if (response.MatchCode == null || response.MatchCode == "")
                {
                    // error situation
                }
                else
                {
                    App.Present.MainPage.Navigation.PushModalAsync(new Scoreboard(response.MatchCode));
                }

            });
        }

** curl to AASA**

curl -v https://app.rackemapp.com/.well-known/apple-app-site-association
* Host app.rackemapp.com:443 was resolved.
* IPv6: (none)
* IPv4: 104.21.50.101, 172.67.204.183
*   Making an attempt 104.21.50.101:443...
* Related to app.rackemapp.com (104.21.50.101) port 443
* ALPN: curl gives h2,http/1.1
* (304) (OUT), TLS handshake, Consumer hiya (1):
*  CAfile: /and so forth/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hiya (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificates (11):
* (304) (IN), TLS handshake, CERT confirm (15):
* (304) (IN), TLS handshake, Completed (20):
* (304) (OUT), TLS handshake, Completed (20):
* SSL connection utilizing TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificates:
*  topic: CN=rackemapp.com
*  begin date: Dec 27 10:10:42 2024 GMT
*  expire date: Mar 27 11:08:16 2025 GMT
*  subjectAltName: host "app.rackemapp.com" matched cert's "*.rackemapp.com"
*  issuer: C=US; O=Google Belief Providers; CN=WE1
*  SSL certificates confirm okay.
* utilizing HTTP/2
* [HTTP/2] [1] OPENED stream for https://app.rackemapp.com/.well-known/apple-app-site-association
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: app.rackemapp.com]
* [HTTP/2] [1] [:path: /.well-known/apple-app-site-association]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET /.well-known/apple-app-site-association HTTP/2
> Host: app.rackemapp.com
> Consumer-Agent: curl/8.7.1
> Settle for: */*
> 
* Request fully despatched off
< HTTP/2 200 
< date: Sat, 28 Dec 2024 21:57:37 GMT
< content-type: utility/json
< content-length: 315
< last-modified: Tue, 24 Dec 2024 22:39:41 GMT
< accept-ranges: bytes
< etag: "589c11b95456db1:0"
< x-powered-by: ASP.NET
< cf-cache-status: DYNAMIC
< report-to: {"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=oe3dB4x1fALVNQ6f%2FDzDNWMBUj772yNTdc7RsseLGWDPbOWJ4hgLRn3%2FitA%2BY4vBR4KN5juDa4x9wxu9z0CGbK4jXP5m0n6f0VTyKamvPIGlvEJl6VobT6dMJOdHMuiCqkMtMA%3D%3D"}],"group":"cf-nel","max_age":604800}
< nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
< strict-transport-security: max-age=0; includeSubDomains; preload
< x-content-type-options: nosniff
< x-cloudflare-enabled: true
< server: cloudflare
< cf-ray: 8f94ce9b09d271f2-LHR
< alt-svc: h3=":443"; ma=86400
< server-timing: cfL4;desc="?proto=TCP&rtt=41458&min_rtt=36685&rtt_var=18592&despatched=5&recv=9&misplaced=0&retrans=0&sent_bytes=2911&recv_bytes=585&delivery_rate=50756&cwnd=227&unsent_bytes=0&cid=15096d52c33a80ae&ts=100&x=0"
< 
{
    "activitycontinuation": {
        "apps": [ "[Teamid].com.rackemapp.mobileapp" ]
    },
    "applinks": {
        "apps": [],
        "particulars": [
            {
                "appID": "[Teamid].com.rackemapp.mobileapp",
                "paths": [ "*", "/*" ]
            }
        ]
    }
* Connection #0 to host app.rackemapp.com left intact

LEAVE A REPLY

Please enter your comment!
Please enter your name here