Java Android 安全异常

8

我的应用程序中,用户可以拍照或将照片添加到应用程序中。

当应用程序尝试在ImageView中显示保存的图像时,我收到了java.lang.SecurityException崩溃报告。

它出错的行是:

holder.imageV.setImageURI(uriParsed);

我无法在我的设备或模拟器上复制这个错误,它们都可以正常显示图片。

我使用的完整代码是

JoinProjectPicture projectPicture = mProjects.get(position);
Project current = projectPicture.getProject();
Picture picture = projectPicture.getPicture();

 holder.projectName.setText(current.getProjectName() + "(" + current.getWidth() + "x" + current.getHeight() + ")");
 holder.projectStatusTV.setText(current.getStatus());

 if(picture != null) {
      String pictureName = picture.getPictureName();
      Uri uriParsed = Uri.parse(pictureName);

      if(uriParsed != null) {
           Log.d("URIParsed", "Project: " + current.getProjectName() + " - Parsed: " + uriParsed);
           holder.imageV.setImageURI(uriParsed);
    }
}

我的设备上显示的日志输出(3个项目,其中一个没有图片)

项目:测试 - 解析:file:///storage/emulated/0/Android/data/com.desbrina.diamondpaintinglogbook/files/Pictures/20191111_1408166491573472523237896.jpg

项目:测试3 - 解析:content://com.android.providers.media.documents/document/image%3A1891

错误

java.lang.SecurityException: 
  at android.os.Parcel.createException (Parcel.java:1966)
  at android.os.Parcel.readException (Parcel.java:1934)
  at android.os.Parcel.readException (Parcel.java:1884)
  at android.app.IActivityManager$Stub$Proxy.getContentProvider (IActivityManager.java:4039)
  at android.app.ActivityThread.acquireProvider (ActivityThread.java:6365)
  at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider (ContextImpl.java:2825)
  at android.content.ContentResolver.acquireUnstableProvider (ContentResolver.java:1835)
  at android.content.ContentResolver.openTypedAssetFileDescriptor (ContentResolver.java:1449)
  at android.content.ContentResolver.openAssetFileDescriptor (ContentResolver.java:1302)
  at android.content.ContentResolver.openAssetFileDescriptor (ContentResolver.java:1225)
  at android.graphics.ImageDecoder$ContentResolverSource.createImageDecoder (ImageDecoder.java:273)
  at android.graphics.ImageDecoder.decodeDrawableImpl (ImageDecoder.java:1652)
  at android.graphics.ImageDecoder.decodeDrawable (ImageDecoder.java:1645)
  at android.widget.ImageView.getDrawableFromUri (ImageView.java:952)
  at android.widget.ImageView.resolveUri (ImageView.java:921)
  at android.widget.ImageView.setImageURI (ImageView.java:532)
  at android.support.v7.widget.AppCompatImageView.setImageURI (AppCompatImageView.java:116)
  at com.desbrina.diamondpaintinglogbook.ui.main.Adapters.ProjectListAdapter.onBindViewHolder (ProjectListAdapter.java:88)
  at com.desbrina.diamondpaintinglogbook.ui.main.Adapters.ProjectListAdapter.onBindViewHolder (ProjectListAdapter.java:23)
  at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder (RecyclerView.java:6781)
  at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder (RecyclerView.java:6823)
  at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline (RecyclerView.java:5752)
  at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline (RecyclerView.java:6019)
  at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition (RecyclerView.java:5858)
  at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition (RecyclerView.java:5854)
  at android.support.v7.widget.LinearLayoutManager$LayoutState.next (LinearLayoutManager.java:2230)
  at android.support.v7.widget.LinearLayoutManager.layoutChunk (LinearLayoutManager.java:1557)
  at android.support.v7.widget.LinearLayoutManager.fill (LinearLayoutManager.java:1517)
  at android.support.v7.widget.LinearLayoutManager.onLayoutChildren (LinearLayoutManager.java:612)
  at android.support.v7.widget.RecyclerView.dispatchLayoutStep2 (RecyclerView.java:3924)
  at android.support.v7.widget.RecyclerView.dispatchLayout (RecyclerView.java:3641)
  at android.support.v7.widget.RecyclerView.onLayout (RecyclerView.java:4194)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.support.constraint.ConstraintLayout.onLayout (ConstraintLayout.java:1915)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.support.v4.view.ViewPager.onLayout (ViewPager.java:1775)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.widget.LinearLayout.setChildFrame (LinearLayout.java:1812)
  at android.widget.LinearLayout.layoutVertical (LinearLayout.java:1656)
  at android.widget.LinearLayout.onLayout (LinearLayout.java:1565)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.widget.FrameLayout.layoutChildren (FrameLayout.java:323)
  at android.widget.FrameLayout.onLayout (FrameLayout.java:261)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.widget.LinearLayout.setChildFrame (LinearLayout.java:1812)
  at android.widget.LinearLayout.layoutVertical (LinearLayout.java:1656)
  at android.widget.LinearLayout.onLayout (LinearLayout.java:1565)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.widget.FrameLayout.layoutChildren (FrameLayout.java:323)
  at android.widget.FrameLayout.onLayout (FrameLayout.java:261)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.widget.LinearLayout.setChildFrame (LinearLayout.java:1812)
  at android.widget.LinearLayout.layoutVertical (LinearLayout.java:1656)
  at android.widget.LinearLayout.onLayout (LinearLayout.java:1565)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.widget.FrameLayout.layoutChildren (FrameLayout.java:323)
  at android.widget.FrameLayout.onLayout (FrameLayout.java:261)
  at com.android.internal.policy.DecorView.onLayout (DecorView.java:1088)
  at android.view.View.layout (View.java:22406)
  at android.view.ViewGroup.layout (ViewGroup.java:6594)
  at android.view.ViewRootImpl.performLayout (ViewRootImpl.java:3417)
  at android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:2884)
  at android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:1932)
  at android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:8589)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:949)
  at android.view.Choreographer.doCallbacks (Choreographer.java:761)
  at android.view.Choreographer.doFrame (Choreographer.java:696)
  at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:935)
  at android.os.Handler.handleCallback (Handler.java:873)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:214)
  at android.app.ActivityThread.main (ActivityThread.java:7094)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
