应用程序在 Android 10 时崩溃?

Application crashes on Android 10?

我的应用程序在 Play 商店上架了 2 年,运行 一切正常。但是在过去的两周内,用户突然报告在使用时应用程序崩溃。

所有崩溃都是针对 Android 10 个用户。

结构日志显示错误,

java.lang.IllegalStateException: Only owner is able to interact with pending media content://media/external/images/media/259525
        at android.os.Parcel.createException(Parcel.java:2079)
        at android.os.Parcel.readException(Parcel.java:2039)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:188)
        at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:151)
        at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:705)
        at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1687)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1503)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1420)
        at android.graphics.ImageDecoder$ContentResolverSource.createImageDecoder(ImageDecoder.java:277)
        at android.graphics.ImageDecoder.decodeDrawableImpl(ImageDecoder.java:1743)
        at android.graphics.ImageDecoder.decodeDrawable(ImageDecoder.java:1736)
        at android.widget.ImageView.getDrawableFromUri(ImageView.java:1022)
        at android.widget.ImageView.resolveUri(ImageView.java:991)
        at android.widget.ImageView.setImageURI(ImageView.java:568)
        at androidx.appcompat.widget.AppCompatImageView.setImageURI(AppCompatImageView.java:116)
        at androidx.databinding.adapters.ImageViewBindingAdapter.setImageUri(ImageViewBindingAdapter.java:46)

在此屏幕上发生的事情是,用户应该捕获屏幕截图。我保存此屏幕截图并稍后在 ImageView 上显示。我通过 URI 检索屏幕截图图像。

当我使用 URI.

检索图像时发生崩溃
  1. App编译SDK版本:28
  2. 应用目标 SDK 版本:28

为图像 URI 使用文件提供程序。

试试这个代码:

添加代码AndroidManifest.xml

<application>
  <provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.mypackage.myprovider"
    android:exported="false"
    android:grantUriPermissions="true">
   <meta-data
     android:name="android.support.FILE_PROVIDER_PATHS"
     android:resource="@xml/provider_paths"/>
  </provider>
</application>

在 res.

下的 xml 文件夹中添加 provider_paths.xml 文件
<paths xmlns:android="http://schemas.android.com/apk/res/android">
   <external-path name="external_files" path="."/>
</paths>

从您的 activity class.

中的底部代码获取 uri
final Uri data = FileProvider.getUriForFile(context, "myprovider", new File(file_path)); //here your image uri

让我来解释一下您收到此异常的确切原因是什么以及如何解决它

但首先,请仔细记住您的错误信息

"Only owner is able to interact with pending media content://media/external/images/media/259525"

请记住“拥有者”这个词,后面我的解释你就会知道这个词的意义了。

我是怎么遇到这个异常的:

我正在开发一个已经在 Play 商店上架的 pdf reader 应用程序。 我们也从 crashlytics 得到了同样的异常。就像你的情况一样,大多数设备都是 Android 10.

为什么这个异常发生在我的案例中

一些用户曾经做的是, 他们会开始从网络下载 pdf 文件, 然后他们会意识到,pdf文件太大了, 然后他们会暂停 pdf 下载(可能是为了稍后下载), 然后他们会转到文件管理器并尝试使用我的应用程序打开部分下载的 pdf 文件。 此时 pdf 已部分下载,我的应用程序将在 openInputStream() 方法处崩溃(就像您的应用程序在 openAssetFileDescriptor() 处崩溃)

“所有者”一词的含义:

“主人”二字在这里很重要。让我来告诉你为什么。 就我而言,最终用户过去常常使用下载管理器(在 chrome 内)下载 pdf。所以下载管理器的手是从网络上获取文件包,重新assemble它们并重新创建原始文件。现在,只要文件没有完全下载并重新 assembled,下载管理器就会保留该文件的“所有者”。这意味着文件将被一个同步进程锁定,只有下载管理器才有权释放锁。因此,当文件完全下载后,chrome 将释放对该文件的锁定,所有其他应用程序都可以访问该文件。

我是如何解决崩溃问题的:

我用 try-catch 块包围了错误行。如果我得到 IllegalStateException,我会向用户表示祝酒词,文件已部分下载或损坏 我做了这样的事情

    try{
        try (InputStream in = getContentResolver().openInputStream(uri);)
        {
                 -------
                 -------
        } catch (IOException | SecurityException e) {
                Timber.e(e, "Could not save work file");
                finishError(getString(R.string.mopria_document_reading_error));
        }
    }catch(IllegalStateException exception){
            Toast.makeText(getApplicationContext(), "The file is either partially 
                     downloaded or corrupted", Toast.LENGTH_LONG).show();
            finishAndRemoveTask();
        }

为什么 Android 10 大部分:

此问题并非仅针对 android 10。巧合的是 android 推出了大多数服务的更新,例如 chrome、google 文件等等,允许其他应用程序查看这些部分创建的文件。

你的情况:

屏幕截图将由android的屏幕截图管理器捕获(我不记得确切的名称)。因此,只要将捕获的屏幕截图保存到存储中,您就无法获取屏幕截图。在较新的 android 版本中,捕获屏幕截图后,您将可以快速预览该屏幕截图。除非预览成功,否则屏幕截图管理器将成为该文件的所有者。