dotnet / dotnet/android-libraries
Transitive native library is embedded in consuming class library AAR and duplicated in APK
- Dominant language
- C#
- Stars
- 317
- Forks
- 73
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 17
Description
### Android framework version
net10.0-android
### Affected platform version
.NET SDK 10.0.x with the net10.0-android workload; also reproduced with Android workload 37.0.0-preview.6.59
### Description
`Xamarin.AndroidX.Graphics.Path 1.1.0.1` causes its native `libandroidx.graphics.path.so` payload to be embedded into every consuming Android class library's generated AAR. When that class library is packed as a NuGet, the NuGet also correctly retains `Xamarin.AndroidX.Graphics.Path` as a dependency. An application consuming the outer NuGet therefore receives the same native library twice and reports XA4301.
The MSBuild item flow is:
1. `Xamarin.AndroidX.Graphics.Path.targets` adds `androidx.graphics.graphics-path.aar` as `AndroidAarLibrary`.
2. `_GetLibraryImports` extracts its native files as `AndroidNativeLibrary`.
3. For a class library, `_CategorizeAndroidLibraries` copies every `AndroidNativeLibrary` to `EmbeddedNativeLibrary`.
4. `_CreateAar` passes all `EmbeddedNativeLibrary` items to `CreateAar`, embedding them into the outer library's generated AAR.
5. NuGet packing includes that generated AAR and retains the package dependency, so an application receives both copies.
The two copies are byte-for-byte identical. This is not specific to Compose, but it is exposed by packing `Microsoft.AndroidX.Compose`, which depends transitively on `Xamarin.AndroidX.Graphics.Path` through `Xamarin.AndroidX.Compose.UI.Graphics.Android`.
A minimal reproduction is an Android class library with:
```xml
net10.0-android
```
Run `dotnet pack` and inspect the resulting package:
- The generated class-library AAR contains `jni//libandroidx.graphics.path.so`.
- The nuspec retains the `Xamarin.AndroidX.Graphics.Path` dependency.
Consume that package from a `net10.0-android` application and build an APK. The application sees the native library both through the outer AAR and through `Xamarin.AndroidX.Graphics.Path`.
Expected behavior: a native asset already supplied by a retained NuGet dependency should not also be embedded in the consuming class library's AAR. This may require package-generation changes, an Android SDK item-metadata mechanism, or limiting runtime AAR inclusion to the final application without breaking class-library Java compilation.
We are working around this in `Microsoft.AndroidX.Compose` by removing `libandroidx.graphics.path.so` from `EmbeddedNativeLibrary` after `_CategorizeAndroidLibraries` and before `_CreateAarCache`. The package dependency remains, and the final APK still contains one copy per selected ABI.
### Relevant log output
```shell
obj/Debug/net10.0-android/lp/203/jl/jni/x86_64/libandroidx.graphics.path.so : warning XA4301: APK already contains the item lib/x86_64/libandroidx.graphics.path.so; ignoring.
obj/Debug/net10.0-android/lp/203/jl/jni/arm64-v8a/libandroidx.graphics.path.so : warning XA4301: APK already contains the item lib/arm64-v8a/libandroidx.graphics.path.so; ignoring.
```
Contributor guide
Research direction
Reproduce the issue with the minimal net10.0-android class library and run dotnet pack, then inspect the generated AAR and nuspec. Read the _GetLibraryImports, _CategorizeAndroidLibraries, _CreateAar, and _CreateAarCache item flow; done means the retained dependency supplies one native library without duplicating it in the outer AAR or breaking class-library Java compilation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, csharp
- Domain
- build-system, mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100