Italian Aprire un pdf da SDK >= 24 (Nougat)

Star-Dust

Expert
Licensed User
Longtime User
3) Un pò di spiegazioni:

Ho allegato un esempio creato da @Erel per spiegare come condividere i file per con Android 7+ (24+). Ti consiglio di provarlo e vedere se ti funziona.
I file prima vengono copiati nella cartella SHARE e poi condivisi da quella cartella perché è l'unica cartella che è possibile far leggere a un App esterna e quindi condividere.

Nelle versioni precedenti, il file doveva trovarsi nella memoria esterna (non nelle cartelle dell'App) perché solo la memoria esterna poteva essere condivisibile. Adesso non più a motivo dei permessi che le altre App dovrebbero chiedere.

Quindi va copiata nella Cartella SHARE e poi condivisa. Ovviamente fai un controllo per verificare che versione di Android ha il dispositivo e poi avvi un metodo oppure l'altro.

4) Alcune correzioni da fare al tuo codice
Nel tuo codice manca la modifica del Manifest, ovvero devi aggiungere questo: (come vedrai nell'esempio che ti ho allegato)
B4X:
AddManifestText(<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18" />
)

AddApplicationText(
  <provider
  android:name="android.support.v4.content.FileProvider"
  android:authorities="$PACKAGE$.provider"
  android:exported="false"
  android:grantUriPermissions="true">
  <meta-data
  android:name="android.support.FILE_PROVIDER_PATHS"
  android:resource="@xml/provider_paths"/>
  </provider>
)
CreateResource(xml, provider_paths,
   <external-files-path name="name" path="shared" />
)

Inoltre nel tuo progetto hai sbagliato il modo di chiamare l'intent:
B4X:
Dim i As Intent
    i.Initialize(i.ACTION_VIEW, "content://" & File.Combine(shared,"esempio_shared.pdf"))
    i.SetType("application/pdf")
    i.Flags = 1 + 268435456
    StartActivity(i)

Il Modo corretto è questo:
B4X:
Dim in As Intent
    in.Initialize(in.ACTION_SEND, "")
    in.SetType("text/plain") 'it is not related to the file itself.
    in.PutExtra("android.intent.extra.STREAM",  CreateFileProviderUri(Starter.shared, "1.bal"))
    in.Flags = 1
    StartActivity(in)
avendo questa sub:
B4X:
Sub CreateFileProviderUri (Dir As String, FileName As String) As Object
    Dim FileProvider As JavaObject
    Dim context As JavaObject
    context.InitializeContext
    FileProvider.InitializeStatic("android.support.v4.content.FileProvider")
    Dim f As JavaObject
    f.InitializeNewInstance("java.io.File", Array(Dir, FileName))
    Return FileProvider.RunMethod("getUriForFile", Array(context, Application.PackageName & ".provider", f))
End Sub
 
Last edited:

Gianni Sassanelli

Active Member
Licensed User
Longtime User
Ciao Star-Dust, ci siamo quasi,
ma non è ancora perfetto

anzitutto l'esempio che tu mi hai mandato dovrebbe servire per condividere i file.Infatti questo metodo l'avevo già utilizzato per spedire la mail.

A me serve visualizzare il pdf.

posto de esempi che funzionano al 90%

Esempio 1 (funziona solo se il visualizzatore è Acrobat) ho provato con altri visualizzatori e non riescono a mostrare a video il pdf
B4X:
   [/B]
If Not(rp.Check(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)) Then
       'MsgboxAsync("E' need this permission because reasons so press Allow.", "Important info")
      ' Wait For Msgbox_Result (Result As Int)
       rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
       Wait For Activity_PermissionResult (Permission As String, havePermission As Boolean)
       If havePermission = False Then
           ToastMessageShow("Sorry, can't continue, press button to try again.", True)
           Return
       End If
   End If
    
   Log("We have permission")
    Public shared As String
    shared = rp.GetSafeDirDefaultExternal("shared")
    File.Copy(File.DirAssets, "esempio.pdf", shared, "esempio_shared.pdf")
    Dim i As Intent
    i.Initialize(i.ACTION_VIEW, "content://" & File.Combine(shared,"esempio_shared.pdf"))
    i.SetType("application/pdf")
    i.Flags = 1 + 268435456 
    StartActivity(i)
[B]

Esempio 2 con l'utilizzo del file provider, funziona con tutti i visualizzatori, solo che è impostata la modalità STREAM e quindi mi presenta una lista di applicazioni Gmail, Whatsup ecc ecc in quanto cerca di condividere il file

B4X:
   [/B]
If Not(rp.Check(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)) Then
       'MsgboxAsync("E' need this permission because reasons so press Allow.", "Important info")
      ' Wait For Msgbox_Result (Result As Int)
       rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
       Wait For Activity_PermissionResult (Permission As String, havePermission As Boolean)
       If havePermission = False Then
           ToastMessageShow("Sorry, can't continue, press button to try again.", True)
           Return
       End If
   End If
   Log("We have permission")
    Public shared As String
    shared = rp.GetSafeDirDefaultExternal("shared")
    File.Copy(File.DirAssets, "esempio.pdf", shared, "esempio_shared.pdf")   
    Dim in As Intent
    in.Initialize(in.ACTION_SEND, "")
   in.SetType("application/pdf")         'it is not related to the file itself.

' Io credo che il problema sia in questa riga ma non conosco le opzioni da inserire nel Intent.PutExtra
   in.PutExtra("android.intent.extra.STREAM",  CreateFileProviderUri(shared, "esempio_shared.pdf"))
   in.Flags = 1
    StartActivity(in)
[B]

' Io credo che il problema sia in questa riga ma non conosco le opzioni da inserire nel Intent.PutExtra
in.PutExtra("android.intent.extra.STREAM", CreateFileProviderUri(shared, "esempio_shared.pdf"))

sai per caso dove posso reperirle ???
ci dovrebbe qualcosa tipo android.intent.extra.APRIFILE ecc
 

Star-Dust

Expert
Licensed User
Longtime User
Ciao Star-Dust, ci siamo quasi,
ma non è ancora perfetto

anzitutto l'esempio che tu mi hai mandato dovrebbe servire per condividere i file.Infatti questo metodo l'avevo già utilizzato per spedire la mail.

A me serve visualizzare il pdf.

posto de esempi che funzionano al 90%

Esempio 1 (funziona solo se il visualizzatore è Acrobat) ho provato con altri visualizzatori e non riescono a mostrare a video il pdf
B4X:
   [/B]
If Not(rp.Check(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)) Then
       'MsgboxAsync("E' need this permission because reasons so press Allow.", "Important info")
      ' Wait For Msgbox_Result (Result As Int)
       rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
       Wait For Activity_PermissionResult (Permission As String, havePermission As Boolean)
       If havePermission = False Then
           ToastMessageShow("Sorry, can't continue, press button to try again.", True)
           Return
       End If
   End If
 
   Log("We have permission")
    Public shared As String
    shared = rp.GetSafeDirDefaultExternal("shared")
    File.Copy(File.DirAssets, "esempio.pdf", shared, "esempio_shared.pdf")
    Dim i As Intent
    i.Initialize(i.ACTION_VIEW, "content://" & File.Combine(shared,"esempio_shared.pdf"))
    i.SetType("application/pdf")
    i.Flags = 1 + 268435456
    StartActivity(i)
[B]

Esempio 2 con l'utilizzo del file provider, funziona con tutti i visualizzatori, solo che è impostata la modalità STREAM e quindi mi presenta una lista di applicazioni Gmail, Whatsup ecc ecc in quanto cerca di condividere il file

B4X:
   [/B]
If Not(rp.Check(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)) Then
       'MsgboxAsync("E' need this permission because reasons so press Allow.", "Important info")
      ' Wait For Msgbox_Result (Result As Int)
       rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
       Wait For Activity_PermissionResult (Permission As String, havePermission As Boolean)
       If havePermission = False Then
           ToastMessageShow("Sorry, can't continue, press button to try again.", True)
           Return
       End If
   End If
   Log("We have permission")
    Public shared As String
    shared = rp.GetSafeDirDefaultExternal("shared")
    File.Copy(File.DirAssets, "esempio.pdf", shared, "esempio_shared.pdf")
    Dim in As Intent
    in.Initialize(in.ACTION_SEND, "")
   in.SetType("application/pdf")         'it is not related to the file itself.

' Io credo che il problema sia in questa riga ma non conosco le opzioni da inserire nel Intent.PutExtra
   in.PutExtra("android.intent.extra.STREAM",  CreateFileProviderUri(shared, "esempio_shared.pdf"))
   in.Flags = 1
    StartActivity(in)
[B]

' Io credo che il problema sia in questa riga ma non conosco le opzioni da inserire nel Intent.PutExtra
in.PutExtra("android.intent.extra.STREAM", CreateFileProviderUri(shared, "esempio_shared.pdf"))

sai per caso dove posso reperirle ???
ci dovrebbe qualcosa tipo android.intent.extra.APRIFILE ecc
Ok. Non devi condividere ma solo visualizzare.
Adesso sono fuori sede di nuovo, quindi non posso vedere come ho fatto io nelle mie App. Forse riesco stasera.

Cosi al volo proverei a richiedere i permessi per la scrittura nella memoria (rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE) ) del del dispositivo. Salverei il file in una cartella esterna e poi lo condividerei col vecchio metodo.
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Prova a sostituire ACTION_SEND con
ACTION_VIEW lasciando il resto uguale all'esempio di Erel.

