External SD Card Root Folder

tdocs2

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

Djembefola

Active Member
Licensed User
How do I get the name of the External SD Card Root Folder?
Perhaps some day there will exist something like File.DirSDCard

For now, it is pretty difficult to find the external SD Card, because the card is mounted by the manufacturer and can have any name.

For this reason you need to know the name of a unique file or folder on the external SD card. Then you can find it with a recursive search.

You should use file.listfiles recursively and skip system folders like
"/dev", "/proc", "/sys", "/system","/data", "/d", "/acct", because otherwise strange things will happen.
Note that file.listfiles returns null for some system folders. You should always check the result with .isInitialized.
 
Last edited:

tdocs2

Well-Known Member
Licensed User
The SDCard is File.DirDefaultExternal
Thank you for your reply.

The File.DirDefaultExternal returns the default folder in the internal storage.

I have two tablets - same mfr. In both, the internal storage root folder is /mnt/sdcard and the external SD root folder is /mnt/extsd. The name of the root folder varies from manufacturer to manufacturer.

My question remains: Is there a way to get the name of the external SD root folder?

Thank you.
 

tdocs2

Well-Known Member
Licensed User
Perhaps some day there will exist something like File.DirSDCard

For now, it is pretty difficult to find the external SD Card, because the card is mounted by the manufacturer and can have any name.

For this reason you need to know the name of a unique file or folder on the external SD card. Then you can find it with a recursive search.

You should use file.listfiles recursively and skip system folders like
"/dev", "/proc", "/sys", "/system","/data", "/d", "/acct", because otherwise strange things will happen.
Note that file.listfiles returns null for some system folders. You should always check the result with .isInitialized.
Thank you. I was hoping for a different answer but based on all that I read, I think you are right. Maybe the NJDude or another expert can still provide a solution.

Let's hope that Erel can look at the feasibility of implementing your suggestion for a File.RootExternalSDCard
 

NJDude

Expert
Licensed User
As far as I know, there's no standard, some devices might name it /mnt/sdcard2, /storage/sdcard-ext, etc etc.
 

tdocs2

Well-Known Member
Licensed User
As far as I know, there's no standard, some devices might name it /mnt/sdcard2, /storage/sdcard-ext, etc etc.
Has anyone found a workaround?

Google must have realized this shortcoming and developed a response... I may be mistaken, but this seems to be a commonly desired function.

Thanks for your help.

Thank you, Erel for further clarification.
 

margret

Well-Known Member
Licensed User
This is an issue for many of us. I have used many devices and they are all over the place as far as the mount point of the SDCard. Some are a folder off of the Internal memory while others are mount points off of /mnt and yet other mount from /. At the same time the SDCard mount point names are all over the place:

external_sd
ext_sdcard
sdcard
ext_media

It would be nice to have a good solution.
 

Jost aus Soest

Active Member
Licensed User
The problem of android and sdcards is, that usualy the internal memory uses already the two official mount points of android:
/data contains the first (smaller) partition.
/sdcard contains the second (larger rest) partition (often called usbStorage, because you can access this partition via USB by connecting to your PC).

When I remember right, the second entry of /etc/vold.fstab contains the (manufactor specific) mount point.
 
Last edited:

Djembefola

Active Member
Licensed User
When I remember right, the second entry of /etc/vold.fstab contains the (manufactor specific) mount point.
:sign0162:
This is great news. Now it's easy to find the external sd card. I have tested the following b4a code on several devices and it always worked fine. (Perhaps someone else can test and confirm this).

B4X:
'returns external SD Card directory
'the mount point of the external sdcard
'is stored in /system/etc/vold.fstab
'the first or second entry beginning with "dev_mount" contains the sdcard path
Private Sub getSDCard() As String
Dim List1 As List    
Dim Entry1 As String
Dim Entry2 As String
Dim Root As String
Dim mDirectory as String
Dim s As String
   List1 = File.ReadList( "/system/etc/","vold.fstab")
   For i = 0 To List1.Size-1
       s = List1.Get(i)
      If s.StartsWith("dev_mount") Then
         Select True
         Case (Entry1 = "")
            Entry1 = s
         Case (Entry2 = "")
            Entry2 = s
           Exit
         Case Else
            Exit
         End Select     
      End If     
      Log (s)   
   Next
   Root = File.DirRootExternal
   Entry1 = fstabExtract(Entry1)
   Entry2 = fstabExtract(Entry2)
   If Entry1 <> Root Then
      mDirectory = Entry1
   Else
      mDirectory = Entry2
   End If
   If mDirectory = "" Then mDirectory = Root
   Return mDirectory      
End Sub

