External SD Card Root Folder

tdocs2

Well-Known Member
Licensed User
Longtime User
How do I get the name of the External SD Card Root Folder? I have searched for hours and experimented with my own code, but to no avail.

The File.DirRootExternal returns the internal storage root folder name.

My objective is:

In any device, I want to get a file list in a folder in the external SD card.
I can do this in the internal storage by using File.DirRootExternal.

Thank you.
 

Jost aus Soest

Active Member
Licensed User
Longtime User
getSDCardPath bug'fixed

My first sub had not payed attention for comment lines. But now - with two changed lines (by searching for CRLF & "dev_mount ") - it works as intended:
B4X:
'Returns external/physical SD Card directory
Public Sub getSDCardPath() As String

    Dim iMount, iCRLF, iSlash, iAuto As Int
    Dim fstab As String = File.ReadString("/system/etc/", "vold.fstab")
    Dim Mount As String

    Do While True
    
        'get next line with mount point:
        iMount = fstab.IndexOf2(CRLF & "dev_mount ", iCRLF) + 2
        If iMount < 2 Then Exit
        iCRLF = fstab.IndexOf2(CRLF, iMount)
        If iCRLF < 0 Then Exit
        Mount = fstab.SubString2(iMount, iCRLF)
        
        'get mount path:
        iSlash = Mount.IndexOf("/")
        If iSlash < 0 Then Continue
        iAuto = Mount.IndexOf2("auto", iSlash)
        If iAuto < iSlash Then Continue
        Mount = Mount.SubString2(iSlash, iAuto).Trim
        
        'return this one, if new:
        If Mount <> File.DirRootExternal Then Return Mount
    
    Loop
    Return File.DirRootExternal

End Sub
Now it should run correctly also on Margrets' Kindle Fire and Informatix' Nexus 7...
 
Upvote 0

Djembefola

Active Member
Licensed User
Longtime User
Here is the vold.fstab file from my 7" Aluratek tablet 4.03...

Mahares, thank you for posting the file.

After reading both of your posts i could find two issues:

The syntax is clearly described in a comment line:
B4X:
Format: dev_mount <label> <mount_point> <part> <sysfs_path1...>
but nevertheless some "creative" motorola programmers use ":" instead of a blank on your motorola razr and others use multiple blanks on your Aluratek.

So what i have to do now as a workaround in my code (post#13):
1. Replace ":" with " "
2. Trim extracted strings

I will update the code in post #13 later.

Another issue came up with Margrets "noob device".
I have heard, that there exist some older devices with no external device memory, they only have one external memory on the sd card.
(this is the historical reason for naming the external memory "sdcard")

Currently the code is not able to deal with this special case.
 
Upvote 0

margret

Well-Known Member
Licensed User
Longtime User
I have run your updated code on all my devices and they all return the correct SDCard path info! :sign0188:

Now, another issue. If the returned mount is different than File.DirRootExternal, how will you test for: File.ExternalWritable. This may return True but be another mount point all together. :confused: Also, File.DirRootExternal does provide special permissions for access.

Jost aus Soest;
Now it should run correctly also on Margrets' Kindle Fire and Informatix' Nexus 7...
 
Last edited:
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Not so fast. The issue still exists even with Joast latest code, at least in my case. It returned /mnt/sdcard when it should have been /mnt/extsd.
 
Upvote 0

margret

Well-Known Member
Licensed User
Longtime User
This code should not fail to return every mount point on the system. The issue is each manufacture seems to name the port what ever they want and it's not standard. So, here is every mounting path, but what do we do with it?

UPDATED to add Write permission and to correct for fstab with :
B4X:
Sub DevicePaths
   Dim lp, dPaths As List : Dim ChkVal, dp = File.DirRootExternal As String : dPaths.Initialize
   lp = File.ReadList("/system/etc/", "vold.fstab")
   For i = 0 To lp.Size -1
      ChkVal = lp.get(i) : ChkVal = ChkVal.Replace(":", " ")
      If ChkVal.ToLowerCase.StartsWith("dev_mount") Then 
         dPaths.Add(SGW(ChkVal, 2) & ", " & SGW(ChkVal, 3))
      End If
   Next
   InputList(dPaths, "Device Mounting Paths", -1)
End Sub
Sub SGW(CStr As String, GE As Int) As String
   Dim t As List : Dim rs, sd As String : sd = " "
   t = Regex.Split(sd, CStr)
   rs = t.Get(GE-1)
   Return rs
End Sub
 
Last edited:
Upvote 0

NJDude

Expert
Licensed User
Longtime User
I think you got it Margret, however, there are a few of things to consider.

1- To be able to write to the external SDCard you have to add this line to the manifest:
B4X:
AddPermission("android.permission.WRITE_EXTERNAL_STORAGE")

2- Devices without an external SDCard will return an empty list (e.g. Nexus 7), so, these lines should be added after the For...Next in Sub DevicePaths
B4X:
If dPaths.Size = 0 Then
   dPaths.Add("/mnt/sdcard, /mnt/sdcard")
End If

3- On ICS and up you CANNOT write to the external SDCard, I think Google changed the permissions, so, having something something like:
B4X:
File.OpenOutput(SGW(ChkVal, 3), "test.txt", False)

Or

File.OpenOutput("mnt/sdcard/ext_sd", "test.txt", False)

Will show a "FILE NOT FOUND" error (Assuming you added the permissions in item 1, otherwise you'll get File Not found + Permission denied).

I have read about a workaround but it requires root access. Well, at least you solved part of the problem and we learned from it.
 
Last edited:
Upvote 0

Jost aus Soest

Active Member
Licensed User
Longtime User
Not so fast. The issue still exists even with Joast latest code, at least in my case. It returned /mnt/sdcard when it should have been /mnt/extsd.

This is not possible: As my sub tries to avoid all mount points equal to FileDirExternal, it must return the first other mount point. In your fstab - you showed it in http://www.b4x.com/forum/basic4andr...-external-sd-card-root-folder.html#post134036 - it's clearly /mnt/extsd!

And yes: When I use your fstab as input for my sub it works...

Are you sure, that you have used the unmodified latest version of my getSDCardPath-sub?

One idea remains:
Please can you check, if the newline-characters in your fstab really consists of CRLF? Theoretically it could be, that they are only CR or LF...
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Are you sure, that you have used the unmodified latest version of my getSDCardPath-sub?

Mahares answers: Yes. It is Jost's unmodified latest version. Unfortunately it still reports: /mnt/sdcard.
I however, tested it on another 7" tablet. It showed the correct SD path, but when I tried to copy a file to it, permission was denied.
I have included the vold.fstab file you requested in its original form. I had to change its extension so it gets uploaded. I hope you can still solve it. If you need anything else on my end, I will be more than happy to supply it to you.
 

Attachments

  • vold.txt
    844 bytes · Views: 396
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Read NJDude's post above. It is pretty conclusive.
@my friend TDS: The Aluratek 7" has ICS 4.03 and I can write to it and save files programmatically at will, but the other 7" has also ICS, but I cannot write to it.
 
Upvote 0

thedesolatesoul

Expert
Licensed User
Longtime User
@my friend TDS: The Aluratek 7" has ICS 4.03 and I can write to it and save files programmatically at will, but the other 7" has also ICS, but I cannot write to it.
Okay, this is a little confusing with you refering to 'other' 7 inch tab.
What is the manufacturer, model number of this?
Can you not write to it via B4A apps, or you cannot write with any apps, so it is always read-only? Also log the exact error.
Can you find out the rw permissions on the sdcard?
Post the vold.fstab of the other 7" tab.
 
Upvote 0

margret

Well-Known Member
Licensed User
Longtime User
I did point out in my post #44 about the permissions issue that we would have next. I may know a solution but I don't know yet if we can do it from B4A, but I am looking into it.

ALSO, I am able to write to the External SDCard on my ASUS running ICS 4.0.3 but not on the NOOK HD running ICS.

Are we having fun yet???
 
Last edited:
Upvote 0

Mahares

Expert
Licensed User
Longtime User
OK TDS: For the sake of the forum community:
What is the manufacturer, model number of this?
MAHARES ANSWERS:It is an off brand called Newsmy with OS 4.03
Can you not write to it via B4A apps, or you cannot write with any apps, so it is always read-only? Also log the exact error.
MAHARES ANSWERS: I cannot write to the card via the below command. The error returned is "filenotfound Access DENIED". But I can copy any files I want to the card proper via file manager.:
B4X:
File.Copy(DBFilePath,TextFile,"/mnt/external_sd",TextFile)
Post the vold.fstab of the other 7" tab.
MAHARES ANSWERS:Here it is attached:
 

Attachments

  • voldnewsmy.txt
    1.3 KB · Views: 405
Upvote 0

Jost aus Soest

Active Member
Licensed User
Longtime User
Shot the whitespaces!

Thanx Mahares and thedesolatesoul I was able to adjust my sub, so it should run under "all circumstances"... ;)

The trick: Normalizing the problematic whitespaces (TABs and CRLFs) before the analyzing starts:

B4X:
'Returns external/physical SD Card directory
Public Sub getSDCardPath() As String

   Dim LF As String = Chr(10) 'line feed' character
   Dim CR As String = Chr(13) 'carriage return' character
   Dim iMount, iLF, iSlash, iAuto As Int
   Dim fstab As String = File.ReadString("/system/etc/", "vold.fstab")
   Dim Mount As String

   fstab = fstab.Replace(TAB, " ") 'replace tab characters
   fstab = fstab.Replace(CR, LF)   'normalize linefeeds
   fstab = fstab.Replace(":", " ") 'replace colon characters (Motorola-case)
   Do While True
   
     'get next line with mount point:
     iMount = fstab.IndexOf2(LF & "dev_mount ", iLF) + 1
     If iMount < 1 Then Exit
     iLF = fstab.IndexOf2(LF, iMount)
     If iLF < 0 Then Exit
     Mount = fstab.SubString2(iMount, iLF)
      
     'get mount path:
     iSlash = Mount.IndexOf("/")
     If iSlash < 0 Then Continue
     iAuto = Mount.IndexOf2("auto", iSlash)
     If iAuto < 0 Then Continue
     Mount = Mount.SubString2(iSlash, iAuto).Trim
     
     'return this one, if new:
     If Mount <> File.DirRootExternal Then Return Mount
   
   Loop
   Return File.DirRootExternal

End Sub

BTW, to check for writeable:
For me it's important, that the end user has not to choose the right path. So I would prefer the lazy solution:
1. Try to write an temp file using getSDCardPath.
2. If it's working, use getSDCardPath, else simply use File.DirRootExternal.
3. Ignore all other possibilities for beeing pleasant. :)
 
Last edited:
Upvote 0

Mahares

Expert
Licensed User
Longtime User
I was able to adjust my sub, so it should run under "all circumstances
@Jost: You are getting and inching closer, but for instance the Razr phone returns: /mnt/sdcard-ext:none:lun1 as a path using your latest version of getSDCardPath, which will of course crash unless I parse the string and get rid of the text from the colon on.
My question is: How many more devices out there that have weird additional text like that? Probably many. How would one handle that? That can become a nightmare.
Thank you
 
Upvote 0
Top