Caused by: android.os.RemoteException: 
  at com.android.server.am.ActivityManagerService.getContentProviderImpl (ActivityManagerService.java:15677)
  at com.android.server.am.ActivityManagerService.getContentProviderImpl (ActivityManagerService.java:15586)
  at com.android.server.am.ActivityManagerService.getContentProvider (ActivityManagerService.java:16151)
  at android.app.IActivityManager$Stub.onTransact$getContentProvider$ (IActivityManager.java:11035)
  at android.app.IActivityManager$Stub.onTransact (IActivityManager.java:295)

你尝试过构建混淆的发布版本并进行测试吗?它能正常工作吗? - Sagar
你能否发布完整的错误日志?你是否使用了手机存储中的URI? - Amit Tiwary
这将取决于照片是从相册中添加还是在应用程序中使用相机拍摄,因此它将来自手机存储或应用程序内部。完整的崩溃已添加。 - Ceri Turner
1
请检查以下内容是否满足:写入权限,并且如果您要保存到自定义内部路径,则需要具有文件提供程序。 - TheRealChx101
看这里,也许能帮到你:https://medium.com/@egemenhamutcu/fixing-securityexception-requiring-a-valid-contentprovider-on-android-8-1110d840522 - King of Masses
显示剩余3条评论
5个回答

4
我认为你在Android Pie或更高版本的操作系统上遇到了安全异常。这是因为在这些系统上,您必须声明应用程序想要使用的路径。
请查看:https://developer.android.com/reference/android/support/v4/content/FileProvider 另外,可能是您的应用程序正在尝试从另一个需要权限的应用程序获取内容,例如Google照片需要:<uses-permission android:name="com.google.android.apps.photos.permission.GOOGLE_PHOTOS"/> 请检查:java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.content.GooglePhotosImageProvider

我在9上遇到了这个问题,但我现在用的是10,自己无法复现。我已经尝试在类似于9的环境中进行复现,但没有成功。 - Ceri Turner
当我尝试向第三方应用程序(在我的情况下是Google相册)发出意图以选择照片供我的应用程序使用时,我遇到了这个错误。因此,您可能还需要一个需要授权才能向其提供意图的应用程序。 - Vatish Sharma
我已经添加了那个,但它仍然崩溃。 - Ceri Turner

