Android Question Create directory issue

tkristensen

Member
Licensed User
Longtime User
I have a program that needs to create folders in the file.DirRootExternal path.

I have reviewed the permissions tutorial and made sure to implement the PERMISSION_WRITE_EXTERNAL_STORAGE permission.

It of course works just fine on older versions of android like used in the BlueStacks simulator, however it does not work on a new Samsung Tab A running running android 10.

In short, I have the permissions in the manifest, I do the permissions check in the code and I have the permission. It will not create a directory in the file.DirRootExternal.

I can create the folder manually on the tablet and it does detect it's presence, but if I try to write a file into that directory it gets a permission error.

So I figure I have something messed up in the permissions, but I am not seeing it. Log excerpt, code and manifest entries listed below.

Thanks in advance.

B4X:
Error occurred on line: 37 (Main)
java.io.FileNotFoundException: /storage/emulated/0/Test/tstfile.txt: open failed: EACCES (Permission denied)
    at libcore.io.IoBridge.open(IoBridge.java:496)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
    at anywheresoftware.b4a.objects.streams.File.OpenOutput(File.java:448)
    at anywheresoftware.b4a.objects.streams.File.WriteString(File.java:263)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:777)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:354)
    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.raiseEvent(BA.java:193)
    at anywheresoftware.b4a.shell.DebugResumableSub$RemoteResumableSub.resume(DebugResumableSub.java:22)
    at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:267)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:137)
    at anywheresoftware.b4a.BA$2.run(BA.java:387)
    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:8107)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
    at libcore.io.Linux.open(Native Method)
    at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
    at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
    at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7984)
    at libcore.io.IoBridge.open(IoBridge.java:482)
    ... 21 more





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.basic4ppc.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="29"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")

'End of default text.
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,
   <files-path name="name" path="shared" />
)




B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
    Private rp As RuntimePermissions
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    
    File.MakeDir(File.DirRootExternal ,  "/Test")
    If File.Exists(File.DirRootExternal & "/Test", "") Then
        Log("exists")
    Else
        Log("Does not exist")
    End If
    File.WriteString(File.DirRootExternal &  "/Test", "tstfile.txt", "xxx")
    
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Button1_Click
    xui.MsgboxAsync("Hello world!", "B4X")
End Sub
 

Alex_197

Well-Known Member
Licensed User
Longtime User
Try this

in Starter
B4X:
Public rp As RuntimePermissions

and then in your code

B4X:
Dim FileDir as String
FileDir = Starter.rp.GetSafeDirDefaultExternal("")
 
Upvote 0

tkristensen

Member
Licensed User
Longtime User
Try this

in Starter
B4X:
Public rp As RuntimePermissions

and then in your code

B4X:
Dim FileDir as String
FileDir = Starter.rp.GetSafeDirDefaultExternal("")

I tried that with no change to manifest both with the original code and modifying it to use the filedir.

Using the filedir does allow it to execute, however the directory created is in the wrong place to where I need it to be for legacy support.

It generates the following path - /storage/emulated/0/Android/data/b4a.example/files - and the code behaves as you would expect. It creates a directory /storage/emulated/0/Android/data/b4a.example/files/Test and creates a file in that directory.

Where I need it create the directory is /storage/emulated/0 - which is the value of file.DirRootExternal

So it would create /storage/emulated/0/Test

And create a file inside that folder.
 
Upvote 0
Top