Introduction: Control Keyboard & Mouse W/ Android App Via Arduino

This instructable will show you how to control your computer's keyboard and mouse with an Android app via bluetooth to an Arduino.



BACKGROUND
Ever wanted to control your computer's mouse/keyboard functionality without having to actually sit in front of it? I do all the time. For instance, I often hook my laptop up to the TV in my living room to watch a show on Netflix. Well, roughly 20 minutes later, when the show is finished I have to get up, walk over to the laptop, click next episode, let it buffer for several seconds, click full screen mode, then walk back to the couch. This becomes a hassle when watching multiple episodes back-to-back... for several hours... burning through an entire season in one sitting. Okay, so maybe I'm just lazy and this doesn't exactly apply to you but this has been bugging me for awhile and that's what us makers do, we engineer solutions to our problems. (Regardless of how oddly specific those problems may be.)

I'm sure many of you will find other uses for this project, like a custom video game controller with buttons that send specific keystrokes from your phone... Or perhaps something more practical. Either way, here's how you build it....

Before we start, familiarize yourself with the diagram describing the flow of communication. (I recommend clicking the "i" in the upper-left corner, then clicking the link to the original file, in order to view full size)

Step 1: Materials | Hardware and Software

Now that you understand how it works, let's get your materials ready....

HARDWARE
- 1 x Arduino board (I'm using an Arduino UNO: http://arduino.cc/en/Main/arduinoBoardUno)
- 1 x Android device (I'm using a Droid 2)
- 1 x Bluetooth stick (I'm using BlueSMiRF Gold: http://www.sparkfun.com/products/10268)
- 2 x USB cable (A to B to program Arduino; A to Micro-B to program Droid 2)
- 1 x computer

SOFTWARE
- Arduino IDE (to program your Arduino board: http://arduino.cc/en/Main/Software)
- Eclipse IDE (to write the Android app: http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/heliossr2)
- Android SDK/ADT Plug-in for Eclipse (http://developer.android.com/sdk/index.html)
- Processing IDE (to control your computer's keyboard/mouse at runtime: http://processing.org/download/)
- Amarino and MeetAndroid Arduino library (to assist bluetooth communcation from Android to Arduino: http://www.amarino-toolkit.net/index.php/docs.html)

Step 2: Installing the Software

I'm not going to reinvent the wheel for installation guides. The links below are provided directly from the source.

Installing Arduino: http://arduino.cc/en/Guide/HomePage
Installing Processing: http://processing.org/learning/gettingstarted/
Installing Android SDK: http://developer.android.com/sdk/installing.html
Installing ADT Plugin for Eclipse: http://developer.android.com/sdk/eclipse-adt.html#installing

Never wrote a simple Android app before? I recommend becoming familiar with the environment first by following this following instructable: https://www.instructables.com/id/How-to-Write-a-Hello-World-app-for-Android/

Step 3: Wiring and Pairing the BlueSMiRF

Hook up the BlueSMiRF Gold to your Arduino, directly or to a breadboard.

(From BlueSMIRF to Arduino...)
- Wire VCC to 5V.
- Wire GND to GND.
- Wire TX-0 to Digital pin 1 (RX).
- Wire RX-1 to Digital pin 2 (TX).

Once wired, hook up your Arduino to an external power source so we can set the baud rate. By external power source, I mean other than your computer. I was fortunate to have a USB wall charger adapter that came with my phone. Or there's a power jack mounted on the board. Or hook up a 9V battery: with a battery clip, wire positive to "Vin" on the Arduino and negative to ground (GND) on the Arduino.

Once powered externally, you should see a blinking red LED on your BlueSMiRF. (This means it is powered but not yet connected to another bluetooth device.)


Pair your BlueSMiRF device to your computer

On Mac OS X...

1. Open Applications > System Preferences. Click on Bluetooth under "Internet and Wireless".
2. Make sure "On" and "Discoverable" are checked so that BlueSMiRF can find your computer.
3. Click the + sign to setup a new device. This will open Bluetooth Setup Assistant.
4. Bluetooth Setup Assistant will search for bluetooth devices nearby. You should see "FireFly" in the list. This is your BlueSMiRF. Select it and click Continue.
5. On the next screen click Passcode Options. It will pop a dialog box. Choose "Use a specific passcode" and enter 1234. Click OK.
Click Continue. You device should now be paired. Click quit.

Step 4: Configuring the BlueSMiRF

Setting the baud rate of the BlueSMiRF

NOTE: The following must be done within the first 60 seconds of restarting the BlueSMiRF. So unplug your Arduino and plug it back in, then follow these steps.

1. Open the Arduino software.
2. In the menu bar, choose Tools > Serial Port > /dev/tty.FireFly-ADFE-SPP (your name may be slightly different).
3. Open the Serial Monitor within the Arduino Software, Tools > Serial Monitor. (Your BlueSMiRF should display a steady green LED.)
4. In the serial monitor, set the drop-downs to "No line ending" and "9600 baud".
5. Type $$$ and click Send (or hit enter).
6. You should immediately see "CMD" in the output area.

If you don't see "CMD", you did not complete steps 3 through 5 within the first 60 seconds of restarting the BlueSMiRF. Close the serial monitor, unplug the Arduino from the external power source, plug it back in and repeat steps 3 through 5.

7. Now that you see "CMD", you can configure the BlueSMiRF. You should see a steady green light along with a blinking red light.
8. Change "No line ending" to "Carriage return".
9. Type "D" (without the quotes) and click Send (or hit enter). You will see current information about your BlueSMiRF. "Baudrt" is the BlueSMiRF's current baud rate.
10. To change the baud rate, type "SU,57" (without the quotes) to change the baud rate to 57600. If the baud rate was changed successfully, you will see "AOK" in the output area; otherwise, you will see "ERR". (To verify, you can send "D" again and see a difference in "Baudrt" value.
11. Lastly, exit the configuration mode by sending "---", which is 3 minus signs (or hyphens) followed by "". You should see "END" in the output area and the BlueSMiRF should display a steady green light only.

Step 5: Bluetooth Communication Via Amarino

Install Amarino on your Android phone

1. The easiest way to install the Amarino app is by scanning this qr code with a qr code scanner app (I use an app called Barcode Scanner). Choose "Open in Browser". In a few moments the .apk file should start downloading.
2. While it's downloading, get a head-start and change your application settings to allow for installation from sources other than the Android Market: Settings > Applications > Check "Unknown Sources" > OK.
3. Open the file once the download is complete. Tap the "Install" button.
4. Once the installation is complete, tap the "Open" button to launch the app.


Installing the MeetAndroid library for Arduino

1. Go to this link: http://www.amarino-toolkit.net/index.php/download.html
2. Click "MeetAndroid - Arduino Library". This will bring you to a page where you can download a ZIP file.
3. Once download, unzip the file. You should now have a "MeetAndroid" folder.
4. Move the "MeetAndroid" folder inside the "libraries" folder inside of your Arduino sketchbook directory.

The resulting path for me looks like this...
/Users/plowdk51/Documents/Arduino/libraries/MeetAndroid

NOTE: If this is your first Arduino library you've installed, you may need to create a folder named "libraries" inside of this directory.

Not sure where your Arduino sketchbook directory is located? Open up Preferences in the Arduino software. You should see the path under Sketchbook location.

5. In order for the changes to show up in Arduino, close the Arduino software and reopen it. To verify that it installed successfully, to Sketch > Import Library and check that "MeetAndroid" is in the list.


Test communication from Amarino to Arduino

To avoid reinventing the wheel, visit this link and follow these instructions...
http://www.amarino-toolkit.net/index.php/getting-started.html

You'll quickly see why the past few steps (change the baud rate and install the MeetAndroid library) were required for me to describe since it states: "This quick start guide assumes that you have installed Amarino on your phone and you have added the MeetAndroid library to your Arduino working environment and your Bluetooth module is set to 57600 [...]" at the beginning of the article.

Step 6: The Arduino Sketch

Modify the BlueSMiRF wiring to the Arduino

You'll need to change the wiring of the BlueSMiRF to the Arduino very slightly. Currently, TX on the BlueSMiRF is wired to RX on the Arduino and RX on the BlueSMiRF is wired to TX on the Arduino. This was necessary in order to set the baud rate of the BlueSMiRF. Now that you're writing the actual Arduino sketch, wire TX on the BlueSMiRF to Digital Pin 2 on the Arduino. Then wire RX on the BlueSMiRF to Digital Pin 3 on the Arduino.

How will the BlueSMiRF still work if it's not plugged into RX and TX on the Arduino? The SoftwareSerial library (included in Arduino 1.0) allows you to run another serial device through the digital pins, which enables you to use the default functionality of the on board USB port.


The Arduino code

The role of the Arduino program is to listen to commands sent from the Android app over Bluetooth, interpret those commands, and pass it over the serial port to the Processing program, which controls the keyboard and mouse.

Upload the following code to your Arduino board:


#include <SoftwareSerial.h>
#include <MeetAndroid.h>

// TX = digital pin 2, RX = digital pin 3
SoftwareSerial portOne(2, 3);
MeetAndroid meetAndroid;

void setup()
{
  // Start the hardware serial port
  Serial.begin(57600);
  // Start the software serial port
  portOne.begin(57600);
  portOne.listen();
  // sync with android app
  meetAndroid.registerFunction(stringValue, '^'); // keyboard
  meetAndroid.registerFunction(stringValue, '`'); // backspace
  meetAndroid.registerFunction(stringValue, '~'); // mouse
}

void loop()
{
  // while there is data coming in...
  while (portOne.available() > 0) {
    // read value of character
    char c = portOne.read();
    // write value to serial port
    Serial.write(c);
  }
}

void stringValue(byte flag, byte numOfValues){}

Step 7: The Android App

For the next step, I'm going to assume that you are comfortable with writing an Android app. If not, please revisit the links the Step 2. The source code is below.

NOTES:
* Be sure to change the value of DEVICE_ADDRESS. This can be found on the sticker on your BlueSMiRF. It can also be found while setting the baud rate in Step 4 (#9). It's the string of letters and numbers after "BTA", which is one value above "BAUDRT".
* Be sure to change the package name (first line of MyRemote.java) to match your project's directory structure

MyRemote.java

package edu.mit.media.amarino.myremote;

import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import at.abraxas.amarino.Amarino;

public class MyRemote extends Activity {

//public TextView result;
public int a, b;
public EditText inputField;

/* change the address to the address of your Bluetooth module
  * and ensure your device is added to Amarino */
private static final String DEVICE_ADDRESS = "00:06:66:07:AD:FE";

final int DELAY = 150;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

  Amarino.connect(this, DEVICE_ADDRESS);
 
        final Button lClick = (Button) findViewById(R.id.leftClick);
        lClick.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Perform action on click
             onLeftClick();
            }
        });
        final Button rClick = (Button) findViewById(R.id.rightClick);
        rClick.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Perform action on click
             onRightClick();
            }
        });
        final Button plus = (Button) findViewById(R.id.plusBtn);
        plus.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Perform action on click
             onPlus();
            }
        });
        final Button minus = (Button) findViewById(R.id.minusBtn);
        minus.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Perform action on click
             onMinus();
            }
        });
       
        inputField = (EditText)findViewById(R.id.input);

        TextWatcher fieldValidatorTextWatcher = new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
             String str = inputField.getText().toString();
             int len = str.length();
             char c;
            
             // backspaced
             if(len <= start){
              onDelete();
             }
             // Swyped
             else if(len > (start+1)){
              String temp = "";
              for(int i = start; i < len; i++){
               c = str.charAt(i);
                  temp += Character.toString(c);
              }
              onSend(temp);
             }
             // typed normally
             else{
              c = str.charAt(len-1);
              str = Character.toString(c);
              onSend(str);
             }
            }

   @Override
   public void afterTextChanged(Editable arg0) {
   }
        };
        inputField.addTextChangedListener(fieldValidatorTextWatcher);

    }
   
