Skip to content
Open
1 change: 1 addition & 0 deletions Documentation/docs-mobile/messages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ Either change the value in the AndroidManifest.xml to match the $(SupportedOSPla
+ [XA4253](xa4253.md): Generated Java callable wrapper code changed: '{path}'
+ [XA4254](xa4254.md): Trimmable type map Java source input directory '{input}' and output directory '{output}' must be different.
+ [XA4255](xa4255.md): Generated trimmable type map Java source '{path}' was not found.
+ [XA4256](xa4256.md): Skipping Java peer type '{type}' from assembly '{assembly}' because referenced type '{referencedType}' from assembly '{referencedAssembly}' could not be resolved in '{path}'. This type will not be included in the trimmable type map.
+ XA4300: Native library '{library}' will not be bundled because it has an unsupported ABI.
+ [XA4301](xa4301.md): Apk already contains the item `xxx`.
+ [XA4302](xa4302.md): Unhandled exception merging \`AndroidManifest.xml\`: {ex}
Expand Down
27 changes: 27 additions & 0 deletions Documentation/docs-mobile/messages/xa4256.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: .NET for Android warning XA4256
description: XA4256 warning code
ms.date: 06/25/2026
f1_keywords:
- "XA4256"
---

# .NET for Android warning XA4256

## Example message

```
warning XA4256: Skipping Java peer type 'Google.Android.Material.Shadow.ShadowDrawableWrapper' from assembly 'Xamarin.Google.Android.Material' because referenced type 'AndroidX.AppCompat.Graphics.Drawable.DrawableWrapper' from assembly 'Xamarin.AndroidX.AppCompat.AppCompatResources' could not be resolved in '/home/user/.nuget/packages/xamarin.androidx.appcompat.appcompatresources/1.6.0/lib/net6.0-android31.0/Xamarin.AndroidX.AppCompat.AppCompatResources.dll'. This type will not be included in the trimmable type map.
```

## Issue

The trimmable type map found a Java peer type whose managed base type or implemented interface references a type that is not present in the resolved assembly set.

This can happen when NuGet packages in the Android binding graph were built against different versions of another binding package. The type may be unused by the app, but NativeAOT compiles a closed world and must resolve rooted managed types eagerly.

## Solution

If your app uses the skipped type, update the affected NuGet packages so the referenced type exists, or update to versions of the binding packages that are compatible with each other.

If your app does not use the skipped type, no action is required. The type is omitted from the trimmable type map so NativeAOT does not fail while resolving unused stale metadata.
5 changes: 5 additions & 0 deletions src/Microsoft.Android.Sdk.TrimmableTypeMap/AssemblyInput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using System.Reflection.PortableExecutable;

namespace Microsoft.Android.Sdk.TrimmableTypeMap;

public readonly record struct AssemblyInput (string Name, string Path, PEReader Reader);
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,11 @@ public interface ITrimmableTypeMapLogger
void LogGeneratedJcwFilesInfo (int sourceCount);
void LogRootingManifestReferencedTypeInfo (string javaTypeName, string managedTypeName);
void LogManifestReferencedTypeNotFoundWarning (string javaTypeName);
void LogUnresolvableJavaPeerSkippedWarning (
string managedTypeName,
string assemblyName,
string unresolvedTypeName,
string unresolvedAssemblyName,
string unresolvedAssemblyPath);
void LogJniAddNativeMethodRegistrationAttributeError (string managedTypeName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ sealed class AssemblyIndex : IDisposable

public MetadataReader Reader { get; }
public string AssemblyName { get; }
public string AssemblyPath { get; }

/// <summary>
/// Maps full managed type name (e.g., "Android.App.Activity") to its TypeDefinitionHandle.
Expand All @@ -38,6 +39,11 @@ sealed class AssemblyIndex : IDisposable
/// </summary>
public Dictionary<string, HashSet<string>> ReferencedTypeNamesByAssembly { get; } = new (StringComparer.OrdinalIgnoreCase);

/// <summary>
/// Type-forwarded or otherwise exported types declared by this assembly.
/// </summary>
public HashSet<string> ExportedTypeNames { get; } = new (StringComparer.Ordinal);

/// <summary>
/// True iff the assembly's metadata mentions
/// <c>Java.Interop.JniAddNativeMethodRegistrationAttribute</c> (as a
Expand All @@ -48,18 +54,19 @@ sealed class AssemblyIndex : IDisposable
/// </summary>
public bool MayUseJniAddNativeMethodRegistrationAttribute { get; private set; }

AssemblyIndex (PEReader peReader, MetadataReader reader, string assemblyName)
AssemblyIndex (PEReader peReader, MetadataReader reader, string assemblyName, string assemblyPath)
{
this.peReader = peReader;
this.customAttributeTypeProvider = new CustomAttributeTypeProvider (reader);
Reader = reader;
AssemblyName = assemblyName;
AssemblyPath = assemblyPath;
}

public static AssemblyIndex Create (PEReader peReader, string assemblyName)
public static AssemblyIndex Create (PEReader peReader, string assemblyName, string assemblyPath = "")
{
var reader = peReader.GetMetadataReader ();
var index = new AssemblyIndex (peReader, reader, assemblyName);
var index = new AssemblyIndex (peReader, reader, assemblyName, assemblyPath);
index.Build ();
return index;
}
Expand Down Expand Up @@ -88,6 +95,11 @@ void Build ()
}
}

foreach (var exportedTypeHandle in Reader.ExportedTypes) {
var exportedType = Reader.GetExportedType (exportedTypeHandle);
ExportedTypeNames.Add (GetExportedTypeFullName (exportedType));
}

foreach (var typeHandle in Reader.TypeDefinitions) {
var typeDef = Reader.GetTypeDefinition (typeHandle);

Expand All @@ -113,6 +125,17 @@ void Build ()
RegisterInfoByType [typeHandle] = registerInfo;
}
}

string GetExportedTypeFullName (ExportedType exportedType)
{
var name = Reader.GetString (exportedType.Name);
if (exportedType.Implementation.Kind == HandleKind.ExportedType) {
var declaringType = Reader.GetExportedType ((ExportedTypeHandle) exportedType.Implementation);
return MetadataTypeNameResolver.JoinNestedTypeName (GetExportedTypeFullName (declaringType), name);
}
var ns = Reader.GetString (exportedType.Namespace);
return MetadataTypeNameResolver.JoinNamespaceAndName (ns, name);
}
}

bool TryGetTypeReferenceAssemblyName (TypeReference typeReference, [NotNullWhen (true)] out string? assemblyName)
Expand Down
Loading
Loading