xamarin-android-migration
Xamarin.Android → .NET for Android Migration
For SDK-style project templates, MSBuild property tables, ABI conversion, namespace mappings, and CLI commands, see references/android-migration-api.md.
⚠️ Field-tested advice: Android migration is significantly harder than iOS. Expect more UI bugs, OEM-specific rendering differences, and issues not reproducible on emulators. Test on physical devices.
Migration Workflow
- Create new .NET for Android project (
dotnet new android) - Copy code and resources into the new project
- Update MSBuild properties (see
references/android-migration-api.md) - Update AndroidManifest.xml — remove
<uses-sdk>, use csproj properties - Delete
Resource.designer.cs(regenerated automatically) - Update NuGet dependencies
- Migrate binding libraries (if applicable)
- Replace Xamarin.Essentials with
<UseMauiEssentials>true</UseMauiEssentials> - Handle encoding changes
- Delete
bin//obj/, build, test on physical devices
Strategy: Create a new project and copy code into it — don't edit the existing project file in place.
Critical Gotchas
⚠️ Remove <uses-sdk> from AndroidManifest.xml
<!-- ❌ Xamarin-style — causes build warnings/errors -->
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<!-- ✅ Use MSBuild properties instead -->
<TargetFramework>net8.0-android</TargetFramework>
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
⚠️ Delete Resource.designer.cs
This file is auto-generated. Leftover copies from Xamarin cause duplicate symbol errors. Delete it — it will be regenerated.
⚠️ No .dll.config or .exe.config Support
.dll.config and <dllmap> are not supported in .NET Core. If your app uses System.Configuration.ConfigurationManager, migrate to appsettings.json or platform preferences.
⚠️ Essentials: Override Permissions in Every Activity
// ❌ Forgetting this → permissions silently fail
// ✅ Required in EVERY Activity that uses Essentials
public override void OnRequestPermissionsResult(
int requestCode, string[] permissions, Permission[] grantResults)
{
Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
⚠️ AndroidManifest.xml Location Changed
AndroidManifest.xml is now in the project root (not Properties/). The SDK-style project finds it there by default.
Platform-Specific Pitfalls
| Pitfall | Impact | Mitigation |
|---|---|---|
| OEM rendering differences | UI bugs not visible on emulators | Test on physical devices from multiple vendors |
| Shadow rendering varies by OEM/API level | Inconsistent shadow appearance | Implement shadows in platform-specific handler code |
| Android Wear references | Not supported in .NET for Android | Remove Wear project references |
MAndroidI18n removed |
Encoding errors at runtime | Replace with System.Text.Encoding.CodePages NuGet |
AotAssemblies deprecated |
Build warnings | Use RunAOTCompilation instead |
jar2xml not supported |
Binding library build failures | Use default class-parse parser |
DebugType=full not supported |
Build errors | Use default portable |
NuGet Compatibility Note
Android is unique: packages targeting monoandroid still work on .NET for Android. No recompilation needed for most Android-specific packages. This is NOT true for iOS/Mac.
If no compatible version exists:
- Recompile with .NET TFMs (if you own it)
- Look for a preview .NET version
- Replace with a .NET-compatible alternative
API Currency Warning
If your migrated app will also adopt .NET MAUI controls (e.g., via UseMaui), check the maui-current-apis skill for deprecated MAUI APIs to avoid (ListView, Frame, Device.*, etc.).
Quick Checklist
- ☐ Created new .NET for Android project (
dotnet new android) - ☐ Set
TargetFrameworktonet8.0-android(or later) - ☐ Set
SupportedOSPlatformVersionfor minimum SDK - ☐ Converted
AndroidSupportedAbis→RuntimeIdentifiers - ☐ Removed
<uses-sdk>from AndroidManifest.xml - ☐ Copied source, resources, and project properties
- ☐ Deleted
Resource.designer.cs,bin/,obj/ - ☐ Updated NuGet dependencies
- ☐ Added
UseMauiEssentials+Platform.Init()if using Essentials - ☐ Overridden
OnRequestPermissionsResultin every Activity - ☐ Replaced
MAndroidI18nwithSystem.Text.Encoding.CodePages - ☐ Verified AOT settings (
RunAOTCompilation, notAotAssemblies) - ☐ Tested on physical Android device(s) from multiple vendors