@Override
protected void onStart() {
  super.onStart();
}

@Override
protected void onStop() {
  super.onStop();
  // stop Amarino's background service, we don't need it any more
  Amarino.disconnect(this, DEVICE_ADDRESS);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
     int x = (int)event.getX();
     int y = (int)event.getY();
     int diffX;
     int diffY;
     boolean isUp, isDown, isLeft, isRight;
     switch (event.getAction()) {
         case MotionEvent.ACTION_DOWN:
          a = x;
          b = y;
          break;
         case MotionEvent.ACTION_MOVE:
          // determine left or right
          if(a > x){
           isLeft = true;
           isRight = false;
          }else {
           isRight = true;
           isLeft = false;
          }
          // determine up or down
          if(b > y){
           isUp = true;
           isDown = false;
          }else{
           isDown = true;
           isUp = false;
          }
          // calculate difference
          diffX = a - x;
          if(diffX < 0) diffX *= -1;
          diffY = b - y;
          if(diffY < 0) diffY *= -1;
          // determine larger difference
          if(isLeft && isUp){
           if(diffX > diffY) onLeft();
           else onUp();
          }
          else if(isLeft && isDown){
           if(diffX > diffY) onLeft();
           else onDown();
          }
          else if(isRight && isDown){
           if(diffX > diffY) onRight();
           else onDown();
          }
          else if(isRight && isUp){
           if(diffX > diffY) onRight();
           else onUp();
          }
        
          break;
         case MotionEvent.ACTION_UP:
          break;
     }
     return false;
}

