Autore Topic: Aprire un file PDF dall'interno dell'applicazione  (Letto 1167 volte)

Offline Lubron

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S III
  • Sistema operativo:
    Max OS X 10.10.3
Aprire un file PDF dall'interno dell'applicazione
« il: 27 Aprile 2015, 17:28:20 CEST »
0
Salve a tutti!
Sto sviluppando un'applicazione che richiede di visualizzare dei file PDF selezionabili dalla barra del menù. Ho trovato inizialmente una soluzione salvando i miei file nella cartella "assets" della mia applicazione e poi copiandoli sull'external storage e aprendoli una volta esportati ; questo ha funzionato bene fino al momento in cui il mio reader di default per PDF (Adobe Reader) non è stato cambiato in Adobe Reader DC (o almeno cosi credo) : dal momento che ho questa nuova app per visionare i miei PDF non riesco più ad aprire i PDF dall'interno della mia applicazione in quanto mi esce fuori sempre lo stesso errore : "Impossibile accedere a questo file.Controllare il percorso o la rete e riprovare". Sinceramente non capisco come mai prima funzionasse perfettamente e ora no. Suggerimenti??

Questo è il codice che utilizzo per selezionare una voce dal menu della barra di stato e che utilizzo in ogni Activity :

EveryActivity.java

Codice (Java): [Seleziona]
 @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        AssetManager assetManager = getAssets();
        File fileDir = getFilesDir();
        OutputStream out = null;
        try {

            out = openFileOutput(fileDir.getName(), Context.MODE_WORLD_READABLE);

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        }

        Context ctx = this;

        //noinspection SimplifiableIfStatement
        if (id == R.id.menu_tutorial)

            Utility.loadPDF(assetManager,fileDir,out,ctx,"Tutorial.pdf");


        if (id == R.id.menu_schedule) {

            Utility.loadPDF(assetManager, fileDir, out, ctx, "Lavoro.pdf");

        }

        if (id == R.id.menu_table) {

            Utility.loadPDF(assetManager, fileDir, out, ctx, "Tabella.pdf");

        }

        return super.onOptionsItemSelected(item);

    }

E questo è il codice che fà quanto ho descritto sopra :

Utility.java

Codice (Java): [Seleziona]
public static void loadPDF(AssetManager assetManager,File filesDir,OutputStream out,Context ctx, String path) {

        InputStream in = null;
        File file = new File(filesDir, path);

        try {

            in = assetManager.open(path);

            copyFile(in, out);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;

        } catch (Exception e) {

            Log.e("tag", e.getMessage());

        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.parse("file://" + filesDir + "/" + path),"application/pdf");

        // Start an intent to open the application that reads PDF
        ctx.startActivity(intent);

    }

    // Function used to copy the PDF file from inside the app to external storage.
    // PDF cannot be read from inside the assets folder, we should take it outside
    // Manifest was modified to permit that
    private static void copyFile(InputStream in, OutputStream out) throws IOException {

        byte[] buffer = new byte[1024];
        int read;

        while ((read = in.read(buffer)) != -1) {

            out.write(buffer, 0, read);

        }

    }

Target SDK : 22
Min SDK : 8

Lo sto testando su un Samsung Galaxy S III con Android 4.4.4, ma come ho già scritto è un problema sorto dopo il passaggio al nuovo Reader, credo c'entri poco il resto.

Grazie dell'attenzione

Offline tonno16

  • Utente storico
  • *****
  • Post: 1226
  • Respect: +59
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Aprire un file PDF dall'interno dell'applicazione
« Risposta #1 il: 27 Aprile 2015, 18:12:05 CEST »
0
Io salverei in sdcard i PDF e con intent lo aprire cosi l'utente sceglie l' app che ha

Offline Lubron

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S III
  • Sistema operativo:
    Max OS X 10.10.3
Re:Aprire un file PDF dall'interno dell'applicazione
« Risposta #2 il: 27 Aprile 2015, 18:20:07 CEST »
0
Tralasciando che non ho una sdcard da utilizzare...vorrei che la mia app fosse utilizzabile da chiunque, possessore o meno di sdcard