Oppure aspetti un anima pia che ti aiuti o in alternativa aspetti che io rientri :p
 

Star-Dust

Expert
Licensed User
Longtime User
Questo è il metodo che uso io per la visualizzazione e mi funziona correttamente su Android 7 e 8
Prova sui tuoi dispositivi, adesso ti lascio alle tue capacità.
 

Attachments

  • sassanelli.zip
    192 KB · Views: 249

Gianni Sassanelli

Active Member
Licensed User
Longtime User
Così è più pulito e finalmente funziona.
Avevo risolto, creando la variabile UriFileName andando a sbirciare negli oggetti

In effetti la sub CreateFileProviderUri copia il file in un'altra cartella condivisa da tutte le app,
e quindi il file viene copiato 2 volte. Che casino!!!

Tutta la storia dei permessi non serve visto che la mia app. può già scrivere nelle sue cartelle in quanto ha diritti di Owner sulle stesse
Il problema sta tutto nel fatto che le applicazioni esterne non possono leggere un file creato dalla mia app nemmeno se lo copio nella cartella shared. quindi va fatto un doppio passaggio.
Chissà perchè Acrobat Reader ci riesce... mah


1) File.Copy(File.DirAssets, "esempio.pdf", nella cartella shared, "esempio.pdf") (1ª copia)
2) CreateFileProviderUri(.....) in una cartella sua il cui percorso è (2ªcopia)

B4X:
'Alla fine il percorso risulta essere il seguente:
Dim FileName as String = "esempio.pdf"
Dim UriFileName As String = "content://" & Application.PackageName & ".provider/name/" & FileName

'a questo punto...
intent.Initialize(in.ACTION_VIEW,UriFileName)
startactivity(intent)  'Finalmente si Visualizza sto c... di PDF

Io sono a Bari se sei da queste parti ci beviamo una birra insieme.
 
Top