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.
This is a Xamarin Forms app, however I've asked the question here in the iOS forum, because it involves the new iOS Version 13+ SceneDelegate with modified AppDelegate.
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
Does anyone know why the OpenUrlContexts method is not being called?
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
public partial class App : Application { public App() { InitializeComponent(); DependencyService.Register<MockDataStore>(); MainPage = new MainPage(); } protected override void OnStart() { } protected override void OnSleep() { } protected override void OnResume() { } protected override void OnAppLinkRequestReceived(Uri uri) { // DOES NOT FIRE EITHER base.OnAppLinkRequestReceived(uri); } }
Answers
It seems that when the app is launched on a cold start the
openURLContexts
function WILL NOT get called , butWillConnect
method triggers , so as a workaround you can check the url inWillConnect
method .Check https://stackoverflow.com/a/59207558/8187800 .
Xamarin forums are migrating to a new home on Microsoft Q&A!
We invite you to post new questions in the Xamarin forums’ new home on Microsoft Q&A!
For more information, please refer to this sticky post.
Hi @ColeX !!!
Thanks for trying to help but my preliminary excitement quickly faded because in
WillConnect
I'd have expectedconnectionOptions.UrlContexts.AnyObject.Url
to show the URL howeverUrlContexts
is null.Also, a proper solution has to provide the same functionality that existed before iOS 13 came out, and that is:
Even if the URL could be identified in WillConnect, that would only cater for case 1 above, and not 2.
Although I am very very thankful for the Xamarin staff who help out in these forums, I'm very disappointed that there is singularly no documentation of these patterns for Xamarin Forms, and that the Xamarin.Forms solution templates in Visual Studio have not been updated with SceneDelegate and associated files, yet iOS 13 was released on the 19th of September 2019.
In that changeover from iOS 12 to 13, every single developer has been left stranded without documentation.
Anyway, thanks again, I’ve raised the issue as a Xamarin.Forms issue here: https://github.com/xamarin/Xamarin.Forms/issues/13786