[[12/8]] * [[ADK 開発環境の構築]] の例題&ref(#m657b89d)のプログラムを説明します。 [#b4900654] *** プログラムの内容 [#e781b71c] - Arduino の光センサの状態をAndroid に表示、Android でArduino のLEDを点滅 *** 使い方 [#sd0103e8] - Arduino とAndroid 端末を USB ケーブルで接続し、Android 端末でこのアプリケーションを起動します。 起動すると、最初、Android ロボットが寝た絵が表示された後、以下のような表示が出ます。 - 表示画面上部の [In], [Out] タブで入出力表示を切り替えます。起動した直後は入力データを表示しています。 - 入力表示のとき、 *** ADK利用の流れ [#n3745f4b] - 1. BroadcastReceiver を利用して、ACTION_USB_PERMISSION を判定する。 - 2. UsbAccessoryのインスタンスを取得する。 - 3. UsbAccessoryのインスタンスよりParcelFileDescriptorを取得する。 - 4. ParcelFileDescriptorよりFileDescriptorを取得し、FileInputStreamとFileOutputStreamを取得する - 5. 各Streamを利用し、入出力の処理を行う。 *** Manifest の内容 [#i71ade82] - Android 端末とADKのデバイスがUsb で接続されるか、または、Android 端末のアプリケーションのリストから、このアプリケーション(AdkArduino01) がクリックされたら、AdkArduinoActivity が起動されます。 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.yamalab.android.AdkArduino01" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="11" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.PERSISTENT_ACTIVITY"/> <application android:icon="@drawable/ic_launcher_demokit" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar"> <uses-library android:name="com.android.future.usb.accessory" /> <activity android:name=".AdkArduinoLaunch" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="org.yamalab.android.AdkArduino01.UsbAccessoryActivity" android:label="AdkArduino" android:taskAffinity="" android:launchMode="singleInstance"> <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/accessory_filter" /> </activity> <activity android:name=".AdkArduinoActivity" android:label="@string/app_name" android:screenOrientation="portrait"> </activity> <service android:name=".AdkService" /> </application> </manifest> -- UsbAccessoryActivity --- Usb ケーブルをADKと接続すると、暗黙的 intent が発行され、intent-filter を通じて、UsbAccessoryActivity が起動します。UsbAccessoryActivity は 明示的 intent を使って、AdkArduinoLaunch を起動します。AdkArduinoLaunch は明示的 intent を使って AdkArduinoActivity を起動します。 -- AdkArduinoLaunch --- Android 端末のアプリケーションのリストから、このアプリケーション(AdkArduino01) がクリックされたら、暗黙的 intent が発行され、AdkArduinoLaunch が起動されます。 --- intent-filter の「android.intent.action.MAIN」は、actionタグの親のactivityが、このアプリケーションのエントリーポイント、開始画面として設定されていることを表します。ランチャーからアプリケーションを起動して、一番最初に表示されるわけです。 --- ランチャーを叩くと、ACTIONが「ACTION_MAIN」であるIntentがアプリケーションに対して投げられ、それを処理できる「android.intent.action.MAIN」のintent-filterを持つactivityがintentを受理し、AdkArduinoLaunch が起動されます。「android.intent.category.LAUNCHER」は、categoryというのはactionを受理する際に付加的な情報を付け加えます(http://blog.haw.co.jp/android/?p=54)。 --- AdkArduinoLaunch は明示的 intent を使って AdkArduinoActivity を起動します。 -- AdkArduinoActivity --- 本アプリケーションのGUI とUsb 接続開始を担当するクラスです。 -- AdkService --- Arduino との通信を担当するサービスです。永続的に動作させるため、Service を使っています。 --- AdkArduinoActivity の内部で明示的intent を使って AdkService が起動されます。 *** AdkArduinoActivity.java [#qae80e20] - 本アプリケーションの GUI を担当しているクラスのソースです。UsbAccessory の起動なども行います。 - このActivity の起動時に onCreate(), onStart() と共に, onResume() がシステム側から起動されます。 -- onResume() 内で prepareUsbConnection() が呼び出され、prepareUsbConnection() 内で mUsbManager を作成します。 -- また、prepareUsbConnection() では、Usb が接続されたときに、それを認識する準備を行います。この準備により、Usbが接続されたとき、以下の部分によってそれが受信され、Usb との接続が行われます。 private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent){ Log.i(TAG, "BroadcastReceiver-onRecieve"); String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { Log.i(TAG, "BroadcastReceiver-onRecieve- ACTION_USB_PERMISSION"); synchronized (this) { UsbAccessory accessory = UsbManager.getAccessory(intent); if (intent.getBooleanExtra( UsbManager.EXTRA_PERMISSION_GRANTED, false)) { openAccessory(accessory); startService(); doBindService(); } else { Log.d(TAG, "permission denied for accessory " + accessory); } mPermissionRequestPending = false; } } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) { Log.i(TAG, "BroadcastReceiver-onRecieve- ACTION_USB_ACCESSORY_DETACHED"); UsbAccessory accessory = UsbManager.getAccessory(intent); if (accessory != null && accessory.equals(mAccessory)) { closeAccessory(); } } } }; -- openAccessory(accessory); で 入出力ストリームが作成され、startService(); で AdkService を起動します。 --- AdkService が ADK を使って、Arduino との情報交換を行います。 -- doBindService(); は、AdkArduinoActivity と AdkService を結びつけ、この間の情報交換を可能にします。 *** AdkService.java [#jc0dae4f] *** AdkThread.java [#q0cd643c] *** Arduino-Android(AdkService, AdkThread)間通信 [#fa09b056] *** AdkService-AdkArduinoActivity間通信 [#udce8720] *** ArduinoProcess.java [#w6c964c5]