Offline tonno16

  • Utente storico
  • *****
  • Post: 1226
  • Respect: +59
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Aprire un file PDF dall'interno dell'applicazione
« Risposta #3 il: 27 Aprile 2015, 19:04:53 CEST »
0
Intendo la memoria esterna. Usi gli stessi costrutti per i file. Environment.getExternalStorageDirectory() torna la path della sdcard. Se non hai SD allora ritorna la memoria interna

Offline Lubron

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S III
  • Sistema operativo:
    Max OS X 10.10.3
Re:Aprire un file PDF dall'interno dell'applicazione
« Risposta #4 il: 28 Aprile 2015, 09:59:09 CEST »
0
Ho provato a sostituire

Codice (Java): [Seleziona]
File fileDir = getFilesDir();
con

Codice (Java): [Seleziona]
File fileDir = Environment.getExternalStorageDirectory();
come da te consigliato ma l'errore che mi dà Adobe Acrobat DC è sempre lo stesso.

Offline tonno16

  • Utente storico
  • *****
  • Post: 1226
  • Respect: +59
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Aprire un file PDF dall'interno dell'applicazione
« Risposta #5 il: 28 Aprile 2015, 10:13:03 CEST »
0
È sbagliato. Quella riga ritorna la path e basta. Poi puoi creare e leggere file ma devi specificare il nome e il percorso.
Inoltre con quel codice devi mettere i permessi di scrittura e lettura nel manifest.
L'errore deve essere generato da altro.
Ma hai un log? Prova a mettere un terzo PDF reader e vedere come si comporta. Io ho drive PDF reader che un file di 400 pagine lo carica bene.

Offline Lubron

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S III
  • Sistema operativo:
    Max OS X 10.10.3
Re:Aprire un file PDF dall\'interno dell\'applicazione
« Risposta #6 il: 28 Aprile 2015, 10:19:25 CEST »
0
I permessi nel manifest ci sono altrimenti non sarebbe potuto funzionare neanche prima :

Codice (XML): [Seleziona]
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
L'errore comunque è solo in fase di esecuzione, Gradle builda tranquillamente e tutto ha funzionato fino a poco fa,è questo che non capisco visto che è stata una delle prime cose che ho fatto e non ci ho messo mano da un pò di tempo. I file PDF comunque non si avvicinano lontanamente alla dimensione che tu pensi, solo qualche mega.

Grazie

Post unito: 28 Aprile 2015, 10:39:25 CEST
Comunque non so se mi sono espresso bene all'inizio : ciò che vorrei è aprire questi PDF che ho nella mia cartella "assets" (ci fosse bisogno di cambiare cartella per renderlo possibile va più che bene, è solo che la soluzione che ho trovato li posizionava li e ho seguito quella strada) con l'app di default per PDF.
« Ultima modifica: 28 Aprile 2015, 10:39:25 CEST da Lubron, Reason: Merged DoublePost »

Offline tonno16

  • Utente storico
  • *****
  • Post: 1226
  • Respect: +59
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Aprire un file PDF dall'interno dell'applicazione
« Risposta #7 il: 28 Aprile 2015, 11:07:20 CEST »
0
Essendo in assetto l' app aumenterà di dimensione. Inoltre salvando su memoria interna o esterna sono accessibili anche da PC.
Ho chiesto del log perché vorrei sapere che tipo di errore hai in esecuzione. Gli errori in fase di scrittura sono facili da correggere. Quelli in esecuzione "l' app è crashata" si risolvono analizzando un log se c'è.

Offline Lubron

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S III
  • Sistema operativo:
    Max OS X 10.10.3
Re:Aprire un file PDF dall'interno dell'applicazione
« Risposta #8 il: 28 Aprile 2015, 11:48:46 CEST »
0
Che l'app aumenti di dimensione era preventivato, però non mi è venuto a mente niente di diverso : d'altronde chi me l'ha commissionata vuole fornire questi PDF a chi ne usufruirà.
Ho provato 5 diversi programmi per aprire PDF tra cui anche quello che mi hai consigliato ma nessuno di questi trova il file che ho selezionato.
Non ho un log perchè l'app non è cosi complessa e non mi serve seguire costantemente il flusso, poi l'app non crasha assolutamente nè dà eccezioni sulla logCat, semplicemente apre questi PDF viewer correttamente ma sono loro che danno errore dicendo che non riescono a recuperare il file.

