question

hotn avatar image
0 Votes"
hotn asked hotn commented

Deep Linking does not work in Xamarin Forms where iOS is 13 or greater

I'd very much appreciate a resolution to the following problem, as well as Microsoft both:

  1. Releasing some official documentation on the issue, and

  2. Updating the Xamarin Forms Solution Templates in Visual Studio

iOS 13 was released on the 19th of September 2019 and yet there is still a bug in the new iOS SceneDelegate pattern as relates to Xamarin Forms, in that when using Xamarin.Forms (not Xamarin.iOS), that the developer cannot intercept the URL that was clicked on to bring the app into the foreground.

Furthermore, these 18 months later, the Xamarin.Forms solution that is generated in Visual Studio (File / New Solution, etc) does not include the new SceneDelegate pattern _in the iOS project of that Xamarin.Forms solution.

In that changeover from iOS 12 to 13 in September 2019, every single developer has also been left stranded without documentation of the new Xamarin Forms pattern that allows a user to click a link and the application to be opened and the developer being advised of what URL opened the link.

The following code demonstrates that I have a deep link registered, and where iOS is 13 or greater, although clicking on the link opens the app, the OpenUrlContexts override does not fire, hence I am unable to filter then navigate, based upon the URL.

I've included the following code files:
1. SceneDelegate
2. AppDelegate
3. apple-app-site-association
4. Entitlements.plist
5. Info.plist extract
6. App.xaml.cs

Note: the following has the pre-iOS 13 code stripped out, which in the finmal result should be included to cater for iPhones that have not yet upgraded to iOS 13 and above.

In short, the OpenUrlContexts method does not fire when a link is clicked on, and even in WillConnect I'd have expected connectionOptions.UrlContexts.AnyObject.Url to show the URL however UrlContexts is null.