private void onUp() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "U");
}
private void onLeft() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "L");
}
private void onRight() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "R");
}
private void onDown() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "D");
}
private void onLeftClick() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "Z");
}
private void onRightClick() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "X");
}
private void onPlus() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "P");
}
private void onMinus() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "M");
}

private void onSend(String str) {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '^', str);
}
private void onDelete() {
  Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '`', 'B');
}
}

===============================

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
   
<LinearLayout android:layout_width="400px" android:layout_height="100px" android:layout_gravity="center_horizontal"
  android:layout_marginTop="20px">
    
     <Button android:id="@+id/leftClick"
   android:text="@string/clickLeft" android:textSize="32px"
   android:layout_width="200px" android:layout_height="100px"></Button>
  
  <Button android:id="@+id/rightClick"
   android:text="@string/clickRight" android:textSize="32px"
   android:layout_width="200px" android:layout_height="100px"></Button>
  
</LinearLayout>

<LinearLayout android:layout_width="200px" android:layout_height="100px" android:layout_gravity="center_horizontal"
  android:layout_marginTop="20px">

  <Button android:id="@+id/minusBtn"
      android:text="@string/minus" android:textSize="48px"
      android:layout_width="100px" android:layout_height="100px"></Button>
     
  <Button android:id="@+id/plusBtn"
   android:text="@string/plus" android:textSize="48px"
   android:layout_width="100px" android:layout_height="100px"></Button>
    
    </LinearLayout>
   
    <LinearLayout android:layout_width="450px" android:layout_height="100px" android:layout_gravity="center_horizontal"
     android:layout_marginTop="20px">
    
     <EditText android:id="@+id/input" android:textSize="32px"
      android:layout_width="fill_parent" android:layout_height="100px" />
     
    </LinearLayout>
   
