Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[One .NET] support latest C# 10 language features #6118

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
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)
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
<TargetFramework>net6.0-android</TargetFramework>
<SupportedOSPlatformVersion>SUPPORTED_OS_PLATFORM_VERSION</SupportedOSPlatformVersion>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">AndroidBinding1</RootNamespace>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we update AndroidBinding1.csproj to also set $(AndroidGenerateResourceDesigner)=False, as per #6224?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can have an .aar with resources, then you might want to use Resource.designer.cs values from C#.

So I don't think we need this by default, but it's there if you need to turn it off.

</PropertyGroup>
</Project>
2 changes: 2 additions & 0 deletions src/Microsoft.Android.Templates/android/AndroidApp1.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
<SupportedOSPlatformVersion>SUPPORTED_OS_PLATFORM_VERSION</SupportedOSPlatformVersion>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">AndroidApp1</RootNamespace>
<OutputType>Exe</OutputType>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
7 changes: 1 addition & 6 deletions src/Microsoft.Android.Templates/android/MainActivity.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
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)
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
<TargetFramework>net6.0-android</TargetFramework>
<SupportedOSPlatformVersion>SUPPORTED_OS_PLATFORM_VERSION</SupportedOSPlatformVersion>
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">AndroidLib1</RootNamespace>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
2 changes: 0 additions & 2 deletions src/Microsoft.Android.Templates/androidlib/Class1.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;