4

从 API 24 开始,您无法直接访问文件 URI。您需要使用文件夹的文件权限,然后使用它们。

val photoURI = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", File(path));

AndroidManifest.xml 文件中,
application 标签下添加以下内容。其中 packagename 为 BuildConfig.APPLICATION_ID
<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="packagename.provider"
            android:enabled="true"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external"
        path="." />
</paths>

3

这个异常通常是使用第三方应用程序的图片uri引起的。解决方案是实现文件提供程序。您可以获取许多关于如何实现文件提供程序的解决方案。


我一直在寻找,但不确定需要改变什么。目前我正在使用https://pastebin.com/Xswi7puK添加图像,并使用https://pastebin.com/EQVvyRnG显示它们。 - Ceri Turner
不,它仍然崩溃。 - Ceri Turner
我尝试在ImageView中设置imageUri,但对我来说它运行良好。另一种解决方案是从imageUri创建位图并将其设置为ImageView。我认为imageUri存在问题。你从哪里获取它的? - AkashToSky
我尝试使用位图时遇到了相同的错误。这些图像是使用此处的代码添加的。https://pastebin.com/Xswi7puK - Ceri Turner
在onActivityResult的第一个情况下,photoUri未被赋值。 - AkashToSky
在第一个情况下,它会在菜单点击时设置。 - Ceri Turner

2
由于新版本的Android 9引入了一个新的FOREGROUND_SERVICE权限,因此出现了这种情况。文档中指出:
注意:面向API级别28或更高级别并使用前台服务的应用程序必须请求FOREGROUND_SERVICE权限。这是一项普通权限,因此系统会自动将其授予请求的应用程序。如果面向API级别28或更高级别的应用程序尝试创建前台服务而没有请求FOREGROUND_SERVICE,则系统会抛出SecurityException异常。
只需在清单文件中添加权限即可解决问题,理论上来说如此。请告诉我们结果吧!像这样:
<manifest ...>   
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> 
     <application ...>
</manifest>

让我们尝试接受这个赏金: 您是否拥有这些权限?:

<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

我认为这个尝试并不太糟:

public static final String KITKAT_VALUE = 1002;

  Intent intent;

    if (Build.VERSION.SDK_INT < 19){
                            intent = new Intent();
                            intent.setAction(Intent.ACTION_GET_CONTENT);
                            intent.setType("image/*");
                            startActivityForResult(intent, KITKAT_VALUE);
                        } else {
                            intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                            intent.addCategory(Intent.CATEGORY_OPENABLE);
                            intent.setType("image/*");
                            startActivityForResult(intent, KITKAT_VALUE);
                    }

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (requestCode == KITKAT_VALUE ) {
     if (resultCode == Activity.RESULT_OK) {
       // do something here
     }
  }
}

1
我已经快速浏览了这些信息,不确定它如何适用。 - Ceri Turner
你没有名为 AndroidManifest.xml 的文件吗?在这个文件中,你可以设置所有权限,例如:<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> </manifest> - Qiqke
我已经添加了那个,但它仍然崩溃。 - Ceri Turner
你正在使用第三方应用程序服务吗?也许那个第三方应用程序正在使用一些无法使用的权限? - Qiqke
它所访问的第三方应用程序是手机的照片应用程序。我能想到的唯一可能就是一段时间前我改变了它访问方式,我在想如果权限没有设置为保持访问可能会出现这样的情况。最近添加的照片可以正常使用,但似乎旧的照片不能。这是添加图片的方式:https://pastebin.com/5CcqXQQu - Ceri Turner
请检查我的答案,希望能有所帮助! - Qiqke

2

我怀疑这是由于您在AndroidManifest.xml文件中实施的权限所致。如果您正在调试API Level 23或更高版本的Android,则必须在运行时获取WRITE_EXTERNAL_STORAGE的运行时权限,因为设备由于权限被拒绝而导致安全异常。


读写外部存储已经在清单文件中了。 - Ceri Turner
顺便提一下,WRITE_EXTERNAL_STORAGE 将在下一个 Android 版本中被弃用。 - user70

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