Не удается получить Content Uri с помощью поставщика файлов

Я провел дни, читая документы и следуя различным руководствам по этому вопросу, но я получаю ошибки, что бы я ни делал. Я пытаюсь сохранить изображение во внутреннем хранилище, а затем преобразовать его в Uri контента, чтобы я мог использовать системную функцию обрезки и изменения размера. Если кто-нибудь может заметить, где мой код неверен, я был бы очень благодарен:

Основное действие:

new Thread(() -> {
try {
    String temp = "temp";

    //Convert bitmap to byte array
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
    byte[] bitmapData = bos.toByteArray();

    //Write the bytes in file
    FileOutputStream fos = openFileOutput(temp, MODE_PRIVATE);
    fos.write(bitmapData);
    fos.flush();
    fos.close();

    //Convert file to contentUri
    File file = new File(getFilesDir(), temp);

    Intent intent = new Intent();
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    Uri imageUri = FileProvider.getUriForFile(MainActivity.this, "@string/file_provider_authority", file);
    intent.setDataAndType(imageUri, "image/jpg");

    intent = WallpaperManager.getInstance(getApplicationContext()).getCropAndSetWallpaperIntent(imageUri);
    startActivityForResult(intent, ACTIVITY_CROP);

} catch (Exception e) {
    e.printStackTrace();
}
}).start();

Манифест:

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="@string/file_provider_authority"
        android:grantUriPermissions="true"
        android:exported="false">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_provider_paths" />
    </provider>
</application>

file_provider_paths.xml:

<paths>
<files-path
    path="/" name="temp" />

strings.xml:

<resources>
<string name="file_provider_authority"
    translatable="false">com.me.wallpaper_app.provider
</string>

Error:

    W/System.err(12162): java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
    W/System.err(12162):    at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:604)
    W/System.err(12162):    at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:578)
    W/System.err(12162):    at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:416)
    W/System.err(12162):    at com.me.wallpaper_app.MainActivity$1$1.lambda$onResourceReady$0$MainActivity$1$1(MainActivity.java:82)
    W/System.err(12162):    at com.me.wallpaper_app.-$$Lambda$MainActivity$1$1$Xm-7yym42zTgTZOFP5GGtbF6p2U.run(Unknown Source:4)
    W/System.err(12162):    at java.lang.Thread.run(Thread.java:919)

person Code Poet    schedule 25.05.2019    source источник


Ответы (2)


"@string/file_provider_authority" - это не то, как вы ссылаетесь на строковые ресурсы в Java. Используйте getString(R.string.file_provider_authority).

ОБНОВЛЕНИЕ. Судя по комментариям, вторая серьезная проблема заключается в том, что потребитель этого контента не использует тип MIME из Intent, а вместо этого вызывает getType() в ContentResolver, чтобы получить тип из ContentProvider. В данном случае это ваш FileProvider, а FileProvider знает только, как работать с расширениями файлов и преобразовывать их в типы MIME. Таким образом, использование temp.jpeg дало FileProvider информацию, необходимую для возврата правильного типа MIME.

person CommonsWare    schedule 25.05.2019
comment
О, спасибо за это! И теперь я получаю эту ошибку: Невозможно использовать переданный URI для установки обоев; убедитесь, что тип, возвращаемый ContentProvider, соответствует image/*. Но я установил данные и тип изображения. Хм... - person Code Poet; 25.05.2019
comment
@ user9480972: Попробуйте "image/jpeg" вместо "image/jpg" для типа MIME. - person CommonsWare; 25.05.2019
comment
@ user9480972: Замените setFlags() на addFlags() в обоих местах. Прямо сейчас ваш второй вызов setFlags() перезаписывает результат первого. - person CommonsWare; 25.05.2019
comment
Окей, сделано. Очевидно, я делаю что-то еще неправильно, потому что это то, что я сейчас получаю: I/System.out(20634): Image Data and Type = Intent { dat=content://com.me.wallpaper_app.provider/files/temp typ =image/* flg=0x3 } I/System.out(20634): Uri изображения = content://com.me.wallpaper_app.provider/files/temp W/System.err(20634): java.lang.IllegalArgumentException: Нельзя использовать переданный URI для установки обоев; проверить, соответствует ли тип, возвращаемый ContentProvider, image/* Должен ли я вызывать temp по-другому? Нравится изображение, например? - person Code Poet; 25.05.2019
comment
@ user9480972: Используйте image/jpeg, а не image/*, в Intent. Я также предлагаю перейти от openFileOutput() к созданию FileOutputStream напрямую, используя тот же объект File, который вы используете с FileProvider.getUriForFile(). Затем используйте compress() напрямую с этим FileOutputStream (избавившись от посредника ByteArrayOutputStream). Наконец, используйте temp.jpg или temp.jpeg для имени файла, если обои игнорируют тип MIME в Intent и запрашивают FileProvider для типа MIME`. - person CommonsWare; 25.05.2019
comment
Использование temp.jpeg для имени файла помогло. Также адаптирую мой код к тому, что вы предлагаете. Очень благодарен. - person Code Poet; 25.05.2019

Попробуйте это

      Uri imageUri = FileProvider.getUriForFile(MainActivity.this, R.string.file_provider_authority, file);

Также изменить

    <paths>
    <files-path
    path="/" name="temp" />

Кому

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <external-path name="external_files" path="."/>
    </paths>
person Siddarth Jain    schedule 25.05.2019