</LinearLayout>

===============================

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">MyRemote</string>
    <string name="clickLeft">Left Click</string>
    <string name="clickRight">Right Click</string>
    <string name="plus">+</string>
    <string name="minus">–</string>
    <string name="send">Send</string>
</resources>


===============================


I'd like to say a word about the several functions at the bottom of "MyRemote.java". They call the same method with similar parameters:
Amarino.sendDataToArduino(this, DEVICE_ADDRESS, '~', "Z");

This method does the actual commucation with the BlueSMiRF wired to the Arduino. It knows what device to send it to by the DEVICE_ADDRESS variable, which is the unique identifier for the BlueSMiRF. Pretty straight forward. But the next to parameters may need a little more explanation, the ~ and the Z. The 3rd parameter (~) tells the Processing sketch, which we'll write in the next step, what mode we're in:
~ = mouse movement, mouse click, and mouse sensitivity
^ = keyboard input
` = backspace

I chose those random characters purposefully for a couple reasons. Mainly, I needed a few reserved characters to denote the "mode" so I chose those characters that I would never use while running this project. This may seem confusing, but hopefully this will clear it up: The fourth parameter ("Z" in the above snippet) can do one thing if send it with a ~  or it can do something entirely different if I send it with a ^. This grows the possibilities exponentially.

Note the use of these characters on the next step, our Processing sketch.

Step 8: The Processing Sketch

The role of the Processing sketch is to receive characters sent from the Arduino (via USB) and act accordingly. For instance, when it receives the letter 'L' (under the ~ flag, which I designated for mouse mode), it moves the computer mouse cursor to the [L]eft by a certain number of pixels. You're able to control the computer's keyboard and mouse functionality in Processing by utilizing Java's Robot class.

NOTES:
* In the setup() function, be sure to change "[0]" in the line "myPort = new Serial(this, Serial.list()[0], 57600);" to the appropriate number, meaning which ever serial/USB port you have the Arduino plugged into. In order to determine that number, run the processing sketch once and you'll see a list of the your serial ports in the output panel. Change the code to reflect your choice.


The source code:

import processing.serial.*;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.event.InputEvent;

Serial myPort;
char in = '0';
Robot robot;
int x = 720;
int y = 450;
int amt = 10;
boolean isBackspace = false;
boolean isKeyboard = false;
boolean isMouse = false;

void setup()
{
  try {
    robot = new Robot();
  } catch (AWTException e) {
    e.printStackTrace();
  }
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 57600);
}


void draw()
{
 
  robot.setAutoDelay(40);
  robot.setAutoWaitForIdle(true);
 
  if(myPort.available() > 0)
  {
   
    in = myPort.readChar();

    // determine keyboard or mouse
    if(in == '`')
    {
      isBackspace = true;
      isKeyboard = false;
      isMouse = false;
    }
    else if(in == '^')
    {
      isKeyboard = true;
      isBackspace = false;
      isMouse = false;
    }
    else if(in == '~'){
      isMouse = true;
      isBackspace = false;
      isKeyboard = false;
    }
   
    // act as backspace
    if(isBackspace)
    {
      if(in == 'B') type(KeyEvent.VK_BACK_SPACE);
    }
    // act as keyboard
    else if(isKeyboard)
    {
      switch(in)
      {
        case 'A':
          typeCaps(KeyEvent.VK_A);
          break;
        case 'B':
          typeCaps(KeyEvent.VK_B);
          break;
        case 'C':
          typeCaps(KeyEvent.VK_C);
          break;
        case 'D':
          typeCaps(KeyEvent.VK_D);
          break;
        case 'E':
          typeCaps(KeyEvent.VK_E);
          break;
        case 'F':
          typeCaps(KeyEvent.VK_F);
          break;
        case 'G':
          typeCaps(KeyEvent.VK_G);
          break;
        case 'H':
          typeCaps(KeyEvent.VK_H);
          break;
        case 'I':
          typeCaps(KeyEvent.VK_I);
          break;
        case 'J':
          typeCaps(KeyEvent.VK_J);
          break;
        case 'K':
          typeCaps(KeyEvent.VK_K);
          break;
        case 'L':
          typeCaps(KeyEvent.VK_L);
          break;
        case 'M':
          typeCaps(KeyEvent.VK_M);
          break;
        case 'N':
          typeCaps(KeyEvent.VK_N);
          break;
        case 'O':
          typeCaps(KeyEvent.VK_O);
          break;
        case 'P':
          typeCaps(KeyEvent.VK_P);
          break;
        case 'Q':
          typeCaps(KeyEvent.VK_Q);
          break;
        case 'R':
          typeCaps(KeyEvent.VK_R);
          break;
        case 'S':
          typeCaps(KeyEvent.VK_S);
          break;
        case 'T':
          typeCaps(KeyEvent.VK_T);
          break;
        case 'U':
          typeCaps(KeyEvent.VK_U);
          break;
        case 'V':
          typeCaps(KeyEvent.VK_V);
          break;
        case 'W':
          typeCaps(KeyEvent.VK_W);
          break;
        case 'X':
          typeCaps(KeyEvent.VK_X);
          break;
        case 'Y':
          typeCaps(KeyEvent.VK_Y);
          break;
        case 'Z':
          typeCaps(KeyEvent.VK_Z);
          break;
        case 'a':
          type(KeyEvent.VK_A);
          break;
        case 'b':
          type(KeyEvent.VK_B);
          break;
        case 'c':
          type(KeyEvent.VK_C);
          break;
        case 'd':
          type(KeyEvent.VK_D);
          break;
        case 'e':
          type(KeyEvent.VK_E);
          break;
        case 'f':
          type(KeyEvent.VK_F);
          break;
        case 'g':
          type(KeyEvent.VK_G);
          break;
        case 'h':
          type(KeyEvent.VK_H);
          break;
        case 'i':
          type(KeyEvent.VK_I);
          break;
        case 'j':
          type(KeyEvent.VK_J);
          break;
        case 'k':
          type(KeyEvent.VK_K);
          break;
        case 'l':
          type(KeyEvent.VK_L);
          break;
        case 'm':
          type(KeyEvent.VK_M);
          break;
        case 'n':
          type(KeyEvent.VK_N);
          break;
        case 'o':
          type(KeyEvent.VK_O);
          break;
        case 'p':
          type(KeyEvent.VK_P);
          break;
        case 'q':
          type(KeyEvent.VK_Q);
          break;
        case 'r':
          type(KeyEvent.VK_R);
          break;
        case 's':
          type(KeyEvent.VK_S);
          break;
        case 't':
          type(KeyEvent.VK_T);
          break;
        case 'u':
          type(KeyEvent.VK_U);
          break;
        case 'v':
          type(KeyEvent.VK_V);
          break;
        case 'w':
          type(KeyEvent.VK_W);
          break;
        case 'x':
          type(KeyEvent.VK_X);
          break;
        case 'y':
          type(KeyEvent.VK_Y);
          break;
        case 'z':
          type(KeyEvent.VK_Z);
          break;
        case '0':
          type(KeyEvent.VK_0);
          break;
        case '1':
          type(KeyEvent.VK_1);
          break;
        case '2':
          type(KeyEvent.VK_2);
          break;
        case '3':
          type(KeyEvent.VK_3);
          break;
        case '4':
          type(KeyEvent.VK_4);
          break;
        case '5':
          type(KeyEvent.VK_5);
          break;
        case '6':
          type(KeyEvent.VK_6);
          break;
        case '7':
          type(KeyEvent.VK_7);
          break;
        case '8':
          type(KeyEvent.VK_8);
          break;
        case '9':
          type(KeyEvent.VK_9);
          break;
        case ' ':
          type(KeyEvent.VK_SPACE);
          break;
        case '\n':
          type(KeyEvent.VK_ENTER);
          break;
        case '.':
          type(KeyEvent.VK_PERIOD);
          break;
        case ',':
          type(KeyEvent.VK_COMMA);
          break;
        case '/':
          type(KeyEvent.VK_SLASH);
          break;
        case ';':
          type(KeyEvent.VK_SEMICOLON);
          break;
        case '=':
          type(KeyEvent.VK_EQUALS);
          break;
        case '-':
          type(KeyEvent.VK_MINUS);
          break;
         
        default:
          break;
      }
    }
    // act as a mouse
    else if(isMouse)
    {
      switch(in)
      {
        case 'Z':
          robot.mousePress(InputEvent.BUTTON1_MASK);
          delay(100);
          robot.mouseRelease(InputEvent.BUTTON1_MASK);
          break;
        case 'X':
          robot.mousePress(InputEvent.BUTTON3_MASK);
          delay(100);
          robot.mouseRelease(InputEvent.BUTTON3_MASK);
          break;
        case 'U':
          if(y > 0) y -= amt;
          robot.mouseMove(x, y);
          break;
        case 'D':
          if(y < 900) y += amt;
          robot.mouseMove(x, y);
          break;
        case 'L':
          if(x > 0) x -= amt;
          robot.mouseMove(x, y);
          break;
        case 'R':
          if(x < 1440) x += amt;
          robot.mouseMove(x, y);
          break;
        case 'P':
          if(amt < 500) amt += 5;
          break;
        case 'M':
          if(amt > 5) amt -= 5;
          else if(amt > 1) amt -= 1;
          break;
       
        default:
          break;
      }
    }
  }
}

