Arduino ADK Board: How Send Data From The Board To The Android Device

by Miguel on December 31, 2011

in Android,Arduino

In my last post I showed you how to read data from an Android device with the ADK board, int this post I will show you how to the opposite: send data from the Arduino ADK to your Android device.

Android App Interface

Our app’s interface is going to be a text box where we will display the data sent from the Arduino.

application showing textbox field and app name

this is how the app looks when you first open it

File: layout/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"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Data from Arduino board will be displayed here"
    android:id="@+id/arduinoresponse"
    />
</LinearLayout>

We are going to do a little bit more than just display the data, we will also show the date and time of when the data was sent and also a flag that will help you identify the data. The following figure shows our final result.

app showing data received from board and time

The application showing the flag, data from Arduino board, and time

How To Send Data From Board

Sending data from the board to the Android device is done with the use of the write function. The functions needs two arguments: the data array and length of the array. What our Arduino code will do is it will send the numbers 10-0 (decrementing) and 0-10 (incrementing).

In the following code, in the write function, the byte array msg holds the data we are sending to the Android device, the number 1 is the length of this msg array.

File: arduino_file.pde
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>

AndroidAccessory acc("Manufacturer",
		     "Model",
		     "Description",
		     "1.0",
		     "http://yoursite.com",
		     "0000000012345678");
void setup()
{
  Serial.begin(115200);
  acc.powerOn();
}

void loop()
{
  byte msg[1]; // one byte
  int value=10; // value to send,we'll increment and decrement this variable
  if (acc.isConnected()) 
  {
    // is connected
    while(value>0)
    {
      // count down
      msg[0] = value;
      acc.write(msg, 1);
      delay(1000);
      value-=1;
    }
    
    while(value<=10)
    {
      // count up
      msg[0] = value;
      acc.write(msg, 1);
      delay(1000);
      value+=1;
    }
  }
}

Receiving Data From The ADK Board

Before I begin I must confess that the code am about to give you is a heavily trimmed down version of this code. Their code did more than send data to the device but and it’s pretty cool, but I needed a simple example to see how everything worked so I cut down and edited a lot of it.

Like with reading data most of the USB communication code is standard, so I will explain the part you need to really understand. Don’t worry about where the code goes for now, I will give you the full code after the explanation.

What we need is a function that runs indefinitely. That function is called run(), you cannot change the name of this method because it’s an abstract method of Runnable which we are implementing in our activity.

The run function
	public void run() {
		int ret = 0;
		byte[] buffer = new byte[16384];
		int i;

		while (true) { // read data
			try {
				ret = mInputStream.read(buffer);
			} catch (IOException e) {
				break;
			}

			i = 0;
			while (i < ret) {
				int len = ret - i;
				if (len >= 1) {
					Message m = Message.obtain(mHandler);
					int value = (int)buffer[i];
					// &squot;f&squot; is the flag, use for your own logic
					// value is the value from the arduino
					m.obj = new ValueMsg(&squot;f&squot;, value);
					mHandler.sendMessage(m);
				}
				i += 1; // number of bytes sent from arduino
			}

		}
	}

In the code above the mHandler object sends the data from the board to another function where we can access the data. The function is called handleMessage(), and it is where where we update the text box with our Arduino data, flat and date and time.

The handleMessage method
	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			ValueMsg t = (ValueMsg) msg.obj;
			// this is where you handle the data you sent. You get it by calling the getReading() function
			mResponseField.setText("Flag: "+t.getFlag()+"; Reading: "+t.getReading()+"; Date: "+(new Date().toString()));
		}
	};

Now here is the full code with the previous two snippets included.

ArduinoReceiveDataActivity.java
package com.yoursite.arduinoreceivedata;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;


import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.widget.TextView;

import com.android.future.usb.UsbAccessory;
import com.android.future.usb.UsbManager;


public class ArduinoReceiveDataActivity extends Activity implements Runnable {

