[Java for Android App Development] MidnightJava:
Sure. Here's the class that manages starting, stopping, and statusing (running or not) the binary executable. In this case, it's the omniNames service of the omni ORB (CORBA broker).

public class RHManager {

private TimerTask task = new TimerTask() {

@Override
public void run() {
if (RHManager.this.listener != null) {
listener.running(isOmniNamesRunning());
}
}

};

private IStatusListener listener;

public RHManager() {

}

public void startOmniNames() {
final Exec exec = new Exec();
final String[] args = new String[]
{RhMgrConstants.INSTALL_LOCATION_OMNI_NAMES_SCRIPTS + "/" + RhMgrConstants.OMNI_NAMES_SCRIPT_FILE,
"start"};
final String[] env = new String[] {"LD_LIBRARY_PATH=/sdcard/data/com.axiosengineering.rhmanager/omniORB/lib"};
Thread t = new Thread() {
public void run() {
try {
int res = exec.doExec(args, env);
logMsg("omniNames start return code " + res);
} catch (IOException e) {
logMsg("Failed to start omniNames");
e.printStackTrace();
}
String std = exec.getOutResult();
logMsg("omniNames start: std out==> " + std );
String err = exec.getErrResult();
logMsg("omniNames start: err out==> " + err );
};
};
t.start();
logMsg("omniNames started");

}

private boolean isOmniNamesRunning() {
String pid_s = getOmniNamesPid();
Integer pid = null;
if (pid_s != null) {
try {
pid = Integer.parseInt(pid_s);
} catch (NumberFormatException e) {
return false;
}
}

if (pid != null) {
RunningAppProcessInfo activityMgr = new ActivityManager.RunningAppProcessInfo("omniNames", pid, null);
return activityMgr.processName != null ;
}
return false;
}

public void stopOmniNames() {
String pid = getOmniNamesPid();
android.os.Process.killProcess(Integer.parseInt(pid));
android.os.Process.sendSignal(Integer.parseInt(pid), android.os.Process.SIGNAL_KILL);
}

private String getOmniNamesPid() {
Exec exec = new Exec();
final String[] args = new String[]
{RhMgrConstants.INSTALL_LOCATION_OMNI_NAMES_SCRIPTS + "/" + RhMgrConstants.OMNI_NAMES_SCRIPT_FILE,
"pid"};
String pid = "";
try {
int res = exec.doExec(args, null);
logMsg("oniNames pid return code: " + res);
} catch (IOException e) {
logMsg("Failed to start omniNames");
e.printStackTrace();
return pid;
}
String std = exec.getOutResult();
logMsg("omniNames pid: std out ==> " + std);
String err = exec.getErrResult();
logMsg("omniNames pid: err out ==> " + err);

String[] parts = std.split("\\s+");
if (parts.length >= 2) {
pid = parts[1];
}
return pid;
}

//monitor omniNames status and report status periodically to an IStatusListener
public void startMonitorProcess(IStatusListener listener, String string) {
this.listener = listener;
Timer t = new Timer();
t.schedule(task, 0, 1000);
}

private void logMsg(String msg) {
if (RhMgrConstants.DEBUG) {
System.err.println(msg);
}
}

}

Here's the Exec class that handles invocation of Runtime#exec(), consumes std and err out, and reports those and process return status to the caller.

public class Exec {

private String outResult;
private String errResult;
private Process process;
private boolean failed = false;
StreamReader outReader;
StreamReader errReader;

public int doExec(String[] cmd, String[] envp) throws IOException{
Timer t = null;
try {
process = Runtime.getRuntime().exec(cmd, envp);
outReader = new StreamReader(process.getInputStream());
outReader.setPriority(10);
errReader = new StreamReader(process.getErrorStream());
outReader.start();
errReader.start();
t = new Timer();
t.schedule(task, 10000);
int status = process.waitFor();
outReader.join();
errReader.join();
StringWriter outWriter = outReader.getResult();
outResult = outWriter.toString();
outWriter.close();
StringWriter errWriter = errReader.getResult();
errResult = errWriter.toString();
errWriter.close();
return (failed ? -1: status);
} catch (InterruptedException e) {
return -1;
} finally {
if (t != null) {
t.cancel();
}
}
}

public int doExec(String[] cmd) throws IOException{
return doExec(cmd, null);
}

public String getOutResult(){
return outResult;
}

public String getErrResult(){
return errResult;
}

private static class StreamReader extends Thread {
private InputStream is;
private StringWriter sw;

StreamReader(InputStream is) {
this.is = is;
sw = new StringWriter(30000);
}
public void run() {
try {
int c;
while ((c = is.read()) != -1){
sw.write(c);
}
}
catch (IOException e) { ; }
}

StringWriter getResult() {
try {
is.close();
} catch (IOException e) {
System.err.println("Unable to close input stream in StreamReader");
}
return sw;
}
}

private TimerTask task = new TimerTask() {

@Override
public void run() {
failed = true;
process.destroy();
}

};
}

Here's the script that startOminNames() invokes. It's the shell script installed with omniORB with functions other than start and get_pid removed, since those are handled by Android classes. You can invoke any executable in place of the script, or wrap your executable in a script.

#
# omniNames init file for starting up the OMNI Naming service
#
# chkconfig: - 20 80
# description: Starts and stops the OMNI Naming service
#

exec="/sdcard/data/com.axiosengineering.rhmanager/omniORB/bin/omniNames"
prog="omniNames"
logdir="/sdcard/data/com.axiosengineering.rhmanager/omniORB/logs"
logfile="/sdcard/data/com.axiosengineering.rhmanager/omniORB/logs/omninames-localhost.err.log"
options=" -start -always -logdir $logdir -errlog $logfile"

start() {
#[ -x $exec ] || exit 5
echo -n $"Starting $prog: "
$exec $options
}

get_pid() {
ps | grep omniNames
}

case "$1" in
start)
start && exit 0
$1
;;
pid)
get_pid
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?

And here's the IStatusListener interface

public interface IStatusListener {

public void running(boolean running);

}

Runtime.exec() has some pitfalls. See this helpful Runtime.exec tutorial for a nice explanation.

And you may also want to check out this post on loading native binaries in Android.