Getting into detail
The Android application is a simple demo that toggles a LED connected to the accessory (the Arduino UNO). The Android code can be found under the java
directory in the source git:
git clone git://github.com/joekickass/Arduino-Uno-Android-Accessory.git
Below I will highlight parts of the code. Most of the information given can be found in the Google Accessory Dev Guide.
AndroidManifest.xml
The are a few important lines to notice:
<intent-filter> <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /> </intent-filter>
Declare that the Activity wants to receive events when an accessory is connected.
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" android:resource="@xml/accessory_filter" />
In order to specify what particular accessory to connect to, an additional resource must be created (see accessory_filter).
<uses-library android:name="com.android.future.usb.accessory" />
Classes that support USB accessory mode where added to the android.hardware.usb namespace in Android 3.1. It was also backported to Android 2.3.4 in the Google APIs add-on library (which you downloaded in Part I) in the com.android.future.usb namespace. This application is written for version 2.3.4 and thus the library needs to be declared in the manifest.
accessory_filter.xml
Also, a resource specifying what resource to connect to is required. Add the following accessory_filter.xml
file to the res/xml/
directory in the Android project:
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-accessory manufacturer="JoeKickass" model="AndroidApkTakeTwo" version="1.0" /> </resources>
The manufacturer, model and version attributes should match the information given to the ADK
class in the Arduino firmware.
ToggleLedActivity
The application opens a connection to the accessory when the ACTION_USB_ACCESSORY_ATTACHED
intent is received. The user can then toggle the LED by pressing the button in the application. Whenever the application is paused, the connection is closed. However, application takes many shortcuts in order to keep the code small (but it is still slightly verbose to be more readable). First of all, it does not handle disconnects/reconnects particularly well. Also, it doesn’t obtain permission to connect to device, which requires the user to actively accept the accessory the first time it is connected.
The following lines are using the Google APIs Add-on library to create a UsbManager and open a UsbAccessory:
private UsbManager mUsbManager = UsbManager.getInstance(this);
private UsbAccessory mAccessory;
@Override
protected void onResume() {
super.onResume();
setupDetachingAccessoryHandler();
reOpenAccessoryIfNecessary();
}
private void reOpenAccessoryIfNecessary() {
setStatusWaiting();
if (mOutputStream != null) {
setStatusConnected();
return;
}
Intent intent = getIntent();
String action = intent.getAction();
if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
mAccessory = UsbManager.getAccessory(intent);
openAccessory();
}
}
private void openAccessory() {
try {
mFileDescriptor = mUsbManager.openAccessory(mAccessory);
if (mFileDescriptor != null) {
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mOutputStream = new FileOutputStream(fd);
setStatusConnected();
}
} catch (IllegalArgumentException ex) {
// Accessory detached while activity was inactive
closeAccessory();
}
}
The next section shows how to register a BroadcastReceiver to listen for detaching accessories. By declaring and registering the receiver in the Activity instead of in the Manifest, detaching accessories are only handled when the Activity is running.
private void setupDetachingAccessoryHandler() {
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
closeAccessory();
finish();
}
}
};
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mReceiver, filter);
}
Interaction with the user is handled in the following piece of code. When the toggle button is clicked, the TOGGLE_LED_COMMAND is sent to the accessory.
private void setupToggleButton() {
Button button = (Button) findViewById(R.id.toggle_button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
sendCommand(TOGGLE_LED_COMMAND);
}
});
}
private void sendCommand(byte command) {
if (mOutputStream != null) {
try {
mOutputStream.write(command);
} catch (IOException e) {
// Do nothing
}
}
}
That’s the main components of the java code.
The last step describes the Arduino code; Step III.
Here are all posts in the series:
Pingback: itemprop="name">Arduino UNO and the Google ADK – part I | Jayway Team Blog - Sharing Experience
Hi,
I have an Android aplication that needs to connect with an mbed chip.
At the moment the app works like this:
-If the application is closed and I connect the mbed chip, show a message to open the application and I can control correctly the mbed.
-Then, when I disconnect the Usb wire, the app detect it. But the problem is that if I connect once again the Usb (mbed) the app doesn’t detect the accessory. I need to detect the mbed.
I’ve followed your example and the demokit code and I don’t know what to do. Could you give me some advice? I think one solution could be ask user for permission but I have problems to mix your Broadcast Receiver and the demokit Broadcast (it asks user for permission).
Thank you a lot!
Aleix
hey can you help me getting data from arduino uno board going to the android app??
Hey guys, I love your concept, and ralely want to start playing with this great idea. However question : I live in France, and apparently you are not sending anything to France throught Google Checkout ? Is there a way to get your magic kit by any chance ? (I am looking for an Unassembled Acrylic Truckbot ) ???
Hello
I want to do the same using GSM shield , is it possible? ?
NIce tutorial sir. Sir i need to know is there any callback method exist in adk that notify the android device that there is data available on descriptor to read.For example when i connect an usb accessory to my android device and i have written an application for reading data from the accessory but that time there is no data for read but later data is available for read so how i came to know this without checking the inputstream at the descriptor.Any help would be greatly appreciated.Thanks in advance.