SceneDelegate file:

 [Register("SceneDelegate")]
     public class SceneDelegate : UIWindowSceneDelegate
     {
         [Export("scene:openURLContexts:")]
         public override void OpenUrlContexts(UIScene scene, NSSet<UIOpenUrlContext> urlContexts)
         {
             Debug.WriteLine("*** URL property =====" + urlContexts.AnyObject.Url);
             var urlString = urlContexts.AnyObject.Url;
             if (urlString.Equals("https://REDACTED"))
             {
                 // Run code 
             }
         }
    
    
         public override UIWindow Window { get; set; }
    
         public override void WillConnect(UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
         {
             var windowScene = scene as UIWindowScene;
             if (windowScene != null)
             {
                 Window = new UIWindow(windowScene.CoordinateSpace.Bounds);
                 if (Window != null)
                 {
                     // This just creates a new App instance without creating a new AppDelegate
                     // In iether case I still see issues with navigation events going to the wrong window,
                     // i.e. I tap Add Item in one window, but the new item page launches in another window
                     // Or use the menu to go to the ABout page, and the About page opens in the other window
                     // This is in keeping with what I have seen in reagrds to embedding forms pages into native 
                     // projects. In this case, you need to use the platforms navigation APIs, not Xamarin.Forms
                     // navigation APIs
                     var fApp = new App();
                     try
                     {
                         // Set the scene's RootViewController from the one X.Forms created
                         Window.RootViewController = fApp.MainPage.CreateViewController();
    
    
                         //// This creates the Xamarin.Forms UI with a new app delegate
                         var ad = new AppDelegate();
                         ad.GetUI();
                         //
                         //// Set the scene's RootViewController from the one X.Forms created
                         Window.RootViewController = ad.Window.RootViewController;
    
    
                         // Set the WindowScene
                         Window.WindowScene = windowScene;
                     }
                     catch(Exception ex)
                     {
    
                     }
    
    
                 }
             }
         }
     }

AppDelegate file:


 [Register("AppDelegate")]
     public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
     {
         public UIApplication application;
         public NSDictionary options;
         //
         // This method is invoked when the application has loaded and is ready to run. In this 
         // method you should instantiate the window, load the UI into it and then make the window
         // visible.
         //
         // You have 17 seconds to return from this method, or iOS will terminate your application.
         //
         [Export("application:didFinishLaunchingWithOptions:")]
         public override bool FinishedLaunching(UIApplication app, NSDictionary options)
         {
             global::Xamarin.Forms.Forms.Init();
    
             if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
             {
                 // only used when creating a new app delegate in the scene delegate in order to be able to call 
                 // LoadApplication in GetUI method
                 this.application = app;
                 this.options = options;
    
                 return true;
             }
             else
             {
                 LoadApplication(new App());
                 return base.FinishedLaunching(app, options);
             }
         }
    
         // only used when creating a new app delegate in the scene delegate
         public void GetUI()
         {
             LoadApplication(new App());
    
             // This call populates the Window property so it needs to be called after LoadApplication for every scene 
             base.FinishedLaunching(application, options);
    
         }
     }

apple-app-site-association file:

 {
    "applinks": {
      "apps": [],
      "details": [
        {
          "appID": "REDACTED",
          "paths": [ "/", "/REDACTED/*"]
        }
      ]
    }
 }

Entitlements.plist file

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
     <key>com.apple.developer.associated-domains</key>
     <array>
         <string>applinks:REDACTED</string>
     </array>
 </dict>
 </plist>

Registration of SceneDelegate in info.plist

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
     <!-- other stuff not shown here -->
     <key>UIApplicationSceneManifest</key>
     <dict>
         <key>UIApplicationSupportsMultipleScenes</key>
         <true/>
         <key>UISceneConfigurations</key>
         <dict>
             <key>UIWindowSceneSessionRoleApplication</key>
             <array>
                 <dict>
                     <key>UISceneConfigurationName</key>
                     <string>Default Configuration</string>
                     <key>UISceneDelegateClassName</key>
                     <string>SceneDelegate</string>
                     <key>UISceneStoryboardFile</key>
                     <string>EmptyStoryboard</string>
                 </dict>
             </array>
         </dict>
     </dict>
 </dict>

Xamarin.Forms App.xaml.cs

(Does not want to paste however the example only has the standard overrides without any user-added code.)

dotnet-xamarin
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

ColeXia-MSFT avatar image
0 Votes"
ColeXia-MSFT answered hotn commented

Hello,

Welcome to Microsoft Q&A!

Try Application.OnAppLinkRequestReceived method in App.cs instead of OpenUrlContexts method .

The method is triggered when the user initiates an app link request .

Refer to the comment in the link : https://github.com/xamarin/Xamarin.Forms/issues/13786#issuecomment-781416504 .



If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks @ColeXia-MSFT, I'll try that and report back here!!!!

0 Votes 0 ·

Hi @hotn Is there any update ?

0 Votes 0 ·

Hi Cole! I managed the fix above, but (for reasons mentioned in my post below just now, for the sake of others) it's a short term workaround. Thanks for all your help, which has been across at least two forums where I also sought help! So the good news is that we'll be able to put the app in the App Store later this week (all being well!). Thanks again!!!

1 Vote 1 ·
hotn avatar image
0 Votes"
hotn answered

My resolution of the problem as a short-term fix is to implement the AppLinks as suggested.

It is, of course, a short term fix, in the sense that as soon as something necessitates the use of SceneDelegate with Xamarin Forms, then this solution does not work: i.e. I haven't been able to get AppLinks working with SceneDelegate included in iOS in a Xamarin Forms solution.

However I have tested it in separate POC apps, as follows:

XF Shell App
XF Blank App
XF Shell App with Content Pages NOT in the XF project but in a different .Net Standard project with the XF nuget installed
(I didn't get to try the XF Master-Detail because the standard template solution wouldn't build and by then I'd had enough).

Android continues to work, it's a delight!

I hope that they've solved this SceneDelegate issue by the time .Net Maui is released later this year, as 'click and view' is a major component of my client's mobile app business model.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.