Android Question How to write files.

MikleS

Member
Licensed User
Longtime User
Hi.
Android 5.1.1. How to use intent "ACTION_OPEN_DOCUMENT_TREE" to gain access to external SD card to save files. Reading files runs ok, files write not work.
 

MikleS

Member
Licensed User
Longtime User
Thanks Erel

My simple code

B4X:
Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   'Activity.LoadLayout("Layout1")
   Dim p As Object
   Log("file.DirInternal=  " &  File.DirInternal )
  Log("File.DirDefaultExternal=  " &  File.DirDefaultExternal )
  Log("File.DirRootExternal=  " &  File.DirRootExternal ) 
  Log("File.ExternalWritable=  " &  File.ExternalWritable )
 
  Dim paths() As Object = GetContext.RunMethod("getExternalFilesDirs", Array(Null))
  For Each p As Object In paths
  Log(p)
  Next
  Try

   Dim folder As List= rp.GetAllSafeDirsExternal ("")
   Log("folder= " & folder)
   rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
   Catch
   Msgbox("no permission", "check permission ")
   End Try
 
End Sub
Sub Activity_PermissionResult (Permission As String, Result As Boolean)
   Dim z As Object
   If Permission = rp.PERMISSION_WRITE_EXTERNAL_STORAGE Then
  If Result = True Then
  'do whatever you need to do with the sd card
    z=rp.GetAllSafeDirsExternal ("")
        File.MakeDir(z, "mytxt1")
  Else
  'no permission. Close app
  Activity.Finish
  End If
End If
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub GetContext As JavaObject
  Return GetBA.GetField("context")
End Sub

Sub GetBA As JavaObject
  Dim jo As JavaObject
  Dim cls As String = Me
  cls = cls.SubString("class ".Length)
  jo.InitializeStatic(cls)
  Return jo.GetFieldJO("processBA")
End Sub


My logs

** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
file.DirInternal=  /data/data/b4a.example/files
File.DirDefaultExternal=  /storage/emulated/0/Android/data/b4a.example/files
File.DirRootExternal=  /storage/emulated/0
File.ExternalWritable=  true
/storage/emulated/0/Android/data/b4a.example/files
folder= (ArrayList) [/storage/emulated/0/Android/data/b4a.example/files]
** Activity (main) Resume **



Folder mytxt1 is not make.

Warning. External SD card installed Android system along path /mnt/external_sd.
My example of this path (/mnt/external_sd ) is not search.
 
Upvote 0

MikleS

Member
Licensed User
Longtime User
I changed program and use method described here -https://www.b4x.com/android/forum/threads/getting-the-mount-points-nailed.44289/
I make folder "Testfolder" on external SD-card.
I make file 111.txt into this folder.
In file 111.txt written text "Welcome to B4A"
I get access to the memory card, but read-only. When you try to write to a file does not have access.

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Dim p As Object
        label1.Initialize("")
    Log("file.DirInternal=  " &  File.DirInternal )
   Log("File.DirDefaultExternal=  " &  File.DirDefaultExternal )
  Log("File.DirRootExternal=  " &  File.DirRootExternal ) 
   Log("File.ExternalWritable=  " &  File.ExternalWritable )
 
       SDCards
    Log( path_external_sdcard)
     Dim Rslt As Boolean
        Rslt= File.Exists(path_external_sdcard & "/Testfolder/","111.txt")
            If Rslt=True Then
            Log(    "file 111.txt found on path " &path_external_sdcard)
                label1.text=File.ReadString(path_external_sdcard&"/Testfolder","111.txt")
                Log ("Text on file is= " &label1.text)
                Else
                    Log ("file 111.txt not found on path " &path_external_sdcard )  
                           End If
      
                         
      Dim paths() As Object = GetContext.RunMethod("getExternalFilesDirs", Array(Null))
   For Each p As Object In paths
     Log(p)
   Next
   Try
     Dim folder As String = rp.GetAllSafeDirsExternal ("")
    Log("folder= " & folder)
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
     Catch
     Msgbox("no permission", "check permission ")
     End Try
       For Each s As String In rp.GetAllSafeDirsExternal("")
     Log(s)
   Next
 
   File.WriteString(path_external_sdcard&"/Testfolder","111.txt", "00000")
 
 
End Sub

Sub Activity_PermissionResult (Permission As String, Result As Boolean)
    Dim z As String
    Dim R As String

    If Permission = rp.PERMISSION_WRITE_EXTERNAL_STORAGE Then
     If Result = True Then
       'do whatever you need to do with the sd card
       z=rp.GetAllSafeDirsExternal ("")
              File.MakeDir(z, "mytxt1")
           Dim Rslt As Boolean
        Rslt= File.Exists(s & "/Testfolder/","111.txt")
            If Rslt=True Then
                label1.text=File.ReadString(s&"/Testfolder","111.txt")
                Log ("Text on file is= " &label1.text)
                Else
                    Log ("file 111.txt not found on path " &s )  
                           End If
             Else
     End If
