Modify AndroidManifest.xml to add <uses-feature> of "android.hardware.usb.accessory", <intent-filter> of "android.hardware.usb.action.USB_ACCESSORY_ATTACHED", and <meta-data> of resource="@xml/myfilter".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidadkled"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="12"
android:targetSdkVersion="17" />
<uses-feature android:name="android.hardware.usb.accessory"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidadkled.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/myfilter"/>
</activity>
</application>
</manifest>
Create file /res/xml/myfilter.xml
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<usb-accessory
manufacturer="Arduino-er"
model="HelloADKLED"
version="0.1"/>
</resources>
Layout file, /res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Arduino LED Control" />
<TextView
android:id="@+id/textin"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:id="@+id/LedOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LED On" />
<RadioButton
android:id="@+id/LedOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LED Off" />
</RadioGroup>
</LinearLayout>
Create a abstract class AbstractAdkActivity.java to extend Activity, implement the function of ADK; such that we can easy re-use it in furture and reduce the ADK related job in MainActivity.java.
/*
* abstract class for Activities have to read ADK
* for android:minSdkVersion="12"
*
*/
package com.example.androidadkled;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
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.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
public abstract class AbstractAdkActivity extends Activity {
private static int RQS_USB_PERMISSION = 0;
private static final String ACTION_USB_PERMISSION = "arduino-er.usb_permission";
private PendingIntent PendingIntent_UsbPermission;
private UsbManager myUsbManager;
private UsbAccessory myUsbAccessory;
private ParcelFileDescriptor myAdkParcelFileDescriptor;
private FileInputStream myAdkInputStream;
private FileOutputStream myAdkOutputStream;
boolean firstRqsPermission;
//do something in onCreate()
protected abstract void doOnCreate(Bundle savedInstanceState);
//do something after adk read
protected abstract void doAdkRead(String stringIn);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
myUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(myUsbReceiver, intentFilter);
//Ask USB Permission from user
Intent intent_UsbPermission = new Intent(ACTION_USB_PERMISSION);
PendingIntent_UsbPermission = PendingIntent.getBroadcast(
this, //context
RQS_USB_PERMISSION, //request code
intent_UsbPermission, //intent
0); //flags
IntentFilter intentFilter_UsbPermission = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(myUsbPermissionReceiver, intentFilter_UsbPermission);
firstRqsPermission = true;
doOnCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
if(myAdkInputStream == null || myAdkOutputStream == null){
UsbAccessory[] usbAccessoryList = myUsbManager.getAccessoryList();
UsbAccessory usbAccessory = null;
if(usbAccessoryList != null){
usbAccessory = usbAccessoryList[0];
if(usbAccessory != null){
if(myUsbManager.hasPermission(usbAccessory)){
//already have permission
OpenUsbAccessory(usbAccessory);
}else{
if(firstRqsPermission){
firstRqsPermission = false;
synchronized(myUsbReceiver){
myUsbManager.requestPermission(usbAccessory,
PendingIntent_UsbPermission);
}
}
}
}
}
}
}
//Write String to Adk
void WriteAdk(String text){
byte[] buffer = text.getBytes();
if(myAdkOutputStream != null){
try {
myAdkOutputStream.write(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
protected void onPause() {
super.onPause();
closeUsbAccessory();
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myUsbReceiver);
unregisterReceiver(myUsbPermissionReceiver);
}
Runnable runnableReadAdk = new Runnable(){
@Override
public void run() {
int numberOfByteRead = 0;
byte[] buffer = new byte[255];
while(numberOfByteRead >= 0){
try {
numberOfByteRead = myAdkInputStream.read(buffer, 0, buffer.length);
final StringBuilder stringBuilder = new StringBuilder();
for(int i=0; i<numberOfByteRead; i++){
stringBuilder.append((char)buffer[i]);
}
runOnUiThread(new Runnable(){
@Override
public void run() {
doAdkRead(stringBuilder.toString());
}});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break;
}
}
}
};
private BroadcastReceiver myUsbReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(UsbManager.ACTION_USB_ACCESSORY_DETACHED)){
UsbAccessory usbAccessory =
(UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if(usbAccessory!=null && usbAccessory.equals(myUsbAccessory)){
closeUsbAccessory();
}
}
}
};
private BroadcastReceiver myUsbPermissionReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(ACTION_USB_PERMISSION)){
synchronized(this){
UsbAccessory usbAccessory =
(UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)){
OpenUsbAccessory(usbAccessory);
}else{
finish();
}
}
}
}
};
private void OpenUsbAccessory(UsbAccessory acc){
myAdkParcelFileDescriptor = myUsbManager.openAccessory(acc);
if(myAdkParcelFileDescriptor != null){
myUsbAccessory = acc;
FileDescriptor fileDescriptor = myAdkParcelFileDescriptor.getFileDescriptor();
myAdkInputStream = new FileInputStream(fileDescriptor);
myAdkOutputStream = new FileOutputStream(fileDescriptor);
Thread thread = new Thread(runnableReadAdk);
thread.start();
}
}
private void closeUsbAccessory(){
if(myAdkParcelFileDescriptor != null){
try {
myAdkParcelFileDescriptor.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
myAdkParcelFileDescriptor = null;
myUsbAccessory = null;
}
}
Modify MainActivity.java to extend AbstractAdkActivity, and extend Activity in-turn. With AbstractAdkActivity handle most of the ADK related job, we only have to override the methods doOnCreate()(called in onCreate() method) and doAdkRead()(called after command read from ADK). To send command to ADK, call WriteAdk() method.
package com.example.androidadkled;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AbstractAdkActivity {
TextView textIn;
RadioButton ledOn, ledOff;
@Override
protected void doOnCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
textIn = (TextView)findViewById(R.id.textin);
ledOn = (RadioButton)findViewById(R.id.LedOn);
ledOff = (RadioButton)findViewById(R.id.LedOff);
ledOn.setOnCheckedChangeListener(new OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked){
WriteAdk("LEDON");
Toast.makeText(getApplicationContext(),
"LEDON", Toast.LENGTH_LONG).show();
}
}});
ledOff.setOnCheckedChangeListener(new OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if(isChecked){
WriteAdk("LEDOFF");
Toast.makeText(getApplicationContext(),
"LEDOFF", Toast.LENGTH_SHORT).show();
}
}});
}
@Override
protected void doAdkRead(String stringIn) {
textIn.setText(stringIn);
}
}
Download the files.Refer the another post for the code in Arduino Due side.
Updated@2015-10-15: Android control Arduino Due LED, using ADK (Accessory Development Kit)
Hi.I simply wonder about that: What does your android app send to usb?String, char?I want to use your on-off interface and just using serial read in arduino
ReplyDeleteIt's String in this example.
DeleteHi,
ReplyDeleteWhow!
I'm new to the arduino & android world, but that's what i'm looking for (sort of :-) )
I am making a high-end chronometer for a dogsport called flyball, and i would love to get the chrono results (through USB cable) on a low cost android tablet (USB host capable) as output to the refereés of the game.
I use an MEGA 2560 ADK to control and check the sensors, would it be possible to get the data on the tablet?
How do I begin to program such interface?
I need a few inputs to come on the tablet:
for example:
"Dog1 : " +time the dog was on the track + "Crossing" + time the next dog needed to pass the previous dog.
and so on for the four dogs
is there a sort of GUI for that sort of programing that i can use?
Grtz
Yves
If the screen rotates, someone hits back, the screen locks, etc, when the app restarts the app stops to communicate with the board. So I have to unplug the USB before the connection can be made again.
ReplyDeleteDo you know how to fix it?
Thanks! :D
Yes, it may be the most headache problem for me, when configuration change and the app re-create!
ReplyDeleteMaybe you can force the app run in one orientation only.
Hi! I have been trying to do what you are doing with your example here for some time now. I have not been able to get communication going, even with a copy paste of your code. The android app always freezes about 3-5 seconds after i try to send something. Do you have any idea why this could happen?
ReplyDeleteI re-build the example again on Android Studio, http://arduino-er.blogspot.com/2015/10/android-control-arduino-due-led-using.html
DeleteWith APK, you can try it.
May be not all android devices support ADK.