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());
    }
}
View Code

然后接口中使用

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;
        }
    }
}
View Code

参考: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/),但是这样写入文件需要获取设备的写权限,有点不太友好。

在参考了:

Android私有目录和公有目录

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) ,
此时如果没有把Providerandroid:authorities的属性也换掉,
安装乙APP到手机上,provider就会和甲APP的冲突.

需要修改项目中的配置文件:AndroidManifest.xml,可以改为如下
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);
                    });
                });
            }
        }

参考:xamarin优化listView.ScrollTo

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.

  1. Close Visual Studio and navigate to the Solution in File Explorer
  2. Delete the hidden .vs folder
  3. Go into each affected project sub folder and delete the following files; project_name.nuget.props and project_name.nuget.targets
  4. 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>

 

posted @ 2019-10-13 18:50  peterYong  阅读(4649)  评论(0编辑  收藏  举报