Android OREO-java.lang.SecurityException:无法找到用户0的提供程序;期望为此授权机构找到有效的ContentProvider

时间:2018-10-25 04:05:13

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

我遵循了以下教程并修改了代码 https://medium.com/@egemenhamutcu/fixing-securityexception-requiring-a-valid-contentprovider-on-android-8-1110d840522

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

update tablex
set columnb = datefromparts(year(column_a),month(column_b), day(column_b))

这就是我定义权限的方式

<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();
}

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

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

甚至在<8.0版本上也会发生这种情况。

2 个答案:

答案 0 :(得分:1)

我已经从该链接实现了,并且对我有用。

这是您的解决方案,创建一个名为PhotoProvider的类,以扩展ContentProvider并自动实现其方法。声明一个静态的最终String来定义权限,最后实现一个静态方法以返回我们全新的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);

尝试一下- 开心编码:) :) :)

答案 1 :(得分:0)

试试这个... 清单

$permission1 = Permission::create(['name' => 'Create Client']);
$permission2 = Permission::create(['name' => 'View Invoice']);
$permission3 = Permission::create(['name' => 'Add Product']);

$role = Role::findById(1);
$role->givePermissionTo([$permission1, $permission2, $permission3]);

并在xml / provider_path文件中

<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>

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