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}\"");
}