Robots! Part 2, the android client

Continuing on from my previous post, I’ve created an android client that I can use to send commands to my python server.

Ultimately I want to be able to control the robot remotely, the best way to do this would be to control the robot from a tablet or a phone which communicates wirelessly with the pi via bluetooth or wifi. In my previous post I described setting up a python application that will run on the raspberry pi and listen for commands. All I needed to do was to create a very basic android interface that can send commands to the raspberry pi.

The robot I intend to build will be based on tracks instead of wheels, there are many benefits to this but the most significant is that from an engineering perspective is that its much easier to build. A car needs forward and backwards drive, but also sideways drive for the front axle. In my opinion, it is far simpler to have a tracked vehicle with a motor controlling each side. When both motors are turned in the same direction the vehicle moves forward or backwards, and when the motors run in opposite directions the vehicle will turn on the spot.

My app interface mimics the layout of the vehicle itself, with an up and down button on the left and right hand side of the screen, as shown below.

Arrow buttons for controlling robots tracks
Arrow buttons for controlling robots tracks

You can see the code for this layout on the github repo here.

I want the user to be able to hold a button and the motor will run until they take their finger off. For this I’ve attached listeners on the buttons that will listen for the key up and key down events. It will send separate events for starting and stopping the motors, like so:

        Button leftForward = (Button) findViewById(R.id.leftForward);

        leftForward.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_DOWN: {
                        sendCommand(leftForwardCommand + "-Start");
                        break;
                    }
                    case MotionEvent.ACTION_UP: {
                        sendCommand(leftForwardCommand + "-Stop");
                        break;
                    }
                }
                return false;
            }
        });

As the sendCommand needs send a message over the network, I need to take this off the main UI thread otherwise I’d get an exception such as:

android.os.NetworkOnMainThreadException

To take this off the UI thread, I simply move the sending of the command into an AsyncTask, like so:

private void sendCommand(String command) {
        new SendCommandTask().execute(command);
    }

    class SendCommandTask extends AsyncTask<String, Void, Void> {

        @Override
        protected Void doInBackground(String... commands) {
            String command = commands[0];
            try {
                //TODO: make this configurable inside the app
                Socket socket = new Socket("192.168.0.6", 3033);
                PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                out.println(command);

                Log.d(TAG, "Successfully sent " + command);
            } catch (IOException ioe) {
                Log.d(TAG, "Unable to send command", ioe);
            }
            return null;
        }
    }

Now if I run the python server and then send press the buttons in the app, I see this output from the python application.

Server listening on port 3033...
...L-FORWARD-Start…..L-FORWARD-Stop….

Thats all for now, you can access this code on my github repository. Next post will either be in relation to building the robot, or using the BrickPi APIs.

Extracting out your AsyncTasks into separate classes makes your code cleaner

If you’re an android developer, chances are you’ve used an Async task more than once. As your apps develop, grow, and become more complex, theres a high chance you’re going to have multiple Async tasks. In an application I’ve recently been developing, I had around 5 Async tasks for a single activity, which made the actual activity quite difficult to read.

Adhering to KIS and DRY, I wanted to devise a mechanism for extracting the logic of these Async tasks out into separate external classes, thus reducing the clutter of inner classes in my activities, and also meaning that I could re-use these Async tasks elsewhere, and also externalising them makes them easier to mock and unit test.

The easiest mechanism I’ve found, is to use generics and provide a callback, which is somewhat similar to the delegate/protocol pattern in iOS programming.

Firstly, create a class with a generic method, like follows :

/**
 * This is a useful callback mechanism so we can abstract our AsyncTasks out into separate, re-usable
 * and testable classes yet still retain a hook back into the calling activity. Basically, it'll make classes
 * cleaner and easier to unit test.
 *
 * @param <T>
 */
public interface AsyncTaskCompleteListener<T>
{
    /**
     * Invoked when the AsyncTask has completed its execution.
     * @param result The resulting object from the AsyncTask.
     */
    public void onTaskComplete(T result);
}

Then, in your activity you can reduce the inner class to just the following :

public class FetchMyDataTaskCompleteListener implements AsyncTaskCompleteListener<MyPojo>
    {

        @Override
        public void onTaskComplete(MyPojo result)
        {
            // do something with the result
        }
    }

This means you can now create a separate class for the task, below is an example. Don’t forget to assign the callback listener in the constructor, so when the onPostExecute() happens you can invoke the callback to the onTaskComplete in your activity:

public class FetchMyDataTask extends AsyncTask<String, Integer, MyPojo>
{
    private static final String TAG = "FetchMyDataTask";

    private Context context;
    private AsyncTaskCompleteListener<MyPojo> listener;

    public FetchVehicleTask(Context ctx, AsyncTaskCompleteListener<MyPojo> listener)
    {
        this.context = ctx;
        this.listener = listener;
    }

    protected void onPreExecute()
    {
        super.onPreExecute();
    }

    @Override
    protected MyPojo doInBackground(String... strings)
    {
        MyPojo myPojo = null;
        // do something with myPojo
        return myPojo;
    }

    @Override
    protected void onPostExecute(MyPojo myPojo)
    {
        super.onPostExecute(myPojo);
        listener.onTaskComplete(myPojo);
    }

All thats left to do, is to now “new up” the async task in your activity and start it. Don’t forget to initialise them with the callback listener, so use this to create the tasks in your activity:

new FetchMyDataTask(this, new FetchMyDataTaskCompleteListener()).execute("InputString");

Thats it, it takes a little while to understand how this fits together, but its an incredibly flexible technique for tidying up your Async tasks, I’ve seen it used in a number of applications.

Thanks!