using System; using System.Diagnostics; using System.Reflection; using System.Linq; namespace Ooui { static class Platform { static readonly Assembly iosAssembly; static readonly Type iosUIViewControllerType; static readonly Type iosUIApplicationType; static readonly Type iosUIWebViewType; static readonly Type iosNSUrl; static readonly Type iosNSUrlRequest; static readonly Assembly androidAssembly; static readonly Type androidActivityType; static readonly Type androidWebViewType; static Platform () { var asms = AppDomain.CurrentDomain.GetAssemblies ().ToDictionary ( x => x.GetName ().Name); asms.TryGetValue ("Xamarin.iOS", out iosAssembly); if (iosAssembly != null) { iosUIViewControllerType = iosAssembly.GetType ("UIKit.UIViewController"); iosUIApplicationType = iosAssembly.GetType ("UIKit.UIApplication"); iosUIWebViewType = iosAssembly.GetType ("UIKit.UIWebView"); iosNSUrl = iosAssembly.GetType ("Foundation.NSUrl"); iosNSUrlRequest = iosAssembly.GetType ("Foundation.NSUrlRequest"); } asms.TryGetValue ("Mono.Android", out androidAssembly); if (androidAssembly != null) { androidActivityType = androidAssembly.GetType ("Android.App.Activity"); androidWebViewType = androidAssembly.GetType ("Android.Webkit.WebView"); } } public static void OpenBrowser (string url, object presenter) { if (iosAssembly != null) { OpenBrowserOniOS (url, presenter); } else if (androidAssembly != null) { OpenBrowserOnAndroid (url, presenter); } else { StartBrowserProcess (url); } } static void OpenBrowserOnAndroid (string url, object presenter) { var presenterType = GetObjectType (presenter); object presenterWebView = null; if (presenter != null && androidWebViewType.IsAssignableFrom (presenterType)) { presenterWebView = presenter; } if (presenterWebView == null) { throw new ArgumentException ("Presenter must be a WebView", nameof (presenter)); } var m = androidWebViewType.GetMethod ("LoadUrl", BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, new Type[] { typeof (string) }, null); m.Invoke (presenterWebView, new object[] { url }); } static void OpenBrowserOniOS (string url, object presenter) { var presenterType = GetObjectType (presenter); // // Find a presenter view controller // 1. Try the given presenter // 2. Find the key window vc // 3. Create a window? // object presenterViewController = null; if (presenter != null && iosUIViewControllerType.IsAssignableFrom (presenterType)) { presenterViewController = presenter; } if (presenterViewController == null) { var app = iosUIApplicationType.GetProperty ("SharedApplication").GetValue (null, null); var window = iosUIApplicationType.GetProperty ("KeyWindow").GetValue (app, null); if (window != null) { var rvc = window.GetType ().GetProperty ("RootViewController").GetValue (window, null); if (rvc != null) { var pvc = rvc.GetType ().GetProperty ("PresentedViewController").GetValue (rvc, null); presenterViewController = pvc ?? rvc; } } } if (presenterViewController == null) { throw new InvalidOperationException ("Cannot find a view controller from which to present"); } // // Create the browser // var browserVC = Activator.CreateInstance (iosUIViewControllerType); var browserV = Activator.CreateInstance (iosUIWebViewType); var nsUrl = iosNSUrl.GetMethod ("FromString").Invoke (null, new object[] { url }); var nsUrlRequest = iosNSUrlRequest.GetMethod ("FromUrl").Invoke (null, new object[] { nsUrl }); iosUIWebViewType.GetMethod ("LoadRequest").Invoke (browserV, new object[] { nsUrlRequest }); iosUIViewControllerType.GetProperty ("View").SetValue (browserVC, browserV, null); var m = iosUIViewControllerType.GetMethod ("PresentViewController"); // Console.WriteLine (presenterViewController); // Console.WriteLine (browserVC); m.Invoke (presenterViewController, new object[] { browserVC, false, null }); } static Type GetObjectType (object o) { var t = typeof (object); if (o is IReflectableType rt) { t = rt.GetTypeInfo ().AsType (); } else if (o != null) { t = o.GetType (); } return t; } static void StartBrowserProcess (string url) { // var vs = Environment.GetEnvironmentVariables (); // foreach (System.Collections.DictionaryEntry kv in vs) { // System.Console.WriteLine($"K={kv.Key}, V={kv.Value}"); // } // Console.WriteLine ($"Process.Start {cmd} {args}"); if (Environment.OSVersion.Platform == PlatformID.Unix) { Process.Start ("open", url); } else { Process.Start (new ProcessStartInfo (url) { UseShellExecute = true }); } } } }