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)