	private TextView mResponseField;
	private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";
	private UsbManager mUsbManager;
	private PendingIntent mPermissionIntent;
	private boolean mPermissionRequestPending;
	private UsbAccessory mAccessory;
	private ParcelFileDescriptor mFileDescriptor;
	private FileInputStream mInputStream;
	private FileOutputStream mOutputStream;


	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mResponseField = (TextView)findViewById(R.id.arduinoresponse);
		setupAccessory();
	}

	@Override
	public Object onRetainNonConfigurationInstance() {
		if (mAccessory != null) {
			return mAccessory;
		} else {
			return super.onRetainNonConfigurationInstance();
		}
	}

	@Override
	public void onResume() {
		super.onResume();


		if (mInputStream != null && mOutputStream != null) {
			//streams were not null");
			return;
		}
		//streams were null");
		UsbAccessory[] accessories = mUsbManager.getAccessoryList();
		UsbAccessory accessory = (accessories == null ? null : accessories[0]);
		if (accessory != null) {
			if (mUsbManager.hasPermission(accessory)) {
				openAccessory(accessory);
			} else {
				synchronized (mUsbReceiver) {
					if (!mPermissionRequestPending) {
						mUsbManager.requestPermission(accessory, mPermissionIntent);
						mPermissionRequestPending = true;
					}
				}
			}
		} else {
			// null accessory
		}
	}

	@Override
	public void onPause() {
		super.onPause();
	}

	@Override
	public void onDestroy() {
		unregisterReceiver(mUsbReceiver);
		super.onDestroy();
	}

	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			ValueMsg t = (ValueMsg) msg.obj;
			// this is where you handle the data you sent. You get it by calling the getReading() function
			mResponseField.setText("Flag: "+t.getFlag()+"; Reading: "+t.getReading()+"; Date: "+(new Date().toString()));
		}
	};


	private void setupAccessory() {
		mUsbManager = UsbManager.getInstance(this);
		mPermissionIntent =PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
		IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
		filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
		registerReceiver(mUsbReceiver, filter);
		if (getLastNonConfigurationInstance() != null) {
			mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
			openAccessory(mAccessory);
		}
	}

	private void openAccessory(UsbAccessory accessory) {
		mFileDescriptor = mUsbManager.openAccessory(accessory);
		if (mFileDescriptor != null) {
			mAccessory = accessory;
			FileDescriptor fd = mFileDescriptor.getFileDescriptor();
			mInputStream = new FileInputStream(fd);
			mOutputStream = new FileOutputStream(fd);
			Thread thread = new Thread(null, this, "OpenAccessoryTest");
			thread.start();
			//Accessory opened
		} else {
			// failed to open accessory
		}
	}

	private void closeAccessory() {
		try {
			if (mFileDescriptor != null) {
				mFileDescriptor.close();
			}
		} catch (IOException e) {
		} finally {
			mFileDescriptor = null;
			mAccessory = null;
		}
	}


	public void run() {
		int ret = 0;
		byte[] buffer = new byte[16384];
		int i;

		while (true) { // read data
			try {
				ret = mInputStream.read(buffer);
			} catch (IOException e) {
				break;
			}

			i = 0;
			while (i < ret) {
				int len = ret - i;
				if (len >= 1) {
					Message m = Message.obtain(mHandler);
					int value = (int)buffer[i];
					// 'f' is the flag, use for your own logic
					// value is the value from the arduino
					m.obj = new ValueMsg('f', value);
					mHandler.sendMessage(m);
				}
				i += 1; // number of bytes sent from arduino
			}

		}
	}

	private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (ACTION_USB_PERMISSION.equals(action)) {
				synchronized (this) {
					UsbAccessory accessory = UsbManager.getAccessory(intent);
					if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
						openAccessory(accessory);
					} else {
						// USB permission denied
					}
				}
			} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
				UsbAccessory accessory = UsbManager.getAccessory(intent);
				if (accessory != null && accessory.equals(mAccessory)) {
					//accessory detached
					closeAccessory();
				}
			}
		}
	};

}

You also need this Java since it’s what is used to call the handler.

ValueMsg.java
package com.yoursite.arduinoreceivedata;
public class ValueMsg {
	private char flag;
	private int reading;

	public ValueMsg(char flag, int reading) {
		this.flag = flag;
		this.reading = reading;
	}

	public int getReading() {
		return reading;
	}
	
	public char getFlag() {
		return flag;
	}
}

So what cool apps are you going to make?

Related posts:

blog comments powered by Disqus

Previous post:

Next post: