Android Question Write to File

FlyingEagle

Member
Licensed User
Longtime User
I tried a lot but nothing works for me ... Google Pixel 3 XL Android 11 No-Root-Access

I want to write to files, I tried every single option from File.Dir_xxxx

I want to write to my own Directory on /data/emulated/0/xxxx.

I tried here
Sub Activity_PermissionResult:
Expand Collapse Copy
Sub Activity_PermissionResult (Permission As String, Result As Boolean)
  
    If Permission = Starter.rp.PERMISSION_ACCESS_COARSE_LOCATION Then
        Result = True
    Else
        Log ( "PERMISSION_ACCESS_COARSE_LOCATION" )
    End If
  
    If Permission = Starter.rp.PERMISSION_ACCESS_FINE_LOCATION Then
        Result = True
    Else
        Log ( "PERMISSION_ACCESS_FINE_LOCATION" )
    End If
  
    If Permission = Starter.rp.PERMISSION_READ_EXTERNAL_STORAGE Then
        Result = True
    Else
        Log ( "PERMISSION_READ_EXTERNAL_STORAGE" )
    End If
  
    If Permission = Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE Then
        Result = True
    Else
        Log ( "PERMISSION_WRITE_EXTERNAL_STORAGE" )
    End If
  
    B4XPages.Delegate.Activity_PermissionResult(Permission, Result)
  
End Sub


Or here

Sub Activity_Create:
Expand Collapse Copy
Sub Activity_Create(FirstTime As Boolean)
    Dim pm As B4XPagesManager
    pm.Initialize(Activity)
  
'    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_ACCESS_COARSE_LOCATION)
'    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION)
'    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_READ_EXTERNAL_STORAGE)
'    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE)

    For Each permission As String In Array( Starter.rp.PERMISSION_ACCESS_COARSE_LOCATION, _
                                            Starter.rp.PERMISSION_ACCESS_FINE_LOCATION, _
                                            Starter.rp.PERMISSION_READ_EXTERNAL_STORAGE, _
                                            Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE )
                                          
        Starter.rp.CheckAndRequest(permission)
      
        Wait For Activity_PermissionResult (permission As String, Result As Boolean)
      
        If Result = False Then
            Log ("No permission!" ) ', True)
            Activity.Finish
            Return
        End If
    Next

End Sub


Or here

Manifest:
Expand Collapse Copy
AddManifestText            (
                            <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="29"/>
                            <supports-screens    android:largeScreens="true"
                                                android:normalScreens="true"
                                                android:smallScreens="true"
                                                android:anyDensity="true"/>
                            <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
                            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
                            <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
                            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
                        )

It took me the whole evening ... who can help?


PS: Where do this lines have to be, in front of or at last of the code of a sub?

Delegate:
Expand Collapse Copy
B4XPages.Delegate
 
If you want to get access to File.DirRootExternal,
add this to the MANIFEST:
B4X:
Expand Collapse Copy
SetApplicationAttribute(android:requestLegacyExternalStorage, true)

this will be a workaround for the next 1 or two years. Afterwards we all need a new solution

and this to the SUBs where you want to access to the External Directories:

B4X:
Expand Collapse Copy
Sub CopyFileFromRoot(Datei As String)
    Dim Pfad As String= File.Combine(File.DirRootExternal,"MyFolder")

    Dim rp As RuntimePermissions
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    If Result= False Then Return
    
    If File.Exists(Pfad,Datei)=True Then
        File.Copy(Pfad,Datei,File.DirInternal,Datei)
 
Last edited:
Upvote 0
I want to write to my own Directory on /data/emulated/0/xxxx.

your own directory is File.DirInternal. you can can write whatever you want there. all the other stuff you have in your post has nothing to do with writing to your own directory. your own directory is File.DirInternal.

by the way, did i mention that your own directory is File.DirInternal ?
 
Upvote 0
i don't know how many levels i'm confused about your message, ...
What @drgottjr means is this, I think ...

In your first post you say that "I want to write to my own Directory ...". If by "own directory" you mean a file location that is "owned" by your app then you write to File.DirInternal. This is private storage, in that it cannot be reached by any other app, including File Manager apps.

But if by "my own directory" you mean that you want to create a new folder in the public storage space then things are more complicated due to increasingly restrictive rules being set by Google. These have been covered many times in other posts so I will not repeat them here.
 
Upvote 0
The 2nd is more what I want, but I wanted it more because DirAssets resp. DirInternal was also not working. Permission denied.

I read a lot, as I said before, I spent a lot of time, but with no success.

But when I need this Permission, and I wrote them in Manifest or Code, why do I did not get this Permissions?
Other Apps are able to write there ...
 
Upvote 0
There are several restriction with the different directories. Each directory has a purpose and reasons, why some functions are not working.

So what works on all three direcories is a DirFile command...
B4X:
Expand Collapse Copy
Dim Dir as List=File.ListFiles(File.DirAssets)
For Each Element As String In Dir
    log("Asset DIR=" & Element)
Next

Dir =File.ListFiles(File.DirInternal)
For Each Element As String In Dir
    log("Internal DIR=" & Element)
Next

Dim rp As RuntimePermissions
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    If Result= False Then Return


Dir =File.ListFiles(File.DirRootExternal)
For Each Element As String In Dir
    log("Root DIR=" & Element)
Next
Only for the last one you need the manifest code line I wrote in my first post.

Test it:
Open a new project, write this code in a Sub Button1_Click, be sure to use a DEBUG KEY and transfer the apk with B4A-Bridge. Press the button1.

Then report if anything worked, send the log. Then we continue....
 
Upvote 0
... but I wanted it more because DirAssets resp.
I am afraid that does not make sense to me, so I am going to ignore it except to say that DirAssets is a read-only location that contains data that you added to your apk by adding it in the B4A project "Files" folder. You cannot write anything there from your app.
DirInternal was also not working. Permission denied.
Writing to DirInternal does not require permissions. If you think that you got "Permission denied" that you are mistaken, possibly because you are trying too many things at once (that is, thrashing about in desperation!). You obviously understand that permission is needed to write to DirExternal - this link seems to be the best reference to follow. Writing to DirInternal is quite straightforward. Here is a simple demo project.
 

Attachments

Upvote 0

I tried your code, it looks like this:
B4A:
Expand Collapse Copy
    Dim Dir As List=File.ListFiles(File.DirAssets)
    For Each Element As String In Dir
        Log("Asset DIR=" & Element)
    Next

    Dir = File.ListFiles(File.DirInternal)
    For Each Element As String In Dir
        Log("Internal DIR=" & Element)
    Next

    Dir = File.ListFiles(File.DirRootExternal)
    For Each Element As String In Dir
        Log("Root 1 DIR=" & Element)
    Next
   
    Dim rp As RuntimePermissions
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Res As Boolean)
    ** If Res = False Then
    **    Return
    End If

    Dir = File.ListFiles(File.DirRootExternal)
    For Each Element As String In Dir
    **    Log("Root 2 DIR=" & Element)
    Next

The PermissionResult looks like

B4A:
Expand Collapse Copy
Sub Activity_PermissionResult (Permission As String, Result As Boolean)
   
    If Permission = Starter.rp.PERMISSION_ACCESS_COARSE_LOCATION Then
        Result = True
        Log ( "PERMISSION_ACCESS_COARSE_LOCATION" )
    Else If Permission = Starter.rp.PERMISSION_ACCESS_FINE_LOCATION Then
        Result = True
        Log ( "PERMISSION_ACCESS_FINE_LOCATION" )
    Else If Permission = Starter.rp.PERMISSION_READ_EXTERNAL_STORAGE Then
        Result = True
        Log ( "PERMISSION_READ_EXTERNAL_STORAGE" )
    Else If Permission = Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE Then
        Result = True
        Log ( "PERMISSION_WRITE_EXTERNAL_STORAGE" )
    End If
   
    B4XPages.Delegate.Activity_PermissionResult(Permission, Result)
   
End Sub

I got a long list of filenames, but I see only "Root 1" not "Root 2", Asset, Internal is ok..

I set some breakpoints at "**" (see code above) but they where never reached ...

And I do not get any dialog for permissions ... but I do not used a new project, I used my current one.
 
Upvote 0
Yes it is B4XPage, In which File should this be?

See also my last Q in my 1st post.

Is the Sub Activity_Create in my 1st post correct?
 
Upvote 0
Upvote 0
Ok, it looks like this app can write files to the "sandbox"-dir File.DirInternal. This is already the best decision for writing "in-app-files": accessable from inside the app, but not visible for the "user". Please descripe us, what you want to do with the files. Is it neccessary, that the files are avaiable for the user?

It looks like you already have reading access to File.DirRootExternal. You wrote you saw logs with a "Root 1 DIR=" in front of the log? This means File.DirRootExternal is open for you. No need for asking further permissions.

I think your self-made sub Activity_PermissionResult is nonsense. You cannot give the permissions by yourself. you have to expect them from the system. So there is no need to write this sub. You only have to wait for the event.

I'm not experienced in B4XPages... But if Erel writes the permission comes from B4XPage_PermissionResult the code should look like this:
B4X:
Expand Collapse Copy
...
Dim rp As RuntimePermissions
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean)
    If Result= False Then Return
...
Is this correct, Erel?
 
Upvote 0
There are different aspects, first I do want to download some files and store them for further use in a directory. The content of this file(s) are not confidential to the users.

The second, the user can generate content which I'd like to store in a directory where the user can have access to.

At he moment I follow the approache to store my files in json and share them online with other users, for the moment I do not have a better idea.
The data do not have the abbability to be just in time delivered to the other users ... but it should be not the final ...
 
