App.GetFreeSpace(path) <-- return free space in Gb byte count.
App.GetFileSize(path) <-- return file size in bytes count.
A bit confusing. I prefer both return in byte count format and let me do the convertion/computation for display or whatever purpose.
Unless there is a switch option to make both of them return in byte count.
I agree it would be nice to have them both return bytes. Perhaps you can submit this in the "Tell us what you want" thread. However, I understand that free space is somewhat harder to calculate accurately, especially with some filesystems that retain a buffer of space which may be garbage collected later, or may be shared space, etc. Thus, a byte count may not be particularly useful: Someone may try to fill the filesystem down to the last byte, but find it gets full faster than expected. (I've had that happen to me).
On a related note, I created a DiskUsage function to find the usage of an entire tree, as well as a DiskUsedSynchronous() function (more convenient for the programmer). I found the latter to be slightly slower though, so take your pick:
var nn1=null;
var nn2=null;
var basePath="/sdcard/0RadioAudio"; // Customize this
//Called when application is started.
function OnStart() {
app.SetDebugEnabled( false );
//Create a layout with objects vertically centered.
lay = app.CreateLayout( "linear", "VCenter,FillXY" );
//Create a button and add it to layout.
btn1 = app.CreateButton( "Check 1" );
btn1.SetTextSize( 32 );
btn1.SetOnTouch(onClick1);
lay.AddChild( btn1 );
//Create a button and add it to layout.
btn2 = app.CreateButton( "Check 2" );
btn2.SetTextSize( 32 );
btn2.SetOnTouch(onClick2);
lay.AddChild( btn2 );
//Add layout to app.
app.AddLayout( lay );
alert("Free Space: "+app.GetFreeSpace(basePath)*1024*1024*1024);
// alert(app.diskUsed("basePath)); // 2970561643
var d=new Date();
var result=app.diskUsedSyncronous(basePath+"/Logs");
alert("diskUsedSyncronous="+result+" took "+((new Date()-d))/1000+" sec"); // 68681 took 0.249
var d=new Date();
var result=app.diskUsedSyncronous(basePath);
alert("diskUsedSyncronous="+result+" took "+((new Date()-d))/1000+" sec"); // 68681 took 35.977
}
function onClick1(p1) {
if(nn1 == null) {
var d=new Date();
nn1=new DiskUsage(basePath, function(result) { // 2970561643 took 53.067 w/o status
nn1=null;
alert('result='+result+" took "+((new Date()-d))/1000+" sec");
}).check();
}
else app.ShowPopup('curTotal1='+nn1.total);
}
function onClick2(p1) {
if(nn2 == null) {
var d=new Date();
nn2=new DiskUsage(basePath+"/Logs", function(result) { // 68681 took 4.421, .356 w/o status
nn2=null;
alert('result='+result+" took "+((new Date()-d))/1000+" sec");
}).check();
}
else app.ShowPopup('curTotal2='+nn2.total);
}
function DiskUsage(path, callback) {
this.path = path;
this.callback = callback;
this.q = [];
this.total = 0;
this.check = function(path) {
if(path == null) { path=this.path; }
if(!app.IsFolder(path)) { this.total += app.GetFileSize(path); }
else {
//app.ShowPopup('Listing folder: '+path);
var files=app.ListFolder(path, null, null, "FullPath");
//app.ShowPopup('Listed folder: '+path+'; '+files.length);
for(var xa=0; xa<files.length; xa++) { this.q.push(files[xa]); }
}
//app.ShowPopup('Current Total('+this.path+')='+this.total);
var nextPath=this.q.shift();
if(nextPath != null) {
setTimeout(function() { this.check(nextPath); }.bind(this), 0);
}
else { callback(this.total); }
}
}
app.diskUsedSyncronous=function(path) {
var files=app.ListFolder(path);
var total=0;
for(var xa=0; xa<files.length; xa++) {
var subPath=path + "/" + files[xa];
if(!app.IsFolder(subPath)) { total += app.GetFileSize(subPath); }
else { total += app.diskUsedSyncronous(subPath); }
}
return total;
}
}
Here's a code method from my (big plugin) library you might find it useful. Converts bytes size to relevant display size. Its set to last 2 decimal places but you could adjust it if you want more. The strFilesize() can handle an insane file size up to yottabyte. This method wont be obsolete anytime soon.
I use tabs instead of spaces. Just cut and paste the code.
// display the filesize in string with proper units
// option -> decimal (SI standard)
function strFilesize (size,option) {
// binary counting base 2
var usiz=1024;
// decimal "SI" international system
if (option!=undefined)
if ((option=="decimal") || (option=="si")) usiz=1000;
// determine unit display
var dsize=size; dunt=0;
while (dsize>usiz) { dunt++; dsize=dsize/usiz; }
// file size unit
var dunit="";
switch (dunt) {
case 0: dunit="B"; break; // Byte
case 1: dunit="K"; break; // Kilobyte
case 2: dunit="M"; break; // Megabyte
case 3: dunit="G"; break; // Gigabyte
case 4: dunit="T"; break; // Terrabyte
case 5: dunit="P"; break; // Petabyte
case 6: dunit="E"; break; // Exabyte
case 7: dunit="Z"; break; // Zettabyte
case 8: dunit="Y"; break; // Yottabyte
}
var dstr="";
if (dunt==0) dstr=dsize.toString()+dunit;
else {
if (usiz==1000) dunit=dunit.toLowerCase();
dstr=dsize.toFixed(2).toString()+dunit+"B";
}
return dstr
} // strFilesize (size,option)
Here's the line of code to test.
extsd=app.GetExternalFolder();
Alert('Disk space: '+app.GetFreeSpace(extsd);
alert(app.GetFreeSpace("internal")+' '+app.GetFreeSpace("external"));
Check if both return the same number of free space. They are suppose to be different between internal sd card and external sd card. Thanks.
@everybody.
Please before trying it out. Please check your droidscript version. My version is 1.34.
here the results again:
1.5824318
1.5629005
//Get amount of free space on internal or external sdcard in Gigs
public static float GetFreeSpace( String mode )
{
StatFs stat;
if( mode.toLowerCase().indexOf("extern") > -1 )
stat = new StatFs( Environment.getExternalStorageDirectory().getPath() );
else
stat = new StatFs( Environment.getDataDirectory().getPath() );
//One binary gigabyte equals 1,073,741,824 bytes.
double sdAvailSize = (double)stat.getAvailableBlocks() * (double)stat.getBlockSize();
return (float)(sdAvailSize / 1073741824);
}
Android regards evey device as having external and internal storage, whether it has an removable drive or not.
The difference between internal and external is whether they are private or public, not where they are stored.
For a while, a removable card could be pretty much recognised as Secondary Storage, but that seems to have gone out the window recently.
Personally, I can't find anyway to separate my removeable card from fixed storage on my Marshmallow phone.
If I move a gigabyte of files from one to another, the free space of nothing gets bigger or smaller, even as reported by df.
Environment variable point to volumes that haven't existed since I was on lollipop.
I am sure the utility-writers have kept track of all this as it happens but my main source of information on fhis sort of thing, Stack Overflow, seems to be as confused as I am.
If anyone can find a source of information on dealing with this in Java, please post a link.
Dave has recently posted his current Java code for internal and external space.
If I could find a good suggestion for removable storage(which I suspect includes different algorithms for different API levels) I would be happy to try building a plugin function and ask others to test it on different devices.
If we can get a reliable plugin, I am sure Dave will be happy to absorb the code into DroidScript.
However, I can't currently find even any sensible suggestions.