Android Question How can I open file from FileProvider.SharedFolder?

PhrotonX

Member
I tried following some tutorials found in this forum, but I couldn't make it work. I often get InvocationTargetException errors. If not, I get "Media not found" on Android's Photos app when opening some files of MIME type images/*.


B4X:
Public Sub GetAttachmentFilePath(attachment_id As Long) As String
    Log("DirDefautlExternal: " & Starter.Permissions.GetSafeDirDefaultExternal(m_fileRepository.DIRECTORY))
    For Each item As String In File.ListFiles(Starter.Permissions.GetSafeDirDefaultExternal(m_fileRepository.DIRECTORY))
        Log("File from DirDefaultExternal: " & item)
    Next
  
    Return File.Combine(Starter.Permissions.GetSafeDirDefaultExternal(m_fileRepository.DIRECTORY), _
    GetAttachment(attachment_id).GetFilename)
End Sub

' Returns true if the insertion succeeded.
Public Sub OpenAttachment(attachment_id As Long) As Boolean
    Try
        Dim filePath As String = GetAttachmentFilePath(attachment_id)
        Dim fileName As String = GetAttachment(attachment_id).GetFilename
  
        Log("filePath: " & filePath)
        Log("fileName: " & fileName)
  
        File.Copy(Starter.Permissions.GetSafeDirDefaultExternal(m_fileRepository.DIRECTORY), _
        fileName, Starter.Provider.SharedFolder, fileName)
  
        Log("SharedFolder: " & Starter.Provider.SharedFolder)
  
        For Each item As String In File.ListFiles(Starter.Provider.SharedFolder)
            Log("File from SharedFolder: " & item)
        Next
  
        Dim intentObj As Intent
        intentObj.Initialize(intentObj.ACTION_VIEW, "")
        ' intentObj.Initialize(intentObj.ACTION_VIEW, File.Combine(Starter.Provider.SharedFolder, fileName)) ' Doesn't work
        Starter.Provider.SetFileUriAsIntentData(intentObj, fileName) ' Doesn't work
        'intentObj.SetComponent("android/com.android.internal.app.ResolverActivity")
        intentObj.SetType("image/*")
        StartActivity(intentObj)
      
        Return True
    Catch
        Log(LastException)
    End Try
  
    Return False
End Sub

The logs:

B4X:
DirDefautlExternal: /storage/emulated/0/Android/data/com.cm.todolist/files/attachments
File from DirDefaultExternal: 1744788485734_IMG_20250407_204747.jpg
filePath: /storage/emulated/0/Android/data/com.cm.todolist/files/attachments/1744788485734_IMG_20250407_204747.jpg
fileName: 1744788485734_IMG_20250407_204747.jpg
SharedFolder: /data/user/0/com.cm.todolist/files/shared
File from SharedFolder: 1744788485734_IMG_20250407_204747.jpg
Error occurred on line: 33 (FileProvider)
java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
    at com.cm.todolist.fileprovider._getfileuri(fileprovider.java:147)
    at com.cm.todolist.fileprovider._setfileuriasintentdata(fileprovider.java:98)
    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:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:262)
    at com.cm.todolist.attachmentviewmodel._openattachment(attachmentviewmodel.java:203)
    at com.cm.todolist.editoractivity._clvattachments_itemclick(editoractivity.java:1425)
    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:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:1114)
    at anywheresoftware.b4a.keywords.Common.CallSubNew3(Common.java:1077)
    at b4a.example3.customlistview$ResumableSub_PanelClickHandler.resume(customlistview.java:805)
    at b4a.example3.customlistview._panelclickhandler(customlistview.java:748)
    at b4a.example3.customlistview._panel_click(customlistview.java:735)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
    at android.view.View.performClick(View.java:8028)
    at android.view.View.performClickInternal(View.java:8005)
    at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
    at android.view.View$PerformClick.run(View.java:31229)
    at android.os.Handler.handleCallback(Handler.java:959)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loopOnce(Looper.java:232)
    at android.os.Looper.loop(Looper.java:317)
    at android.app.ActivityThread.main(ActivityThread.java:8705)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886)
Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.cm.todolist/files/shared/1744788485734_IMG_20250407_204747.jpg
    at androidx.core.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:825)
    at androidx.core.content.FileProvider.getUriForFile(FileProvider.java:450)
    ... 40 more
(Exception) java.lang.Exception:  java.lang.reflect.InvocationTargetException
 

PhrotonX

Member
Did you configure your paths for the file provider in your Manifest?
Here is my manifest:
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: http://www.b4x.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="24"
android:targetSdkVersion="33" />
<supports-screens android:largeScreens="true"
    android:debuggable="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
AddManifestText(
<uses-permission
  android:name="android.permission.WRITE_EXTERNAL_STORAGE"
  android:maxSdkVersion="33" />
)
AddManifestText(
<uses-permission
  android:name="android.permission.READ_EXTERNAL_STORAGE"
  android:maxSdkVersion="33" />
)
AddManifestText(
<uses-permission
  android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
  android:maxSdkVersion="33" />
)

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,
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="root" path="" />
</paths>
)
'End of default text.
 
Upvote 0

b4x-de

Active Member
Licensed User
Longtime User
Please double check your external-path for sharing. Have a look here:
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Upvote 0

b4x-de

Active Member
Licensed User
Longtime User
I have actually followed that exact same example before posting this thread. I tried copying my files from source folder into FIleProvider.SharedFolder and then tried opening the filename of the file copied into that folder. However, it doesn't work.
When you have followed this example, you should have noticed this line in its Manifest:

CreateResource(xml, provider_paths,
<files-path name="name" path="shared" />
)

In your Manifest the line is:

CreateResource(xml, provider_paths,
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="root" path="" />
</paths>
)

It makes a difference, whether you have an empty path (your Manifest) or have a folder path "shared" (example). You can't access in your code to the path "shared" because it is missing in your Manifest.
 
Upvote 0
Top