Italian Aprire un file PDF con app esterna

Pisinho

Active Member
Licensed User
Longtime User
Buongiorno,
leggendo nlel forum ho trovato questo codice:
B4X:
    ia.Initialize(ia.ACTION_VIEW,"file://" &  File.Combine(File.DirRootExternal, "Download") & "/" & PDF_Filename)
    ia.SetType("application/pdf")
    StartActivity(ia)

Il debug mi prende però questo errore:
android.os.FileUriExposedException: file:///storage/emulated/0/Download/Ultimo.pdf exposed beyond app through Intent.getData()
sembra che debba sostituire file:// con content:// ho provato ma a parte andare avanti e chiedermi con quale visualizzatore aprire il file, una volta
aperto sembra che non apra il file voluto ma apra un file pdf nuovo da modificare, schermo nero. Nessun errore.
Forse devo aggiungere delle autorizzazioni nel Manifest ?

Grazie mille.
 

Star-Dust

Expert
Licensed User
Longtime User
Dipende su che versione di Android gira l'app, quel metodo funziona fino alle versione 5 (o meno) dopo non ti permette di accedere alla memoria interna senza richiedere permessi specifici.

Poi tieni conto che non accedi al file in una cartella esterna dalla tua app, dove potresti richiedere le autorizzazioni di runtime, ma vuoi aprire il file con un app esterna, questo è un altro discorso.

Il lettore del file PDF (presumo Adobe Reader) deve avere l'autorizzazione per accedere alla memoria visto che il file si trova nella cartella download.

Oppure scarichi il file all'interno della tua app e la apri con un lettore esterno con il metodo share.
Vedi qua https://www.b4x.com/android/forum/threads/class-fileprovider-share-files.97865/
 

Pisinho

Active Member
Licensed User
Longtime User
Grazie LucaMs e Star-Dust ma non c'ho capito nulla.
Io salvo il file nella cartella Download perchè pensavo fosse più semplice visto che quasi tute le applicazioni salvano li i propri file, invece non è così.
Grazie lo stesso, ci studio ma la vedo dura...nel caso riposto gli errori.
 

LucaMs

Expert
Licensed User
Longtime User
Io ti ho indicato al volo (non è che abbia "studiato" tanto il tuo problema) su come usare un intent per il pdf.
Quel codice, però, usa una cartella "shared", che è solo "citata" là, viene creata nello Starter di quell'esempio.
Devi crearla anche tu, per essere certo di avere una cartella-directory accessibile, per questione di permessi.

Quando avrò un po' di tempo, se non avrai risolto, tornerò da queste parti; ma ci sono anche altri membri che potranno darti una mano, sicuramente.
 

Pisinho

Active Member
Licensed User
Longtime User
Andiamo per step.
Ho aggiunto il modulo FileProvider, aggiunto le linee nel Manifest di default, ma qui non capisco come definire la directory 'Download' come shared. Non capisco che percorso prende. Ho provato a scrivere anche il mio file all'interno dell'APP con DirInternal ma dice che non ho i permessi...Non c'è un tutorial fatto bene o a prova di newbie ?
 

Pisinho

Active Member
Licensed User
Longtime User
Adesso questo è l'errore che prende....qualcuno ci capisce qualcosa ?

