Archive for Android

Running native code in Android

As everyone probably knows by now, Doom has been ported to Android.

This is exciting for two reasons,

  1. It’s Doom!
  2. It’s actually native code running with a Dalvik frontend.

Now, Dalvik doesn’t have JNI, so how can you write something in C and run it?

This guy will lead you down a link-clicking rabbit hole that’ll tell you how. The important parts are the compiler (Choose ARM GNU/Linux and IA32 GNU/Linux), and the technique of running system commands from Dalvik, which is detailed on Gimite’s page.

One note, he links to a dynamic link method of getting everything to work, which doesn’t seem to be strictly necessary. I just compiled this:

#include <stdio.h>

int main (int argc, char** argv) {
	printf("Hello world!\n");
	return 0;
}
and it wrote to stdio just fine. The other important part is getting the native code to actually run. You can put your binaries in your assets directory, but I'm thinking that the directory is within the .apk your app gets bundled into, and I don't think can even run anything from there. I wound up copying the binaries from the assets directory to /data/data/com.joshsera (where com.joshsera is replaced by your package name), chmodding it, and running it.
File newHello = new File("/data/data/com.joshsera/hello");
try {
	newHello.createNewFile();
	BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(newHello));
	BufferedInputStream in = new BufferedInputStream(this.getAssets().open("hello"));
	int b;
	while ((b = in.read()) != -1) {
		out.write(b);
	}
	//
	out.flush();
	out.close();
	in.close();
	// chmod?
	this.doCommand("/system/bin/chmod", "777", "/data/data/com.joshsera/hello");
} catch (IOException ex) {

}
doCommand is where I stuck the code to run system commands.
public void doCommand(String command, String arg0, String arg1) {
	try {
		// android.os.Exec is not included in android.jar so we need to use reflection.
		Class execClass = Class.forName("android.os.Exec");
		Method createSubprocess = execClass.getMethod("createSubprocess",
		String.class, String.class, String.class, int[].class);
		Method waitFor = execClass.getMethod("waitFor", int.class);
		
		// Executes the command.
		// NOTE: createSubprocess() is asynchronous.
		int[] pid = new int[1];
		FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(
		null, command, arg0, arg1, pid);
		
		// Reads stdout.
		// NOTE: You can write to stdin of the command using new FileOutputStream(fd).
		FileInputStream in = new FileInputStream(fd);
		BufferedReader reader = new BufferedReader(new InputStreamReader(in));
		String output = "";
		try {
			String line;
			while ((line = reader.readLine()) != null) {
				output += line + "\n";
			}
		} catch (IOException e) {
			// It seems IOException is thrown when it reaches EOF.
		}
		
		// Waits for the command to finish.
		waitFor.invoke(null, pid[0]);
		
		// send output to the textbox
		this.addText(output);
	} catch (ClassNotFoundException e) {
		throw new RuntimeException(e.getMessage());
	} catch (SecurityException e) {
		throw new RuntimeException(e.getMessage());
	} catch (NoSuchMethodException e) {
		throw new RuntimeException(e.getMessage());
	} catch (IllegalArgumentException e) {
		throw new RuntimeException(e.getMessage());
	} catch (IllegalAccessException e) {
		throw new RuntimeException(e.getMessage());
	} catch (InvocationTargetException e) {
		throw new RuntimeException(e.getMessage());
	}
}

Anyway, this has a few issues:

  1. The newly created file is out of control of the install/uninstall process. When the user uninstalls your applicaton, the binaries you’ve copied will remain where they are, taking up space. This is bad. What I’m doing, is copying the file over in the onCreate method, then rm-ing it in the onDestroy method. This adds to the startup time as you’re copying files around whenever you start up, but at least it’s clean.
  2. If Android goes to a machine with a different processor, your app probably won’t work. At the moment, this isn’t a big deal, but there’s rumors of Android being installed on netbooks, so this could become a problem later.

Leave a Comment

Filtering out accelerometer noise

At one point, I thought about using the accelerometer and compass in the G1 to turn the phone into a gyromouse/Wiimote style thing. After playing around with the accelerometer and compass, I decided that they were a bit too noisy to do that easily, so I shelved it because of time constraints.

Well, googling around today, I found this article on Kalman filtering, which might help me to cut down on some of that noise.

Kalman Filtering

Maybe, if I can get that working, Wiimote-style pointing could find it’s way into RemoteDroid sometime in the future.

Comments (6)

Updating UI items from multiple threads

So I recently found out that only one thread is ever allowed to update things like ImageViews and whatnot. If you try to make another thread update them, everything breaks, and all of a sudden, that ImageView never ever updates again. This was causing trouble in RemoteDroid because I wanted the tap to click to update the on-screen button state, but the tap events had to come from a Timer object, which put everything in a different thread.

Anyway, if you need to make a graphical change from another thread, the solution is to use the Handler class. The you use it is by creating a handler in your UI thread, then create some Runnable objects that call all your graphics methods. Here’s an example:

public class Thing extends Activity {
	private Handler = new Handler();
	// runnables for updating state
	private runnable buttonOn = new Runnable() {
		private void run() {
			drawImageOn();
		}
	};
	private runnable buttonOff = new Runnable() {
		private void run() {
			drawImageOff();
		}
	};
	// our ImageView
	private ImageView iv;
	// a Timer object, which creates another thread for doing something else
	private Timer timer = new Timer();

	public void onCreate(Bundle savedInstanceState) {
		// set ref to ImageView
		this.iv = (ImageView)this.findViewById(R.id.whatever);
		//
		this.handler.post(this.buttonOn);
		// Let's start up another thread for whatever reason
		this.timer.scheduleAtFixedRate(new TimerTask() {
			public void run() {
				// If we tried to call drawImageOff() here directly, something would break.
				handler.post(buttonOff);
			}
		}, 0, 500);
	}
	
	// drawing methods
	
	public void drawImageOn() {
		// draw in our ImageView here
		...
	}
	
	public void drawImageOff() {
		// draw in our ImageView here
		...
	}
}

So basically, you’re setting up a few Runnables for changing graphical state, and then making every thread use the Handler for changing between those states.

Leave a Comment