ADKのサンプルを動かそう

Table of Contents

しかだよ。

ADKバージョンが変わったりしてて正規のサンプルが動かなかったりしますよね。

というわけで、2012/9/30 現時点で動くサンプルをご紹介します。

Android

動作環境
ソースコード

Y.A.M の 雑記帳: Android Hello ADK つくった!ソースコードをほんの一部だけ修正しています。

MainActivity.java

package com.example.adksample;

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.Handler; import android.os.Message; import android.os.ParcelFileDescriptor; import android.util.Log; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.TextView; import android.widget.ToggleButton;

public class MainActivity extends Activity implements Runnable{

private static final String ACTION_USB_PERMISSION = "com.example.adksample.action.USB_PERMISSION";

private static final String TAG = "ADKSample";

private UsbManager mUsbMng; private PendingIntent mPermissionIntent ; private boolean mPermissionRequestPending; private UsbAccessory mAccessory;

/*input output stream */ private ParcelFileDescriptor mFileDescriptor; private FileInputStream mInputStream; private FileOutputStream mOutputStream;

/view/ private ToggleButton mToggleButton; private TextView mLedStateView; private TextView mStatusView;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

/* initialize instance */ mUsbMng = (UsbManager) getSystemService(USB_SERVICE); mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);

/* receiver */ IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_USB_PERMISSION); filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED); registerReceiver(mUsbReceiver, filter);

/* view */ setContentView(R.layout.activity_main); mToggleButton = (ToggleButton) findViewById(R.id.toggleBtn); mLedStateView = (TextView) findViewById(R.id.ledState); mStatusView = (TextView) findViewById(R.id.status);

mToggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { byte command = 0x1; byte value = (byte) (isChecked ? 0x1 : 0x0); sendCommand(command, value); } });

enableControls(false);
}

@Override protected void onResume() { super.onResume(); if(mInputStream != null && mOutputStream != null){ return; }

UsbAccessory[] accessories = mUsbMng.getAccessoryList(); UsbAccessory accessory = (accessories == null ? null : accessories[0]); if(accessory != null){ if(mUsbMng.hasPermission(accessory)){ openAccessory(accessory); }else{ synchronized (mUsbReceiver) { if(!mPermissionRequestPending){ mUsbMng.requestPermission(accessory, mPermissionIntent); mPermissionRequestPending = true; } } } }else{ Log.d(TAG, "mAccessory is null"); } }

@Override protected void onPause() { super.onPause(); closeAccessory(); }

@Override protected void onDestroy() { unregisterReceiver(mUsbReceiver); super.onDestroy(); }

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver(){

@Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if(ACTION_USB_PERMISSION.equals(action)){ synchronized (this) { UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)){ openAccessory(accessory); }else{ Log.d("adksample", "permission denied for accessory "+ accessory); } mPermissionRequestPending = false; } }else if(UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)){ UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); if(accessory!= null && accessory.equals(mAccessory)){ closeAccessory(); } }

}

};

private void openAccessory(UsbAccessory accessory){ mFileDescriptor = mUsbMng.openAccessory(accessory);

if(mFileDescriptor != null){ mAccessory = accessory; FileDescriptor fd = mFileDescriptor.getFileDescriptor(); mInputStream = new FileInputStream(fd); mOutputStream = new FileOutputStream(fd);

new Thread(null, this, "DemoKit").start(); Log.d(TAG, "accessory opend");

enableControls(true); }else{ Log.d(TAG, "accessory open fail"); } }

private void closeAccessory(){ enableControls(false);

try{ if(mFileDescriptor != null){ mFileDescriptor.close(); } }catch(IOException e){ }finally{ mFileDescriptor = null; mAccessory = null; } }

private void enableControls(boolean enable){ if(enable){ mStatusView.setText("connected"); }else{ mStatusView.setText("not connected"); } mToggleButton.setEnabled(enable); }

private static final int MESSAGE_LED = 1;

private class LedMsg{ private byte on; public LedMsg(byte on) { this.on = on; } public boolean isOn(){ if(on == 0x1){ return true; }else{ return false; } } }

