【问题标题】:Application crashes on Android 10?应用程序在 Android 10 上崩溃?
【发布时间】:2021-03-26 15:58:52
【问题描述】:

我的应用程序在 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

【问题讨论】:

  • 请出示您的代码。没有人知道你在做什么。当然,您不需要文件提供程序。
  • 你好,你是怎么解决的?当我在ContentResolver 上调用openInputStream() 时,我的应用程序崩溃了。
  • 您的问题解决了吗。我有一个类似的问题。如果您解决了问题,请更新

标签: android illegalstateexception


【解决方案1】:

让我解释一下你得到这个异常的确切原因以及如何解决它

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

“只有所有者才能与待处理的媒体进行交互 内容://media/external/images/media/259525"

请记住“所有者”这个词,稍后在我的解释中你会知道这个词的含义。

我是如何遇到这个异常的:

我正在开发一个已在 Play 商店上架的 pdf 阅读器应用程序。 我们也从 crashlytics 得到了同样的例外。就像您的情况一样,大多数设备都是 Android 10。

为什么在我的案例中会发生此异常

一些用户过去常做的事情是, 他们会开始从网络下载一个pdf文件, 然后他们会意识到,pdf尺寸太大, 然后他们会暂停 pdf 下载(也许以后再下载), 然后他们会去文件管理器并尝试用我的应用程序打开部分下载的 pdf 文件。 此时,由于部分下载了 pdf,我的应用程序将在 openInputStream() 方法中崩溃(就像您在 openAssetFileDescriptor() 中的崩溃一样)

“所有者”一词的意义:

“所有者”这个词在这里非常重要。让我来告诉你为什么。 就我而言,最终用户过去常常使用下载管理器(chrome 内部)下载 pdf。所以下载管理器从网络上获取文件包,重新组装它们并重新创建原始文件。现在,只要文件没有完全下载并重新组装,下载管理器将保持该文件的“所有者”。这意味着文件将被同步过程锁定,只有下载管理器有权释放锁定。因此,当文件完全下载后,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 版本中,当捕获屏幕截图时,您将获得该屏幕截图的快速预览。除非该预览成功,否则屏幕截图管理器将是该文件的所有者。

【讨论】:

    【解决方案2】:

    为图像 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 类的底部代码中获取 uri。

    final Uri data = FileProvider.getUriForFile(context, "myprovider", new File(file_path)); //here your image uri
    

    【讨论】:

    • 让我试试这个,如果有事我会通知你的。
    • 不需要FileProvider - 在与其他应用程序共享文件时使用它。
    猜你喜欢
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多