Créer clic téléchargement fichier pdf android

Résolu
iKelSilver - 21 oct. 2018 à 17:07
 iKelSilver - 24 oct. 2018 à 16:33
Bonjour,
Je suis sur un projet mobile qui demande d'intégrer des fichiers pdf dans cette application. J'ai mis tous ces fichiers dans le dossier < isset >. J'utilise Androïd studio.
Je veux que tous les fichiers soient lus en local sur le téléphone de l'utilisateur lorsqu'il dispose d'un lecteur pdf sur son téléphone sinon, lui afficher un message.
Dans une activité, j'ai créé des Layout qui doivent recevoir des clics. Et au clic sur un Layout, que le fichier pdf qui lui est attaché se lance en téléchargement automatique.
Bref, je veux que lorsque l'utilisateur clique sur un Layout, qu'un fichier pdf soit téléchargé automatiquement.
Comment réaliser cela ?
Je ne suis qu'un débutant.
J'ai à première idée faire une lecture en local dans mon application, mais, tous les testes et recherches ne me donnent pas de bons résultats. Voilà pourquoi je veux proposer un téléchargement à l'utilisateur dès qu'il clique sur un Layout.
Aidez-moi avec des liens ou des propositions de codes.
Merci
A voir également:

2 réponses

Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
23 oct. 2018 à 22:18
Ci après un exemple complet:

Le fichier Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.myapplication">

  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

  <application
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>

</manifest>


Le fichier layout activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity">

  <Button
    android:id="@+id/openPdf"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Open PDF"
    android:layout_centerInParent="true"/>

</RelativeLayout>


Le fichier java:
package com.example.myapplication;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.StrictMode;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    /* Workaround pour le pb URI (PAS PROPRE et surement inutile si tu n'es pas sur Nougat ou plus) */
    try{
      Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
      m.invoke(null);
    }catch(Exception e){
      e.printStackTrace();
    }

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    /* clic sur le bouton */
    findViewById(R.id.openPdf).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Context c = getApplicationContext();
        try {
          File fileInDataDir = copyFileFromAssetsToDownloads(c, "", "file.pdf");
          Intent intent = new Intent(Intent.ACTION_VIEW);
          intent.setDataAndType(Uri.fromFile(fileInDataDir), "application/pdf");
          intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
          startActivity(intent);
        } catch(Exception e) {
          Log.e(getClass().getSimpleName(), "Exception: " + e.getMessage(), e);
        }
      }
    });

    /* Permissions Nougat et +*/
    ActivityCompat.requestPermissions(this, new String[] {
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.READ_EXTERNAL_STORAGE,
    }, 1);
  }

  private static File copyFileFromAssetsToDownloads(final Context context, final String assetFolder, final String fileName)
      throws IOException {
    /* utilisation du répertoire download pour pour que l'application externe puisse lire le fichier sinon ça semble coincer. */
    File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + fileName);
    if(f.exists())
      //noinspection ResultOfMethodCallIgnored
      f.delete();
    InputStream in = null;
    FileOutputStream out = null;
    try {
      in = context.getAssets().open(assetFolder + fileName);
      out = new FileOutputStream(f);
      int read;
      final byte[] buffer = new byte[4096];
      while ((read = in.read(buffer)) > 0)
        out.write(buffer, 0, read);
    } catch(IOException ioe) {
      throw new IOException(ioe);
    } finally {
      if(out != null)
        out.close();
      if(in != null)
        in.close();
    }
    return f;
  }
}


J'ai modifié l'emplacement de stockage du fichier PDF pour le mettre dans le répertoire Download (chez moi /storage/emulated/0/Download/)
Pour ce qui est du fichier pdf que j'ai placé dans le répertoire assets du projet, j'ai utilisé celui-ci que j'ai renommé en file.pdf (en lieu et place de pdf.pdf)

Pour le reste des fichiers, ils sont inchangés par rapport à la création du projet sous Android Studio 3.1.4

1
Twinuts, tu es vraiment super.
Tu m'as sauvé. ) :
0
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
24 oct. 2018 à 08:35
Salut,

Pense à valider le sujet si ton problème est résolu.

++
0
Bonjour,
J'ai validé depuis ma boîte mail en cliquant sur < Votre question est résolue > plusieurs fois, mais, ça ne donne toujours aucun résultat.
Merci pour tout
0
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
22 oct. 2018 à 08:17
Salut,

J'ai pas tout compris, mais si tu veux lire un fichier qui est dans le répertoire assets de ton projet il suffit d'utiliser la méthode open disponible via l'asset manager, (getAssets depuis le context (au mieux celui de l'application)).
Context c = getApplicationContext();
try {
  InputStreamReader isr = new InputStreamReader(c.getAssets().open("fichier.pdf"));
} catch(IOException ie) {
  Log.e(getClass().getSimpleName(), "IOException: " + ie.getMessage(), ie);
}


