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:
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:
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:
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:
B4XPages.Delegate
 

Midimaster

Active Member
Licensed User
If you want to get access to File.DirRootExternal,
add this to the MANIFEST:
B4X:
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:
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

drgottjr

Expert
Licensed User
Longtime User
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

Brian Dean

Well-Known Member
Licensed User
Longtime User
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

FlyingEagle

Member
Licensed User
Longtime User
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

Midimaster

Active Member
Licensed User
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:
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

Brian Dean

Well-Known Member
Licensed User
Longtime User
... 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

  • WriteFile.zip
    9.2 KB · Views: 268
Upvote 0

FlyingEagle

Member
Licensed User
Longtime User

I tried your code, it looks like this:
B4A:
    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:
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

FlyingEagle

Member
Licensed User
Longtime User
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

Erel

B4X founder
Staff member
Licensed User
Longtime User
Upvote 0

Midimaster

Active Member
Licensed User
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:
...
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

FlyingEagle

Member
Licensed User
Longtime User
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

drgottjr

Expert
Licensed User
Longtime User
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

FlyingEagle

Member
Licensed User
Longtime User
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

Lucas Siqueira

Active 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:
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:
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:
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:
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:
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
Top