【问题标题】:Android OREO - java.lang.SecurityException: Failed to find provider for user 0; expected to find a valid ContentProvider for this authorityAndroid OREO - java.lang.SecurityException:找不到用户 0 的提供者;期望为此权限找到一个有效的 ContentProvider
【发布时间】:2018-10-25 04:05:13
【问题描述】:

我按照下面的教程修改了代码 https://medium.com/@egemenhamutcu/fixing-securityexception-requiring-a-valid-contentprovider-on-android-8-1110d840522

我在清单文件中定义了提供程序。

<provider
    android:name="com.test.PhotoProvider"
    android:authorities="${applicationId}.PhotoProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

provider paths has the below line

<external-path name="/storage/emulated/0" path="/" />

I’m loading the uri using below code

   Uri decodedImgUri = PhotoProvider.getPhotoUri(new File(imgPath));
   ContentResolver cr = activity.getContentResolver();
   cr.notifyChange(decodedImgUri, null);
   ImageLoader.getInstance().displayImage(decodedImgUri.toString(), holder.image);

public static Uri getPhotoUri(File file) {
    Uri outputUri = Uri.fromFile(file);
    Uri.Builder builder = new Uri.Builder()
            .authority(CONTENT_PROVIDER_AUTHORITY)
            .scheme("file")
            .path(outputUri.getPath())
            .query(outputUri.getQuery())
            .fragment(outputUri.getFragment());

    return builder.build();
}

这就是我定义我的权威的方式

public static final String CONTENT_PROVIDER_AUTHORITY = "com.test.PhotoProvider";

但是当我尝试将 uri 加载到图像视图中时,我不断收到以下错误。

java.io.FileNotFoundException:com.test.PhotoProvider/data/user/0/com.test/cache/cropped953508219.jpg:打开失败:ENOENT(没有这样的文件或目录)

即使在

【问题讨论】:

  • 嘿 Rajesh,应用程序似乎没有访问存储空间的权限。您能否确认您使用的是 Marshmallow 以上的版本?如果是,则需要动态向用户请求权限。

标签: android android-contentprovider android-8.0-oreo


【解决方案1】:

我已经从该链接实现,它对我有用。

这是您的解决方案,创建一个名为 PhotoProvider 的类,扩展 ContentProvider 并自动实现其方法。声明一个定义权限的静态最终字符串,最后实现一个静态方法返回我们全新的Uri。下面是整个班级:

public class PhotoProvider extends ContentProvider {

    public static final String CONTENT_PROVIDER_AUTHORITY = "com.example.magnificentapp.PhotoProvider";

    @Override
    public boolean onCreate() {
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    public static Uri getPhotoUri(File file) {
        Uri outputUri = Uri.fromFile(file);
        Uri.Builder builder = new Uri.Builder()
                .authority(CONTENT_PROVIDER_AUTHORITY)
                .scheme("file")
                .path(outputUri.getPath())
                .query(outputUri.getQuery())
                .fragment(outputUri.getFragment());

        return builder.build();
    }
}

ContentProvider 权限由 CONTENT_PROVIDER_AUTHORITY 持有。

不要忘记在 onCreate 方法中返回 true。

终于getPhotoUri(File file) 方法成就了我们的一天。您尚未将 File 对象传递给该方法并使用 fromFile(file) 获取 Uri,就像我在上面所做的那样。然后你必须使用Uri.Builder 并从我们非法的outputUri 中复制必要的字段,最后将权限设置为CONTENT_PROVIDER_AUTHORITY

我实际上模仿Uri.fromFile(file)方法,除了设置自定义权限。 Uri 类中的原始方法如下所示:

public static Uri fromFile(File file) {
    if (file == null) {
        throw new NullPointerException("file");
    }

    PathPart path = PathPart.fromDecoded(file.getAbsolutePath());
    return new HierarchicalUri(
            "file", Part.EMPTY, path, Part.NULL, Part.NULL);
}

此方法将权限设置为 Part.EMPTY,因此 Android Oreo 崩溃说它必须有一个未导出的 ContentProvider 定义所有 Uris 的权限。

设置权限可解决问题并帮助 Android 保护您的数据(在我的情况下为照片)不会泄露给恶意应用

不要忘记将提供程序添加到 AndroidManifest.xml

<provider
    android:name="com.example.magnificentapp.PhotoProvider"
    android:authorities="com.example.magnificentapp.PhotoProvider"
    android:exported="false"
    android:grantUriPermissions="true" />

最后,您必须调用PhotoProvider.getPhotoUri(file) 而不是Uri.fromFile(file),如下所示:

outputUri = PhotoProvider.getPhotoUri(new File(activity.getCacheDir(), "cropped"));
ContentResolver cr = activity.getContentResolver();
cr.notifyChange(outputUri, null);

试一试—— 快乐编码:) :) :)

【讨论】:

  • 我在这个过程中使用了一个裁剪库。图像裁剪完成后,当我使用 ImageLoader 加载裁剪后的图像时,我遇到了这个问题。
  • 此外,裁剪文件的原始路径是 /data/user/0/com.test/cache/cropped1569238977.jpg 和我从 PhotoProvider.getPhotoUri(new File(imgPath));是 com.test.PhotoProvider/data/user/0/com.test/cache/cropped1569238977.jpg。这给了我 FileNotFoundException
【解决方案2】:

试试这个... 在清单中

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

在 xml/provider_path 文件中

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path path="Android/data/com.your.package/" name="files_root"/>
    <external-path name="external_files" path="."/>
</paths>

希望它会有所帮助...!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-17
    相关资源
    最近更新 更多