Skip to content
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
1 change: 1 addition & 0 deletions Documentation/docs-mobile/messages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ Either change the value in the AndroidManifest.xml to match the $(SupportedOSPla
+ [XA4247](xa4247.md): Could not resolve POM file for artifact '{artifact}'.
+ [XA4248](xa4248.md): Could not find NuGet package '{nugetId}' version '{version}' in lock file. Ensure NuGet Restore has run since this `<PackageReference>` was added.
+ [XA4235](xa4249.md): Maven artifact specification '{artifact}' is invalid. The correct format is 'group_id:artifact_id:version'.
+ [XA4250](xa4250.md): Manifest-referenced type '{type}' was not found in any scanned assembly. It may be a framework type.
+ 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
33 changes: 33 additions & 0 deletions Documentation/docs-mobile/messages/xa4250.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: .NET for Android warning XA4250
description: XA4250 warning code
ms.date: 04/07/2026
f1_keywords:
- "XA4250"
---

# .NET for Android warning XA4250

## Example message

Manifest-referenced type '{0}' was not found in any scanned assembly. It may be a framework type.

```text
warning XA4250: Manifest-referenced type 'com.example.MainActivity' was not found in any scanned assembly. It may be a framework type.
```

## Issue

The build found a type name in `AndroidManifest.xml`, but it could not match that name to any Java peer discovered in the app's managed assemblies.

This can be expected for framework-provided types, but it can also indicate that the manifest entry does not match the name generated for a managed Android component.

## Solution

If the manifest entry refers to an Android framework type, this warning can usually be ignored.

Otherwise:

1. Verify the `android:name` value in the manifest.
2. Ensure the managed type is included in the app build.
3. Check for namespace, `[Register]`, or nested-type naming mismatches between the manifest and the managed type.
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ internal static void UpdateApplicationElement (XElement app, JavaPeerInfo peer)
PropertyMapper.ApplyMappings (app, component.Properties, PropertyMapper.ApplicationElementMappings);
}

internal static void AddInstrumentation (XElement manifest, JavaPeerInfo peer)
internal static void AddInstrumentation (XElement manifest, JavaPeerInfo peer, string packageName)
{
string jniName = JniSignatureHelper.JniNameToJavaName (peer.JavaName);
var element = new XElement ("instrumentation",
Expand All @@ -176,6 +176,9 @@ internal static void AddInstrumentation (XElement manifest, JavaPeerInfo peer)
return;
}
PropertyMapper.ApplyMappings (element, component.Properties, PropertyMapper.InstrumentationMappings);
if (element.Attribute (AndroidNs + "targetPackage") is null && !packageName.IsNullOrEmpty ()) {
element.SetAttributeValue (AndroidNs + "targetPackage", packageName);
}

manifest.Add (element);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class ManifestGenerator
}

if (peer.ComponentAttribute.Kind == ComponentKind.Instrumentation) {
ComponentElementBuilder.AddInstrumentation (manifest, peer);
ComponentElementBuilder.AddInstrumentation (manifest, peer, PackageName);
continue;
}

Expand Down Expand Up @@ -116,10 +116,7 @@ class ManifestGenerator
}

// Apply manifest placeholders
string? placeholders = ManifestPlaceholders;
if (placeholders is not null && placeholders.Length > 0) {
ApplyPlaceholders (doc, placeholders);
}
ApplyPlaceholders (doc, ManifestPlaceholders);

return (doc, providerNames);
}
Expand Down Expand Up @@ -250,8 +247,12 @@ XElement CreateRuntimeProvider (string name, string? processName, int initOrder)
/// Replaces ${key} placeholders in all attribute values throughout the document.
/// Placeholder format: "key1=value1;key2=value2"
/// </summary>
static void ApplyPlaceholders (XDocument doc, string placeholders)
internal static void ApplyPlaceholders (XDocument doc, string? placeholders)
{
if (placeholders.IsNullOrEmpty ()) {
return;
}

var replacements = new Dictionary<string, string> (StringComparer.Ordinal);
foreach (var entry in placeholders.Split (PlaceholderSeparators, StringSplitOptions.RemoveEmptyEntries)) {
var eqIndex = entry.IndexOf ('=');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public interface ITrimmableTypeMapLogger
void LogGeneratedRootTypeMapInfo (int assemblyReferenceCount);
void LogGeneratedTypeMapAssembliesInfo (int assemblyCount);
void LogGeneratedJcwFilesInfo (int sourceCount);
void LogUnresolvedTypeWarning (string name);
void LogRootingManifestReferencedTypeInfo (string name, string managedTypeName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ public sealed record JavaPeerInfo
{
/// <summary>
/// JNI type name, e.g., "android/app/Activity".
/// Extracted from the [Register] attribute.
/// Extracted from the [Register] attribute or auto-computed during scanning.
/// Manifest rooting may later promote this to <see cref="CompatJniName"/> when
/// a component is referenced by its managed-namespace form.
/// </summary>
public required string JavaName { get; init; }
public required string JavaName { get; set; }

/// <summary>
/// Compat JNI type name, e.g., "myapp.namespace/MyType" for user types (uses raw namespace, not CRC64).
Expand Down Expand Up @@ -48,7 +50,7 @@ public sealed record JavaPeerInfo
/// that extends Activity. Null for java/lang/Object or types without a Java base.
/// Needed by JCW Java source generation ("extends" clause).
/// </summary>
public string? BaseJavaName { get; init; }
public string? BaseJavaName { get; set; }

/// <summary>
/// JNI names of Java interfaces this type implements, e.g., ["android/view/View$OnClickListener"].
Expand All @@ -69,16 +71,23 @@ public sealed record JavaPeerInfo
/// Types with component attributes ([Activity], [Service], etc.),
/// custom views from layout XML, or manifest-declared components
/// are unconditionally preserved (not trimmable).
/// May be set to <c>true</c> after scanning when the manifest references a type
/// that the scanner did not mark as unconditional. Should only ever be set
/// to <c>true</c>, never back to <c>false</c>.
/// </summary>
public bool IsUnconditional { get; init; }
public bool IsUnconditional { get; set; }

/// <summary>
/// True for Application and Instrumentation types. These types cannot call
/// True for Application and Instrumentation types, plus any generated managed
/// base classes they rely on during startup. These types cannot call
/// <c>registerNatives</c> in their static initializer because the native library
/// (<c>libmonodroid.so</c>) is not loaded until after the Application class is instantiated.
/// Registration is deferred to <c>ApplicationRegistration.registerApplications()</c>.
/// This may also be set after scanning when a type is only discovered from
/// manifest <c>android:name</c> usage on <c>&lt;application&gt;</c> or
/// <c>&lt;instrumentation&gt;</c>.
/// </summary>
public bool CannotRegisterInStaticConstructor { get; init; }
public bool CannotRegisterInStaticConstructor { get; set; }

/// <summary>
/// Marshal methods: methods with [Register(name, sig, connector)], [Export], or
Expand Down
Loading