Android Question VideoRecordApp with FileProvider: Failed to find configured root

Eldad Onojetah

Member
Licensed User
I have tried this for video.Record3(...) and it fails.
What I have done:

1. In my Manifest

B4X:
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" /> 
)

2. I have FileProvider v1.0 added to the project
3. In Starter,
B4X:
Provider.Initialze
4. I use the following code
B4X:
Dim folder As String = Starter.Provider.SharedFolder
Dim FileName As String = "1.mp4"
'videoRecorder initialised elsewhere
videoRecorder.Record3(folder, FileName, -1, Starter.Provider.GetFileUri(File.Combine(folder, FileName)))

I get the following error
B4X:
** Activity (main) Pause, UserClosed = false **
** Activity (homeactivity) Create, isFirst = true **
** Activity (homeactivity) Resume **
geolocationmanager started
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
FusedLocationProvider1_ConnectionSuccess
(Location) Location[fused 65.966700,-18.533300 acc=4 et=+40m22s373ms alt=15.04444408 {Bundle[mParcelledData.dataSize=52]}]
FusedLocationProvider1_LocationChanged
[GeoCodeInfo=(MyMap) {address_components=[{long_name=13, short_name=13, types=[street_number]}, {long_name=Sunnubraut, short_name=Sunnubraut, types=[route]}, {long_name=Dalvík, short_name=Dalvík, types=[locality, political]}, {long_name=Iceland, short_name=IS, types=[country, political]}], formatted_address=Sunnubraut 13, Dalvík, Iceland, geometry={location={lat=65.9678782, lng=-18.5373444}, location_type=ROOFTOP, viewport={northeast={lat=65.96922718029151, lng=-18.5359954197085}, southwest={lat=65.9665292197085, lng=-18.5386933802915}}}, place_id=ChIJsa_AHMi-0kgRn6RJ1HlXnVQ, plus_code={compound_code=XF97+53 Dalvik, Iceland, global_code=9CQ3XF97+53}, types=[street_address]}, IsInitialized=false, Latitude=65.9667
, Location=Sunnubraut 13, Dalvík, Iceland, LocationOk=true, Longitude=-18.5333
]
registerdevice -> {
  "id": "yt97d0",
  "success": true
}
** Activity (homeactivity) Pause, UserClosed = false **
** Activity (sendreportactivity) Create, isFirst = true **
** Activity (sendreportactivity) Resume **
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 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$2.run(BA.java:370)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6077)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.ohiritech.app/files/shared/data/user/0/com.ohiritech.app/files/shared/1.mp4
    at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:739)
    at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:418)
    ... 16 more
I have also tried
Code:
...
videoRecorder.Record3(folder, FileName, -1, Starter.Provider.GetFileUri(folder, FileName))

I have also tried
B4X:
...
videoRecorder.Record3(folder, FileName, -1, Starter.Provider.GetFileUri(folder, FileName))
The error is similar.

I currently use this same code for recording audio and using the file Chooser and it works file.
 

Eldad Onojetah

Member
Licensed User
I think I have solved it.

I made the following changes to FileProvider
B4X:
Public Sub Initialize
    Dim p As Phone
    If p.SdkVersion >= 24 Or File.ExternalWritable = False Then
        UseFileProvider = True
        'added the following line
        SharedFolder = rp.GetSafeDirDefaultExternal("shared") 
        'commented out the next two lines.
        'File.Combine(File.DirInternal, "shared")
        'File.MakeDir("", SharedFolder)
    Else
        UseFileProvider = False
        SharedFolder = rp.GetSafeDirDefaultExternal("shared")
    End If
    Log($"Using FileProvider? ${UseFileProvider}"$)
End Sub

The error was fixed. And audio recording still works. Will test further to ensure nothing else fails
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
SharedFolder = rp.GetSafeDirDefaultExternal("shared")

What is the final working settings (all parts of codes) ?
I tried, but for any variant - the video recording system app shows the pop-up message "Record failed". No errors in logcat.
 
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
All was done, but no success. So, i have thrown out this code, not solved.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
OK,

I just ran into this problem and I found out the cause...

Basically, there must have been an older example of the File Provider sample in this forum that included these lines in the manifest file:

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

You will notice it says "<external-files-path...", but in the latest version of Erel's file provider class, that line should be "<files-path...":

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

Basically, Erel's file provider class decides which method a file can be shared depending on the API level and if there is external writable memory:

1) The newer way (for API 24+) which can share a private file that is located in an *internal* directory of the app with other apps by using the File Provider feature (uses the URI prefix of "content:" to reference the file). This method uses the above manifest code. But it appears the older version of the manifest code was meant to work with a file that was "external" to the app's internal directory, hence the "external-" phrase in the declaration. But since Erel's file provider class uses an "internal" directory when using this method, that is why the manifest code must match this.

2) Or (the older way) it can share the file without using the File Provider feature by simply prefixing the file with "file://". But this requires that the file be located in an "external" directory that's "visible" by other apps - and that's why a call to RP.GetSafeDirDefaultExternal("shared") is needed to obtain that "visible" directory. And when using this older method, it does not use the file provider feature (and accordingly does not use the manifest declaration), so the lack of "<external-" in the manifest code wont cause any problems.
 
Last edited:
Upvote 0
Top