diff --git a/Documentation/guides/building-apps/build-targets.md b/Documentation/guides/building-apps/build-targets.md index fc6697ce83f..4e62ceab39e 100644 --- a/Documentation/guides/building-apps/build-targets.md +++ b/Documentation/guides/building-apps/build-targets.md @@ -91,6 +91,20 @@ MSBuild /t:Install ProjectName.csproj /p:AdbTarget=-e Calls the [`GetAndroidDependencies`](#getandroiddependencies) target, then installs the Android SDK packages specified in the `@(AndroidDependency)` item group. +```dotnetcli +dotnet build -t:InstallAndroidDependencies -f net8.0-android "-p:AndroidSdkDirectory=" "-p:JavaSdkDirectory=" +``` + +The `-f net8.0-android` is required as this target is a .NET Android specific target. If you omit this argument +you will get the following error: + +``` +error MSB4057: The target "InstallAndroidDependencies" does not exist in the project. +``` + +The `AndroidSdkDirectory` and `JavaSdkDirectory` properties are required as we need to know where to install the required components. These directories can be empty or existing. Sdk components +will be installed on top on an existing sdk installation. + The [`$(AndroidManifestType)`](~/android/deploy-test/building-apps/build-properties.md#androidmanifesttype) MSBuild property controls which [Visual Studio SDK Manager repository](~/android/get-started/installation/android-sdk.md?tabs=windows#repository-selection) diff --git a/Documentation/guides/messages/xa5207.md b/Documentation/guides/messages/xa5207.md index 56ac2937fcd..90e89e21925 100644 --- a/Documentation/guides/messages/xa5207.md +++ b/Documentation/guides/messages/xa5207.md @@ -7,14 +7,35 @@ ms.date: 06/26/2019 ## Example messages -``` +```dotnetcli XA5207: Could not find android.jar for API Level 28. This means the Android SDK platform for API Level 28 is not installed. Either install it in the Android SDK Manager (Tools > Android > Android SDK Manager...), or change your Xamarin.Android project to target an API version that is installed. ``` ## Issue -In order to build a project, the Android SDK Platform matching the target API level must be installed. +In order to build a project, the Android SDK Platform matching the target API level must be installed. ## Solution -Use the Android SDK Manager to install the Android SDK Platform for the desired API level. +Use the Android SDK Manager (Tools > Android > Android SDK Manager...) to install the Android SDK Platform for the desired API level. Alternatively you can install the missing API level by running the following command from a terminal or command prompt: + +```dotnetcli +dotnet build -t:InstallAndroidDependencies -f net8.0-android "-p:AndroidSdkDirectory=" +``` + +Part of the new .net android system is when upgrading projects you will automatically be +upgraded to the latest API level. For example net7.0-android allowed you to target API 33, +but net8.0-android will automatically target API 34. If you want to keep your current +target API level you will need to add the 'uses-sdk' `android:targetSdkVersion` to your `AndroidManifest.xml` file. + +```xml + + + + +``` + +You might then need to run the `InstallAndroidDependencies` target as mentioned above to ensure that the required API level is installed. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs index 4e612a10019..e46244bf171 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs @@ -1464,20 +1464,20 @@ public static string XA5207 { } /// - /// Looks up a localized string similar to Tools > Open Android SDK Manager.... + /// Looks up a localized string similar to Tools > Android > Android SDK Manager.... /// - public static string XA5207_SDK_Manager_macOS { + public static string XA5207_SDK_Manager_Windows { get { - return ResourceManager.GetString("XA5207_SDK_Manager_macOS", resourceCulture); + return ResourceManager.GetString("XA5207_SDK_Manager_Windows", resourceCulture); } } /// - /// Looks up a localized string similar to Tools > Android > Android SDK Manager.... + /// Looks up a localized string similar to Tools > Open Android SDK Manager.... /// - public static string XA5207_SDK_Manager_Windows { + public static string XA5207_SDK_Manager_CLI { get { - return ResourceManager.GetString("XA5207_SDK_Manager_Windows", resourceCulture); + return ResourceManager.GetString("XA5207_SDK_Manager_CLI", resourceCulture); } } diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx index 43a90d49729..524a3f1fe3c 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx @@ -416,7 +416,7 @@ The capitalized word "Portable" that appears earlier in the message is plain tex `LibraryProjectProperties` file `{0}` is located in a parent directory of the bindings project's intermediate output directory. Please adjust the path to use the original `project.properties` file directly from the Android library project directory. The following are literal names and should not be translated: LibraryProjectProperties, project.properties, Android -In this message, the term "binding" means a piece of generated code that makes it easy to access an Android API written in Java from a Xamarin.Android project written in C# or F#. +In this message, the term "binding" means a piece of generated code that makes it easy to access an Android API written in Java from a .NET Android project written in C# or F#. {0} - The path of the LibraryProjectProperties file @@ -438,8 +438,8 @@ In this message, the term "binding" means a piece of generated code that makes i The following are literal names and should not be translated: DX, DEX, d8, AndroidDexTool. - Ignoring configuration file '{0}'. .NET configuration files are not supported in Xamarin.Android projects that target .NET 6 or higher. - The following are literal names and should not be translated: .NET, Xamarin.Android. + Ignoring configuration file '{0}'. .NET configuration files are not supported in .NET Android projects that target .NET 6 or higher. + The following are literal names and should not be translated: .NET, .NET Android. {0} - The file name such as 'Foo.dll.config' @@ -451,7 +451,7 @@ In this message, the term "binding" means a piece of generated code that makes i The following are literal names and should not be translated: AAPT, AAPT2, Android, AndroidUseAapt2, true. - Using AAPT is not supported in Xamarin.Android projects that target .NET 6 or higher. Please enable 'Use incremental Android packaging system (aapt2)' in the Visual Studio project property pages or edit the project file in a text editor and set the 'AndroidUseAapt2' MSBuild property to 'true'. + Using AAPT is not supported in .NET Android projects that target .NET 6 or higher. Please enable 'Use incremental Android packaging system (aapt2)' in the Visual Studio project property pages or edit the project file in a text editor and set the 'AndroidUseAapt2' MSBuild property to 'true'. The following are literal names and should not be translated: AAPT, Android, AndroidUseAapt2, true. @@ -511,7 +511,7 @@ Either change the value in the AndroidManifest.xml to match the $(SupportedOSPla {1} - The SupportedOSPlatformVersion property value - Use of AppDomain.CreateDomain() detected in assembly: {0}. .NET 6 and higher will only support a single AppDomain, so this API will no longer be available in Xamarin.Android once .NET 6 is released. + Use of AppDomain.CreateDomain() detected in assembly: {0}. .NET 6 and higher will only support a single AppDomain, so this API will no longer be available in .NET Android once .NET 6 is released. The following are literal names and should not be translated: AppDomain.CreateDomain(), AppDomain {0} - The name of the assembly @@ -710,12 +710,12 @@ In this message, "root element" refers to the root element of an XML file. {0} - The exception message and stack trace of the associated exception - The Android class parser value '{0}' is deprecated and will be removed in a future version of Xamarin.Android. Update the project properties to use 'class-parse'. + The Android class parser value '{0}' is deprecated and will be removed in a future version of .NET Android. Update the project properties to use 'class-parse'. The following are literal names and should not be translated: class-parse {0} - The name of the current class parser value - The Android code generation target '{0}' is deprecated and will be removed in a future version of Xamarin.Android. Update the project properties to use 'XAJavaInterop1'. + The Android code generation target '{0}' is deprecated and will be removed in a future version of .NET Android. Update the project properties to use 'XAJavaInterop1'. The following are literal names and should not be translated: XAJavaInterop1 {0} - The name of the current code generation target @@ -796,7 +796,7 @@ The following are literal names and should not be translated: ABI, 'libs/armeabi "Wear" is a short version of the full product name "Wear OS" and so should not be translated. - Referencing the Android Wear application project '{0}' from an Android application project is deprecated and will no longer be supported in a future version of Xamarin.Android. Remove the Android Wear application project reference from the Android application project and distribute the Wear application as a standalone application instead. + Referencing the Android Wear application project '{0}' from an Android application project is deprecated and will no longer be supported in a future version of .NET Android. Remove the Android Wear application project reference from the Android application project and distribute the Wear application as a standalone application instead. The following are literal names and should not be translated: Android Wear, Android, Wear. {0} - The referenced Android Wear project. @@ -867,19 +867,23 @@ Remove the '{0}' reference from your project and add the '{1}' NuGet package ins {0} - The missing tool name - Could not find android.jar for API level {0}. This means the Android SDK platform for API level {0} is not installed. Either install it in the Android SDK Manager ({2}), or change the Xamarin.Android project to target an API version that is installed. ({1} missing.) + Could not find android.jar for API level {0}. This means the Android SDK platform for API level {0} is not installed; it was expected to be in `{1}`. +{2} +See https://aka.ms/xa5207 for more details. The following are literal names and should not be translated: android.jar {0} - The API level name {1} - The expected path of the android.jar file -{2} - The menu location in Visual Studio that can be used to launch the Android SDK Manager - - - Tools > Open Android SDK Manager... - This string is the location of a menu command in Visual Studio for Mac. +{2} - The instructions to install the missing component - Tools > Android > Android SDK Manager... - This string is the location of a menu command in Visual Studio. + Either install it in the Android SDK Manager (Tools > Android > Android SDK Manager...), or change the .NET Android project to target an API version that is installed. + This string is the instrucitons to install the component + + + You can install the missing API level by running `dotnet build -t:InstallAndroidDependencies -f {0} "-p:AndroidSdkDirectory={1}"`, or change the project to target an API version that is installed. + This string is the instrucitons to install the component +{0} - The TargetFramework the app is targeting. +{1} - The current AndroidSdkDirectory path. Embedded Wear app package name differs from handheld app package name ({0} != {1}). diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GetJavaPlatformJar.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GetJavaPlatformJar.cs index 171913f78e3..cb9b22f88da 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GetJavaPlatformJar.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GetJavaPlatformJar.cs @@ -25,8 +25,14 @@ public class GetJavaPlatformJar : AndroidTask public bool DesignTimeBuild { get; set; } + public bool BuildingInsideVisualStudio { get; set; } + public string SupportedOSPlatformVersion { get; set; } + public string TargetFramework { get; set; } + + public string AndroidSdkDirectory { get; set; } + [Output] public string JavaPlatformJarPath { get; set; } @@ -95,7 +101,9 @@ public override bool RunTask () } platform = GetTargetSdkVersion (platform, target_sdk); - JavaPlatformJarPath = MonoAndroidHelper.TryGetAndroidJarPath (Log, platform, designTimeBuild: DesignTimeBuild); + JavaPlatformJarPath = MonoAndroidHelper.TryGetAndroidJarPath (Log, platform, + designTimeBuild: DesignTimeBuild, buildingInsideVisualStudio: BuildingInsideVisualStudio, + targetFramework: TargetFramework, androidSdkDirectory: AndroidSdkDirectory); TargetSdkVersion = MonoAndroidHelper.SupportedVersions.GetApiLevelFromId (platform).ToString (); if (JavaPlatformJarPath == null) return !Log.HasLoggedErrors; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index 4c654b41637..f0819191393 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -778,7 +778,7 @@ public void BuildInDesignTimeMode ([Values(false, true)] bool useManagedParser) } [Test] - public void IfAndroidJarDoesNotExistThrowXA5207 () + public void IfAndroidJarDoesNotExistThrowXA5207 ([Values(true, false)] bool buildingInsideVisualStudio) { var path = Path.Combine ("temp", TestName); var AndroidSdkDirectory = CreateFauxAndroidSdkDirectory (Path.Combine (path, "android-sdk"), "24.0.1", new ApiInfo [] { new ApiInfo { Id = "30" } }); @@ -788,6 +788,7 @@ public void IfAndroidJarDoesNotExistThrowXA5207 () using (var builder = CreateApkBuilder (Path.Combine (path, proj.ProjectName), false, false)) { builder.ThrowOnBuildFailure = false; + builder.BuildingInsideVisualStudio = buildingInsideVisualStudio; Assert.IsTrue (builder.DesignTimeBuild (proj), "DesignTime build should succeed."); Assert.IsFalse (builder.LastBuildOutput.ContainsText ("error XA5207:"), "XA5207 should not have been raised."); builder.Target = "AndroidPrepareForBuild"; @@ -797,6 +798,10 @@ public void IfAndroidJarDoesNotExistThrowXA5207 () }), "Build should have failed"); Assert.IsTrue (builder.LastBuildOutput.ContainsText ("error XA5207:"), "XA5207 should have been raised."); Assert.IsTrue (builder.LastBuildOutput.ContainsText ($"Could not find android.jar for API level {proj.TargetSdkVersion}"), "XA5207 should have had a good error message."); + if (buildingInsideVisualStudio) + Assert.IsTrue (builder.LastBuildOutput.ContainsText ($"Either install it in the Android SDK Manager"), "XA5207 should have an error message for Visual Studio."); + else + Assert.IsTrue (builder.LastBuildOutput.ContainsText ($"You can install the missing API level by running"), "XA5207 should have an error message for the command line."); } Directory.Delete (AndroidSdkDirectory, recursive: true); } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs index d72b347d5e9..4efceda5141 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs @@ -482,14 +482,14 @@ public static IEnumerable Executables (string executable) yield return executable; } - public static string TryGetAndroidJarPath (TaskLoggingHelper log, string platform, bool designTimeBuild = false) + public static string TryGetAndroidJarPath (TaskLoggingHelper log, string platform, bool designTimeBuild = false, bool buildingInsideVisualStudio = false, string targetFramework = "", string androidSdkDirectory = "") { var platformPath = MonoAndroidHelper.AndroidSdk.TryGetPlatformDirectoryFromApiLevel (platform, MonoAndroidHelper.SupportedVersions); if (platformPath == null) { if (!designTimeBuild) { var expectedPath = MonoAndroidHelper.AndroidSdk.GetPlatformDirectoryFromId (platform); - var sdkManagerMenuPath = OS.IsWindows ? Properties.Resources.XA5207_SDK_Manager_Windows : Properties.Resources.XA5207_SDK_Manager_macOS; - log.LogCodedError ("XA5207", Properties.Resources.XA5207, platform, Path.Combine (expectedPath, "android.jar"), sdkManagerMenuPath); + var sdkManagerMenuPath = buildingInsideVisualStudio ? Properties.Resources.XA5207_SDK_Manager_Windows : Properties.Resources.XA5207_SDK_Manager_CLI; + log.LogCodedError ("XA5207", Properties.Resources.XA5207, platform, Path.Combine (expectedPath, "android.jar"), string.Format (sdkManagerMenuPath, targetFramework, androidSdkDirectory)); } return null; } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Tooling.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Tooling.targets index ff86b19b484..a0c0abd4262 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Tooling.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Tooling.targets @@ -99,9 +99,12 @@ projects.