User Tools

Site Tools


Sidebar

Privacy Policy

News

Version 2.50 is out since Jan 1st 2022


Frequently Asked Questions


Namespaces

Note for contributors

If you wish to create a new page in the DroidScript wiki, please click on the most appropriate namespace above and follow the notes for contributors there.

Because of spam, it has been necessary to add a CAPTCHA to the registration form and the save option for editing pages. You will not need to prove you are human if you are logged in, so please register.

Please feel free to improve any existing page, as well as adding new pages to increase the sum of public knowledge about DroidScript.

Formatting Syntax

sample_code:sys_out

This is an old revision of the document!


sysout.js
// Demonstrate calling external programs, by Warren E. Downs (2015)
// Based on examples by Steve Garman
// This program also demonstrates using Asynchronous Callbacks
// to continue processing once the result of the external program
// is received.
 
//Called when application is started.
function OnStart() {
    // Show roots >100 Mb in size.
    showRoots(100,function() { // Called when showRoots is complete
        alert('3. The program continues here');
        runCmd( "ExpectAnErrorHere", function(lines) {
            alert("Expected empty array: "+JSON.stringify(lines));
        }, function(errmsg) {
            alert('Expected Error: '+errmsg);
        });
    });
    alert('1. Immediate continuation.');
 } 
 
// Shows a list of roots greater than specified minMb in size
// Calls next function (if any) once complete.
function showRoots(minMb, next) {
    listRoots(minMb*1000, function(roots) {
        var result="2. Roots:\n";
        for(var xa=0; xa<roots.length; xa++) {
            var freeGb=(roots[xa].available/1024/1024).toFixed(2);
            result += " " + freeGb + " Gb free on "+roots[xa].mountedOn+"\n";
        }
        alert(result);
        if(next) next();
    });
 }
 
//////////////////////////////////////////////////////////////
/**************** Run External Commands *********************/
function runCmd(cmd, gotLines, gotError) {
    var tmp="/sdcard/."+app.GetAppName()+"_runcmd.txt";
    var tmpErr=tmp+".err";
    if(typeof globs === "undefined") { globs={}; }
    if(cmd != null) { // Pull result from previous run if cmd == null
        var outTmp=tmp+".tmp";
        var errTmp=tmpErr+".tmp";
        var redOut=" >"  + outTmp;
        var redErr=" 2>" + errTmp;
        cmd += redOut  + redErr;
        cmd += "; mv " + outTmp + " " + tmp;    // Rename out & err once done.
        cmd += "; mv " + errTmp + " " + tmpErr;
        cmd += "\n";
 
        // On-demand create globs.sys if not already created
        if(globs.sys == null) { globs.sys = app.CreateSysProc("sh"); }
        globs.sys.Out(cmd);
        globs.runCmdGotLines=gotLines;
        globs.runCmdGotError=gotError;
    }
 
    // Retry until both stdout and stderr exist (though they may be empty)
    if(!app.FileExists(tmp) || !app.FileExists(tmpErr)) {
        setTimeout('runCmd(null, globs.runCmdGotLines, globs.runCmdGotError)', 1);
        return;
    }
 
    // Read stdout and stderr
    var lines=app.ReadFile(tmp); // Retrieve command stdout
    if(lines == null) { alert("Unable to read stdout("+cmd+"): "+tmp); return; }
    var errmsg=app.ReadFile(tmpErr); // Retrieve command stderr
    if(errmsg == null) { alert("Unable to read stderr("+cmd+"): "+tmpErr); return; }
 
    // Process stdout
    lines = lines.split("\n");
    app.DeleteFile(tmp);
 
    gotLines(lines);
    if(errmsg.length > 0) { gotError(errmsg); }
}
 
/****************** List Storage Roots **********************/
function listRoots(minSize, gotRoots) {
    runCmd( "busybox df -k", function(lines) {
        // Filesystem 1K-blocks Used Available Use% Mounted on
        // L                  R    R         R    R L
        // ^^^^^^^^^^^^^^^^^^ HEAD ALIGNMENT ^^^^^^^^^^^^^^^^^
        var head=lines[0];
        // Parse the variable length/fixed-width column headers
        // Columns are fixed width but width depends on content.
        // If content exceeds a column (e.g. Filesystem path),
        // the next line will contain the remaining columns.
        lines=lines.slice(1);
        var headOfs={filesystem:0,blocks:head.indexOf('1K-blocks'),
            used:head.indexOf('Used'),available:head.indexOf('Available'),
            usepct:head.indexOf('Use%'),mountedOn:head.indexOf('Mounted on')};
        headOfs.available = headOfs.used + 4;
        headOfs.used = headOfs.blocks + 9;
        for(var xa=0; xa<lines.length; xa++) {
            var item={};
            var line=lines[xa];
            var nextLine = (xa < lines.length-1) ? lines[xa+1] : "";
            var ret=parseDfLine(headOfs, line, item, nextLine);
            lines[xa]=item;
            if(ret == null) { // Skip next line (already processed)
                lines[++xa] = {};
            }
        }
        var roots=[];
        for(var xa=0; xa<lines.length; xa++) {
            var ll=lines[xa];
            if(ll.blocks > minSize) {
                var mo=ll.mountedOn;
                if(mo.indexOf('/dev') == 0) { continue; }
                if(mo.indexOf('/mnt/') == 0) { continue; }
                if(mo.indexOf('/cache') == 0) { continue; }
                if(mo.indexOf('/system') == 0) { continue; }
                if(mo.indexOf('/Android/data/') > -1) { continue; }
                roots.push(ll);
            }
        }
        roots.sort(function(a, b) {
            if(a.available > b.available) { return -1; }
            if(a.available < b.available) { return  1; }
            return 0;
        });
        gotRoots(roots);
    }, function(errmsg) {
        // alert('Error: '+errmsg); // Uncomment if alert desired
    });
}
 
function parseDfLine(headOfs, line, item, nextLine) {
    if(line.indexOf(' ') > -1) {
        if(item.filesystem == null) { item.filesystem=line.substring(0,headOfs.blocks); }
        item.blocks=parseInt(line.substring(headOfs.blocks, headOfs.used));
        item.used=parseInt(line.substring(headOfs.used, headOfs.available));
        item.available=parseInt(line.substring(headOfs.available, headOfs.usepct));
        item.usepct=parseInt(line.substring(headOfs.usepct, headOfs.mountedOn));
        item.mountedOn=line.substring(headOfs.mountedOn);
    }
    else {
        item.filesystem=line;
        parseDfLine(headOfs, nextLine, item, null);
        return null;
    }
    return item;
}
 
//////////////////////////////////////////////////////////
sample_code/sys_out.1447299895.txt.gz · Last modified: 2015/11/12 11:44 (external edit)