Android Question fail to create dir

marcick

Well-Known Member
Licensed User
Longtime User
My app is running since two years on a hundred devices and suddenly I have problems creating a directory.
I don't know if it is related to Android 6 or the latest B4A updates.
This is the code

Code: Copy
Dim AppPath As String=File.DirRootExternal & "/test"
If File.exists("",AppPath)=False Then
   Log("creating apppath")
   File.MakeDir("",AppPath)
End If
If File.exists("",AppPath)=False Then Log("dir not exists")

The code is executed in the StarterService and I have the log "dir not exists" (and the dir is really not created).

If I start from a blank project the code works, as it had worked for two years.
But inside my app, the code fails (I test it in release after a clean project).
Where could be the problem ?

I'm looking for another device to test it, to see if it is device related or not.
 
if you use api 23 then you need to use the runtimepermissions library to get the correct path... There is a method in RTP lib for this...
 
Upvote 0
I was just now realizing that moving back to API22 the problem does not exists ....
I'll search for RTP, many thanks
 
Upvote 0
READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE

This is the most common dangerous permission. It is added automatically when you use File.DirDefaultExternal or File.DirRootExternal.
However there is a simple workaround for this.

1. Use RuntimePermissions.GetSafeDirDefaultExternal("") instead of File.DirDefaultExternal. The parameter passed is an optional subfolder that will be created under the default folder.

2. Add this code to the manifest editor:
Code:
AddManifestText(
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
)
The explanation for this is that GetSafeDirDefaultExternal doesn't require any permission on Android 4.4+ (API 18) and requires the WRITE_EXTERNAL_STORAGE on older versions. The code above adds the permission to older devices.
 
Upvote 0
I'm reading, but it is not clear to me how to obtain the DirRootExternal path.
What to do before using this ?

Dim AppPath As String=File.DirRootExternal & "/test"
 
Upvote 0
I've tried this but have the same problem:

Code: Copy
Private rp As RuntimePermissions
rp.GetAllSafeDirsExternal("")
Dim AppPath As String=File.DirRootExternal & "/test"
If File.exists("",AppPath)=False Then
   Log("creating apppath")
   File.MakeDir("",AppPath)
End If
If File.exists("",AppPath)=False Then Log("dir not exists")
 
Upvote 0
You cannot access File.DirRootExternal without the WRITE_EXTERNAL_STORAGE permission.

If you don't want to handle runtime permissions then set the targetSdkVersion to 22 instead of 23. Note that if you have already uploaded your app to Google Play then you cannot change this.

Another, better option is to use a different external storage path such as the one returned from RuntimePermissions.GetSafeDirDefaultExternal("").

Runtime permissions tutorial:
https://www.b4x.com/android/forum/threads/runtime-permissions-android-6-0-permissions.67689/#content
 
Upvote 0
I have the WRITE_EXTERNAL_STORAGE permission in the manifest as explained. And I need target 23.
What to do then to access to DirRootExternal ?
 
Upvote 0
Code: Copy
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private rp As RuntimePermissions
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim sdcardEnabled As Boolean
End Sub
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    sdcardEnabled = False
End Sub
Sub Activity_Resume
    If sdcardEnabled = False Then
        rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    End If
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
Sub Activity_PermissionResult (Permission As String, Result As Boolean)
  If Permission = rp.PERMISSION_WRITE_EXTERNAL_STORAGE Then
     If Result Then
       sdcardEnabled = true
       Log("You NOW can write to File.DirRootExternal")    
       File.WriteString(File.DirRootExternal, "String.txt", _
  "This is some string" & CRLF & "and this is another one.")
     End If
  End If
End Sub
 
Upvote 0
I would have removed the sdcardenabled variable. It is not needed (specifically in your code it should be a process_global variable).
Sorry, i used the RTP lib the first time yesterday to create a working code which writes to DirRootExternal.

specifically in your code
Code was simplified to do a write to RootExternal when the permission is granted...

Thank you for correcting me. You are surely right that the variable should be a process global one. Especially for @marcick requirements.
 
Upvote 0
Another, better option is to use a different external storage path such as the one returned from RuntimePermissions.GetSafeDirDefaultExternal("").

I'm oriented on this solution, but the actaul app (target 22) is working with DirRootExternal.
If I publish the updated app (target 23) can I simply read the DirRootExternal and copy all what is related to my app to the new path returned by RuntimePermissions.GetSafeDirDefaultExternal("") ?
Or do I need to acquire the permission also for read DirRootExternal ? (this would be a dog biting its tail ...)
 
Upvote 0
My intention moving the existing app to GetSafeDirDefaultExternal, was to avoid the permission request, that cause me troubles in the program flow......
Need to think.
Once again thanks to Google, every update causes us to waste time and invent some workaround.
Once again thanks to the people of this forum that are always here to help us.
 
Upvote 0
Back
Top