Visual Studio NuGet是否支持Xamarin.Android使用AndroidX库?
问题背景
我将应用的目标版本设置为Android P,在Android Studio中可以正常使用AndroidX库,但在Visual Studio的NuGet包管理器中找不到这些库。布局文件中使用了<androidx.constraintlayout.widget.ConstraintLayout>,运行时抛出如下异常:
02-09 21:31:59.970 I/MonoDroid( 8843): UNHANDLED EXCEPTION: 02-09 21:32:00.137 I/MonoDroid( 8843): Android.Views.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class androidx.constraintlayout.widget.ConstraintLayout ---> Android.Views.InflateException: Binary XML file line #1: Error inflating class androidx.constraintlayout.widget.ConstraintLayout ---> Java.Lang.ClassNotFoundException: Didn't find class "androidx.constraintlayout.widget.ConstraintLayout" on path: DexPathList[[zip file "/data/app/Keystore.Keystore-aaHeQkjsNRoUnkfPmnf7Tw==/base.apk"],nativeLibraryDirectories=[/data/app/Keystore.Keystore-aaHeQkjsNRoUnkfPmnf7Tw==/lib/x86, /data/app/Keystore.Keystore-aaHeQkjsNRoUnkfPmnf7Tw==/base.apk!/lib/x86, /system/lib]] 02-09 21:32:00.137 I/MonoDroid( 8843): --- End of inner exception stack trace --- 02-09 21:32:00.137 I/MonoDroid( 8843): --- End of inner exception stack trace --- 02-09 21:32:00.137 I/MonoDroid( 8843): at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00089] in <8acc8089c2ed40d08469fbaa6710a44c>:0 02-09 21:32:00.137 I/MonoDroid( 8843): at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0005d] in <8acc8089c2ed40d08469fbaa6710a44c>:0 02-09 21:32:00.137 I/MonoDroid( 8843): at Android.App.Activity.SetContentView (System.Int32 layoutResID) [0x00022] in <957bbfdfda4341e2939c881206c1140a>:0 02-09 21:32:00.137 I/MonoDroid( 8843): at Keystore.MainActivity.OnCreate (Android.OS.Bundle savedInstanceState) [0x00009] in H:\My Projects\Android\Samples\Keystore\MainActivity.cs:19 02-09 21:32:00.137 I/MonoDroid( 8843): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <957bbfdfda4341e2939c881206c1140a>:0 02-09 21:32:00.138 I/MonoDroid( 8843): at (wrapper dynamic-method) System.Object.3(intptr,intptr,intptr) 02-09 21:32:00.138 I/MonoDroid( 8843): --- End of managed Android.Views.InflateException stack trace --- 02-09 21:32:00.138 I/MonoDroid( 8843): android.view.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class androidx.constraintlayout.widget.ConstraintLayout 02-09 21:32:00.138 I/MonoDroid( 8843): Caused by: android.view.InflateException: Binary XML file line #1: Error inflating class androidx.constraintlayout.widget.ConstraintLayout 02-09 21:32:00.138 I/MonoDroid( 8843): Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.constraintlayout.widget.ConstraintLayout" on path: DexPathList[[zip file "/data/app/Keystore.Keystore-aaHeQkjsNRoUnkfPmnf7Tw==/base.apk"],nativeLibraryDirectories=[/data/app/Keystore.Keystore-aaHeQkjsNRoUnkfPmnf7Tw==/lib/x86, /data/app/Keystore.Keystore-aaHeQkjsNRoUnkfPmnf7Tw==/base.apk!/lib/x86, /system/lib]] 02-09 21:32:00.138 I/MonoDroid( 8843): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134) 02-09 21:32:00.138 I/MonoDroid( 8843): at java.lang.ClassLoader.loadClass(ClassLoader.java:379) 02-09 21:32:00.138 I/MonoDroid( 8843): at java.lang.ClassLoader.loadClass(ClassLoader.java:312) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.view.LayoutInflater.createView(LayoutInflater.java:606) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:790) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.view.LayoutInflater.inflate(LayoutInflater.java:492) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.support.v7.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:469) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 02-09 21:32:00.138 I/MonoDroid( 8843): at md561c0eefc2ba1e38323457d81b00d3caf.MainActivity.n_onCreate(Native Method) 02-09 21:32:00.138 I/MonoDroid( 8843): at md561c0eefc2ba1e38323457d81b00d3caf.MainActivity.onCreate(MainActivity.java:31) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.app.Activity.performCreate(Activity.java:7136) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.app.Activity.performCreate(Activity.java:7127) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 02-09 21:32:00.138 I/MonoDroid( 8843): at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 02-09 21:32:00.139 I/MonoDroid( 8843): at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 02-09 21:32:00.139 I/MonoDroid( 8843): at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 02-09 21:32:00.139 I/MonoDroid( 8843): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 02-09 21:32:00.139 I/MonoDroid( 8843): at android.os.Handler.dispatchMessage(Handler.java:106) 02-09 21:32:00.139 I/MonoDroid( 8843): at android.os.Looper.loop(Looper.java:193) 02-09 21:32:00.139 I/MonoDroid( 8843): at android.app.ActivityThread.main(ActivityThread.java:6669) 02-09 21:32:00.139 I/MonoDroid( 8843): at java.lang.reflect.Method.invoke(Native Method) 02-09 21:32:00.139 I/MonoDroid( 8843): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 02-09 21:32:00.139 I/MonoDroid( 8843): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
解决方案
当然可以在Xamarin.Android中使用AndroidX库!你遇到的问题主要是因为还没完成AndroidX的基础配置和库引用,按照下面的步骤操作就能解决:
更新你的Xamarin环境
AndroidX在Xamarin中的支持需要较新的版本,确保你的Visual Studio是2019 16.4及以上版本,同时Xamarin.Android版本至少为10.0(对应Android 10/Q)。如果版本过低,NuGet里是找不到AndroidX相关包的。启用AndroidX支持
右键你的Xamarin.Android项目 → 选择属性 → 切换到应用程序标签页,找到AndroidX选项,勾选“使用AndroidX”。如果你的项目之前使用的是旧的Support Library,这个操作会自动帮你把所有Support库的引用替换成对应的AndroidX库,避免版本冲突。通过NuGet安装所需的AndroidX库
现在打开NuGet包管理器,搜索你需要的库。比如你用到的ConstraintLayout,对应的NuGet包是Xamarin.AndroidX.ConstraintLayout,安装这个包后,布局文件里的<androidx.constraintlayout.widget.ConstraintLayout>就能被正确识别和加载了。清理重建项目
安装完包后,执行清理解决方案然后重建解决方案,清除可能存在的缓存问题,确保所有引用都能正确生效。
额外提示
如果之前手动修改过布局文件或者代码中的引用,要检查所有android.support.xxx的路径是否都替换成了androidx.xxx,比如原来的AppCompatActivity要换成AndroidX.AppCompat.App.AppCompatActivity,避免混合使用导致的异常。
内容的提问来源于stack exchange,提问作者Nongthonbam Tonthoi

