ActivityはTestADKActivityクラス1つだけで作る事にする。
ADKのDemoKitの実装箇所を参考にする。

onCreate()
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
①mUsbManager = UsbManager.getInstance(this);
②mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver, filter);
③ if(getLastNonConfigurationInstance() != null){
mAccessory = (UsbAccessory)getLastNonConfigurationInstance();
④openAccessory(mAccessory);
}
⑤setContentView(R.layout.main);
mSlider = (Slider)findViewById(R.id.LedSlider);
mSlider.setPositionListener(this);
mLed = (TextView)findViewById(R.id.Led);
mLed.setOnClickListener(this);
mLed.setText("0");
⑥getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
①UsbManagerの生成
②USB Accessory通信のパーミッションを取得するための
BroadcastReceiverを登録する。
BroadcastReceiver:PendingIntentを登録しておくとこでイベント発生時に呼び出す事が出来る。
③UsbAccessoryがキャッシュに無ければ通信を確立する。
キャッシュ登録:onRetainNonConfigurationInstance
キャッシュ取得:getLastNonConfigurationInstance
④USB AccessoryとのIOストリームを生成する自作関数。⑤レイアウトとのひもづけ
SliderレイアウトはDemokitの自作View。
⑥ADKはスリープ状態になると切断されてしまうのでスリープ防止。
onResume()
protected void onResume() {
super.onResume();
Intent intent = getIntent();
①if (mInputStream != null && mOutputStream != null) {
return;
}
②UsbAccessory[] accessories = mUsbManager.getAccessoryList();
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null) {
③if (mUsbManager.hasPermission(accessory)) {
openAccessory(accessory);
} else {
④synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
mUsbManager.requestPermission(accessory, mPermissionIntent)
mPermissionRequestPending = true;
}
}
}
} else {
Log.d(TAG, "mAccessory is null");
⑤setContentView(R.layout.no_device);
}
}
①通信確立済みなら何もしない。②UsbManagerオブジェクトからUsbAccessoryのリストを取得する。
リストの先頭を決め打ち使用(将来の拡張用らしい)
③通信許可を取得済みならIOストリームの生成。
④BroadcastReceiverに同期してユーザに通信許可の問い合わせ。
⑤USBAccessory未接続の場合のView表示。
BroadcastReceiver
①onCreate()で指定したBroadcastReceiver
②受け取ったイベントがUSB通信許可だった。
③受け取ったイベントがUSBAccessory切断だった。
①IOストリームの生成
②入力受付用のスレッド生成
run()
①Arduinoからの入力を受け取る
Handler
①HandlerのsendMessageを受け取る。
onPositionChange()
BroadcastReceiver
①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 = UsbManager.getAccessory(intent);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
openAccessory(accessory);
} else {
Log.d(TAG, "permission denied for accessory " + accessory);
}
mPermissionRequestPending = false;
}
③} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (accessory != null && accessory.equals(mAccessory)) {
closeAccessory();
}
} }
};
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
②if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
openAccessory(accessory);
} else {
Log.d(TAG, "permission denied for accessory " + accessory);
}
mPermissionRequestPending = false;
}
③} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (accessory != null && accessory.equals(mAccessory)) {
closeAccessory();
}
} }
};
①onCreate()で指定したBroadcastReceiver
②受け取ったイベントがUSB通信許可だった。
③受け取ったイベントがUSBAccessory切断だった。
private void openAccessory(UsbAccessory accessory){
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
mAccessory = accessory;
①FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
②Thread thread = new Thread(null, this, "TestADK");
thread.start();
Log.d(TAG, "accessory opened");
} else {
Log.d(TAG, "accessory open fail");
}
}
②入力受付用のスレッド生成
run()
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 >= 3) {
③Message m = Message.obtain(mHandler, MESSAGE_DISTANCE);
m.obj = new DistanceMsg(buffer[i + 1]);
mHandler.sendMessage(m);
}
i += 3;
break;
default:
Log.d(TAG, "unknown msg: " + buffer[i]);
i = len;
break;
}
}
}
}
②1byte目が入力種別(ここでは赤外線測距のcm)
これはArduinoと示し合わせておく
③MessageクラスはHandlerへ値を渡す為の器。
Handler:UIスレッドはシングルスレッドであるため、
この入力信号待ちスレッド等の別スレッドからアクセスすると
例外が発生する。
Handlerを使うとUIスレッドが実行するキューに登録できる。
これはArduinoと示し合わせておく
③MessageクラスはHandlerへ値を渡す為の器。
Handler:UIスレッドはシングルスレッドであるため、
この入力信号待ちスレッド等の別スレッドからアクセスすると
例外が発生する。
Handlerを使うとUIスレッドが実行するキューに登録できる。
Handler
Handler mHandler = new Handler() {
@Override
①public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_DISTANCE:
②DistanceMsg o = (DistanceMsg) msg.obj;
mDistance.setText(String.valueOf(o.getDistance()) + "cm");
break;
}
}
};
②Messageクラスから値を取り出してViewに反映。
onPause()
通信切断
通信切断
onDestroy()
BroadcastReceiverを登録削除
BroadcastReceiverを登録削除
onPositionChange()
①public void onPositionChange(double value) {
int v = (int) (255 * value);
mLed.setText(String.valueOf(v));
②sendCommand(LED_SERVO_COMMAND, (byte)LED_RED, (byte) v);
}
①onCreate()で登録したスライダViewのリスナー
②出力用自作関数
sendCommand()
public void sendCommand(byte command, byte target, int value) {
①byte[] buffer = new byte[3];
if (value > 255)
value = 255;
buffer[0] = command;
buffer[1] = target;
buffer[2] = (byte) value;
if (mOutputStream != null && buffer[1] != -1) {
try {
mOutputStream.write(buffer);
} catch (IOException e) {
Log.e(TAG, "write failed", e);
}
}
}
①3byteで「コマンド/対象/値」を表している。
Arduino側の処理と示し合わせておく。
0 件のコメント:
コメントを投稿