namespace AndroidLib1
{
public class Class1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ https://github.com/dotnet/designs/blob/4703666296f5e59964961464c25807c727282cae/
<_DefaultJavaSourceJarPattern>**\*-source.jar;**\*-sources.jar;**\*-src.jar</_DefaultJavaSourceJarPattern>
</PropertyGroup>

<ItemGroup Condition=" '$(TargetPlatformIdentifier)' == 'android' and ('$(ImplicitUsings)' == 'true' or '$(ImplicitUsings)' == 'enable') ">
<Using Include="Android.App" />
<Using Include="Android.Widget" />
<Using Include="Android.OS.Bundle" Alias="Bundle" />
</ItemGroup>

<ItemGroup Condition=" '$(EnableDefaultAndroidItems)' == 'true' ">
<!-- Default Resource file inclusion -->
<!-- https://developer.android.com/guide/topics/resources/providing-resources -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ protected override void CleanupTest ()
{
if (HasDevices && TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed &&
TestOutputDirectories.TryGetValue (TestContext.CurrentContext.Test.ID, out string outputDir)) {
Directory.CreateDirectory (outputDir);
string local = Path.Combine (outputDir, "screenshot.png");
string deviceLog = Path.Combine (outputDir, "logcat-failed.log");
string remote = "/data/local/tmp/screenshot.png";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ public void DotNetNew ([Values ("android", "androidlib", "android-bindinglib")]
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");
dotnet.AssertHasNoWarnings ();
}

[Test]
Expand Down Expand Up @@ -519,7 +520,7 @@ public void SupportedOSPlatformVersion ([Values (21, 30)] int minSdkVersion)
};
// Call AccessibilityTraversalAfter from API level 22
// https://developer.android.com/reference/android/view/View#getAccessibilityTraversalAfter()
proj.MainActivity = proj.DefaultMainActivity.Replace ("button.Click", "button.AccessibilityTraversalAfter.ToString ();\nbutton.Click");
proj.MainActivity = proj.DefaultMainActivity.Replace ("button!.Click", "button!.AccessibilityTraversalAfter.ToString ();\nbutton!.Click");

var dotnet = CreateDotNetBuilder (proj);
Assert.IsTrue (dotnet.Build (), "`dotnet build` should succeed");
Expand Down Expand Up @@ -614,7 +615,7 @@ void CreateEmptyFile (params string [] paths)
public void XamarinLegacySdk ()
{
var proj = new XASdkProject (outputType: "Library") {
Sdk = "Xamarin.Legacy.Sdk/0.1.0-alpha2",
Sdk = "Xamarin.Legacy.Sdk/0.1.0-alpha4",
Sources = {
new AndroidItem.AndroidLibrary ("javaclasses.jar") {
BinaryContent = () => ResourceData.JavaSourceJarTestJar,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public static class KnownProperties
public const string AndroidFastDeploymentType = "AndroidFastDeploymentType";
public const string AndroidClassParser = "AndroidClassParser";
public const string _AndroidAllowDeltaInstall = "_AndroidAllowDeltaInstall";
public const string Nullable = "Nullable";
public const string ImplicitUsings = "ImplicitUsings";
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static XASdkProject ()
var assembly = typeof (XASdkProject).Assembly;
using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.AndroidManifest.xml")))
default_android_manifest = sr.ReadToEnd ();
using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.MainActivity.cs")))
using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.DotNet.MainActivity.cs")))
default_main_activity_cs = sr.ReadToEnd ();
using (var sr = new StreamReader (assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.LayoutMain.axml")))
default_layout_main = sr.ReadToEnd ();
Expand Down Expand Up @@ -61,6 +61,8 @@ public XASdkProject (string outputType = "Exe", [CallerMemberName] string packag
JavaPackageName = JavaPackageName ?? PackageName.ToLowerInvariant ();
GlobalPackagesFolder = FileSystemUtils.FindNugetGlobalPackageFolder ();
SetProperty (KnownProperties.OutputType, outputType);
SetProperty (KnownProperties.Nullable, "enable");
SetProperty (KnownProperties.ImplicitUsings, "enable");

// Add relevant Android content to our project without writing it to the .csproj file
if (outputType == "Exe") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public class XamarinAndroidApplicationProject : XamarinAndroidCommonProject

static XamarinAndroidApplicationProject ()
{
using (var sr = new StreamReader (typeof(XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.MainActivity.cs")))
var folder = Builder.UseDotNet ? "DotNet" : "Base";
using (var sr = new StreamReader (typeof(XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ($"Xamarin.ProjectTools.Resources.{folder}.MainActivity.cs")))
default_main_activity_cs = sr.ReadToEnd ();
using (var sr = new StreamReader (typeof(XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.MainActivity.fs")))
default_main_activity_fs = sr.ReadToEnd ();
Expand All @@ -40,6 +41,8 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
{
if (Builder.UseDotNet) {
SetProperty (KnownProperties.OutputType, "Exe");
SetProperty (KnownProperties.Nullable, "enable");
SetProperty (KnownProperties.ImplicitUsings, "enable");
SetProperty ("XamarinAndroidSupportSkipVerifyVersions", "True");
SetProperty ("_FastDeploymentDiagnosticLogging", "True");

Expand Down Expand Up @@ -81,7 +84,7 @@ public XamarinAndroidApplicationProject (string debugConfigurationName = "Debug"
}

// it is exposed as public because we may want to slightly modify this.
public string DefaultMainActivity {
public virtual string DefaultMainActivity {
get { return Language == XamarinAndroidProjectLanguage.FSharp ? default_main_activity_fs : default_main_activity_cs; }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ public class XamarinAndroidLibraryProject : XamarinAndroidCommonProject
public XamarinAndroidLibraryProject (string debugConfigurationName = "Debug", string releaseConfigurationName = "Release")
: base (debugConfigurationName, releaseConfigurationName)
{
if (!Builder.UseDotNet) {
if (Builder.UseDotNet) {
SetProperty (KnownProperties.Nullable, "enable");
SetProperty (KnownProperties.ImplicitUsings, "enable");
} else {
SetProperty ("AndroidApplication", "False");
SetProperty ("AndroidResgenFile", Path.Combine ("Resources", "Resource.designer.cs"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public XamarinFormsAndroidApplicationProject (string debugConfigurationName = "D
: base (debugConfigurationName, releaseConfigurationName, packageName)
{
if (Builder.UseDotNet) {
// Don't opt into ImplicitUsings
RemoveProperty (KnownProperties.ImplicitUsings);
PackageReferences.Add (KnownPackages.XamarinForms_4_7_0_1142);
} else {
PackageReferences.Add (KnownPackages.XamarinForms_4_0_0_425677);
Expand Down Expand Up @@ -76,6 +78,8 @@ public XamarinFormsAndroidApplicationProject (string debugConfigurationName = "D
MainPage = MainPage_xaml_cs;
}

public override string DefaultMainActivity => default_main_activity_cs;

public string MainPage { get; set; }

protected virtual string MainPageXaml () => ProcessSourceTemplate (MainPage_xaml);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ static XamarinFormsXASdkProject ()
public XamarinFormsXASdkProject (string outputType = "Exe", [CallerMemberName] string packageName = "")
: base (outputType, packageName)
{
// Don't opt into ImplicitUsings
RemoveProperty (KnownProperties.ImplicitUsings);
PackageReferences.Add (KnownPackages.XamarinForms_4_7_0_1142);

// Workaround for AndroidX, see: https://github.com/xamarin/AndroidSupportComponents/pull/239
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"Size": 2681
},
"assemblies/UnnamedProject.dll": {
"Size": 3186
"Size": 3535
},
"classes.dex": {
"Size": 345240
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace ${ROOT_NAMESPACE}
{
[Android.Runtime.Register ("${JAVA_PACKAGENAME}.MainActivity"), Activity (Label = "${PROJECT_NAME}", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
int count = 1;

protected override void OnCreate (Bundle? bundle)
{
base.OnCreate (bundle);

// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);

var button = FindViewById<Button> (Resource.Id.myButton);
button!.Click += delegate {
button.Text = string.Format ("{0} clicks!", count++);
};

//${AFTER_ONCREATE}
}
}
//${AFTER_MAINACTIVITY}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,72 +11,7 @@
<Import Project="..\..\..\..\external\xamarin-android-tools\src\Microsoft.Android.Build.BaseTasks\MSBuildReferences.projitems" />
<ItemGroup>
<Compile Remove="Resources\**\*.cs" />
<EmbeddedResource Include="Resources\AndroidX\Tabbar.xml">
jonathanpeppers marked this conversation as resolved.
Show resolved Hide resolved
<LogicalName>Xamarin.ProjectTools.Resources.AndroidX.Tabbar.xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\AndroidX\Toolbar.xml">
<LogicalName>Xamarin.ProjectTools.Resources.AndroidX.Toolbar.xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Wear\LayoutMain.axml">
<LogicalName>Xamarin.ProjectTools.Resources.Wear.LayoutMain.axml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Wear\LayoutRectMain.axml">
<LogicalName>Xamarin.ProjectTools.Resources.Wear.LayoutRectMain.axml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Wear\LayoutRoundMain.axml">
<LogicalName>Xamarin.ProjectTools.Resources.Wear.LayoutRoundMain.axml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Wear\MainActivity.cs">
<LogicalName>Xamarin.ProjectTools.Resources.Wear.MainActivity.cs</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Wear\Strings.xml">
<LogicalName>Xamarin.ProjectTools.Resources.Wear.Strings.xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\AndroidManifest.xml">
<LogicalName>Xamarin.ProjectTools.Resources.Base.AndroidManifest.xml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\Icon.png">
<LogicalName>Xamarin.ProjectTools.Resources.Base.Icon.png</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\LayoutMain.axml">
<LogicalName>Xamarin.ProjectTools.Resources.Base.LayoutMain.axml</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\MainActivity.cs">
<LogicalName>Xamarin.ProjectTools.Resources.Base.MainActivity.cs</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\MainActivity.fs">
<LogicalName>Xamarin.ProjectTools.Resources.Base.MainActivity.fs</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\AssemblyInfo.fs">
<LogicalName>Xamarin.ProjectTools.Resources.Base.AssemblyInfo.fs</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\Image.9.png">
<LogicalName>Xamarin.ProjectTools.Resources.Base.Image.9.png</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\Image2.9.png">
<LogicalName>Xamarin.ProjectTools.Resources.Base.Image2.9.png</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\test.keystore">
<LogicalName>Xamarin.ProjectTools.Resources.Base.test.keystore</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\classes.jar">
<LogicalName>Xamarin.ProjectTools.Resources.Base.classes.jar</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Base\custom.aotprofile" />
<EmbeddedResource Include="Resources\Base\BuildReleaseArm64SimpleDotNet.apkdesc" />
<EmbeddedResource Include="Resources\Base\BuildReleaseArm64SimpleLegacy.apkdesc" />
<EmbeddedResource Include="Resources\Base\BuildReleaseArm64XFormsDotNet.apkdesc" />
<EmbeddedResource Include="Resources\Base\BuildReleaseArm64XFormsLegacy.apkdesc" />
<EmbeddedResource Include="Resources\Forms\MainActivity.cs" />
<EmbeddedResource Include="Resources\Forms\App.xaml" />
<EmbeddedResource Include="Resources\Forms\App.xaml.cs" />
<EmbeddedResource Include="Resources\Forms\MainPage.xaml" />
<EmbeddedResource Include="Resources\Forms\MainPage.xaml.cs" />
<EmbeddedResource Include="Resources\Forms\MainPageMaps.xaml" />
<EmbeddedResource Include="Resources\Forms\Tabbar.axml" />
<EmbeddedResource Include="Resources\Forms\Toolbar.axml" />
<EmbeddedResource Include="Resources\Forms\colors.xml" />
<EmbeddedResource Include="Resources\Forms\styles.xml" />
<EmbeddedResource Include="Resources\**\*" />
</ItemGroup>
<ItemGroup>
<Content Include="..\..\..\..\.nuget\NuGet.exe">
Expand Down
15 changes: 10 additions & 5 deletions tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public class Class1 {
};
proj.SetAndroidSupportedAbis ("armeabi-v7a", "arm64-v8a", "x86", "x86_64");
proj.SetProperty (proj.ReleaseProperties, "MonoSymbolArchive", "True");
proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_ONCREATE}",
proj.MainActivity = proj.DefaultMainActivity.Replace ("//${AFTER_FORMS_INIT}",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found this test was not using a Forms-based MainActivity.cs before, but it was a Xamarin.Forms app! So we need to use ${AFTER_FORMS_INIT} now and the line number changed.

@" var cl = new Library1.Class1(null);
cl.GetData();
");
Expand Down Expand Up @@ -245,7 +245,7 @@ public class Class1 {
Assert.IsTrue (didParse, $"Unable to parse {proj.TargetSdkVersion} as an int.");
SymbolicateAndAssert (archivePath, logcatPath, new string [] {
Path.Combine (Root, lb.ProjectDirectory, "Class1.cs:12"),
Path.Combine (Root, builder.ProjectDirectory, "MainActivity.cs:33"),
Path.Combine (Root, builder.ProjectDirectory, "MainActivity.cs:23"),
Directory.Exists (builder.BuildOutputDirectory)
? Path.Combine ("src", "Mono.Android", "obj", XABuildPaths.Configuration, "monoandroid10", $"android-{apiLevel}", "mcw", "Android.App.Activity.cs:")
: $"src/Mono.Android/obj/Release/monoandroid10/android-{apiLevel}/mcw/Android.App.Activity.cs:",
Expand Down Expand Up @@ -559,11 +559,16 @@ public override Type BindToType (string assemblyName, string typeName)
return null;
}
}
}").Replace ("using System;", @"using System;
using System.IO;
}");

string usings =
@"using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Json;");
using System.Runtime.Serialization.Json;
";
proj.MainActivity = usings + proj.MainActivity;

builder = CreateApkBuilder ();
Assert.IsTrue (builder.Install (proj), "Install should have succeeded.");
ClearAdbLogcat ();
Expand Down
6 changes: 2 additions & 4 deletions tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,7 @@ public void DotNetDebug ()
AssertCommercialBuild ();
AssertHasDevices ();

XASdkProject proj;
proj = new XASdkProject () {
};
var proj = new XASdkProject ();
proj.SetRuntimeIdentifier (DeviceAbi);
string runtimeId = proj.GetProperty (KnownProperties.RuntimeIdentifier);

Expand All @@ -110,7 +108,7 @@ public void DotNetDebug ()
// setup the debugger
var session = new SoftDebuggerSession ();
session.Breakpoints = new BreakpointStore {
{ Path.Combine (Root, dotnet.ProjectDirectory, "MainActivity.cs"), 19 },
{ Path.Combine (Root, dotnet.ProjectDirectory, "MainActivity.cs"), 10 },
};
session.TargetHitBreakpoint += (sender, e) => {
Console.WriteLine ($"BREAK {e.Type}");
Expand Down