Android OREO - java.lang.SecurityException: не удалось найти провайдера для пользователя 0;Ожидается найти действительный ContentProvider для этого органа - PullRequest
0 голосов
/ 25 октября 2018

Я следовал приведенному ниже руководству и изменил код 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 (нет такого файла или каталога)

Это происходит даже в версии <8.0. </p>

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Попробуйте это ... В манифесте

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

Надеюсь, это поможет ...!

0 голосов
/ 25 октября 2018

Я реализовал по этой ссылке, и у меня это сработало.

Вот ваше решение, создайте класс с именем 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 .

НЕ забывайте возвращать true в onCreate method.

Наконец, getPhotoUri(File file) метод делает наш день.Вы передали свой объект File методу и получили Uri с fromFile(file), как я делал выше.Затем вы должны использовать 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);

Попробуйте - HappyКодирование :) :) :)

...