Offline tonno16

  • Utente storico
  • *****
  • Post: 1226
  • Respect: +59
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Aprire un file PDF dall\'interno dell\'applicazione
« Risposta #9 il: 28 Aprile 2015, 11:53:44 CEST »
0
Potrebbe essere corrotto il file. Anche se hai detto che tempo fa non dava problemi. Prova a creare una cartella in SD. Metrici dentro un PDF che si apre al 100%. Vedi se dalla tua app riesci ad aprirlo.

Post unito: 28 Aprile 2015, 11:54:18 CEST
Dovrebbero esistere anche read estern strage nei permessi

Offline Lubron

  • Nuovo arrivato
  • *
  • Post: 6
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S III
  • Sistema operativo:
    Max OS X 10.10.3
Re:Aprire un file PDF dall'interno dell'applicazione
« Risposta #10 il: 28 Aprile 2015, 15:55:04 CEST »
0
Ho risolto seguendo il tuo consiglio ; ho messo tutto nella stessa activity eliminando la classe Utility.

Codice (Java): [Seleziona]
@Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        String tutorial = getString(R.string.tutorial_path);
        String schedule = getString(R.string.lavoro_path);
        String table = getString(R.string.tabella_path);

        if (id == R.id.menu_tutorial) {

            File fileTutorial = new File("/sdcard/" + tutorial);
            if (!fileTutorial.exists())

                CopyAssetsbrochure(tutorial);

            File file = new File("/sdcard/" + tutorial);

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(file),"application/pdf");
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            try {

                getApplicationContext().startActivity(intent);

            } catch (ActivityNotFoundException e) {

                Toast.makeText(MainActivity.this, "NO Pdf Viewer", Toast.LENGTH_SHORT).show();

            }

        }

        if (id == R.id.menu_schedule) {

            File fileSchedule = new File("/sdcard/" + schedule);
            if (!fileSchedule.exists())

                CopyAssetsbrochure(schedule);

            File file = new File("/sdcard/" + schedule);

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(file),"application/pdf");
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            try {

                getApplicationContext().startActivity(intent);

            } catch (ActivityNotFoundException e) {

                Toast.makeText(MainActivity.this, "NO Pdf Viewer", Toast.LENGTH_SHORT).show();

            }

        }

        if (id == R.id.menu_table) {

            File fileTable = new File("/sdcard/" + table);
            if (!fileTable.exists())

                CopyAssetsbrochure(table);

            File file = new File("/sdcard/" + table);

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(file),"application/pdf");
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            try {

                getApplicationContext().startActivity(intent);

            } catch (ActivityNotFoundException e) {

                Toast.makeText(MainActivity.this, "NO Pdf Viewer", Toast.LENGTH_SHORT).show();

            }

        }

        return super.onOptionsItemSelected(item);

    }

    private void CopyAssetsbrochure(String file) {

        AssetManager assetManager = getAssets();
        String[] files = null;

        try {

            files = assetManager.list("");

        } catch (IOException e) {

            Log.e("tag", e.getMessage());

        }

        for(int i=0; i<files.length; i++) {

            String fStr = files[i];
            if(fStr.equalsIgnoreCase(file)) {

                InputStream in = null;
                OutputStream out = null;

                try {

                    in = assetManager.open(files[i]);
                    out = new FileOutputStream("/sdcard/" + files[i]);
                    copyFile(in, out);
                    in.close();
                    in = null;
                    out.flush();
                    out.close();
                    out = null;
                    break;

                } catch(Exception e) {

                    Log.e("tag", e.getMessage());

                }

            }

        }

    }

    private void copyFile(InputStream in, OutputStream out) throws IOException {

        byte[] buffer = new byte[1024];
        int read;
        while((read = in.read(buffer)) != -1){
            out.write(buffer, 0, read);

        }

    }

Spero sia di aiuto anche ad altri questa soluzione! Grazie ancora!