void type(int k)
{
  robot.keyPress(k);
  robot.keyRelease(k);
}
void typeCaps(int k)
{
  robot.keyPress(KeyEvent.VK_SHIFT);
  robot.keyPress(k);
  robot.keyRelease(k);
  robot.keyRelease(KeyEvent.VK_SHIFT);
}

Step 9: Give It a Whirl!

Now that you have everything set...
1. Plug the Arduino into your computer.
2. Run the Processing sketch.
3. Open your Android app and wait for it connect to the BlueSMiRF.
4. Control your computer remotely!

Step 10: BONUS

As you all know, it can be even more fun to take what you've learned expand upon it. So now that you're able to communicate actions from an Android app to the Arduino over Bluetooth, you can know control anything that be connected to an Arduino. For instance, I simply added a few lines of code (to the Arduino code I provided earlier in Step 6) so that I could control a servo motor (Robots!).


Bonus code:

#include <SoftwareSerial.h>
#include <MeetAndroid.h>
#include <Servo.h>

Servo myServo;
int pos = 0;

// TX = digital pin 2, RX = digital pin 3
SoftwareSerial portOne(2, 3);
MeetAndroid meetAndroid;

void setup()
{
  Serial.begin(57600);
  myServo.attach(9);
  // Start the software serial port
  portOne.begin(57600);
  portOne.listen();
  // sync with android app
  meetAndroid.registerFunction(stringValue, '^'); // keyboard
  meetAndroid.registerFunction(stringValue, '`'); // backspace
  meetAndroid.registerFunction(stringValue, '~'); // mouse
}

void loop()
{
  // while there is data coming in...
  while (portOne.available() > 0) {
    // read value of character
    char c = portOne.read();
    Serial.print(c);
    Serial.println();
    if(c == 'L' && pos > 0){
      pos -= 10;
      myServo.write(pos);
    }
    else if(c == 'R' && pos < 180){
      pos += 10;
      myServo.write(pos);
    }
  }
}

void stringValue(byte flag, byte numOfValues){}

======================================

* Just to clarify, this doesn't require the Processing sketch.