Android 10上应用程序崩溃了?

10

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

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

Fabric日志显示错误为,

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. 应用编译SDK版本:28
  2. 应用目标SDK版本:28

请展示你的代码。没人知道你在做什么。当然,你不需要文件提供者。 - blackapps
你好,你是怎么解决这个问题的?当我调用ContentResolver上的openInputStream()方法时,我的应用程序崩溃了。 - rupinderjeet
1
你解决了你的问题吗?我也遇到了类似的问题。如果你解决了你的问题,请更新一下。 - Jasurbek
2个回答

12

让我向您解释一下,为什么会出现这个异常以及如何解决它。

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

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

请记住“owner”这个单词,因为在我之后的解释中,您将会知道它的重要性。

我遇到这个异常的经历:

我正在开发一个PDF阅读器应用程序,在Play商店上已经推出。我们也从Crashlytics获得了相同的异常报告。就像你们的情况一样,大多数设备都是Android 10。

为什么我的应用程序会出现这个异常

有些用户会这样做:他们会从网络开始下载一个PDF文件,然后意识到PDF文件太大,然后暂停下载(可能稍后再下载),然后他们会去文件管理器并尝试使用我的应用程序打开部分下载的PDF文件。此时,由于PDF文件只被部分下载,我的应用程序将在openInputStream()方法处崩溃(就像你们的应用程序在openAssetFileDescriptor()处崩溃一样)。

“Owner”这个词的重要性:

这个词“owner”在这里非常重要。让我告诉您为什么。 在我的情况下,最终用户使用下载管理器(在Chrome内部)下载PDF文件。因此,从网络获取文件的数据包、重新组装和重新创建原始文件都由下载管理器处理。现在,只要文件没有完全下载和重新组装,下载管理器就会成为该文件的“owner”。也就是说,该文件将被锁定,并且只有下载管理器才有权释放该文件的锁定。因此,在文件完全下载后,Chrome将释放该文件的锁定,其他所有应用程序都可以访问该文件。

我如何解决崩溃问题:

我将错误代码块置于try-catch块中。如果我遇到IllegalStateException异常,我会向用户显示一个toast提示,说明文件只被部分下载或已损坏。我做了类似于这样的操作:

    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版本中,当捕获屏幕截图时,您将获得该屏幕截图的快速预览。除非该预览消失,否则截图管理器将拥有该文件。


解释得非常好。我遇到了完全相同的问题。谢谢! - KiluSs

-1

使用文件提供程序来获取图像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>

从您的活动类底部代码中获取URI。

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

让我试一下,如果发生什么事情,我会更新你的。 - iCantC
不需要使用FileProvider - 它用于在应用程序之间共享文件。 - HB.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接