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.