Android Question File.DirRootExternal access denied also using PERMISSION_WRITE_EXTERNAL_STORAGE

sdesan

Member
Licensed User
Longtime User
Hi,
i made a collection of gpx tracks that i open with an axternal GPS program (like Oruxmaps) copiyng gpx file from File.DirAssets to File.DirRootExternal for permitting GPS program to read it
I know that with android:targetSdkVersion < 23 in AndroidManifest there is no problem but due to Google latest request android:targetSdkVersion must be >=26
So i started to implement RuntimePermission in libraries and CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE) in code
when i start my app first i check if exist an exchange folder where to put my files
B4X:
Sub Process_Globals
    Public rp As RuntimePermissions
End Sub
Sub Activity_Create(FirstTime As Boolean)
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, result As Boolean)
    If result Then
        If File.IsDirectory(File.DirRootExternal,"scabr/") = False Then
            File.MakeDir(File.DirRootExternal, "scabr")
        End If
    End If
    Activity.LoadLayout("Splash")
    Sleep(2000)
    Activity.Finish
    StartActivity("Principale")
End Sub
This works, first time when i start app the system says to enable files access
But when i try to lauch GPS program (it starts automatically due to file association) with this code
B4X:
Sub LstTracce_ItemClick (Position As Int, Value As Object)
    Dim traccia As String
    traccia="Pnalm_" & Value & ".gpx"
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, result As Boolean)
    If result Then
        If File.Exists(File.DirRootExternal, "/scabr/" & traccia) = False Then
            File.Copy(File.DirAssets, traccia, File.DirRootExternal, "/scabr/" & traccia)
        End If
        Dim i As Intent
        i.Initialize(i.ACTION_VIEW, "file://" & File.Combine(File.DirRootExternal, "/scabr/" & traccia))
        i.SetType("text/xml")
        Try
            StartActivity(i)
        Catch
            ToastMessageShow("Non posso aprire il file.", True)
        End Try
    End If
End Sub

I obtain always Toast Message "Non posso aprire il file"
Where is my error?!?
Thank you in advance
Sergio
 

sdesan

Member
Licensed User
Longtime User
Thank you Ronell for the answer.
Removing Try & Catch the orror is
android.os.FileUriExposedException
so i'm looking for a solution based also on the thread you have suggested
ASAP i'll write my solution
 
Upvote 0

npsonic

Active Member
Licensed User
You need to use File Provider there is no way to give file path like you are using it in older android versions.
 
Upvote 0

sdesan

Member
Licensed User
Longtime User
Hi npsonic anda thank you for your answer. i'm near the solution following this thread https://www.b4x.com/android/forum/threads/share-txt-files.73166/#post-464921
This is my last problem: when i choose from list a gpx file to open in Android System Screen 'choose to open with' i see; Dropbox, Beam, Bluethoot.Email, Gamail, Onedrive, Drive, Skype, Whatsapp end WiFi Direct but none of GPS program that i have installed (like Oruxmaps, GPX Viever, ARA Gpx viewer etc.) even if when i choose, from file manager, any gpx file the Android System open it with Oruxmap
This is my actual code

in Manifest i added:
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="shared" path="shared" />
)

in service module called Starter:
B4X:
Sub Service_Create
    'This is the program entry point.
    'This is a good place to load resources that are not specific to a single activity.
    shared = rp.GetSafeDirDefaultExternal("shared")
End Sub

In main activity
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, result As Boolean)
    If result Then
        'If File.IsDirectory(File.DirRootExternal,"scabr/") = False Then
        '    File.MakeDir(File.DirRootExternal, "scabr")
        'End If
        'Starter.shared
        If File.IsDirectory(File.DirRootExternal,Starter.shared) = False Then
            File.MakeDir(File.DirRootExternal, Starter.shared)
        End If
    End If
    Activity.LoadLayout("Splash")
    Sleep(2000)
    Activity.Finish
    StartActivity("Principale")
End Sub
In list of gpx file itemclick
B4X:
Sub LstTracce_ItemClick (Position As Int, Value As Object)
    Dim traccia As String
    traccia="Pnalm_" & Value & ".gpx"
    'If File.Exists(File.DirRootExternal, "/scabr/" & traccia) = False Then
    'If File.Exists(Starter.shared, "/scabr/" & traccia) = False Then
    'i.Initialize(i.ACTION_VIEW, "file://" & File.Combine(Starter.shared, "/scabr/" & traccia))
    'i.Initialize(i.ACTION_VIEW, "file://" & File.Combine(Starter.shared, traccia))
    '   i.SetType("text/xml")
    'Try
    '       StartActivity(i)
    'Catch
    '    ToastMessageShow("Non posso aprire il file.", True)
    'End Try
    If File.Exists(Starter.shared, traccia) = False Then
        'File.Copy(File.DirAssets, traccia, Starter.shared, "/scabr/" & traccia)
        File.Copy(File.DirAssets, traccia, Starter.shared, traccia)
    End If
    Dim i As Intent
    i.Initialize(i.ACTION_SEND, "")
    i.SetType("text/xml") 'it is not related to the file itself.
    i.PutExtra("android.intent.extra.STREAM",  CreateFileProviderUri(Starter.shared, traccia))
    i.Flags = 1
    Try
           StartActivity(i)
    Catch
        ToastMessageShow("Non posso aprire il file.", True)
    End Try
End Sub
with this other 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

I think the problem is connected or to
B4X:
i.SetType("text/xml") 'it is not related to the file itself.
or
B4X:
    f.InitializeNewInstance("java.io.File", Array(Dir, FileName))
    Return FileProvider.RunMethod("getUriForFile", Array(context, Application.PackageName & ".provider", f))
As usual any suggestion will be appreciated
Sergio
 
Upvote 0

npsonic

Active Member
Licensed User
Yeah, you are right problem is related to mime type. Here's something simple that you can try.
I probably went little over with this answer and created simple MimeUtils, but use it how you like.

Example
B4X:
Dim mu As MimeUtils
mu.Initialize
i.SetType(mu.MimeType(mu.FileExtension(path),""))
 

Attachments

  • MimeUtils.bas
    15.6 KB · Views: 179
Upvote 0

sdesan

Member
Licensed User
Longtime User
Thank you npsonic, i quicly modified
B4X:
i.SetType("text/xml") 'it is not related to the file itself.
in
B4X:
i.SetType("text/gpx+xml") 'it is not related to the file itself.
but system shows the same installed application above writed whitout any GPS app. In the evening i'll try to solve.
Thank you again
 
Upvote 0

npsonic

Active Member
Licensed User
Thank you npsonic, i quicly modified
B4X:
i.SetType("text/xml") 'it is not related to the file itself.
in
B4X:
i.SetType("text/gpx+xml") 'it is not related to the file itself.
but system shows the same installed application above writed whitout any GPS app. In the evening i'll try to solve.
Thank you again
Your mime type is still incorrect. Use MimeUtils or mime type "application/gpx+xml"
 
Upvote 0

npsonic

Active Member
Licensed User
no news, i'm still looking for the right mime setting :(
B4X:
Dim i As Intent
i.Initialize(i.ACTION_VIEW, CreateFileProviderUri(Starter.shared, traccia))
i.SetComponent("android/com.android.internal.app.ResolverActivity")
Dim mu As MimeUtils
mu.Initialize
i.SetType(mu.MimeType(mu.FileExtension(traccia),"APPLICATION"))
i.Flags = 1
StartActivity(i)
 
Upvote 0
Top