'helper function for getSDCard
'extracts the path from a line
Private Sub fstabExtract(s As String) As String
Dim i As Int
        
    s = s.Replace(Chr(9), " ") 'replace tabs
   s = s.Replace(":", " ")    'replace ":", workaround for motorola razr
      
   If s.Length < 9 Then Return ""
   s = s.SubString(9)        'strip "dev_mount"
    i = s.IndexOf("/")         'find first slash = start of mount point
    If i = -1 Then Return ""
    s = s.substring(i)         'strip label      
    i = s.IndexOf("auto")      'find end of mount point
    If i = -1 Then i = s.IndexOf("none") 'workaround for motorola razr
    If i = -1 Then Return ""
    s = s.SubString2(0,i-1)    'extract the path
    Return s.trim
End Sub
 
Last edited:

Jost aus Soest

Active Member
Licensed User
Hi Djembefola, nice shot! :)

I've optimized the whole thing (to catch some possible errors and speed it up a little bit):
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("dev_mount ", iCRLF)
      If iMount < 0 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
But does it run without root rights?
I cannot check this, 'cause all my devices are rooted...
 
Last edited:

Djembefola

Active Member
Licensed User
But does it run without root rights?
I cannot check this, 'cause all my devices are rooted...
Yes, it runs fine on unrooted devices. None of my test devices is rooted.

But there is one thing i could not test:
how does the vold.fstab look like on a device without a sd card slot. (All my devices have a card slot) Maybe the code needs to be modified to handle this case.
 

Djembefola

Active Member
Licensed User
I ran the code on a Nexus 7 (no card slot) and the result is:
/storage/sdcard0

Assumed that /storage/sdcard0 is equivalent to File.DirRootExternal on the Nexus 7, this would mean: the code works as expected.
 

NJDude

Expert
Licensed User
Gentlemen, the code seems to work but I don't think it can be fully trusted, this is my opinion of course; the reason I'm stating this is because the following results:

EVO 4G LTE: /mnt/sdcard/ext-sd - Ok

Nexus 7: /storage/sdcard0 - Ok

Galaxy Tab: /mnt/sdcard/exStorages/SdCard - Ok

Tab with 2 EXTERNAL CARDS: /sdcard1 <----huh??

This is the contents of the "vold.fstab" file on that dual external card tab.
B4X:
## Vold 2.0 Generic fstab
## - San Mehat (san@android.com)
## 

#######################
## Regular device mount
##
## Format: dev_mount <label> <mount_point> <part> <sysfs_path1...> 
## label        - Label for the volume
## mount_point  - Where the volume will be mounted
## part         - Partition # (1 based), or 'auto' for first usable partition.
## <sysfs_path> - List of sysfs paths to source devices
######################

## Example of a standard sdcard mount for the emulator / Dream
# Mounts the first usable partition of the specified device
#dev_mount sdcard /mnt/sdcard auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1

## Example of a dual card setup
# dev_mount left_sdcard  /sdcard1  auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
# dev_mount right_sdcard /sdcard2  auto /devices/platform/goldfish_mmc.1 /devices/platform/msm_sdcc.3/mmc_host/mmc1
#dev_mount up_sdcard /mnt/sdcard/sdcard1 auto /devices/platform/imapx200_sdi0.0/mmc_host/mmc0
#dev_mount down_sdcard /mnt/sdcard/sdcard2 auto /devices/platform/imapx200_sdi1.1/mmc_host/mmc1
dev_mount inner_sdcard /mnt/sdcard 6 /devices/platform/imapx200_sdi0.0/mmc_host/mmc0
dev_mount up_sdcard /mnt/sdcard/sdcard1 auto /devices/platform/imapx200_sdi1.1/mmc_host/mmc1
dev_mount down_sdcard /mnt/sdcard/sdcard2 auto /devices/platform/imapx200_sdi2.2/mmc_host/mmc2
dev_mount left_udisk /mnt/sdcard/udisk1 auto /devices/platform/imapx200_usbhost20/usb1/1-3/1-3:1.0
dev_mount right_udisk /mnt/sdcard/udisk2 auto /devices/platform/imapx200_usbhost20/usb1/1-2/1-2:1.0

## Example of specifying a specific partition for mounts
# dev_mount sdcard /sdcard 2 /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
Also, if I get "File.DirRootExternal" on all devices, they ALL report "/mnt/sdcard", except the Nexus 7 which returns "/storage/sdcard0".

Confused yet?
 
Last edited:

NJDude

Expert
Licensed User
I 've checked your vold.fstab with my code (see post #13) and it returned:

/mnt/sdcard/sdcard1

This should be the correct path, isn't it?
Not sure, I get the same results with and without the card inserted.

Using a system browser I see that when the card is inserted a new entry appears on the system: "/mnt/sdcard/udi" no matter which port I insert the card into, but in the browser I see it labels the cards "UDisk1" and "UDisk2" accordingly.

One more thing, like I stated on my post, I don't get "/mnt/sdcard/sdcard1" but only "/sdcard1"
 
Last edited:
Top