.NET Maui无法在Visual Studio for Mac Preview 17.4部署到Android模拟器
问题概述
使用.NET Maui开发跨平台业务应用,此前运行正常。将.NET Core SDK从6.0.400-preview.22330.6升级至6.0.400后,出现部署异常:调试时构建成功,但Visual Studio for Mac在「部署到设备」环节后提示错误:Cannot execute 'Users/xxxx/src/Mobile/bin/Debug/net6.0-android/Mobile.dll'。
「部署到设备」窗口无错误、无警告,多数目标因输出文件已最新被跳过。通过命令行和VS for Mac清理项目均无效,但使用命令dotnet build -t:Run -f:net6.0-android可在模拟器正常运行应用。
查看VS for Mac日志发现核心错误:加载obj/Debug/net6.0-android/android/AndroidManifest.xml时触发ArgumentNullException(参数versions为空),即使该文件实际存在。新建测试项目仍出现相同问题。
解决方法
1. 更新Visual Studio for Mac到最新版本
该问题是VS for Mac与.NET 6.0.400 SDK的兼容性Bug,更新到17.3.6及以上版本可修复Manifest加载时的空参数问题。
2. 临时绕过VS for Mac部署,使用命令行调试
若暂时无法更新VS,可通过以下命令继续开发:
- 启动模拟器调试:
dotnet build -t:Run -f:net6.0-android - 部署到真机:
dotnet build -t:Install -f:net6.0-android,完成后通过VS或adb启动应用调试。
3. 手动指定Android SDK版本(可选)
在项目.csproj文件中明确指定Android SDK相关版本,避免工具链自动检测异常:
<PropertyGroup> <TargetFramework>net6.0-android</TargetFramework> <AndroidSdkVersion>31</AndroidSdkVersion> <AndroidTargetSdkVersion>31</AndroidTargetSdkVersion> <AndroidMinSdkVersion>21</AndroidMinSdkVersion> </PropertyGroup>
问题根源
异常源于VS for Mac的MonoDroid工具链在加载自动生成的AndroidManifest时,未正确初始化AndroidVersions参数,导致空指针异常。命令行工具链不受影响,因其Manifest加载逻辑与VS for Mac内部实现不同。
相关错误日志
ERROR [2022-08-15 15:48:19Z]: Error loading android manifest '/Users/xxxx/src/Mobile/obj/Debug/net6.0-android/android/AndroidManifest.xml' System.ArgumentNullException: Value cannot be null. (Parameter 'versions') at Xamarin.Android.Tools.AndroidAppManifest.Load(String filename, AndroidVersions versions) in /Users/runner/work/1/s/MonoDevelop.MonoDroid/external/androidtools/external/xamarin-android-tools/src/Xamarin.Android.Tools.AndroidSdk/AndroidAppManifest.cs:line 84 at MonoDevelop.MonoDroid.ProjectSystem.AndroidApplicationManifest..ctor(String manifestFile, AndroidProjectProperties projectProperties) in /Users/runner/work/1/s/MonoDevelop.MonoDroid/MonoDevelop.MonoDroid/ProjectSystem/PropertiesProviders/AndroidApplicationManifest.cs:line 13 at MonoDevelop.MonoDroid.ProjectSystem.AndroidManifestCache.CreateNewManifest(String filename) in /Users/runner/work/1/s/MonoDevelop.MonoDroid/MonoDevelop.MonoDroid/ProjectSystem/PropertiesProviders/AndroidManifestCache.cs:line 33 INFO [2022-08-15 15:48:19Z]: Add-in loaded: DotNetCore.Debugger INFO [2022-08-15 15:48:19Z]: Add-in loaded: MonoDevelop.Debugger.Soft.AspNet ERROR [2022-08-15 15:48:19Z]: Cannot execute "/Users/xxxx/src/Mobile/bin/Debug/net6.0-android/Mobile.dll"
不同位置的AndroidManifest内容
1. obj/Debug/net6.0-android下自动生成的Manifest
<?xml version="1.0" encoding="utf-8"?> <!-- This code was generated by a tool. It was generated from /Users/xxxx/src/NewTest/Platforms/Android/AndroidManifest.xml Changes to this file may cause incorrect behavior and will be lost if the contents are regenerated. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" package="com.companyname.newtest" android:versionName="1.0"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true" android:name="crc64035c0982af6367fe.MainApplication" android:label="NewTest" android:debuggable="true" android:extractNativeLibs="true"> <activity android:configChanges="density|orientation|smallestScreenSize|screenLayout|screenSize|uiMode" android:theme="@style/Maui.SplashTheme" android:name="crc64035c0982af6367fe.MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:configChanges="orientation|screenSize" android:exported="true" android:name="crc6468b6408a11370c2f.WebAuthenticatorIntermediateActivity" /> <provider android:authorities="com.companyname.newtest.fileProvider" android:exported="false" android:grantUriPermissions="true" android:name="microsoft.maui.essentials.fileProvider"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/microsoft_maui_essentials_fileprovider_file_paths" /> </provider> <receiver android:enabled="true" android:exported="false" android:label="Essentials Connectivity Broadcast Receiver" android:name="crc64e53d2f592022988e.ConnectivityBroadcastReceiver" /> <activity android:configChanges="orientation|screenSize" android:exported="true" android:name="crc64ba438d8f48cf7e75.IntermediateActivity" /> <receiver android:enabled="true" android:exported="false" android:label="Essentials Battery Broadcast Receiver" android:name="crc640a8d9a12ddbf2cf2.BatteryBroadcastReceiver" /> <receiver android:enabled="true" android:exported="false" android:label="Essentials Energy Saver Broadcast Receiver" android:name="crc640a8d9a12ddbf2cf2.EnergySaverBroadcastReceiver" /> <service android:name="crc64396a3fe5f8138e3f.KeepAliveService" /> <provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="1999999999" android:authorities="com.companyname.newtest.mono.MonoRuntimeProvider.__mono_init__" /> </application> </manifest>
2. Platforms/Android目录下的原始Manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
3. Bin文件夹签名包中提取的Manifest
<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:compileSdkVersion="31" android:compileSdkVersionCodename="12" package="com.companyname.newtest" platformBuildVersionCode="31" platformBuildVersionName="12"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:appComponentFactory="androidx.core.app.CoreComponentFactory" android:debuggable="true" android:extractNativeLibs="true" android:icon="@mipmap/appicon" android:label="NewTest" android:name="crc64035c0982af6367fe.MainApplication" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"> <activity android:configChanges="density|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:exported="true" android:name="crc64035c0982af6367fe.MainActivity" android:theme="@style/Maui.SplashTheme"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:configChanges="orientation|screenSize" android:exported="true" android:name="crc6468b6408a11370c2f.WebAuthenticatorIntermediateActivity"/> <provider android:authorities="com.companyname.newtest.fileProvider" android:exported="false" android:grantUriPermissions="true" android:name="microsoft.maui.essentials.fileProvider"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/microsoft_maui_essentials_fileprovider_file_paths"/> </provider> <receiver android:enabled="true" android:exported="false" android:label="Essentials Connectivity Broadcast Receiver" android:name="crc64e53d2f592022988e.ConnectivityBroadcastReceiver"/> <activity android:configChanges="orientation|screenSize" android:exported="true" android:name="crc64ba438d8f48cf7e75.IntermediateActivity"/> <receiver android:enabled="true" android:exported="false" android:label="Essentials Battery Broadcast Receiver" android:name="crc640a8d9a12ddbf2cf2.BatteryBroadcastReceiver"/> <receiver android:enabled="true" android:exported="false" android:label="Essentials Energy Saver Broadcast Receiver" android:name="crc640a8d9a12ddbf2cf2.EnergySaverBroadcastReceiver"/> <service android:name="crc64396a3fe5f8138e3f.KeepAliveService"/> <provider android:authorities="com.companyname.newtest.mono.MonoRuntimeProvider.__mono_init__" android:exported="false" android:initOrder="1999999999" android:name="mono.MonoRuntimeProvider"/> <provider android:authorities="com.companyname.newtest.androidx-startup" android:exported="false" android:name="androidx.startup.InitializationProvider"> <meta-data android:name="androidx.emoji2.text.EmojiCompatInitializer" android:value="androidx.startup"/> <meta-data android:name="androidx.lifecycle.ProcessLifecycleInitializer" android:value="androidx.startup"/> </provider> <uses-library android:name="androidx.window.extensions" android:required="false"/> <uses-library android:name="androidx.window.sidecar" android:required="false"/> </application> </manifest>
内容的提问来源于stack exchange,提问作者user19771002