End If
End Sub

Sub SDCards 
    Dim Result As List
    Result.Initialize
    Dim tr As TextReader
    tr.Initialize(File.OpenInput("/proc","mounts"))
    Dim line As String
    Do While True
        line = tr.ReadLine
        If line = Null Then Exit
        ' cols: dev mount type options ......
        Dim Col() As String = Regex.Split(" ",line)
        ' things to ignore
        ' put your false positive mount points here
        If Col(1).StartsWith("/dev") Then Continue
        If Col(1).StartsWith("/proc") Then Continue
        If Col(1).StartsWith("/sys") Then Continue
        If Col(1).StartsWith("/system") Then Continue
        If Col(1).StartsWith("/firmware") Then Continue
        If Col(1).StartsWith("/data") Then Continue
        If Col(1).StartsWith("/mnt/shell") Then Continue
        ' vfat is what we are interested in, but my nexus 5 also uses fuse
        If Col(2) = "vfat" Or Col(2) = "fuse" Then
            Dim s As String = Col(1)
            Result.Add(s)
        End If
        Log (s)
    Loop
        tr.Close

        Dim l As List '
        l.Initialize
        Log("")
        Log("path on SDcards")
        For i = 0 To Result.Size - 1
           l.Add(Result.Get(i))
           Log (l)
        Next
        Dim res As Int
          path_external_sdcard=Result.Get(res)
      End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Sub GetContext As JavaObject
  Return GetBA.GetField("context")
End Sub

Sub GetBA As JavaObject
  Dim jo As JavaObject
  Dim cls As String = Me
  cls = cls.SubString("class ".Length)
  jo.InitializeStatic(cls)
  Return jo.GetFieldJO("processBA")
End Sub


Log

B4X:
** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
file.DirInternal=  /data/data/b4a.example/files
File.DirDefaultExternal=  /storage/emulated/0/Android/data/b4a.example/files
File.DirRootExternal=  /storage/emulated/0
File.ExternalWritable=  true
/mnt/external_sd
/mnt/secure/asec
/storage/emulated/0
/storage/emulated/legacy
path on SDcards
(ArrayList) [/mnt/external_sd]
(ArrayList) [/mnt/external_sd, /mnt/secure/asec]
(ArrayList) [/mnt/external_sd, /mnt/secure/asec, /storage/emulated/0]
(ArrayList) [/mnt/external_sd, /mnt/secure/asec, /storage/emulated/0, /storage/emulated/legacy]
/mnt/external_sd
file 111.txt found on path /mnt/external_sd
Text on file is= Welcome to B4A
/storage/emulated/0/Android/data/b4a.example/files
folder= [Ljava.lang.String;@309a7c47
/storage/emulated/0/Android/data/b4a.example/files
Error occurred on line: 68 (Main)
java.io.FileNotFoundException: /mnt/external_sd/Testfolder/111.txt: open failed: EACCES (Permission denied)
    at libcore.io.IoBridge.open(IoBridge.java:456)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
    at anywheresoftware.b4a.objects.streams.File.OpenOutput(File.java:370)
    at anywheresoftware.b4a.objects.streams.File.WriteString(File.java:258)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:753)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:343)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:247)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    at b4a.example.main.afterFirstLayout(main.java:102)
    at b4a.example.main.access$000(main.java:17)
    at b4a.example.main$WaitForLayout.run(main.java:80)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5258)
 
Last edited:
Upvote 0

DPaul

Active Member
Licensed User
Longtime User
Hi,

I do not wish to interfere with any expert advice you will receive, in B4A terms, i'm a beginner.
But this sounds a lot like my early attempts to write to a tablet using file.DirRootExternal.
2 tips:
a) Install ES file explorer an find where the file is on the device, if it's written, you will see it!
b) A few days ago (see other thread), i was told that there are 2 SD Cards, the insertable one
and some "virtual" one on the device itself. DirRootExtrnal writes to the "virtual" one. (Legacy feature)
All this worked for me !
Paul
 
Upvote 0

MikleS

Member
Licensed User
Longtime User
Thank you Paul for your reply.
I installed program "ES file explorer" and "Root explorer".
But they can only read external SD-card, can not write.
:(
 
Upvote 0

DPaul

Active Member
Licensed User
Longtime User
I'm still not convinced, because it looks so similar to my early attempts.
When writing do you get an error message ?, OR, you don't get an error message but you can't find the written file.

The second case was mine. It took me weeks to find out what was going on.
My advice would be: write with file.DirRootExternal some simple file with no specific subdir . Just let it "go".
If no error message, find out with ES explorer where it's located, that's a start.

It should NOT be on the SD card, but the emulated (simulated) SDcard in the tablet.
I can even see the file via USB on my desktop explorer, but that sometimes takes a minute or so...

One thing i cannot prove if it is relevant, i am using a samsung A6 with android 6.0.1 and i see my written files at last :)
Paul
 
Upvote 0
Top