B4X:
Logger connesso a:  samsung SM-N960F
--------- beginning of main
Copying updated assets files (7)
*** Service (starter) Create ***
Using FileProvider? true
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
sending message to waiting queue (activity_permissionresult)
running waiting messages (1)
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
sending message to waiting queue (activity_permissionresult)
running waiting messages (1)
** Activity (main) Resume **
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
Directory : /storage/emulated/0/Download
Nome del FIle: Ultimo.pdf
Error occurred on line: 34 (FileProvider)
java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:131)
    at com.CargoApp.fileprovider._getfileuri(fileprovider.java:160)
    at com.CargoApp.fileprovider._setfileuriasintentdata(fileprovider.java:54)
    at com.CargoApp.main._btnvisualizzapdf_click(main.java:746)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:180)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:176)
    at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
    at android.view.View.performClick(View.java:7870)
    at android.widget.TextView.performClick(TextView.java:14952)
    at android.view.View.performClickInternal(View.java:7839)
    at android.view.View.access$3600(View.java:886)
    at android.view.View$PerformClick.run(View.java:29363)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:237)
    at android.app.ActivityThread.main(ActivityThread.java:7811)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Ultimo.pdf
    at androidx.core.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:744)
    at androidx.core.content.FileProvider.getUriForFile(FileProvider.java:418)
    ... 26 more
 

drgottjr

Expert
Licensed User
Longtime User
non posso più. è più facile mostrarlo:

in Starter:
B4X:
Sub Process_Globals
    Public Provider As FileProvider
End Sub

Sub Service_Create
    Provider.Initialize
End Sub

l'app ha bisogno della "classe" da casa erel sul fileprovider:
https://www.b4x.com/android/forum/attachments/fileprovider-zip.72819/


nell'app:
B4X:
    dim rp as runtimepermissions
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)                     ' <----- libreria runtime permissions
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    If Permission = rp.PERMISSION_WRITE_EXTERNAL_STORAGE And Result = True Then
        Log("permission ok")
        
        Dim filename As String = "file.pdf"   ' <----- metti il nome del file
        
        Try
            File.Copy(File.DirRootExternal & "/Download/", filename, Starter.Provider.SharedFolder, filename)    ' <--- classe fileprovider da erel

            If File.Exists( Starter.Provider.SharedFolder, filename ) Then
                Log("shared file is there")
            Else
                Log("shared file has not been copied")
                activity.finish                
            End If
            
            Dim in As Intent
            in.Initialize(in.ACTION_VIEW, "")
            in.PutExtra("android.intent.extra.STREAM", Starter.Provider.GetFileUri(filename))
            in.Flags = 1 'FLAG_GRANT_READ_URI_PERMISSION
        
            Starter.Provider.SetFileUriAsIntentData(in, filename)
            Log("attempting to share: " & Starter.Provider.GetFileUri( filename ))
            in.SetType("application/pdf")

            Dim pm As PackageManager              ' <------ nella libreria phone
            Dim possibleApps As List = pm.QueryIntentActivities(in)
                            
            If possibleApps.IsInitialized Then            
                Log("you seem to have an app that will handle this...")
                StartActivity(in)
            Else
                Log("no app to handle request")
                Activity.Finish
            End If
        Catch
            Log(LastException.Message)
            Activity.Finish
        End Try
    Else
        Log("no permission")
                                Activity.Finish
    End If

l'ho appena provato (con successo). posso scaricare un archivio .pdf a download e dopo passarlo da download a una app che
può mostrarlo sul schermo. è importante avere quella app. se non, la tua fa crash (leggi la documentazione di android). io
utilizzo pdf viewer da google play. scusi che il codice sia in inglese. sono troppo affatigato per cambiarlo. non ho messo il codice della
"scaricatata" (httputils2). e non ho mostrato il manifest con i permessi (read_external). credo che già l'hai fatto.
 

Pisinho

Active Member
Licensed User
Longtime User
Buongiorno,
grazie mille lo provo subito. Si nel manifest c'è sia il write che read per external.
Per il download tutto ok, era solo avere qualche delucidazione per l'uso del FileProvider.
Grazie a tutti, vi faccio sapere.
 

drgottjr

Expert
Licensed User
Longtime User
l'esempio non è ottimo, e ci sono diferenti manieri di fare la cosa, ma come non capivi "nulla" me sembrava proprio darti un po' di codice. la condivisione
delle cose può essere confusa. la ricezione di un oggetto condiviso e l'invio di un oggetto condiviso non sono la stessa cosa
 
Top