android – 在Huawei设备上的FileProvider错误

android – 在Huawei设备上的FileProvider错误,第1张

概述我有一个例外,只有在我的应用程序中的华为设备上使用FileProvider.getUriForFile时才会发生: Exception: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/<card name>/Android/data/<app package>/fi 我有一个例外,只有在我的应用程序中的华为设备上使用fileProvIDer.getUriForfile时才会发生:
Exception: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/<card name>/AndroID/data/<app package>/files/.export/2016-10-06 13-22-33.pdf   at androID.support.v4.content.fileProvIDer$SimplePathStrategy.getUriForfile(Sourcefile:711)   at androID.support.v4.content.fileProvIDer.getUriForfile(Sourcefile:400)

这是我的清单中我的文件提供者的定义:

<provIDer    androID:name="androID.support.v4.content.fileProvIDer"    androID:authoritIEs="${applicationID}.fileprovIDer"    androID:exported="false"    androID:grantUriPermissions="true">    <Meta-data        androID:name="androID.support.file_PROVIDER_PATHS"        androID:resource="@xml/file_provIDer_paths" /></provIDer>

配置路径的资源文件:

<?xml version="1.0" enCoding="utf-8"?><paths xmlns:androID="http://schemas.androID.com/apk/res/androID">    <external-files-path name="external_files" path="" /></paths>

关于这个问题的原因的任何想法,以及为什么仅在华为设备上发生?鉴于我没有华为设备,我该如何进行调试?

更新:

我在我的应用程序中添加了更多的日志,并且在这些设备上打印ContextCompat.getExternalfilesDirs和context.getExternalfilesDir时,我得到了一些不一致的结果:

ContextCompat.getExternalfilesDirs:/storage/emulated/0/AndroID/data/<package>/files/storage/sdcard1/AndroID/data/<package>/filescontext.getExternalfilesDir:/storage/sdcard1/AndroID/data/<package>/files

这与ContextCompat.getExternalfilesDirs的文档不一致,说明返回的第一个路径与getExternalfilesDir(String)相同,

这解释了我在代码中使用context.getExternalfilesDir并且fileProvIDer使用ContextCompat.getExternalfilesDirs的问题.

解决方法 更新AndroID N(留下原始答案,并已确认这种新方法在生产中有效):

正如您在更新中所指出的那样,许多华为设备型号(例如KIW-L24,ALE-L21,ALE-L02,PLK-L01以及其他各种)将打破AndroIDCompany对ContextCompat#getExternalfilesDirs(String)的调用.而不是返回Context#getExternalfilesDir(String)(即默认条目)作为数组中的第一个对象,而是返回第一个对象作为外部SD卡的路径(如果存在).

通过打破这种订购合同,这些具有外部SD卡的华为设备将在对外部文件路径根的fileProvIDer#getUriForfile(Context,String,file)的调用上与IllegalArgumentException异常崩溃.尽管您可以采取各种解决方案来尝试处理此问题(例如编写一个自定义fileProvIDer实现),但我发现最简单的方法是抓住这个问题:

> Pre-N:返回Uri#fromfile(file),由于fileUrIExposedException,它不能与AndroID N及更高版本配合使用
> N:将文件复制到缓存路径(注意:如果在UI线程上完成,可以引入ANR),然后为复制的文件返回fileProvIDer#getUriForfile(Context,file)(即完全避免错误)

完成此 *** 作的代码可以在下面找到:

public class ContentUriProvIDer {    private static final String HUAWEI_MANUFACTURER = "Huawei";    public static Uri getUriForfile(@NonNull Context context,@NonNull String authority,@NonNull file file) {        if (HUAWEI_MANUFACTURER.equalsIgnoreCase(Build.MANUFACTURER)) {            Log.w(ContentUriProvIDer.class.getSimplename(),"Using a Huawei device Increased likelihood of failure...");            try {                return fileProvIDer.getUriForfile(context,authority,file);            } catch (IllegalArgumentException e) {                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {                    Log.w(ContentUriProvIDer.class.getSimplename(),"Returning Uri.fromfile to avoID Huawei 'external-files-path' BUG for pre-N devices",e);                    return Uri.fromfile(file);                } else {                    Log.w(ContentUriProvIDer.class.getSimplename(),"ANR Risk -- copying the file the location cache to avoID Huawei 'external-files-path' BUG for N+ devices",e);                    // Note: Periodically clear this cache                    final file cacheFolder = new file(context.getCacheDir(),HUAWEI_MANUFACTURER);                    final file cacheLocation = new file(cacheFolder,file.getname());                    inputStream in = null;                    OutputStream out = null;                    try {                        in = new fileinputStream(file);                        out = new fileOutputStream(cacheLocation); // appending output stream                        IoUtils.copy(in,out);                        Log.i(ContentUriProvIDer.class.getSimplename(),"Completed AndroID N+ Huawei file copy. Attempting to return the cached file");                        return fileProvIDer.getUriForfile(context,cacheLocation);                    } catch (IOException e1) {                        Log.e(ContentUriProvIDer.class.getSimplename(),"Failed to copy the Huawei file. Re-throwing exception",e1);                        throw new IllegalArgumentException("Huawei devices are unsupported for AndroID N",e1);                    } finally {                        IoUtils.closeQuIEtly(in);                        IoUtils.closeQuIEtly(out);                    }                }            }        } else {            return fileProvIDer.getUriForfile(context,file);        }    }}

随着file_provIDer_paths.xml:

<?xml version="1.0" enCoding="utf-8"?><paths xmlns:androID="http://schemas.androID.com/apk/res/androID">    <external-files-path name="public-files-path" path="." />    <cache-path name="private-cache-path" path="." /></paths>

创建这样的课程后,将您的调用替换为:

fileProvIDer.getUriForfile(Context,file)

有:

ContentUriProvIDer.getUriForfile(Context,file)

坦白说,我不认为这是一个特别优美的解决方案,但它确实允许我们使用正式记录的AndroID行为,而不做任何太大的事情(例如编写一个自定义fileProvIDer实现).我已经在生产中测试了这个,所以我可以确认它解决了这些华为的崩溃.对我来说,这是最好的办法,因为我不想花太多时间来解决制造商的缺陷.

从华为设备更新之前,此错误更新为AndroID N:

由于fileUrIExposedException,这不会适用于AndroID N及以上版本,但我尚未在AndroID N上遇到这种配置错误的华为设备.

public class ContentUriProvIDer {    private static final String HUAWEI_MANUFACTURER = "Huawei";    public static Uri getUriForfile(@NonNull Context context,@NonNull file file) {        if (HUAWEI_MANUFACTURER.equalsIgnoreCase(Build.MANUFACTURER) && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {            Log.w(ContentUriProvIDer.class.getSimplename(),"Using a Huawei device on pre-N. Increased likelihood of failure...");            try {                return fileProvIDer.getUriForfile(context,file);            } catch (IllegalArgumentException e) {                Log.w(ContentUriProvIDer.class.getSimplename(),"Returning Uri.fromfile to avoID Huawei 'external-files-path' BUG",e);                return Uri.fromfile(file);            }        } else {            return fileProvIDer.getUriForfile(context,file);        }    }}
总结

以上是内存溢出为你收集整理的android – 在Huawei设备上的FileProvider错误全部内容,希望文章能够帮你解决android – 在Huawei设备上的FileProvider错误所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1134138.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-30
下一篇 2022-05-30

发表评论

登录后才能评论

评论列表(0条)

保存