Skip to content

Commit 463e6da

Browse files
authored
[Xamarin.Android.Build.Tasks] XA1041 Check aar has the correct paths (#9918)
Context: #9879 If you create an Android Library project which contains Android Resources: % dotnet new net9-androidlib % mkdir -p Resources/values % cat > Resources/values/strings.xml <<EOF <resources> <string name="lib_name">net9_androidlib</string> </resources> EOF then build the project with `$(MonoAndroidAssetsPrefix)` set to an absolute path: dotnet build -p:MonoAndroidAssetsPrefix=`pwd`/Resources then the resulting `$(MSBuildProjectName).aar` file contains the absolute path! % unzip -l bin/Debug/net9.0-android/net9-androidlib.aar Archive: bin/Debug/net9.0-android/net9-androidlib.aar Length Date Time Name --------- ---------- ----- ---- 78 04-08-2025 14:32 assets//Users/…/net9-androidlib/Resources/values/strings.xml 71 04-08-2025 14:32 res/values/strings.xml 38 04-08-2025 14:32 .net/__res_name_case_map.txt This is "nominally fine" on macOS, but if Windows is the source machine then the entry within the `.aar` contains a `:`, a'la `assets/D:/a/1/s/Foo.Mobile/Foo.Mobile.Droid/Assets/AboutAssets.txt`, which can cause a subsequent error XARLP7024 as in #9879: …\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7024: System.IO.IOException: The filename, directory name, or volume label syntax is incorrect. : 'D:\a\1\s\MyCompany.Mobile\MyCompany.Mobile.Droid\obj\Release\net9.0-android\lp\183\jl\assets\D:\a\1\s\MyCompany.Mobile\MyCompany.Mobile.Droid\Assets'. …\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7024: at System.IO.FileSystem.CreateDirectory(String fullPath, Byte[] securityDescriptor) …\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7024: at Microsoft.Android.Build.Tasks.Files.CopyIfStreamChangedOnce(Stream stream, String destination) in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/Files.cs:line 263 …\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7024: at Microsoft.Android.Build.Tasks.Files.CopyIfStreamChanged(Stream stream, String destination) in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/Files.cs:line 238 …\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7024: at Microsoft.Android.Build.Tasks.Files.ExtractAll(ZipArchive zip, String destination, Action`2 progressCallback, Func`2 modifyCallback, Func`2 deleteCallback, Func`2 skipCallback) in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/Files.cs:line 470 …\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7024: at Xamarin.Android.Tasks.ResolveLibraryProjectImports.Extract(IDictionary`2 jars, ICollection`1 resolvedResourceDirectories, ICollection`1 resolvedAssetDirectories, ICollection`1 resolvedEnvironments, ICollection`1 proguardConfigFiles) in /Users/runner/work/1/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs:line 398 …\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7024: at Xamarin.Android.Tasks.ResolveLibraryProjectImports.RunTask() in /Users/runner/work/1/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Tasks/ResolveLibraryProjectImports.cs:line 95 …\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7024: at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:line 25 which is *not* fine. Update the `<CreateAar/>` and `<AndroidComputeResPaths/>` tasks to verify that the `$(MonoAndroidAssetsPrefix)` MSBuild value is *not* an absolute path value. If it is, then the "originating" build will report an error xa1041: error XA1041: The MSBuild property 'MonoAndroidAssetsPrefix' has an invalid value of '/Absolute/Path'. The value is expected to be a directory path representing the relative location of your Assets or Resources.
1 parent 6a27915 commit 463e6da

File tree

13 files changed

+134
-1
lines changed

13 files changed

+134
-1
lines changed

Documentation/docs-mobile/building-apps/build-properties.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,16 @@ The default value is False.
16621662

16631663
This MSBuild property is obsolete and is no longer supported.
16641664

1665+
## MonoAndroidAssetPrefix
1666+
1667+
Specifies a *path prefix*
1668+
that is removed from the start of filenames with a Build action of
1669+
`AndroidAsset`. This is to allow changing where resources are
1670+
located.
1671+
1672+
The default value is `Assets`. Change this to `assets` for the
1673+
Java project structure.
1674+
16651675
## MonoAndroidResourcePrefix
16661676

16671677
Specifies a *path prefix*

Documentation/docs-mobile/messages/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ or 'Help->Report a Problem' in Visual Studio for Mac.
147147
Either change the value in the AndroidManifest.xml to match the $(SupportedOSPlatformVersion) value, or remove the value in the AndroidManifest.xml (and add a $(SupportedOSPlatformVersion) value to the project file if it doesn't already exist).
148148
+ [XA1037](xa1037.md): The '{0}' MSBuild property is deprecated and will be removed in .NET {1}. See https://aka.ms/net-android-deprecations for more details.
149149
+ [XA1038](xa1038.md): The '{0}' MSBuild property has an invalid value. Value values are {1}.
150+
+ [XA1039](xa1039.md): The Android Support libraries are not supported in .NET 9 and later, please migrate to AndroidX. See https://aka.ms/xamarin/androidx for more details.
151+
+ [XA1040](xa1040.md): The CoreCLR runtime on Android is an experimental feature and not yet suitable for production use. File issues at: https://github.com/dotnet/android/issues
152+
+ [XA1041](xa1041.md): The MSBuild property 'MonoAndroidAssetPrefix' has an invalid value of 'c:\Foo\Assets'. The value is expected to be a directory path representing the relative location of your Assets or Resources
150153

151154
## XA2xxx: Linker
152155

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: .NET for Android warning XA1041
3+
description: XA1041 error code
4+
ms.date: 03/31/2025
5+
---
6+
# .NET for Android error XA1041
7+
8+
## Example messages
9+
10+
```dotnetcli
11+
error XA1040: The MSBuild property 'MonoAndroidAssetPrefix' has an invalid value of 'c:\Foo\Assets'. The value is expected to be a directory path representing the relative location of your Assets or Resources.
12+
error XA1040: The MSBuild property 'MonoAndroidResourcePrefix' has an invalid value of 'c:\Foo\Resources'.The value is expected to be a directory path representing the relative location of your Assets or Resources.
13+
```
14+
15+
## Issue
16+
17+
The problem there is that both the `MonoAndroidAssetPrefix` and `MonoAndroidResourcePrefix` are expected to be
18+
relative directory path . This information is used to "strip" the root directory
19+
information off the asset or resource when we package the app.
20+
The error is raised because the property contains a full path.
21+
22+
For example consider the following structure.
23+
24+
```dotnetcli
25+
Foo.csproj
26+
MyAssets/
27+
Foo.txt
28+
Subfolder/
29+
Bar.txt
30+
MainAcrivity.cs
31+
```
32+
33+
In the final `.apk` we expect the files `Foo.txt` and `Bar.txt` to be placed in the `assets` folder. In order to do this correctly the build system needs to know
34+
the `name` of the folder in which the assets are located. By default this is "Assets" but we should also support other folder name.
35+
36+
In the example above we would expect the user to set the `MonoAndroidAssetPrefix` to a value of "MyAssets". This would ensure that the "MyAssets" part of the path
37+
to "Foo.txt" etc is removed during packaging. If the `MonoAndroidAssetPrefix` as set to
38+
`/Users/xxx/Foo/MyAssets` or `c:\Users\xxx\Foo\MyAssets` you would see this error message.
39+
40+
## Solution
41+
42+
The fix for this is to not use a full path for the values of `MonoAndroidAssetPrefix` or `MonoAndroidResourcePrefix`. They should be a relative
43+
directory path which matches the folder path in which your assets are stored.

src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Assets.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
5252
IntermediateDir="$(MonoAndroidAssetsDirIntermediate)"
5353
AssetPackIntermediateDir="$(MonoAndroidAssetPacksDirIntermediate)"
5454
Prefixes="$(MonoAndroidAssetsPrefix)"
55+
PrefixProperty="MonoAndroidAssetsPrefix"
5556
ProjectDir="$(ProjectDir)"
5657
>
5758
<Output ItemName="_AndroidAssetsDest" TaskParameter="IntermediateFiles" />

src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ projects.
7777
Outputs="$(_AarOutputPath)">
7878
<CreateAar
7979
AssetDirectory="$(MonoAndroidAssetsPrefix)"
80+
PrefixProperty="MonoAndroidAssetsPrefix"
8081
AndroidAssets="@(AndroidAsset)"
8182
AndroidResources="@(_AndroidResourceDest)"
8283
AndroidEnvironment="@(AndroidEnvironment)"

src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Xamarin.Android.Build.Tasks/Properties/Resources.resx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,13 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS
10201020
<value>The {0} runtime on Android is an experimental feature and not yet suitable for production use. File issues at: https://github.com/dotnet/android/issues</value>
10211021
<comment>The following are literal names and should not be translated: .NET.
10221022
{0} - The name of the .NET runtime, such as CoreCLR or NativeAOT.</comment>
1023+
</data>
1024+
<data name="XA1041" xml:space="preserve">
1025+
<value>The MSBuild property '{0}' has an invalid value of '{1}'. The value is expected to be a directory path representing the relative location of your Assets or Resources.</value>
1026+
<comment>The following are literal names and should not be translated: .NET.
1027+
{0} - The MSBuild property that has the incorrect value.
1028+
{1} - The current value of the property
1029+
</comment>
10231030
</data>
10241031
<data name="XA4241" xml:space="preserve">
10251032
<value>Java dependency '{0}' is not satisfied.</value>

src/Xamarin.Android.Build.Tasks/Tasks/AndroidComputeResPaths.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public class AndroidComputeResPaths : AndroidTask
5151

5252
public string Prefixes { get; set; }
5353

54+
public string PrefixProperty { get; set; }
55+
5456
public bool LowercaseFilenames { get; set; }
5557

5658
public string ProjectDir { get; set; }
@@ -75,6 +77,10 @@ public override bool RunTask ()
7577
if (prefixes != null) {
7678
for (int i = 0; i < prefixes.Length; i++) {
7779
string p = prefixes [i];
80+
if (Path.IsPathRooted (p)) {
81+
Log.LogCodedError ("XA1041", message: Properties.Resources.XA1041, PrefixProperty, p);
82+
continue;
83+
}
7884
char c = p [p.Length - 1];
7985
if (c != '\\' && c != '/')
8086
prefixes [i] = p + Path.DirectorySeparatorChar;

src/Xamarin.Android.Build.Tasks/Tasks/CreateAar.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,14 @@ public class CreateAar : AndroidTask
3636
[Required]
3737
public string OutputFile { get; set; }
3838

39+
public string PrefixProperty { get; set; }
40+
3941
public override bool RunTask ()
4042
{
43+
if (Path.IsPathRooted (AssetDirectory)) {
44+
Log.LogCodedError ("XA1041", message: Properties.Resources.XA1041, PrefixProperty, AssetDirectory);
45+
return false;
46+
}
4147
Directory.CreateDirectory (Path.GetDirectoryName (OutputFile));
4248

4349
using (var stream = File.Create (OutputFile))

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ public void BuildAarBindingLibraryStandalone (string classParser)
169169
{
170170
var proj = new XamarinAndroidBindingProject () {
171171
IsRelease = true,
172+
OtherBuildItems = {
173+
new AndroidItem.AndroidAsset ("Assets\\asset1.txt") {
174+
TextContent = () => "Asset1",
175+
Encoding = Encoding.ASCII,
176+
},
177+
}
172178
};
173179
proj.Jars.Add (new AndroidItem.AndroidLibrary ("Jars\\material-menu-1.1.0.aar") {
174180
WebContent = "https://repo1.maven.org/maven2/com/balysv/material-menu/1.1.0/material-menu-1.1.0.aar"

0 commit comments

Comments
 (0)