权限拒绝:编写 android.support.v4.content.FileProvider uri
Posted
技术标签:
【中文标题】权限拒绝:编写 android.support.v4.content.FileProvider uri【英文标题】:Permission Denial: writing android.support.v4.content.FileProvider uri 【发布时间】:2017-02-08 18:32:46 【问题描述】:美好的一天。我有一个奇怪的问题,堆栈溢出中的任何示例都不起作用。我正在打开一个画廊,之后我将用户重定向到裁剪意图。重要的是要提到这只发生在 android N 上而不是下面的设备。问题是一旦作物完成就会抛出这个异常。我不知道是什么原因造成的,但实际上这是我开始作物意图的方式。
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri outPutUri = FileProvider.getUriForFile(activity, activity.getApplicationContext().getPackageName() + ".provider", new File(output));
Uri photoURI = FileProvider.getUriForFile(activity, activity.getApplicationContext().getPackageName() + ".provider", new File(path));
activity.grantUriPermission("com.android.camera.action.CROP", outPutUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
activity.grantUriPermission("com.android.camera.action.CROP", photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
cropIntent.setDataAndType(photoURI, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", aspectX);
cropIntent.putExtra("aspectY", aspectY);
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);
activity.startActivityForResult(cropIntent, CROP_REQUEST);
我已授予 Uri 权限,已将这些添加到清单
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="$applicationId.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
我已经尝试了所有堆栈溢出答案示例,在这种情况下堆栈溢出没有更多问题,并且没有任何一个有效。那么 android N 有什么问题?应该这么难吗?
这是被抛出的异常
FATAL EXCEPTION: main
Process: com.android.gallery3d, PID: 5735
java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://my.package.name/external_files/Android/data/my.package.name/cache/0.5062300225583558.png from pid=5735, uid=10071 requires the provider be exported, or grantUriPermission()
at android.os.Parcel.readException(Parcel.java:1683)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:146)
at android.content.ContentProviderProxy.openAssetFile(ContentProviderNative.java:621)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1000)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:742)
at android.content.ContentResolver.openOutputStream(ContentResolver.java:718)
at com.android.gallery3d.filtershow.crop.CropActivity$BitmapIOTask.<init>(CropActivity.java:408)
at com.android.gallery3d.filtershow.crop.CropActivity.startBitmapIO(CropActivity.java:339)
at com.android.gallery3d.filtershow.crop.CropActivity.startFinishOutput(CropActivity.java:311)
at com.android.gallery3d.filtershow.crop.CropActivity$1.onClick(CropActivity.java:117)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22260)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
09-30 13:19:44.376 11909-11942/volo.global.pingbing E/FA: Task exception on worker thread: java.lang.IncompatibleClassChangeError: The method 'java.io.File android.support.v4.content.ContextCompat.getNoBackupFilesDir(android.content.Context)' was expected to be of type virtual but instead was found to be of type direct (declaration of 'com.google.firebase.iid.zzg' appears in /data/app/volo.global.pingbing-1/base.apk): com.google.android.gms.measurement.internal.zzt.zzEd(Unknown Source)
【问题讨论】:
发布您的logcat 将帮助我们更多地解决您的问题。 病倒一分钟 这不是授予SD读/写权限的正确方式,请参考this link 这不是授予 sd 卡...这是 Android N 上的问题,正如我已经告诉你的那样,这仅在 android N 上发生,在任何其他平台操作系统上都不会发生,仅在 Android N 上我的目标是 24 sdk,我不想降低目标,每个人都说这是唯一的解决方案 仍然谷歌没有更新android N中的权限和安全问题 【参考方案1】:List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList)
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
【讨论】:
虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。 感谢您的建议。让我解释一下这段代码的原因。在Android N中,为了安全,您必须获得“写入或读取Uri文件”的权限。当您想要裁剪系统照片时你的“uri文件”,所以你必须允许系统照片。如果你不知道这个包名,你可以通过所有的包名。【参考方案2】:你应该加上这句话:grantUriPermission();
喜欢
this:grantUriPermission("com.google.android.apps.photos",cropedImageUri,Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
我的错误就像你一样。我通过这个解决它。
【讨论】:
【参考方案3】:首先,Android 没有CROP
Intent
。有many image cropping libraries available for Android。使用一个。
其次,grantUriPermissions()
的第一个参数不是操作字符串或一些随机字符序列。它是一个应用程序 ID(也就是包名)。 com.android.camera.action.CROP
不是包名。
【讨论】:
错误...Android 具有默认的裁剪意图,可以通过它的应用程序 ID(又名包名称)访问,因此假设 android 可以处理给定包名称和处理程序中的意图是足够公平的该意图的类,其次授予 uri 权限需要字符串,这意味着我必须授予 URI 权限,并且 URI 可以是一系列字符。 @fasfsafsaf: "Android 有默认的裁剪意图" -- no, it does not. 按照使用第三方图像裁剪库的建议花费了我大约 4 个小时,结果发现它们都没有使用 FileProvider 正确处理 Uri。我在使用com.android.camera.action.CROP
时从来没有遇到过问题,所以我觉得你对它的警告可能被夸大了。 Tong Tracy 的回答确实有效。
@wvdz:“只是发现它们都没有使用 FileProvider 正确处理 Uri”——您自己项目中的库不需要 Uri
。把File
交给他们。 FileProvider
用于授予对数据的访问权限其他应用程序,而不是您自己应用程序中的库。 “我觉得你对它的警告可能被夸大了”——请随时向大家指出这个无证 Intent
行动的官方文档。
@CommonsWare:我想这是一个很好的观点。所以我应该简单地在活动之间传递文件路径而不是 Uri?尽管如此,我查看的所有库都使用 Uri 来传递文件,例如github.com/ArthurHub/Android-Image-Cropper、github.com/Yalantis/uCrop,并使用Uri.fromFile()
。以上是关于权限拒绝:编写 android.support.v4.content.FileProvider uri的主要内容,如果未能解决你的问题,请参考以下文章
android导入父类红标提示:import android.support.v13.app.xxx
权限拒绝:编写 android.support.v4.content.FileProvider uri