Par contre, ici, tu ne pourras pas le modifier, donc si c'est cela que tu souhaites faire il te faudra faire une copie de ce dernier dans le répertoire data de ton application.

private static File copyFileFromAssets(final Context context, final String assetFolder, final String fileName)
      throws PackageManager.NameNotFoundException, IOException {
  final PackageManager m = context.getPackageManager();
  String newPath = context.getPackageName();

  final PackageInfo p = m.getPackageInfo(newPath, 0);
  newPath = p.applicationInfo.dataDir + "/" + fileName;

  File f = new File(newPath);
  if(f.exists())
    //noinspection ResultOfMethodCallIgnored
    f.delete();
    
  InputStream in = null;
  FileOutputStream out = null;
  try {   
    in = context.getAssets().open(assetFolder + fileName);
    out = new FileOutputStream(f);
    int read;
    final byte[] buffer = new byte[4096];
    while ((read = in.read(buffer)) > 0)
      out.write(buffer, 0, read);
  } catch(IOException ioe) {
    throw new IOException(ioe);
  } finally {
    if(out != null)
      out.close();
    if(in != null)
      in.close();
  }
  return f;
}

/* utilisation*/
Context c = getApplicationContext();
try {
  File fileInDataDir = copyFileFromAssets(c /* Context */,
      "" /* le fichier pourrait être dans le un sous répertoire, ex: foo dans ce cas il faudra mettre 'foo/' */,
      "fichier.pdf" /* fichier dans l'assets */);
} catch(Exception e) {
  Log.e(getClass().getSimpleName(), "Exception: " + e.getMessage(), e);
}

0
Bonjour
Merci Twinuts
C'est la première proposition que je veux.
0
Bonjour,
Merci Twinuts, mais, je n'arrive pas encore à utiliser le code suivant :
Context c = getApplicationContext();
try {
  InputStreamReader isr = new InputStreamReader(c.getAssets().open("fichier.pdf"));
} catch(IOException ie) {
  Log.e(getClass().getSimpleName(), "IOException: " + ie.getMessage(), ie);
}



Ce que je veux faire, c'est que, je veux par exemple :
//Au clic sur ce Layout, que le téléchargement du fichier .pdf soit démarré automatique
LinearLayout afficher_lecture_pdf = (LinearLayout) findViewById(R.id.lecture_pdf);
        afficher_lecture_pdf.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                
Context c = getApplicationContext();
try {
  InputStreamReader isr = new InputStreamReader(c.getAssets().open("fichier.pdf"));
} catch(IOException ie) {
  Log.e(getClass().getSimpleName(), "IOException: " + ie.getMessage(), ie);
}

            }
        });


Comment puis-je arriver à le faire ?
J'ai tout mes fichiers pdf dans le dossier isset.

Merci
0
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
23 oct. 2018 à 13:54
Salut,

Dans le code ci-dessous:
InputStreamReader isr = new InputStreamReader(c.getAssets().open("fichier.pdf"));

"fichier.pdf" doit être remplacé par le fichier de ton choix (celui que tu souhaites ouvrir et qui est dans le répertoire assets).

"isr" n'est rien d'autre qu'un InputStream donc si tu ne l'exploites pas cela ne sert pas à grand chose.

Si dans l'idée tu veux simplement ouvrir le fichier il suffit de faire ceci:
- Copier le fichier du répertoire assets vers un autre répertoire (exemple avec la méthode fournie plus haut (copyFileFromAssets))
- Demander à Android d'ouvrir le fichier PDF avec le viewer par défaut (par exemple):
File pdf = // fichier PDF après la copie depuis l'assets
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(pdf), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);

- En fonction de ta version d'android tu risques d'avoir l'erreur "android.os.FileUriExposedException: xxxxxx exposed beyond app through Intent.getData()" -> solution
- Pense à mettre les permissions WRITE_EXTERNAL_STORAGE et READ_EXTERNAL_STORAGE.
0
Merci Twinuts,
Mais, je ne comprends toujours pas ce que vous dites. Je voulais ouvrir le fichier pdf situant actuellement dans le répertoire isset au clic sur un Layout avec l'application de lecture par défaut du fichier pdf.
Si pouvez m'organiser ce code afin que je puisse vous suivre.
Merci
0
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
23 oct. 2018 à 15:09
Comme tu ne m'as pas repris dessus, je suis resté sur mon idée, mais ils sont où les fichiers ? dans "assets" (embarqué dans ton apk?) ou dans un répertoire "isset" ???? Si il s'agit d'un répertoire isset, pour toi, il est où physiquement sur le téléphone?
0
Rejoignez-nous