diff --git a/Ooui/Platform.cs b/Ooui/Platform.cs index e186c6c..951bd7a 100644 --- a/Ooui/Platform.cs +++ b/Ooui/Platform.cs @@ -14,10 +14,14 @@ namespace Ooui 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); + x => x.GetName ().Name); asms.TryGetValue ("Xamarin.iOS", out iosAssembly); if (iosAssembly != null) { @@ -27,6 +31,12 @@ namespace Ooui 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) @@ -34,11 +44,31 @@ namespace Ooui 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); @@ -83,8 +113,8 @@ namespace Ooui var m = iosUIViewControllerType.GetMethod ("PresentViewController"); - Console.WriteLine (presenterViewController); - Console.WriteLine (browserVC); + // Console.WriteLine (presenterViewController); + // Console.WriteLine (browserVC); m.Invoke (presenterViewController, new object[] { browserVC, false, null }); } @@ -116,7 +146,7 @@ namespace Ooui // System.Console.WriteLine($"K={kv.Key}, V={kv.Value}"); // } - Console.WriteLine ($"Process.Start {cmd} {args}"); + // Console.WriteLine ($"Process.Start {cmd} {args}"); return Process.Start (cmd, args); } } diff --git a/PlatformTests/AndroidTests/AndroidTests.csproj b/PlatformTests/AndroidTests/AndroidTests.csproj new file mode 100644 index 0000000..cf26080 --- /dev/null +++ b/PlatformTests/AndroidTests/AndroidTests.csproj @@ -0,0 +1,181 @@ + + + + Debug + AnyCPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + AndroidTests + AndroidTests + v7.0 + True + Resources\Resource.designer.cs + Resource + Resources + Assets + false + Properties\AndroidManifest.xml + + + true + full + false + bin\Debug + DEBUG;NUNIT + prompt + 4 + None + arm64-v8a;armeabi;armeabi-v7a;x86 + + + true + pdbonly + true + bin\Release + NUNIT + prompt + 4 + true + false + + + + + + + + + + + + + ..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll + + + + + + + + Ooui\Button.cs + + + Ooui\Canvas.cs + + + Ooui\CanvasRenderingContext2D.cs + + + Ooui\Color.cs + + + Ooui\Div.cs + + + Ooui\Element.cs + + + Ooui\EventTarget.cs + + + Ooui\Form.cs + + + Ooui\FormControl.cs + + + Ooui\Heading.cs + + + Ooui\Image.cs + + + Ooui\Input.cs + + + Ooui\Label.cs + + + Ooui\List.cs + + + Ooui\ListItem.cs + + + Ooui\Message.cs + + + Ooui\Node.cs + + + Ooui\Paragraph.cs + + + Ooui\Platform.cs + + + Ooui\Select.cs + + + Ooui\Span.cs + + + Ooui\Style.cs + + + Ooui\TextArea.cs + + + Ooui\TextNode.cs + + + Ooui\UI.cs + + + Tests\ButtonTests.cs + + + Tests\CanvasTests.cs + + + Tests\EventTargetTests.cs + + + Tests\MessageSendTests.cs + + + Tests\NodeTests.cs + + + Tests\StyleTests.cs + + + Tests\UITests.cs + + + + + + + + Ooui\Client.js + + + + + + + + + + + + + + Client.js + Ooui.Client.js + + + + \ No newline at end of file diff --git a/PlatformTests/AndroidTests/Assets/AboutAssets.txt b/PlatformTests/AndroidTests/Assets/AboutAssets.txt new file mode 100644 index 0000000..a9b0638 --- /dev/null +++ b/PlatformTests/AndroidTests/Assets/AboutAssets.txt @@ -0,0 +1,19 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with your package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); diff --git a/PlatformTests/AndroidTests/MainActivity.cs b/PlatformTests/AndroidTests/MainActivity.cs new file mode 100644 index 0000000..9d6450a --- /dev/null +++ b/PlatformTests/AndroidTests/MainActivity.cs @@ -0,0 +1,32 @@ +using System.Reflection; + +using Android.App; +using Android.OS; +using Android.Webkit; +using Xamarin.Android.NUnitLite; + +namespace AndroidTests +{ + [Activity (Label = "AndroidTests", MainLauncher = true)] + public class MainActivity : TestSuiteActivity + { + public static MainActivity Shared; + + public WebView Browser; + + protected override void OnCreate (Bundle bundle) + { + Browser = new WebView (this); + + Shared = this; + + // tests can be inside the main assembly + AddTest (Assembly.GetExecutingAssembly ()); + // or in any reference assemblies + // AddTest (typeof (Your.Library.TestClass).Assembly); + + // Once you called base.OnCreate(), you cannot add more assemblies. + base.OnCreate (bundle); + } + } +} diff --git a/PlatformTests/AndroidTests/PresentTests.cs b/PlatformTests/AndroidTests/PresentTests.cs new file mode 100644 index 0000000..a43e015 --- /dev/null +++ b/PlatformTests/AndroidTests/PresentTests.cs @@ -0,0 +1,18 @@ +using System; +using NUnit.Framework; +using Ooui; + +namespace Tests +{ + [TestFixture] + public class PresentTests + { + [TestCase] + public void Present () + { + var b = new Button ("Click Me"); + UI.Publish ("/b", b); + UI.Present ("/b", AndroidTests.MainActivity.Shared.Browser); + } + } +} diff --git a/PlatformTests/AndroidTests/Properties/AndroidManifest.xml b/PlatformTests/AndroidTests/Properties/AndroidManifest.xml new file mode 100644 index 0000000..3a44a3d --- /dev/null +++ b/PlatformTests/AndroidTests/Properties/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/PlatformTests/AndroidTests/Properties/AssemblyInfo.cs b/PlatformTests/AndroidTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8c6b547 --- /dev/null +++ b/PlatformTests/AndroidTests/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using Android.App; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("AndroidTests")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("${AuthorCopyright}")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.0")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/PlatformTests/AndroidTests/Resources/AboutResources.txt b/PlatformTests/AndroidTests/Resources/AboutResources.txt new file mode 100644 index 0000000..10f52d4 --- /dev/null +++ b/PlatformTests/AndroidTests/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. diff --git a/PlatformTests/AndroidTests/Resources/Resource.designer.cs b/PlatformTests/AndroidTests/Resources/Resource.designer.cs new file mode 100644 index 0000000..b0f5a1a --- /dev/null +++ b/PlatformTests/AndroidTests/Resources/Resource.designer.cs @@ -0,0 +1,175 @@ +#pragma warning disable 1591 +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +[assembly: Android.Runtime.ResourceDesignerAttribute("AndroidTests.Resource", IsApplication=true)] + +namespace AndroidTests +{ + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + global::Xamarin.Android.NUnitLite.Resource.Id.OptionHostName = global::AndroidTests.Resource.Id.OptionHostName; + global::Xamarin.Android.NUnitLite.Resource.Id.OptionPort = global::AndroidTests.Resource.Id.OptionPort; + global::Xamarin.Android.NUnitLite.Resource.Id.OptionRemoteServer = global::AndroidTests.Resource.Id.OptionRemoteServer; + global::Xamarin.Android.NUnitLite.Resource.Id.OptionsButton = global::AndroidTests.Resource.Id.OptionsButton; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultFullName = global::AndroidTests.Resource.Id.ResultFullName; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultMessage = global::AndroidTests.Resource.Id.ResultMessage; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultResultState = global::AndroidTests.Resource.Id.ResultResultState; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultRunSingleMethodTest = global::AndroidTests.Resource.Id.ResultRunSingleMethodTest; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultStackTrace = global::AndroidTests.Resource.Id.ResultStackTrace; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsFailed = global::AndroidTests.Resource.Id.ResultsFailed; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsId = global::AndroidTests.Resource.Id.ResultsId; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsIgnored = global::AndroidTests.Resource.Id.ResultsIgnored; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsInconclusive = global::AndroidTests.Resource.Id.ResultsInconclusive; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsMessage = global::AndroidTests.Resource.Id.ResultsMessage; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsPassed = global::AndroidTests.Resource.Id.ResultsPassed; + global::Xamarin.Android.NUnitLite.Resource.Id.ResultsResult = global::AndroidTests.Resource.Id.ResultsResult; + global::Xamarin.Android.NUnitLite.Resource.Id.RunTestsButton = global::AndroidTests.Resource.Id.RunTestsButton; + global::Xamarin.Android.NUnitLite.Resource.Id.TestSuiteListView = global::AndroidTests.Resource.Id.TestSuiteListView; + global::Xamarin.Android.NUnitLite.Resource.Layout.options = global::AndroidTests.Resource.Layout.options; + global::Xamarin.Android.NUnitLite.Resource.Layout.results = global::AndroidTests.Resource.Layout.results; + global::Xamarin.Android.NUnitLite.Resource.Layout.test_result = global::AndroidTests.Resource.Layout.test_result; + global::Xamarin.Android.NUnitLite.Resource.Layout.test_suite = global::AndroidTests.Resource.Layout.test_suite; + } + + public partial class Attribute + { + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7f040001 + public const int OptionHostName = 2130968577; + + // aapt resource value: 0x7f040002 + public const int OptionPort = 2130968578; + + // aapt resource value: 0x7f040000 + public const int OptionRemoteServer = 2130968576; + + // aapt resource value: 0x7f040010 + public const int OptionsButton = 2130968592; + + // aapt resource value: 0x7f04000b + public const int ResultFullName = 2130968587; + + // aapt resource value: 0x7f04000d + public const int ResultMessage = 2130968589; + + // aapt resource value: 0x7f04000c + public const int ResultResultState = 2130968588; + + // aapt resource value: 0x7f04000a + public const int ResultRunSingleMethodTest = 2130968586; + + // aapt resource value: 0x7f04000e + public const int ResultStackTrace = 2130968590; + + // aapt resource value: 0x7f040006 + public const int ResultsFailed = 2130968582; + + // aapt resource value: 0x7f040003 + public const int ResultsId = 2130968579; + + // aapt resource value: 0x7f040007 + public const int ResultsIgnored = 2130968583; + + // aapt resource value: 0x7f040008 + public const int ResultsInconclusive = 2130968584; + + // aapt resource value: 0x7f040009 + public const int ResultsMessage = 2130968585; + + // aapt resource value: 0x7f040005 + public const int ResultsPassed = 2130968581; + + // aapt resource value: 0x7f040004 + public const int ResultsResult = 2130968580; + + // aapt resource value: 0x7f04000f + public const int RunTestsButton = 2130968591; + + // aapt resource value: 0x7f040011 + public const int TestSuiteListView = 2130968593; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7f030000 + public const int options = 2130903040; + + // aapt resource value: 0x7f030001 + public const int results = 2130903041; + + // aapt resource value: 0x7f030002 + public const int test_result = 2130903042; + + // aapt resource value: 0x7f030003 + public const int test_suite = 2130903043; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class Mipmap + { + + // aapt resource value: 0x7f020000 + public const int Icon = 2130837504; + + static Mipmap() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Mipmap() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/PlatformTests/AndroidTests/Resources/mipmap-hdpi/Icon.png b/PlatformTests/AndroidTests/Resources/mipmap-hdpi/Icon.png new file mode 100644 index 0000000..f4c8046 Binary files /dev/null and b/PlatformTests/AndroidTests/Resources/mipmap-hdpi/Icon.png differ diff --git a/PlatformTests/AndroidTests/Resources/mipmap-mdpi/Icon.png b/PlatformTests/AndroidTests/Resources/mipmap-mdpi/Icon.png new file mode 100644 index 0000000..ef1e1ee Binary files /dev/null and b/PlatformTests/AndroidTests/Resources/mipmap-mdpi/Icon.png differ diff --git a/PlatformTests/AndroidTests/Resources/mipmap-xhdpi/Icon.png b/PlatformTests/AndroidTests/Resources/mipmap-xhdpi/Icon.png new file mode 100644 index 0000000..b7e2e57 Binary files /dev/null and b/PlatformTests/AndroidTests/Resources/mipmap-xhdpi/Icon.png differ diff --git a/PlatformTests/AndroidTests/Resources/mipmap-xxhdpi/Icon.png b/PlatformTests/AndroidTests/Resources/mipmap-xxhdpi/Icon.png new file mode 100644 index 0000000..8d20a38 Binary files /dev/null and b/PlatformTests/AndroidTests/Resources/mipmap-xxhdpi/Icon.png differ diff --git a/PlatformTests/AndroidTests/Resources/mipmap-xxxhdpi/Icon.png b/PlatformTests/AndroidTests/Resources/mipmap-xxxhdpi/Icon.png new file mode 100644 index 0000000..6d9919c Binary files /dev/null and b/PlatformTests/AndroidTests/Resources/mipmap-xxxhdpi/Icon.png differ diff --git a/PlatformTests/AndroidTests/packages.config b/PlatformTests/AndroidTests/packages.config new file mode 100644 index 0000000..615cbd1 --- /dev/null +++ b/PlatformTests/AndroidTests/packages.config @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PlatformTests/PlatformTests.sln b/PlatformTests/PlatformTests.sln index aa1b823..8cd266e 100644 --- a/PlatformTests/PlatformTests.sln +++ b/PlatformTests/PlatformTests.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOSTests", "iOSTests\iOSTests.csproj", "{1379E3B3-99A7-4B46-BED6-1338A94EBBD4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidTests", "AndroidTests\AndroidTests.csproj", "{7E8BF65C-4AA9-4F95-A8E3-527424138AB3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -25,5 +27,17 @@ Global {1379E3B3-99A7-4B46-BED6-1338A94EBBD4}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator {1379E3B3-99A7-4B46-BED6-1338A94EBBD4}.Debug|iPhone.ActiveCfg = Debug|iPhone {1379E3B3-99A7-4B46-BED6-1338A94EBBD4}.Debug|iPhone.Build.0 = Debug|iPhone + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Release|Any CPU.Build.0 = Release|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Release|iPhone.ActiveCfg = Release|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Release|iPhone.Build.0 = Release|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {7E8BF65C-4AA9-4F95-A8E3-527424138AB3}.Debug|iPhone.Build.0 = Debug|Any CPU EndGlobalSection EndGlobal diff --git a/PlatformTests/iOSTests/PresentTests.cs b/PlatformTests/iOSTests/PresentTests.cs index 04bdeeb..cbdc108 100644 --- a/PlatformTests/iOSTests/PresentTests.cs +++ b/PlatformTests/iOSTests/PresentTests.cs @@ -2,7 +2,7 @@ using NUnit.Framework; using Ooui; -namespace iOSTests +namespace Tests { [TestFixture] public class PresentTests diff --git a/Tests/ButtonTests.cs b/Tests/ButtonTests.cs index e0e3eed..74a6409 100644 --- a/Tests/ButtonTests.cs +++ b/Tests/ButtonTests.cs @@ -5,7 +5,7 @@ using NUnit.Framework; using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; using TestMethodAttribute = NUnit.Framework.TestCaseAttribute; #else -using Microsoft.VisualStudio.TestTools.UnitTesting; +using MicrosofVisualStudio.TestTools.UnitTesting; #endif using Ooui;