java - FileUriExposedException в Android




android-intent directory (2)

Можно ли использовать приложение «Мои файлы» по умолчанию для открытия определенной папки?

Да и нет. Нет 100% гарантии, что он будет работать на всех устройствах.

Изменить 1:

Следующее - один из способов, которым это может быть сделано. Я протестировал на нескольких эмуляторах (под управлением Android N и Android O) и загружает проводник по умолчанию:

MainActivity.java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri dirUri = FileProvider.getUriForFile(this,getApplicationContext().getPackageName() + ".com.example.myapplication",Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        //intent.setDataAndtType(); I will change this value in the alternatives below
    }

AndroidManifest.xml

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

GenericFileProvider.java

public class GenericFileProvider extends FileProvider {
}

file_paths.xml

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

Вышеуказанный подход не работает на крупных игроков, таких как Samsung

альтернативы

1. Использование типа DocumentsContract.Document.MIME_TYPE_DIR

intent.setDataAndType(dirUri,DocumentsContract.Document.MIME_TYPE_DIR);

Этот подход работает на нескольких эмуляторах и ограниченном наборе устройств. Это не работает с большими игроками, такими как Samsung или Huawei.

2. Используя тип resource/folder

intent.setDataAndType(dirUri,"resource/folder");

Этот подход работает, только если пользователь установил приложение ES File Explorer.

Если вы решите использовать, то вы должны проверить, доступно ли какое-либо намерение для его обработки, используя:

PackageManager packageManager = getActivity (). GetPackageManager ();

if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
   // either display error or take necessary action
}

3. Используя тип */*

intent.setDataAndType(dirUri,"*/*");

Этот подход работает, если пользователь выбирает приложение File Manager из Intent Chooser и помечает его как приложение по умолчанию для обработки */* . Однако у него есть некоторые недостатки (спасибо @CommonsWare за то, что вывели некоторые из них):

  • Этот тип загрузит все приложения на устройстве и позволит пользователю выбрать одно из них для завершения действия.
  • Если нет файлового менеджера, и пользователь выбирает другие приложения для загрузки ваших намерений, то другое приложение завершится сбоем или просто покажет черный экран. Например, вы используете Галерею или другое приложение для запуска, а не файловый менеджер, тогда приложение Галереи либо вылетит, либо покажет черный экран.
  • Даже если есть файловый менеджер, но пользователь решает использовать другие приложения, другие приложения могут аварийно завершить работу.

4. Используя тип text/csv

intent.setDataAndType(uri, "text/csv")

Это ограничит количество приложений, которые будут отображаться пользователю, но те же ограничения, когда применяется */* . Будут отображены приложения, которые могут обрабатывать csv , и если пользователь выберет его, то приложения будут аварийно завершать работу.

Здесь есть несколько реализаций для конкретных устройств, о которых упоминает @Academy of Programmer, которые требуют определения намерений файлового менеджера по умолчанию и дополнительных потребностей для него.

Заключение:

Для этого нет стандартного типа, поскольку в настоящее время файловые менеджеры не поддерживают стандарты, поддерживающие определенный тип. В будущем, возможно, Google предложит какой-то подход. Лучшая альтернатива - реализовать собственный файловый менеджер, как это делают Dropbox или Google Drive. Есть несколько библиотек, которые предоставляют эту функцию.

Мне нужно открыть папку во внутренней памяти, которая содержит изображения.

Я использую следующий код.

Джава

 File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),  "MyPhotos");
Intent intent = new Intent(Intent.ACTION_VIEW);
String path =folder.getPath();
Uri myImagesdir = Uri.parse("file://" + path );
intent.setDataAndType(myImagesdir,"*/*");   
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);

тропИнок

 <paths xmlns:android="http://schemas.android.com/apk/res/android">
     <external-path name="images" path="Pictures" />
     <external-path name="external_files" path="."/>
     <external-path name="files_root" path="Android/data/${applicationId}"/> </paths>

манифест

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

XML / file_paths

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="images" path="Pictures" />
    <external-path name="external_files" path="."/>
    <external-path name="files_root" path="Android/data/${applicationId}"/>
</paths>

ОШИБКА

ИСКЛЮЧИТЕЛЬНОЕ ИСКЛЮЧЕНИЕ: основной процесс: android.apps.bnb.company.myphotos, PID: 22482 android.os.FileUriExposedException: файл: /// storage / emulated / 0 / Pictures / MyPhotos, доступный за пределами приложения через Intent.getData ()

Есть ли другой способ открыть папку во внутренней памяти? Спасибо!

ОБНОВЛЕНИЕ № 1

Используя эту статью https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en я заменил

Uri myImagesdir = Uri.parse("file://" + path );

с

 Uri myImagesdir = Uri.parse("content://" + path );

И ошибка ушла.

В любом случае я должен всегда выбирать приложение, чтобы открыть эту папку.

Можно ли использовать приложение «Мои файлы» по умолчанию для открытия определенной папки?


Нижеприведенный код используется мной для открытия изображения из хранилища:

StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());

File path = new File(Environment.getExternalStorageDirectory() + "/" + "ParentDirectory" + "/" + "ChildDirectory");

File filepath = new File(path + "/" + yourImageName.png);

Uri uri = Uri.fromFile(filepath);

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "image/jpeg");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Отредактированный ответ:

StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());

File path = new File(Environment.getExternalStorageDirectory() + "/" + "ParentDirectory" + "/" + "ChildDirectory");

Uri uri = Uri.fromFile(path);

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "image/jpeg");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);






directory