public void run() { int ret = 0; byte[] buffer = new byte[16384]; int i;

while(ret==0){ try{ ret = mInputStream.read(buffer); }catch(IOException e){ break; }

i = 0; while(i < ret){ int len = ret - i; switch (buffer[i]) { case 0x1: if(len >= 2){ Message m = Message.obtain(mHandler, MESSAGE_LED); m.obj = new LedMsg(buffer[i+1]); mHandler.sendMessage(m); } i += 2; break;

default: Log.d(TAG, "unknown msg: "+buffer[i]); i = len; break; } } } }

private Handler mHandler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_LED: LedMsg o = (LedMsg) msg.obj; handleLedMessage(o); break;

default: break; } }; };

private void handleLedMessage(LedMsg l){ if(l.isOn()){ mLedStateView.setText("ON"); }else{ mLedStateView.setText("OFF"); } }

public void sendCommand(byte command, byte value){ byte[] buffer = new byte[2];

if(value != 0x1 && value != 0x0) value = 0x0;

buffer[0] = command; buffer[1] = value; if(mOutputStream != null){ try{ mOutputStream.write(buffer); }catch(IOException e){ Log.e(TAG, "write failed", e); } } }

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:gravity="center"  
    android:orientation="vertical" >  
<span class="synIdentifier">&#60;TextView  </span>

android:id="@+id/status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dip" />

<span class="synIdentifier">&#60;ToggleButton  </span>

android:id="@+id/toggleBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dip" />

<span class="synIdentifier">&#60;TextView  </span>

android:id="@+id/ledState" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dip" />

</LinearLayout>

xml/asccessory_filter.xml

manufacturerが Arduinoの AndroidAccessory の第一引数、modelが第二引数になります。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <usb-accessory manufacturer="kojika-ya" model="ADKSample" version="1.0" />
</resources>

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.adksample"
    android:versionCode="1"
    android:versionName="1.0" >
<span class="synIdentifier">&#60;uses-<a class="keyword" href="http://d.hatena.ne.jp/keyword/sdk">sdk</a></span>

android:minSdkVersion="15" android:targetSdkVersion="15" />

<span class="synIdentifier">&#60;application</span>

android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >

    <span class="synIdentifier">&#60;activity</span>

android:name=".MainActivity" android:launchMode="singleInstance" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>

        <span class="synIdentifier">&#60;intent-filter&#62;</span>
            <span class="synIdentifier">&#60;action </span><span class="synType"><a class="keyword" href="http://d.hatena.ne.jp/keyword/android">android</a></span><span class="synComment">:</span><span class="synType">name</span>=<span class="synConstant">&#34;<a class="keyword" href="http://d.hatena.ne.jp/keyword/android">android</a>.hardware.usb.action.USB_ACCESSORY_ATTACHED&#34;</span><span class="synIdentifier"> /&#62;</span>
        <span class="synIdentifier">&#60;/intent-filter&#62;</span>

        <span class="synIdentifier">&#60;meta-data</span>

android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" android:resource="@xml/asccessory_filter"/> </activity> </application>

</manifest>

Arduino

Arduino Labs - Accessory Mode browse

から、ArduinoADK.zipをDLする。

Arduino/libraries/UsbHost を

~/Documents/Arduino/libraries/

にコピーしてUsbHostをArduinoにインストール。

ソースコード
#include <AndroidAccessory.h>

define LED 13

AndroidAccessory acc("kojika-ya", "ADKSample");

void setup() { Serial.begin(115200); Serial.print("\r\nStart");

pinMode(LED, OUTPUT);

if (!acc.begin()) { Serial.println("OSCOKIRQ failed to assert"); while (1); //halt } }

void loop() { uint8_t msg[64] = {0x00}; byte led;

acc.refresh(); if (!acc.isConnected()) { digitalWrite(LED, LOW); return; }

uint16_t len = 0; while (acc.available() > 0) { Serial.print("available"); msg[len] = acc.read(); len++; }

if (len < 1) { return; }

Serial.print("msg[0]" + msg[0]); Serial.print("msg[1]" + msg[1]); if (msg[0] == 0x1) {

if (msg&#91;1] == 0x1) {
  digitalWrite(LED, HIGH);
  msg&#91;0] = 0x1;
  msg&#91;1] = 0x1;
  acc.write(msg, 2);
} else {
  digitalWrite(LED, LOW);
  msg&#91;0] = 0x1;
  msg&#91;1] = 0x2;
  acc.write(msg, 2);
}

}

delay(10); }