Apparent bug in app.GetFreeSpace()

170 views
Skip to first unread message

Warren Downs

unread,
Mar 3, 2015, 9:08:01 PM3/3/15
to androi...@googlegroups.com
I finally got around to trying app.GetFreeSpace().  On my phone, it is returning the same free space value for every path I've tried so far.  For example:

var sdroot=app.GetExternalFolder();
 alert("1="+app.GetFreeSpace("/")+";2="+app.GetFreeSpace("/data")+";3="+app.GetFreeSpace(sdroot));

Returns the value (at the moment) of 0.1686058 for 1,2 and 3.  And none of them seem to be related to the actual space free on those three mount points.
I actually have about 176k free on /data and 1.2 Gb free on /storage/sdcard1 (the path returned by app.GetExternalFolder()).

Is it actually returning a value related to /data?  That seems to be what it is closest to.

Timo Octazid

unread,
Mar 4, 2015, 12:32:27 AM3/4/15
to androi...@googlegroups.com
Hi,
Same problem.
app.GetFreeSpace() returns just the free space from the internal sdcard not from the external sdcard.
Many Greetings
Timo

Dave Smart

unread,
Mar 4, 2015, 4:11:26 AM3/4/15
to androi...@googlegroups.com
Hi Guys,

The app.GetFreeSpace() method is use with the keywords "external" or "internal" only (you can't use paths).

For example:-

  var space = app.GetFreeSpace( "internal" );

Regards
David

Steve Garman

unread,
Mar 4, 2015, 4:50:19 AM3/4/15
to androi...@googlegroups.com
Apologies.
I listed the parameter as "path" on the wiki without proper testing.

Timo Octazid

unread,
Mar 4, 2015, 7:28:25 AM3/4/15
to androi...@googlegroups.com
Ok, I changed my testcode but look at the result... I dont get the right free space on my device.
Many Greetings
Timo
Screenshot_droidscript2015-03-04-13-20-56.png
Screenshot_esExplorer2015-03-04-13-21-19.png

Warren Downs

unread,
Mar 4, 2015, 10:27:28 PM3/4/15
to androi...@googlegroups.com
 Using "internal" or "external" now gives me meaningful results.  However, it is still inconsistent with app.GetExternalFolder(), which returns the path to my internal storage on my phone.  So I have no way to know the path to the external storage (SD card) which app.GetFreeSpace("external") returns the available space on.

So, for example:
app.GetFreeSpace("internal") returns the space available on /data (built in data space on my phone).

app.GetFreeSpace("external") returns the space available on /storage/sdcard0 (which is my removable SD card on my phone).  This is good, what I wanted to know.  But I need an API to tell me which folder this is (I know it on my device but can't guarantee it on other devices).

app.GetExternalFolder() returns the path /storage/sdcard1 (which is my built-in storage space on my phone).  It would be nice to have an app.GetFreeSpace() function that would return the available space here-- but neither internal nor external address this.

From Terminal Emulator, "set" shows me the EXTERNAL_STORAGE environment variable, which has the value, /storage/sdcard0, the value I need to know.  Obviously Android knows about it there-- but that is not the value being returned by app.GetExternalFolder().  I tried accessing the environment variable from /proc/<pid>/environ, but inside DroidScript, the environ file appears empty.  However, if DroidScript itself can read that variable, it should provide the right value.

Christoph Stehl

unread,
Mar 5, 2015, 12:54:16 AM3/5/15
to androi...@googlegroups.com
Have you tried this?:

app.GetFreeSpace(app.GetExternalFolder())

Dave Smart

unread,
Mar 5, 2015, 4:17:01 AM3/5/15
to androi...@googlegroups.com
OK Guys, it seems that the Environment.getExternalStorageDirectory() method is inconsistent across different devices. Seems that different manufacturers return different results for the same call... which is very annoying!

I think that getting the environment variable is probably going to be the best solution, so I'll change it to that method and also expose the  System.getenv() method so you guys can get at environment variables too :)

Dave Smart

unread,
Mar 5, 2015, 4:37:47 AM3/5/15
to androi...@googlegroups.com
Hi Warren,

What does app.GetInternalFolder() return for you?

Can you send me a screen shot of your 'printenv' dump please.

Regards
David

Warren Downs

unread,
Mar 5, 2015, 12:23:06 PM3/5/15
to androi...@googlegroups.com
alert("Internal Folder="+app.GetInternalFolder()+";external="+app.GetExternalFolder());
    // internal=/storage/sdcard0 (which is actually SD card)
    // external=/storage/sdcard1 (which is actually internal)

Below is the printenv output:
_=/system/bin/printenv
LD_LIBRARY_PATH=/vendor/lib:/system/lib
HOSTNAME=android
BOOTCLASSPATH=/system/framework/core.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar:/system/framework/mediatek-common.jar:/system/framework/mediatek-framework.jar:/system/framework/secondary-framework.jar:/system/framework/CustomProperties.jar:/system/framework/mediatek-telephony-common.jar:/system/framework/mediatek-op.jar
PATH=/system/bin:/system/xbin
LOOP_MOUNTPOINT=/mnt/obb
MKSH=/system/bin/sh
ANDROID_DATA=/data
ANDROID_ROOT=/system
SHELL=/system/bin/sh
ANDROID_STORAGE=/storage
ANDROID_SOCKET_zygote=9
USER=u0_a81
ANDROID_PROPERTY_WORKSPACE=8,49664
EXTERNAL_STORAGE=/storage/sdcard0
ANDROID_ASSETS=/system/app
TERM=screen
RANDOM=21832
ASEC_MOUNTPOINT=/mnt/asec
SECONDARY_STORAGE=/storage/sdcard1
HOME=/data/data/jackpal.androidterm/app_HOME
ANDROID_BOOTLOGO=1
PS1=$(precmd)$USER@$HOSTNAME:${PWD:-?} $
--
I see both devices listed correctly here: EXTERNAL_STORAGE is indeed my SD card, and SECONDARY_STORAGE is indeed the internal storage additional to the /data partition.

It would be nice to be able to get both of those mount points, as well as the free space for all three (/data, secondary, and external)

Thanks, Dave!

Dave Smart

unread,
Mar 5, 2015, 2:10:23 PM3/5/15
to androi...@googlegroups.com
Hi Warren,

Are you absolutely sure you have got this the right way round? The External_Storage variable should actually point to your internal sdcard. Strange as it sounds, it's meant to be that way for legacy reasons.

What device are you using?

Regards
David

Steve Garman

unread,
Mar 5, 2015, 2:56:28 PM3/5/15
to androi...@googlegroups.com
Warren,
EXTERNAL_STORAGE certainly points to my internal storage (same as /sdcard)

I can demonstrate this by entering the following shell commands:

cd /
pwd > /sdcard/env.txt
cd $EXTERNAL_STORAGE
pwd >> /sdcard/env.txt
ls >> /sdcard/env.txt

which produces a listing identical to /sdcard including the newly created env.txt

Does this produce different results from that in your terminal?

Warren Downs

unread,
Mar 5, 2015, 2:57:37 PM3/5/15
to androi...@googlegroups.com
Dave,

To give you some more test data, here are results from my Nextbook tablet:

    alert("Internal Folder="+app.GetInternalFolder()+";external="+app.GetExternalFolder());
    // internal=/storage/sdcard0 (which is actually internal)
    // external=null (But there is actually an external SD card)
    
// Variables of interest from printenv :
INTERNAL_STORAGE=/storage/sdcard0
EXTERNAL_STORAGE=/storage/sdcard0
EXTERNAL_STORAGE2=/storage/sdcard0/external_sdcard
I note that all three Android environments I have agree that ANDROID_DATA=/data
Bad news is, both INTERNAL_STORAGE and EXTERNAL_STORAGE are the same here (really internal), and it is the EXTERNAL_STORAGE2 that is truly my external SD card.  Furthermore, there is no SECONDARY_STORAGE environment variable.
---------------------------
And here is data from VirtualBox Android x86:
    alert("Internal Folder="+app.GetInternalFolder()+";external="+app.GetExternalFolder());
    // internal=/storage/emulated/0
    // (This is accurate.  It is the internal storage mount point).
    // Even though it differs from /storage/emulated/legacy, they both point to the  same, internal path
    // external=/storage/usb0:/storage/usb1:/storage/usb2:/storage/usb3:/storage/sdcard1
// (None are accessible but could be when a device is mounted.  These match the list in SECONDARY_STORAGE).

Environment variables of interest:
EXTERNAL_STORAGE=/storage/emulated/legacy
SECONDARY_STORAGE=/storage/usb0:/storage/usb1:/storage/usb2:/storage/usb3:/storage/sdcard1
 
// Bad news: EXTERNAL_STORAGE is really pointing to internal storage here.
// It is the same location as /storage/emulated/0 as they are two mount points for the same data.

--------
In summary, in my three environments, no method seems fool-proof (and that is just my three!).  Even the environment variables differ with the phone using EXTERNAL_STORAGE for the SD card, the tablet using EXTERNAL_STORAGE2 for my SD card, and Android x86 using SECONDARY_STORAGE for external SD or USB devices (I didn't have them plugged in but when I tested on a physical machine before, those mount points were the ones I remember being used).

Meanwhile, the phone used SECONDARY_STORAGE for the internal partition, the tablet didn't have SECONDARY_STORAGE, and Android x86 used it for external SD or USB (as noted above).
---
With this data, I suggest:
1. Giving access to the environment variables (as you were planning)
2. Making app.GetExternalStorage() return the highest nubered of EXTERNAL_STORAGE, EXTERNAL_STORAGE2, etc. but note the possible issues in the documentation.
3. If possible, give us an API to get free space based on an arbitrary path.  That way, we can decide what device has enough space, and try to make an educated guess as to whether it is really external or not (based on size, environment variables pointing to it, etc)

No solution seems ideal though...

Steve Garman

unread,
Mar 5, 2015, 3:25:05 PM3/5/15
to androi...@googlegroups.com
Clearly external's actual location is something of a moveable feast, especially on devices with root access, where external can be remounted at the user's whim.
by default, external and internal would be expected to equate roughly to /sdcard and app.GetPrivateFolder

The text below is pasted from developer.android.com:


Choose Internal or External Storage
All Android devices have two file storage areas: "internal" and "external" storage. These names come from the early days of Android, when most devices offered built-in non-volatile memory (internal storage), plus a removable storage medium such as a micro SD card (external storage). Some devices divide the permanent storage space into "internal" and "external" partitions, so even without a removable storage medium, there are always two storage spaces and the API behavior is the same whether the external storage is removable or not. The following lists summarize the facts about each storage space.

Internal storage:

It's always available.
Files saved here are accessible by only your app by default.
When the user uninstalls your app, the system removes all your app's files from internal storage.
Internal storage is best when you want to be sure that neither the user nor other apps can access your files.

External storage:

It's not always available, because the user can mount the external storage as USB storage and in some cases remove it from the device.
It's world-readable, so files saved here may be read outside of your control.
When the user uninstalls your app, the system removes your app's files from here only if you save them in the directory from getExternalFilesDir().
External storage is the best place for files that don't require access restrictions and for files that you want to share with other apps or allow the user to access with a computer.

Warren Downs

unread,
Mar 5, 2015, 3:31:27 PM3/5/15
to androi...@googlegroups.com
Dave, I've double and triple-checked, and yes, my phone's EXTERNAL_STORAGE=/storage/sdcard0, which is my external one.

$ df | grep /storage
/mnt/secure/asec: Permission denied
/storage/sdcard1         1G    52M     1G   16384
/storage/sdcard0        27G    26G     1G   32768

Shows my nominal 32 Gb SD card with 1G free space is at /storage/sdcard0
while my internal 1G partition (mostly empty) is at /storage/sdcard1.

I've also verified by creating files on it.

My phone device is a BLU Advance 4.0 running Android 4.2.2.

Warren Downs

unread,
Mar 5, 2015, 3:35:36 PM3/5/15
to androi...@googlegroups.com
Steve,
I tried your test and got a file named env.txt starting with:
/
/storage/sdcard0

and containing a following listing of files from my external SD card.  The env.txt file was also saved in that folder.  (Meaning, /sdcard is the same as /storage/sdcard0)

Warren Downs

unread,
Mar 5, 2015, 4:08:59 PM3/5/15
to androi...@googlegroups.com
Another solution would be to provide an app.System() method that could run external commands and pass back the stdout and stderr (receiving stdin would be nice but harder).  That would allow for a lot of flexible development and in this case provide the option of using "df" to find the free space for a path.
Reply all
Reply to author
Forward
0 new messages