diff --git a/Documentation/guides/OneDotNet.md b/Documentation/guides/OneDotNet.md index 27e1d728500..a87f19e20d4 100644 --- a/Documentation/guides/OneDotNet.md +++ b/Documentation/guides/OneDotNet.md @@ -195,12 +195,47 @@ It is recommended to migrate to the new linker settings, as There are currently a few "verbs" we are aiming to get working in Xamarin.Android: + dotnet new dotnet build dotnet publish dotnet run -Currently in .NET 5 console apps, `dotnet publish` is where all the -work to produce a self-contained "app" happens: +### dotnet new + +To support `dotnet new`, we created a few basic project and item +templates for Android that are named following the patterns and naming +of existing .NET templates: + + Templates Short Name Language Tags + -------------------------------------------- ------------------- ---------- ---------------------- + Android Activity template android-activity [C#] Android + Android Java Library Binding android-bindinglib [C#] Android + Android Layout template android-layout [C#] Android + Android Class library androidlib [C#] Android + Android Application android [C#] Android + Console Application console [C#],F#,VB Common/Console + Class library classlib [C#],F#,VB Common/Library + WPF Application wpf [C#],VB Common/WPF + WPF Class library wpflib [C#],VB Common/WPF + NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit + NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit + +To create different types of Android projects: + + dotnet new android --output MyAndroidApp --packageName com.mycompany.myandroidapp + dotnet new androidlib --output MyAndroidLibrary + dotnet new android-bindinglib --output MyJavaBinding + +Once the projects are created, some basic item templates can also be +used such as: + + dotnet new android-activity --name LoginActivity --namespace MyAndroidApp + dotnet new android-layout --name MyLayout --output Resources/layout + +### dotnet build & publish + +Currently in .NET console apps, `dotnet publish` is where all the work +to produce a self-contained "app" happens: * The linker via the `` MSBuild task * .NET Core's version of AOT, named "ReadyToRun" @@ -229,12 +264,18 @@ Play, ad-hoc distribution, etc. It could be able to sign the `.apk` or `.aab` with different keys. As a starting point, this will currently copy the output to a `publish` directory on disk. +[illink]: https://github.com/mono/linker/blob/master/src/linker/README.md + +### dotnet run + `dotnet run` can be used to launch applications on a device or emulator via the `--project` switch: dotnet run --project HelloAndroid.csproj -[illink]: https://github.com/mono/linker/blob/master/src/linker/README.md +Alternatively, you could use the `Run` MSBuild target such as: + + dotnet build HelloAndroid.csproj -t:Run ### Preview testing diff --git a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateWixFile.cs b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateWixFile.cs index 5199f76f9d0..e92e965d507 100644 --- a/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateWixFile.cs +++ b/build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateWixFile.cs @@ -108,9 +108,22 @@ public override bool Execute () packWriter.WriteStartElement ("Directory"); packWriter.WriteAttributeString ("Id", "packs"); packWriter.WriteAttributeString ("Name", "packs"); + packWriter.WriteAttributeString ("FileSource", packs_dir); foreach (var directory in Directory.EnumerateDirectories (packs_dir, "Microsoft.Android.*")) { RecurseDirectory (packs_dir, packWriter, componentWriter, directory); } + packWriter.WriteEndElement (); // packs + + // template-packs + var templates_dir = Path.Combine (DotNetPath, "template-packs"); + packWriter.WriteStartElement ("Directory"); + packWriter.WriteAttributeString ("Id", "templatepacks"); + packWriter.WriteAttributeString ("Name", "template-packs"); + packWriter.WriteAttributeString ("FileSource", templates_dir); + foreach (var file in Directory.EnumerateFiles (templates_dir, "Microsoft.Android.Templates.*.nupkg")) { + AddFile (templates_dir, packWriter, componentWriter, file); + } + packWriter.WriteEndElement (); // template-packs packWriter.WriteEndDocument (); // componentWriter.WriteEndDocument (); // @@ -145,22 +158,27 @@ static void RecurseDirectory (string top_dir, XmlWriter packWriter, XmlWriter co var fileName = Path.GetFileName (file); if (fileName.StartsWith (".") || fileName.StartsWith ("_")) continue; - var componentId = GetId (top_dir, file); - packWriter.WriteStartElement ("Component"); - packWriter.WriteAttributeString ("Id", componentId); - packWriter.WriteStartElement ("File"); - packWriter.WriteAttributeString ("Id", componentId); - packWriter.WriteAttributeString ("Name", Path.GetFileName (file)); - packWriter.WriteAttributeString ("KeyPath", "yes"); - packWriter.WriteEndElement (); // - packWriter.WriteEndElement (); // - componentWriter.WriteStartElement ("ComponentRef"); - componentWriter.WriteAttributeString ("Id", componentId); - componentWriter.WriteEndElement (); // + AddFile (top_dir, packWriter, componentWriter, file); } packWriter.WriteEndElement (); // } + static void AddFile (string top_dir, XmlWriter packWriter, XmlWriter componentWriter, string file) + { + string componentId = GetId (top_dir, file); + packWriter.WriteStartElement ("Component"); + packWriter.WriteAttributeString ("Id", componentId); + packWriter.WriteStartElement ("File"); + packWriter.WriteAttributeString ("Id", componentId); + packWriter.WriteAttributeString ("Name", Path.GetFileName (file)); + packWriter.WriteAttributeString ("KeyPath", "yes"); + packWriter.WriteEndElement (); // + packWriter.WriteEndElement (); // + componentWriter.WriteStartElement ("ComponentRef"); + componentWriter.WriteAttributeString ("Id", componentId); + componentWriter.WriteEndElement (); // + } + static string GetId (string top_dir, string path) { if (string.IsNullOrEmpty (path)) diff --git a/build-tools/create-dotnet-pkg/create-dotnet-pkg.csproj b/build-tools/create-dotnet-pkg/create-dotnet-pkg.csproj index 9ad5c8e1657..2ad0d1baf16 100644 --- a/build-tools/create-dotnet-pkg/create-dotnet-pkg.csproj +++ b/build-tools/create-dotnet-pkg/create-dotnet-pkg.csproj @@ -35,6 +35,7 @@ <_FilesToCopy Include="$(DotNetPreviewPath)\sdk-manifests\$(DotNetPreviewVersionBand)\Microsoft.NET.Workload.Android\**\*" /> <_FilesToCopy Include="$(DotNetPreviewPath)\packs\Microsoft.Android.Ref\**\*" /> <_FilesToCopy Include="$(DotNetPreviewPath)\packs\Microsoft.Android.Sdk.osx-x64\**\*" /> + <_FilesToCopy Include="$(DotNetPreviewPath)\template-packs\Microsoft.Android.Templates.*.nupkg" /> + <_WLPacks Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\nupkgs\Microsoft.Android.Sdk.win-x64.*.nupkg" Condition=" '$(HostOS)' == 'Windows' " /> <_WLPacks Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\nupkgs\Microsoft.Android.Ref.*.nupkg" /> + <_WLTemplates Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\nupkgs\Microsoft.Android.Templates.*.nupkg" /> @@ -106,6 +108,8 @@ SourceFiles="@(_WLPacks)" DestinationFolder="$(DotNetPreviewPath)packs\$([System.String]::Copy('%(_WLPacks.Filename)').Replace('.$(_WLPackVersion)', ''))\$(_WLPackVersion)" /> + + <_UnixExecutables Include="$(DotNetPreviewPath)packs\Microsoft.Android.Sdk.*\*\tools\$(HostOS)\**\*.*" /> <_FilesToTouch Include="$(DotNetPreviewPath)sdk-manifests\$(DotNetPreviewVersionBand)\Microsoft.NET.Workload.Android\**" /> @@ -129,6 +133,7 @@ <_PackFilesToDelete Include="$(DotNetPreviewPath)sdk-manifests\$(DotNetPreviewVersionBand)\Microsoft.Android.Workload\**\*.*" /> <_PackFilesToDelete Include="$(DotNetPreviewPath)sdk-manifests\$(DotNetPreviewVersionBand)\Microsoft.NET.Workload.Android\**\*.*" /> <_PackFilesToDelete Include="$(DotNetPreviewPath)packs\Microsoft.Android*\**\*.*" /> + <_PackFilesToDelete Include="$(DotNetPreviewPath)template-packs\Microsoft.Android.Templates.*.nupkg" /> diff --git a/build-tools/create-packs/Microsoft.NET.Workload.Android.proj b/build-tools/create-packs/Microsoft.NET.Workload.Android.proj index dc9cfb59863..1e040f874de 100644 --- a/build-tools/create-packs/Microsoft.NET.Workload.Android.proj +++ b/build-tools/create-packs/Microsoft.NET.Workload.Android.proj @@ -36,7 +36,7 @@ workload manifest pack containing information about the various Microsoft.Androi + Replacements="@SDK_PACK_VERSION@=$(AndroidPackVersionLong);@REF_PACK_VERSION@=$(AndroidPackVersionLong);@TEMPLATE_PACK_VERSION@=$(AndroidPackVersionLong);"> diff --git a/src/Microsoft.Android.Templates/Directory.Build.targets b/src/Microsoft.Android.Templates/Directory.Build.targets new file mode 100644 index 00000000000..b9dcceb6e79 --- /dev/null +++ b/src/Microsoft.Android.Templates/Directory.Build.targets @@ -0,0 +1,15 @@ + + + + + _GetDefaultPackageVersion; + $(BeforePack); + + + + + $(AndroidPackVersionLong)+sha.$(XAVersionHash) + + + diff --git a/src/Microsoft.Android.Templates/Microsoft.Android.Templates.csproj b/src/Microsoft.Android.Templates/Microsoft.Android.Templates.csproj new file mode 100644 index 00000000000..b5b78b0fe6d --- /dev/null +++ b/src/Microsoft.Android.Templates/Microsoft.Android.Templates.csproj @@ -0,0 +1,23 @@ + + + + netstandard2.0 + Template + Microsoft.Android.Templates + .NET Android Templates + Microsoft + Templates for Android platforms. + true + false + content + ..\..\bin\Build$(Configuration)\nupkgs\ + + + + + + + + + + diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/template.json b/src/Microsoft.Android.Templates/android-activity/.template.config/template.json new file mode 100644 index 00000000000..e2e9417239d --- /dev/null +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/template.json @@ -0,0 +1,25 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Microsoft", + "classifications": [ "Android" ], + "name": "Android Activity template", + "description": "An Android Activity class", + "tags": { + "language": "C#", + "type": "item" + }, + "identity": "Microsoft.Android.AndroidActivity", + "shortName": "android-activity", + "sourceName": "Activity1", + "primaryOutputs": [ + { "path": "Activity1.cs" } + ], + "defaultName": "Activity1", + "symbols": { + "namespace": { + "description": "namespace for the generated code", + "replaces": "AndroidApp1", + "type": "parameter" + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-activity/Activity1.cs b/src/Microsoft.Android.Templates/android-activity/Activity1.cs new file mode 100644 index 00000000000..f974a451ba3 --- /dev/null +++ b/src/Microsoft.Android.Templates/android-activity/Activity1.cs @@ -0,0 +1,18 @@ +using Android.App; +using Android.OS; +using Android.Runtime; +using Android.Widget; + +namespace AndroidApp1 +{ + [Activity(Label = "@string/app_name", MainLauncher = true)] + public class Activity1 : Activity + { + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + + // Create your application here + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-bindinglib/.template.config/template.json b/src/Microsoft.Android.Templates/android-bindinglib/.template.config/template.json new file mode 100644 index 00000000000..fa0ce3e3110 --- /dev/null +++ b/src/Microsoft.Android.Templates/android-bindinglib/.template.config/template.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Microsoft", + "classifications": [ "Android" ], + "identity": "Microsoft.Android.AndroidBinding", + "name": "Android Java Library Binding", + "description": "A project for creating an Android class library that binds to a native Java library", + "shortName": "android-bindinglib", + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "AndroidBinding1", + "preferNameDirectory": true, + "primaryOutputs": [ + { "path": "AndroidBinding1.csproj" } + ], + "defaultName": "AndroidBinding1" +} \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-bindinglib/Additions/AboutAdditions.txt b/src/Microsoft.Android.Templates/android-bindinglib/Additions/AboutAdditions.txt new file mode 100644 index 00000000000..2775bd360d2 --- /dev/null +++ b/src/Microsoft.Android.Templates/android-bindinglib/Additions/AboutAdditions.txt @@ -0,0 +1,48 @@ +Additions allow you to add arbitrary C# to the generated classes +before they are compiled. This can be helpful for providing convenience +methods or adding pure C# classes. + +== Adding Methods to Generated Classes == + +Let's say the library being bound has a Rectangle class with a constructor +that takes an x and y position, and a width and length size. It will look like +this: + +public partial class Rectangle +{ + public Rectangle (int x, int y, int width, int height) + { + // JNI bindings + } +} + +Imagine we want to add a constructor to this class that takes a Point and +Size structure instead of 4 ints. We can add a new file called Rectangle.cs +with a partial class containing our new method: + +public partial class Rectangle +{ + public Rectangle (Point location, Size size) : + this (location.X, location.Y, size.Width, size.Height) + { + } +} + +At compile time, the additions class will be added to the generated class +and the final assembly will a Rectangle class with both constructors. + + +== Adding C# Classes == + +Another thing that can be done is adding fully C# managed classes to the +generated library. In the above example, let's assume that there isn't a +Point class available in Java or our library. The one we create doesn't need +to interact with Java, so we'll create it like a normal class in C#. + +By adding a Point.cs file with this class, it will end up in the binding library: + +public class Point +{ + public int X { get; set; } + public int Y { get; set; } +} \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-bindinglib/AndroidBinding1.csproj b/src/Microsoft.Android.Templates/android-bindinglib/AndroidBinding1.csproj new file mode 100644 index 00000000000..7cf29802739 --- /dev/null +++ b/src/Microsoft.Android.Templates/android-bindinglib/AndroidBinding1.csproj @@ -0,0 +1,6 @@ + + + net6.0-android + AndroidBinding1 + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-bindinglib/Transforms/EnumFields.xml b/src/Microsoft.Android.Templates/android-bindinglib/Transforms/EnumFields.xml new file mode 100644 index 00000000000..22959957ec2 --- /dev/null +++ b/src/Microsoft.Android.Templates/android-bindinglib/Transforms/EnumFields.xml @@ -0,0 +1,14 @@ + + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-bindinglib/Transforms/EnumMethods.xml b/src/Microsoft.Android.Templates/android-bindinglib/Transforms/EnumMethods.xml new file mode 100644 index 00000000000..49216c6183c --- /dev/null +++ b/src/Microsoft.Android.Templates/android-bindinglib/Transforms/EnumMethods.xml @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-bindinglib/Transforms/Metadata.xml b/src/Microsoft.Android.Templates/android-bindinglib/Transforms/Metadata.xml new file mode 100644 index 00000000000..91493a25eaf --- /dev/null +++ b/src/Microsoft.Android.Templates/android-bindinglib/Transforms/Metadata.xml @@ -0,0 +1,9 @@ + + + diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/template.json b/src/Microsoft.Android.Templates/android-layout/.template.config/template.json new file mode 100644 index 00000000000..ef68c57ddf9 --- /dev/null +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/template.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Microsoft", + "classifications": [ "Android" ], + "name": "Android Layout template", + "description": "An Android layout (XML) file", + "tags": { + "language": "C#", + "type": "item" + }, + "identity": "Microsoft.Android.AndroidLayout", + "shortName": "android-layout", + "sourceName": "Layout", + "primaryOutputs": [ + { "path": "Layout.xml" } + ], + "defaultName": "Layout" +} \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/Layout.xml b/src/Microsoft.Android.Templates/android-layout/Layout.xml new file mode 100644 index 00000000000..d829e291cca --- /dev/null +++ b/src/Microsoft.Android.Templates/android-layout/Layout.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/.template.config/template.json b/src/Microsoft.Android.Templates/android/.template.config/template.json new file mode 100644 index 00000000000..734cb956702 --- /dev/null +++ b/src/Microsoft.Android.Templates/android/.template.config/template.json @@ -0,0 +1,27 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Microsoft", + "classifications": [ "Android" ], + "identity": "Microsoft.Android.AndroidApp", + "name": "Android Application", + "description": "A project for creating an Android application", + "shortName": "android", + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "AndroidApp1", + "preferNameDirectory": true, + "primaryOutputs": [ + { "path": "AndroidApp1.csproj" } + ], + "symbols": { + "packageName": { + "type": "parameter", + "description": "Overrides the package name in the AndroidManifest.xml", + "datatype": "string", + "replaces": "com.companyname.AndroidApp1" + } + }, + "defaultName": "AndroidApp1" +} \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/AndroidApp1.csproj b/src/Microsoft.Android.Templates/android/AndroidApp1.csproj new file mode 100644 index 00000000000..a46e175509f --- /dev/null +++ b/src/Microsoft.Android.Templates/android/AndroidApp1.csproj @@ -0,0 +1,7 @@ + + + net6.0-android + AndroidApp1 + Exe + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/AndroidManifest.xml b/src/Microsoft.Android.Templates/android/AndroidManifest.xml new file mode 100644 index 00000000000..3ce625444d4 --- /dev/null +++ b/src/Microsoft.Android.Templates/android/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/MainActivity.cs b/src/Microsoft.Android.Templates/android/MainActivity.cs new file mode 100644 index 00000000000..7e49926946e --- /dev/null +++ b/src/Microsoft.Android.Templates/android/MainActivity.cs @@ -0,0 +1,19 @@ +using Android.App; +using Android.OS; +using Android.Runtime; +using Android.Widget; + +namespace AndroidApp1 +{ + [Activity(Label = "@string/app_name", MainLauncher = true)] + public class MainActivity : Activity + { + protected override void OnCreate(Bundle savedInstanceState) + { + base.OnCreate(savedInstanceState); + + // Set our view from the "main" layout resource + SetContentView(Resource.Layout.activity_main); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/Resources/AboutResources.txt b/src/Microsoft.Android.Templates/android/Resources/AboutResources.txt new file mode 100644 index 00000000000..219f42544be --- /dev/null +++ b/src/Microsoft.Android.Templates/android/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.xml), +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.xml + + 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 "Resource" +(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 Resource class would expose: + +public class Resource { + 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 Resource.Drawable.icon to reference the drawable/icon.png file, or +Resource.Layout.main to reference the layout/main.xml file, or Resource.Strings.first_string +to reference the first string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/Resources/layout/activity_main.xml b/src/Microsoft.Android.Templates/android/Resources/layout/activity_main.xml new file mode 100644 index 00000000000..f94985291bf --- /dev/null +++ b/src/Microsoft.Android.Templates/android/Resources/layout/activity_main.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/src/Microsoft.Android.Templates/android/Resources/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000000..036d09bc5fd --- /dev/null +++ b/src/Microsoft.Android.Templates/android/Resources/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml b/src/Microsoft.Android.Templates/android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000000..036d09bc5fd --- /dev/null +++ b/src/Microsoft.Android.Templates/android/Resources/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000000..2531cb31efc Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 00000000000..7a859c25556 Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher_round.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000000..b8d35b3a1cf Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000000..795ea7c0058 Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher_foreground.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 00000000000..a12b157f00e Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher_round.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000000..8f56909cddf Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000000..761cc91d90f Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher_foreground.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000000..e7d70a5e2d1 Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher_round.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..9737d79c049 Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000000..9133e31b432 Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000000..73ccaa6a2b1 Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher_round.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..c3ae5f5ccde Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000000..d4fd714eeda Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000000..f6584afd4d1 Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher_round.png b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000000..ef89bd5215f Binary files /dev/null and b/src/Microsoft.Android.Templates/android/Resources/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/src/Microsoft.Android.Templates/android/Resources/values/ic_launcher_background.xml b/src/Microsoft.Android.Templates/android/Resources/values/ic_launcher_background.xml new file mode 100644 index 00000000000..6ec24e6413c --- /dev/null +++ b/src/Microsoft.Android.Templates/android/Resources/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #2C3E50 + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android/Resources/values/strings.xml b/src/Microsoft.Android.Templates/android/Resources/values/strings.xml new file mode 100644 index 00000000000..17f62c78ddc --- /dev/null +++ b/src/Microsoft.Android.Templates/android/Resources/values/strings.xml @@ -0,0 +1,4 @@ + + AndroidApp1 + Hello, Android! + diff --git a/src/Microsoft.Android.Templates/androidlib/.template.config/template.json b/src/Microsoft.Android.Templates/androidlib/.template.config/template.json new file mode 100644 index 00000000000..53991ab827a --- /dev/null +++ b/src/Microsoft.Android.Templates/androidlib/.template.config/template.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Microsoft", + "classifications": [ "Android" ], + "identity": "Microsoft.Android.AndroidLib", + "name": "Android Class library", + "description": "A project for creating an Android class library", + "shortName": "androidlib", + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "AndroidLib1", + "preferNameDirectory": true, + "primaryOutputs": [ + { "path": "AndroidLib1.csproj" } + ], + "defaultName": "AndroidLib1" +} \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/androidlib/AndroidLib1.csproj b/src/Microsoft.Android.Templates/androidlib/AndroidLib1.csproj new file mode 100644 index 00000000000..687d1512882 --- /dev/null +++ b/src/Microsoft.Android.Templates/androidlib/AndroidLib1.csproj @@ -0,0 +1,6 @@ + + + net6.0-android + AndroidLib1 + + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/androidlib/Class1.cs b/src/Microsoft.Android.Templates/androidlib/Class1.cs new file mode 100644 index 00000000000..1004d5770c0 --- /dev/null +++ b/src/Microsoft.Android.Templates/androidlib/Class1.cs @@ -0,0 +1,8 @@ +using System; + +namespace AndroidLib1 +{ + public class Class1 + { + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json index fabb3864057..67a76219882 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json @@ -5,7 +5,8 @@ "description": "Android SDK", "packs": [ "Microsoft.Android.Sdk", - "Microsoft.Android.Ref" + "Microsoft.Android.Ref", + "Microsoft.Android.Templates" ] } }, @@ -21,6 +22,10 @@ "Microsoft.Android.Ref": { "kind": "framework", "version": "@REF_PACK_VERSION@" + }, + "Microsoft.Android.Templates": { + "kind": "template", + "version": "@TEMPLATE_PACK_VERSION@" } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index dfbe56820a0..2dcf47e78db 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -177,6 +177,16 @@ public void DotNetBuildLibrary (bool isRelease, bool duplicateAar) StringAssert.Contains ("public const int MyLayout", resource_designer_text); } + [Test] + public void DotNetNew ([Values ("android", "androidlib", "android-bindinglib")] string template) + { + var dotnet = CreateDotNetBuilder (); + Assert.IsTrue (dotnet.New (template), $"`dotnet new {template}` should succeed"); + Assert.IsTrue (dotnet.New ("android-activity"), "`dotnet new android-activity` should succeed"); + Assert.IsTrue (dotnet.New ("android-layout", Path.Combine (dotnet.ProjectDirectory, "Resources", "layout")), "`dotnet new android-layout` should succeed"); + Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed"); + } + [Test] public void DotNetPack ([Values ("net6.0-android", "net6.0-android30")] string targetFramework) { @@ -466,6 +476,16 @@ void CreateEmptyFile (params string [] paths) } } + DotNetCLI CreateDotNetBuilder (string relativeProjectDir = null) + { + if (string.IsNullOrEmpty (relativeProjectDir)) { + relativeProjectDir = Path.Combine ("temp", TestName); + } + TestOutputDirectories [TestContext.CurrentContext.Test.ID] = + FullProjectDirectory = Path.Combine (Root, relativeProjectDir); + return new DotNetCLI (Path.Combine (FullProjectDirectory, $"{TestName}.csproj")); + } + DotNetCLI CreateDotNetBuilder (XASdkProject project, string relativeProjectDir = null) { if (string.IsNullOrEmpty (relativeProjectDir)) { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetCLI.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetCLI.cs index 599e379cd9e..622c1de4d87 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetCLI.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetCLI.cs @@ -21,13 +21,18 @@ public class DotNetCLI readonly XASdkProject project; readonly string projectOrSolution; - public DotNetCLI (XASdkProject project, string projectOrSolution) + public DotNetCLI (string projectOrSolution) { - this.project = project; this.projectOrSolution = projectOrSolution; ProjectDirectory = Path.GetDirectoryName (projectOrSolution); } + public DotNetCLI (XASdkProject project, string projectOrSolution) + : this (projectOrSolution) + { + this.project = project; + } + /// /// Runs the `dotnet` tool with the specified arguments. /// @@ -73,6 +78,16 @@ protected bool Execute (params string [] args) return succeeded; } + public bool New (string template, string output = null) + { + var arguments = new List { + "new", + template, + "--output", $"\"{output ?? ProjectDirectory}\"", + }; + return Execute (arguments.ToArray ()); + } + public bool Build (string target = null, string [] parameters = null) { var arguments = GetDefaultCommandLineArgs ("build", target, parameters); @@ -123,7 +138,6 @@ List GetDefaultCommandLineArgs (string verb, string target = null, strin var arguments = new List { verb, $"\"{projectOrSolution}\"", - $"/p:Configuration={project.Configuration}", "/noconsolelogger", $"/flp1:LogFile=\"{BuildLogFile}\";Encoding=UTF-8;Verbosity={Verbosity}", $"/bl:\"{Path.Combine (testDir, "msbuild.binlog")}\"" @@ -131,6 +145,9 @@ List GetDefaultCommandLineArgs (string verb, string target = null, strin if (!string.IsNullOrEmpty (target)) { arguments.Add ($"/t:{target}"); } + if (project != null) { + arguments.Add ($"/p:Configuration={project.Configuration}"); + } if (Directory.Exists (AndroidSdkPath)) { arguments.Add ($"/p:AndroidSdkDirectory=\"{AndroidSdkPath}\""); }