Xamarin.Android开发中遇到的问题
安卓版本和SDK
开发
1、Resource.Id未包含xxx的定义
打开了一个OK的Id,是位于\obj\Debug\90\designtime\Resource.designer.cs ,打开文件搜索xxx,果然没有。
删除此文件 重新生成项目,并没有重新生成Resource.designer.cs
解决方法:
删除整个obj文件夹,重新生成项目;
或者重启VS,自动重新生成Resource.designer.cs了,并且含有xxx
2、Button文本默认大写
参考:xamarin forms中的Button文本默认大写
将按钮的属性textAllCaps都改为false。默认没有设置 是true。
3、ADB0020: Android ABI 不匹配。
问题1:你正将应用支持的“armeabi,armeabi-v7a,x86”ABI 部署到 ABI“x86_64”的不兼容设备。应创建匹配其中一个应用 ABI 的仿真程序,或将“x86_64”添加到应用生成的 ABI 列表中
问题原因:应该是选择的模拟器(X86_64)不匹配,需要创建一个“armeabi,armeabi-v7a,x86”是模拟器来调试。
或者看下“使用共享运行时”是否选中
参考:
说说Android项目中的armeabi,armeabi-v7a和x86
Android 关于arm64-v8a、armeabi-v7a、armeabi、x86下的so文件兼容问题
问题2:Please open the Android SDK Manager and install the latest version of 'Android Support Repository' from the 'Extras' section, and then reload your solution.
问题原因:上一步选择X86处理器后,需要安装相应的SDK,和工具中的Android Support Repository
4、方法过时
4.1 [Obsolete("This constructor is obsolete as of version 2.5. Please use PageRenderer(Context) instead.")]
在使用PageRenderer时提示这个构造函数已经过时,发生这种情况的原因是从v2.5版本开始的Xamarin.Forms非常简单,将Xamarin.Forms.Forms的Context属性标记为过时。 因此,要获取渲染器的全局上下文,有必要调用该渲染器的基类,这意味着在构造函数中,您需要执行以下操作: 添加以下代码即可(Please use PageRenderer(Context) instead.)
public WriteEmailPageRenderer(Context context) : base(context) { }
参考:How do I resolve WebViewRenderer is obsolete
4.2 Context is obsolete as of version 2.5. Please use a local context instead
报过时的写法:Android.Content.Context content = Forms.Context; 或者 Activity activity = (Activity)Forms.Context;
在Dependencies中定义特定平台的功能时,使用Forms.Context会提示已过时,请改为使用本地环境。
解决方案是在不引用Xamarin.Forms.Forms.Context的情况下获取本地上下文。
注:Android.Content.Context是应用程序环境全局信息上下文,Activity都是继承自此类。
有两种方式解决:
方式1、在接口中提供Init(),然后在MainActivity中调用:VersionHelper.Init(this);
public class VersionHelper : IVersionHelper { static Context _context; public static void Init(Context context) { _context = context; } ...
方式2、在MainActivity类中创建一个静态属性,并将其设置为MainActivity实例:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { internal static MainActivity Instance { get; private set; } protected override void OnCreate(Bundle bundle) { ... global::Xamarin.Forms.Forms.Init(this, bundle); Instance = this; Xamarin.Forms.DependencyService.Register<IVersionHelper, VersionHelper>(); LoadApplication(new App()); } }
然后接口中使用
using Android.Content; namespace DependencyServiceAndLocalContext.Droid { public class VersionHelper : IVersionHelper { public string GetVersionNumber() { var versionNumber = string.Empty; if (MainActivity.Instance != null) { versionNumber = MainActivity.Instance.PackageManager.GetPackageInfo( MainActivity.Instance.PackageName, 0).VersionName; } return versionNumber; } } }
参考:Xamarin.Forms 2.5 and Local Context on Android
5、权限问题
需要获取设备权限时,是由设备自动弹出提醒的。
读权限和写权限由区别:
- 写:WRITE_EXTERNAL_STORAGE 则其具有写和读权限;
- 读:READ_EXTERNAL_STORAGE 则其只具有读权限
5.1 写文件 、文件目录
最近在app中做一个 录音功能时,需要将录音文件保存在手机上,一开始使用了:Android.OS.Environment.ExternalStorageDirectory.AbsolutePath 获取目录(/storage/emulated/0/),但是这样写入文件需要获取设备的写权限,有点不太友好。
在参考了:
open failed: EACCES (Permission denied)解决方法 AndroidQ
之后。
在存储一些临时文件时,可以选用Context.GetExternalFilesDir("").AbsolutePath 方法,不需要获取设备的写权限;
获取到目录为:/storage/emulated/0/Android/data/com.app名称/files/
其中: /storage/emulated/0/目录,就是华为手机打开的 内部存储的根目录。
调试
1、Xamarin.android不能显示网络、远程图片
调试时从IDE的输出可以看出原因:Image load failed: System.ObjectDisposedException: Can not access a closed Stream. 不知这个问题是不是还没有去修复,还是不准备修复
因为看到Mircsoft官方示例eshop都是用的一个开源包:https://github.com/luberda-molinet/FFImageLoading
注意:各个平台需要调用: CachedImageRenderer.Init(false); 【上述github有使用方法】
否则 会报错:
"Please call CachedImageRenderer.Init method in a platform specific project to use FFImageLoading!"
2、Can't install because provider name com.xxx.fileprovider (in package yyy) is already used by com.mesince]
这个问题其实本质就是手机里已经安装有同名的Provider
的APK了.
比如我在甲APP(com.xxx
)中的AndroidManifest.xml
中定义了一个Provider,
安装完这个甲APP,
我把代码里的ApplicationId
改成com.yyy
,即换皮成乙APP(com.yyy
) ,
此时如果没有把Provider
的android:authorities
的属性也换掉,
安装乙APP到手机上,provider就会和甲APP的冲突.
android:authorities= ${applicationId}.provider
参考:[Android] 该文件包与具有同一名称的现有文件包存在冲突
3、Android http 不能联网:Cleartext HTTP traffic to not permitted
在尝试 请求外部的WebApi时,报出错误。
解决:在AndroidManifest.xml配置文件的<application>标签中插入:
android:usesCleartextTraffic="true"
4、Android模拟机时间修改
没做任何修改的前提下,其时间是美国纽约的时区,相对中国是-8小时的。所以程序中DateTime.Now获取的比中国时间小8小时
可以自己修改为和中国一样。
本来想设置 图中1处的时区,但是发现没有中国的。于是直接改图中2处的时间。
5、listView.ScrollTo不生效
需要看下滚动的代码是否有UI线程执行的
txtMessage.Focused += TxtMessage_Focused; private void TxtMessage_Focused(object sender, FocusEventArgs e) { if (listChatMessage.Count > 0) { Task.Delay(100).ContinueWith((t) => { Device.BeginInvokeOnMainThread(() => { listView.ScrollTo(listChatMessage.Last(), ScrollToPosition.End, false); }); }); } }
6、not attached to window manager
not attached to window manager有许多场景发生。最近在做设备锁时,弹出进度圈和取消时碰到此问题
调试判断出大概是Activity 已经销毁了,再调Dismiss时失败,,【泄露】
最终修改代码,发现确实是开启的dialog在Activity销毁之前,没有关闭。。然后在Activity销毁了再去dismiss。
7、Unable to add window -- token android.os.BinderProxy@b1bab0a is not valid; is your activity running?
最近在做设备锁时,需要弹窗的地方碰到此问题
问题:Activity不是处于运行状态
调试查看报错处的Activity是哪个,代码中写的是Activity context = (Activity)Forms.Context;
System.Console.WriteLine(TAG + context.LocalClassName);
发现此Activity调用了OnDestroy()马上就销毁了,所以他不是在运行中。。
修改Activity的赋值:Activity activity = MainActivity.Instance;
8、net::ERR_CLEARTEXT_NOT_PERMITTED
在安卓9.0中调试WebView加载网页时错误。
解决方法: 在AndroidManifest文件中的节点Application中加入 android:usesCleartextTraffic="true"
9、Xamarin.forms包加入不进
在迁移一个项目后,Xamarin.Android中本来有Xamarin.Forms这个包的,但是同事从远程拉取代码后,没有显示此包,导致调试不通过。
报错(17个错误):style attribute 'attr/colorPrimaryDark (aka com.mesince:attr/colorPrimaryDar
在Nuget中引入了 但还是不行。后来尝试 从解决方案中卸载此Xamarin.Android项目,重新添加,居然可以显示了,好奇怪的问题!
10、调试不进断点
这种一般是vs配置或者项目属性配置的问题,
有几个思路:
1) 是否是Debug模式
2)清理解决方案重新调试
3)项目属性,共享运行时 得勾选
11、项目生成报错:Xamarin.Forms targets have been imported multiple times. Please check your project file and remove the duplicate import(s)
见问题12
12、您的项目未引用“.NETPortable,Version=v4.5,Profile=Profile111”框架。在项目文件的“TargetFrameworks”属性中添加对“.NETPortable,Version=v4.5,Profile=Profile111”的引用,然后重新运行NuGet restore。
以上两个问题都可以参考
参考:Error XF001: Xamarin.Forms targets have been imported multiple times
这可能是因为对NuGet包使用PackageReference
This can be because of the move to using PackageReference for your NuGet packages and a simple fix awaits you.
- Close Visual Studio and navigate to the Solution in File Explorer
- Delete the hidden .vs folder
- Go into each affected project sub folder and delete the following files; project_name.nuget.props and project_name.nuget.targets
- Open the solution in Visual Studio, do a Clean and Rebuild,
意思是:关闭vs,进到解决方案目录,删除影藏文件夹: .vs ;进到各个项目目录,删除.obj文件夹 【里面含有 project_name.nuget.props and project_name.nuget.targets】。
13、attribute android:requestLegacyExternalStorage not found.
compileSdkVersion 版本设置为29或以上 (android 10+)
Android 中如何选择 compileSdkVersion, minSdkVersion 和 targetSdkVersion
14、存档不成功
存档发布成apk文件时报错,
需要禁用”使用共享的Mono运行时“,在属性->Android选项中,禁用。若此处没有,则可以打开项目文件(.csproj)本身去修改:
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>