Android Interface With ADK: The Android Part

After hacking on the arduino site of the code, now we can go to the android part

For android side, it is a easier in a way. There is nothing to bypass, just make sure to have the right version of android OS. You need 2.3.4 above to be able to use the Accessory API. Though using the API have quite a lot of stuff to setup. And I am a bit confused with the documentation(which is why I share my notes here)

Essentially openaccessory api open the device as a ParcelFileDescriptor object, which is why you need to import java FileInputStream and FileOutputStream, so you can read and write data to the arduino board

BroadcastReceiver is used because an Android Accessory can broadcast intent to android to launch an android app. IntentFilter and PendingIntent are used to setup the permission necessary for an App is used. More on that later

Remember an ADK device can send intent to an android app. So that when you plug your device, an app that is use to run with it can be launch. Essentially what this does is, when an intent is receive from the ADK, setup the app to read from ADK, via OpenAccessory method, or if it is detached, clean up all the connection via Close necessary.

line 8: Get the permission and action from the Arduino Board

line 11: Get accessory connection

line 13 – 14 : Get extra permission, from the Arduino Board

line 16: Open Accessory function to setup all the code and interface to the Arduino Board

line 27: from action UsbManager will check if there the arduino board id detached, then do cleanup

line 31-32: If cleanup is still exist, then call cleanup function

Initialize Accessory Interface

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

privatevoidopenAccessory(UsbAccessory accessory){

// the interface is a file file descriptor

mFileDescriptor=mUsbManager.openAccessory(accessory);

if(mFileDescriptor!=null){

mUsbAccessory=accessory;

// get the file descriptor

FileDescriptor fd=mFileDescriptor.getFileDescriptor();

// set one to read

mFileInputStream=newFileInputStream(fd);

// set one to write

mFileOutputStream=newFileOutputStream(fd);

Thread thread=newThread(null,this,&quot;ADKTestProject&quot;);

thread.start();

Log.d(TAG,&quot;Accessory Opened&quot;);

}

else{

Log.d(TAG,&quot;Accessory Open Fail&quot;);

}

}

This is how you setup to read from ADK. Accessory will be defined from an intent from the ADK, mUsbManager will open the accessory, and return ParcelFileDescriptor, which will be pass to FileInputStream and FileOutputStream.

FileInputStream is use to read from the ADK, for this project I use FileOutputStream to write to the ADK Board, which start the thread to have them run in background.

Close Connection to Device

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

privatevoidcloseAccessory(){

try{

if(mFileDescriptor!=null){

mFileDescriptor.close();

}

}

catch(IOExceptione){

}

finally{

mFileDescriptor=null;

mUsbAccessory=null;

}

}

Close is easy just close the file descriptor, and set variable to null

Send Commend to Device

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

// send command!!!!

publicvoidsendCommand(intred,intgreen,intblue){

// we will only send 3 byte

byte[]buffer=newbyte[3];

// make sure the value cannot be more than 255,

// the LED can only receive that

if(red&gt;255){

red=255;

}

if(green&gt;255){

green=255;

}

if(blue&gt;255){

blue=255;

}

// assign

buffer[0]=(byte)red;

buffer[1]=(byte)green;

buffer[2]=(byte)blue;

// make sure interface is there

if(mFileOutputStream!=null&amp;&amp;buffer[1]!=-1){

try{

// write it

mFileOutputStream.write(buffer);

}

catch(IOExceptione){

Log.e(TAG,&quot;Write Faile&quot;,e);

}

}

}

Remember I say on the last post that, you just send an array of byte or read an array of bytes , it is the same here.

line 4: define the holder for data to be send to the Arduino

line 7-15: just to setup the value send to be at most 255, the LED only can access such value. It is also nice to make sure value send from app to arduino, because once go to hardware, thing will be fried(shit just turn real!!!)

line 17-19: just to assign value, remember we send bytes to Arduino, so remember to convert accordingly

line 24: send the byte array to arduino

Retain Devices

1

2

3

4

5

6

7

8

9

@Override

publicObjectonRetainNonConfigurationInstance(){

if(mUsbAccessory!=null){

returnmUsbAccessory;

}

else{

returnsuper.onRetainNonConfigurationInstance();

}

}

Retain ADK accessory to be reuse by new activity

Initialize the app to use Accessory

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@Override

publicvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

// get the USB Manager involved

mUsbManager=UsbManager.getInstance(this);

// setup permission

mPermissionIntent=PendingIntent.getBroadcast(this,0,

newIntent(ACTION_USB_PERMISSION),0);

// get the permission

IntentFilter filter=newIntentFilter(ACTION_USB_PERMISSION);

// register receiver

registerReceiver(mUsbReceiver,filter);

// device exist? Open and send value

if(getLastNonConfigurationInstance()!=null){

mUsbAccessory=(UsbAccessory)getLastNonConfigurationInstance();

openAccessory(mUsbAccessory);

sendCommand(redValue,blueValue,greenValue);

}

// snipped for brevity, ui definition down there

This register the Permission needed and the BroadcastReceiver, also setup the retained Accessory object

To resume an activity

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

@Override

publicvoidonResume(){

super.onResume();

Intent intent=getIntent();

// opps interface close, it is cool, do nothing

if(mFileInputStream!=null&amp;&amp;mFileOutputStream!=null){

return;

}

// get a list of accessory

UsbAccessory[]accessories=mUsbManager.getAccessoryList();

// if exist get the first one or give null

UsbAccessory accessory=(accessories==null?null:accessories[0]);

// accessory exist

if(accessory!=null){

// check permission

if(mUsbManager.hasPermission(accessory)){

// open and send value

openAccessory(accessory);

sendCommand(redValue,blueValue,greenValue);

}

else{

synchronized(this){

// request permission

if(!mPermissionRequestPending){

mUsbManager.requestPermission(accessory,

mPermissionIntent);

mPermissionRequestPending=true;

}

}

}

}

else{

Log.d(TAG,&quot;mAccessory isNull&quot;);

}

}

line 7-8: so the connection already closed, it is cool, don’t do anything

line 11-13: get all connected device, if there is nothing return null, else, return the first one(there is only one anyway)

line 17-21: permission checked out, you can open(OpenAccessory) and send value to the arduino(sendCommand)

line 25-29: request permission, again

Using the Using sendCommand

1

2

3

4

5

6

7

publicvoidonProgressChanged(SeekBar seekBar,intprogress,

booleanfromUser){

// snipped out for brevity, set value to be send above

// get value, and send it

sendCommand(redValue,blueValue,greenValue);

}

So just get value from UI change, then send the value to send command. It is a seekbar, that value is progress, and we already save color value anyway.

We’re done

I hope this is useful, though I think I might confuse people more, so just leave a comment if there is any question