2
votes

Impossible d'ouvrir le PDF à partir du stockage interne pour le visualiser sur Android 8 et 9 à l'aide du fournisseur de fichiers

Pour Android 8 et 9 uniquement.

J'ai un fichier PDF ici -

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

J'essaye d'ouvrir ce fichier pour l'afficher en utilisant ceci -

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

L'option de sélection de fichier s'ouvre et lorsque j'ouvre le fichier à l'aide du lecteur Google PDF, le lecteur PDF s'ouvre et se ferme immédiatement. Quel est le problème dans mon code?


4 commentaires

avez-vous fourni une autorisation de lecture / écriture?


Oui j'ai. mon manifeste a ces -


ils ont besoin d'une confirmation d'exécution de la part de l'utilisateur, avez-vous fait cela?


Oui. J'ai également donné des autorisations d'exécution pour ces derniers. ne fonctionne toujours pas.


4 Réponses :


1
votes

accéder au fichier depuis l'application qui possède ce répertoire privé - un Intent ne le coupera pas, car il aurait pu être envoyé par n'importe quelle application. et s'il doit s'agir d'un sélecteur de fichiers Intent , créez un répertoire partagé pour votre application sur la carte SD, où n'importe quelle application peut y accéder; le répertoire régulier Downloads conviendrait également pour cela. une autre option (comme initialement suggéré) serait de créer un simple sélecteur de fichier, qui réside dans l'application, de sorte qu'aucune Intent ne soit nécessaire pour sélectionner un fichier ... désavance; choisissez la possibilité qui vous convient le mieux ... en général, c'est un emplacement de stockage privé ou partagé.


3 commentaires

mais j'utilise un fournisseur de fichiers pour partager un fichier interne accessible par une application tierce. Les fournisseurs de fichiers sont utilisés à cette fin, je suppose. ce serait formidable si vous pouviez donner une solution de travail.


@ Gissipi_453 vous créez un Intent , qui est censé être rempli par une autre application, pendant que celle-ci est en cours d'installation ... voir la documentation: developer.android.com/reference/android/content/… < / a> ... c'est pourquoi il est nécessaire de jouer avec les permissions uri - qui autrement ne seraient pas nécessaires. vous pouvez également le définir dans Manifest.xml déjà: developer.android.com/guide/topics/manifest/... ... correspondant à tous les PDF qui s'y trouvent.


... alors que vous accordez déjà l'accès, mieux vaut simplement utiliser le stockage externe - car alors ce sera une carte SD, (tant qu'une est présente). avec quelques fichiers, votre approche est très bien, avec quelques centaines ou milliers de fichiers, cela peut devenir problématique. il ne s'adapte pas bien - car l'effacement des données (essayez simplement avec les paramètres> les applications) les supprimera complètement, ce qui n'est pas le cas avec le stockage externe.



0
votes

J'ai le problème. Lorsque vous créez un nouveau fichier en utilisant, File file = new File (path), n'ajoutez pas file: // devant le chemin.

C'est correct -

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

C'est faux -

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


0 commentaires

1
votes

Vous essayez de partager un fichier de la mémoire interne avec une autre application. Vous devrez créer un fournisseur de fichiers pour que cela fonctionne. Vous devrez spécifier un répertoire pour lequel vous souhaitez que le fournisseur de fichiers génère des Uris

FileProvider est une sous-classe spéciale de ContentProvider qui facilite le partage sécurisé des fichiers associés à une application en créant un contenu: // Uri pour un fichier au lieu d'un fichier: /// Uri.

Un FileProvider ne peut générer un URI de contenu que pour les fichiers dans les répertoires que vous spécifiez au préalable. Pour spécifier un répertoire, spécifiez sa zone de stockage et son chemin en XML, à l'aide des éléments enfants de l'élément. Par exemple, l'élément de chemins suivant indique à FileProvider que vous avez l'intention de demander des URI de contenu pour les images / sous-répertoire de votre zone de fichiers privés.

Cette réponse a un bon exemple à ce sujet

lien

Voici la page de documentation pour FileProvider

FileProvider


2 commentaires

Merci d'avoir répondu. im utilise déjà un fournisseur de fichiers comme vous pouvez le voir dans ma question. comme je l'ai compris plus tard, le problème était de savoir comment j'utilisais mon chemin de fichier. Lorsque vous créez un nouveau fichier en utilisant, File file = new File (path), n'ajoutez pas file: // en face du chemin.


@ Gissipi_453 il s'attendrait à un schéma de protocole content: // , qui peut être omis (probablement parce qu'il n'y a qu'un seul schéma de protocole à "choisir" - et donc on sait lequel utiliser, à moins dire le contraire).



0
votes

En cela, nous enregistrons d'abord le fichier dans le stockage interne, puis le lisons à l'aide d'une application externe.

J'utilise la méthode ci-dessous pour enregistrer le fichier dans le stockage interne:

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

PFB le fournisseur de fichiers a déclaré file_path.xml:

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

PFB l'entrée de manifeste Android pour le fournisseur de fichiers:

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

Utilisez le code ci-dessous pour lancer le PDF:

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

    }
}


0 commentaires