Upvote 0
everything, except the os, is in a jail. things can be shared through the os.
this ethos is being more and more strongly enforced by android. on the
one hand, it's annoying not to be able to do what you want. on the other
hand, it's good that you can't do bad things to me or vice versa due to
our being in separate jails. android has no choice but to behave this way.

i have no doubt that you will be able to accomplish what you describe
as your goals (although, for me, they are still a little unclear) through the
sharing tools made available by the os. they are described at length
here in the forum. you need to learn about them. you mention sharing
things online, so obviously you grasp the concept. you will be doing the
same things with android.
 
Upvote 0
After some more research and removing the app, clean the project, re-compile everything, android asks for permissions ... and it works ...

I believe that there are some more errors in my code in relation to this thread ;-) but for now it works.

Thanks to everybody!

I promisse I'll come back with more questions ;-)
 
Upvote 0
I tried a lot but nothing works for me ... Google Pixel 3 XL Android 11 No-Root-Access

I want to write to files, I tried every single option from File.Dir_xxxx

I want to write to my own Directory on /data/emulated/0/xxxx.

I tried here
Sub Activity_PermissionResult:
Expand Collapse Copy
Sub Activity_PermissionResult (Permission As String, Result As Boolean)

    If Permission = Starter.rp.PERMISSION_ACCESS_COARSE_LOCATION Then
        Result = True
    Else
        Log ( "PERMISSION_ACCESS_COARSE_LOCATION" )
    End If

    If Permission = Starter.rp.PERMISSION_ACCESS_FINE_LOCATION Then
        Result = True
    Else
        Log ( "PERMISSION_ACCESS_FINE_LOCATION" )
    End If

    If Permission = Starter.rp.PERMISSION_READ_EXTERNAL_STORAGE Then
        Result = True
    Else
        Log ( "PERMISSION_READ_EXTERNAL_STORAGE" )
    End If

    If Permission = Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE Then
        Result = True
    Else
        Log ( "PERMISSION_WRITE_EXTERNAL_STORAGE" )
    End If

    B4XPages.Delegate.Activity_PermissionResult(Permission, Result)

End Sub


Or here

Sub Activity_Create:
Expand Collapse Copy
Sub Activity_Create(FirstTime As Boolean)
    Dim pm As B4XPagesManager
    pm.Initialize(Activity)

'    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_ACCESS_COARSE_LOCATION)
'    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_ACCESS_FINE_LOCATION)
'    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_READ_EXTERNAL_STORAGE)
'    Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE)

    For Each permission As String In Array( Starter.rp.PERMISSION_ACCESS_COARSE_LOCATION, _
                                            Starter.rp.PERMISSION_ACCESS_FINE_LOCATION, _
                                            Starter.rp.PERMISSION_READ_EXTERNAL_STORAGE, _
                                            Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE )
                                        
        Starter.rp.CheckAndRequest(permission)
    
        Wait For Activity_PermissionResult (permission As String, Result As Boolean)
    
        If Result = False Then
            Log ("No permission!" ) ', True)
            Activity.Finish
            Return
        End If
    Next

End Sub


Or here

Manifest:
Expand Collapse Copy
AddManifestText            (
                            <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="29"/>
                            <supports-screens    android:largeScreens="true"
                                                android:normalScreens="true"
                                                android:smallScreens="true"
                                                android:anyDensity="true"/>
                            <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
                            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
                            <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
                            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
                        )

It took me the whole evening ... who can help?


PS: Where do this lines have to be, in front of or at last of the code of a sub?

Delegate:
Expand Collapse Copy
B4XPages.Delegate


Hello I had the same problem, after hours of testing and more testing, I managed to find a solution to my problem.

Note: Erel said "Avoid using File.DirRootExternal. Either use File.DirInternal or RuntimePermissions.GetSafeDirDefaultExternal." at https://www.b4x.com/android/forum/threads/android-jar-targetsdkversion-minsdkversion.87610/#content

With sdk 29 - No permission to access File.DirRootExternal, even with the STORAGE permission. For now there is a simple workaround:

STEP 1 - Update the SDK MANAGER by installing the Android SDK Platform 29 (Android 29).

STEP 2 - in the manifest, set targetSdkVersion = 29 and add the lines:
B4X:
Expand Collapse Copy
SetApplicationAttribute (android: requestLegacyExternalStorage, true)

AddPermission (android.permission.READ_EXTERNAL_STORAGE)
AddPermission (android.permission.WRITE_EXTERNAL_STORAGE)

AddManifestText (
<uses-permission
   android: name = "android.permission.WRITE_EXTERNAL_STORAGE"
   android: maxSdkVersion = "19" />
)

STEP 3 - update the android.jar path in Paths Configuration, to the updated sdk 29.
 
Upvote 0
Back
Top