Невозможно открыть PDF из внутреннего хранилища для просмотра на Android 8 и 9 с помощью File Provider - PullRequest
0 голосов
/ 01 марта 2019

Только для Android 8 и 9.

У меня есть файл PDF здесь -

String url = "file:///storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";

Я пытаюсь открыть этот файл для просмотра, используя это -

File file= new File(url);
file.setReadable(true, false);

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri pdfUri = FileProvider.getUriForFile(getApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", file);
intent.setDataAndType(pdfUri, "application/pdf");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

List<ResolveInfo> resInfoList = getApplicationContext().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    for (ResolveInfo resolveInfo : resInfoList) {
        String packageName = resolveInfo.activityInfo.packageName;
        getApplicationContext().grantUriPermission(packageName, pdfUri,
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

Intent in = Intent.createChooser(intent, "Open File");
startActivity(in);

Открывается опция выбора файлаи когда я открываю файл с помощью Google PDF Reader, PDF Reader открывается и закрывается немедленно.Что не так в моем коде?

Ответы [ 4 ]

0 голосов
/ 01 апреля 2019

При этом мы сначала сохраняем файл во внутреннем хранилище, а затем читаем из него с помощью внешнего приложения.

Я использую метод ниже, чтобы сохранить файл во внутреннем хранилище:

private void savePDFtoInternalStorage(byte[] pdfAsBytes){
    //Save in internal memo cache
    File directory = mFragmentActivity.getFilesDir();
    //updating path for pdf to match with file_path.xml
    mCardStmtFile = new File(directory.getAbsolutePath(), "sample.pdf");
    OutputStream outputStream = null;
    try {
        PbLogger.e(TAG, "writing to mStmtFile");
        outputStream = new FileOutputStream(mCardStmtFile, false);
        outputStream.write(pdfAsBytes);
        outputStream.flush();
        outputStream.close();

    } catch (IOException e) {
        e.printStackTrace();

    }
}

PFBпровайдер файлов объявил file_path.xml:

  <?xml version="1.0" encoding="utf-8"?>
   <paths>
      <files-path path="/" name="secretpdf" />
   </paths>

PFB Запись манифеста Android для провайдера файлов:

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.***.********.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <!-- ressource file to create -->
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">
        </meta-data>
    </provider>

Используйте приведенный ниже код для запуска PDF:

 Intent intentShareFile = new Intent(Intent.ACTION_VIEW);
        if (mStmtFile.exists()) {
            intentShareFile.setType("application/pdf");
            Uri fileUri = FileProvider.getUriForFile(
                    mFragmentActivity,
                    "com.****.********.provider",
                    mCardStmtFile);
            intentShareFile.putExtra(Intent.EXTRA_STREAM, fileUri);
            intentShareFile.putExtra(Intent.EXTRA_SUBJECT,
                    getDescription());
            //adding grant read permission to share internal file
            intentShareFile.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            startActivity(Intent.createChooser(intentShareFile, "Share File"));
        }
0 голосов
/ 02 марта 2019

Я получил вопрос.Когда вы создаете новый файл, используя File file = новый файл (путь), не добавляйте file:// перед путем.

Это правильно -

String url = "/storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";
File file= new File(url);

Это неправильно -

String url = "file:///storage/emulated/0/Android/data/com.verna.poc/files/Download/mypdf.pdf";
File file= new File(url);
0 голосов
/ 02 марта 2019

Вы пытаетесь поделиться файлом из внутреннего хранилища с другим приложением.Вам нужно будет создать провайдер файлов, чтобы это работало.Вам нужно будет указать каталог, из которого вы хотите, чтобы провайдер файлов генерировал Uris для

FileProvider - это специальный подкласс ContentProvider, который обеспечивает безопасный общий доступ к файлам, связанным с приложением, путем создания контента: //Uri для файла вместо файла: /// Uri.

FileProvider может генерировать URI содержимого только для файлов в каталогах, которые вы указали заранее.Чтобы указать каталог, укажите его область хранения и путь в XML, используя дочерние элементы элемента.Например, следующий элемент paths сообщает FileProvider, что вы намереваетесь запросить URI содержимого для подкаталога images / вашей личной файловой области.

Этот ответ имеет хороший пример этого

ссылка

Вот страница документа для FileProvider

FileProvider

0 голосов
/ 01 марта 2019

доступ к файлу из приложения, которому принадлежит этот личный каталог - Intent не обрежет его, потому что он мог быть отправлен любым приложением.и если это должен быть файл-выборщик Intent, то создайте общий каталог для своего приложения на SD-карте, где любое приложение сможет получить к нему доступ;Для этого также подойдет обычный каталог Downloads.другой вариант (как изначально предлагалось) заключался бы в создании простого средства выбора файлов, которое находится внутри приложения, так что Intent не потребовалось бы для выбора файла ... все это имеет определенные преимущества и недостатки;выберите одну возможность, которая подходит вам лучше всего ... в общем, это частное или общее хранилище.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...