さまざまな電話/タブレットと Arduino DUE を使用して、Android オープン アクセサリ プロトコル (AOA) でいくつかの実験を行っています。
アナログ入力ピンからデータを読み取り、Arduino DUE のデジタル出力ピンのステータスを変更する AOA に基づく単純なアプリの異なる動作の原因を見つけようとする助けが必要です。
アプリを試しているすべての電話はルート化されておらず、すべての電話にファイルがあることを確認しました
- /system/framework/com.android.future.usb.accessory.jar
- /system/etc/permissions/android.hardware.usb.accessory.xml
私の知る限り、AOA への支援を求められたのはこの 2 人だけです。
指定されたアプリは、Samsung Galaxy S2 (Android バージョン 4.1.2、カーネル v3.0.31-1211311) および Galaxy Pocket Neo (Android バージョン 4.1.2、カーネル v3.0.15-1456085) で正常に動作しますが、「部分的にしか動作しません。 " Samsung Galaxy Note 3 (Android バージョン 4.3、カーネル v3.4.0-2019540)。
より詳細には、指定されたすべての電話 (Galaxy Note 3 も) にアクセサリを接続すると、アクセサリが正しく認識され、Arduino スケッチに関連付けられたアプリがデジタル出力ピンの状態を正しく (すべての電話で) 制御します。しかし、Galaxy Note は Arduino から受信できず、アナログからデジタルへの変換の結果 (2 バイト) を含むメッセージを表示できないようです。
このアプリは、UDOO 開発プラットフォームのチュートリアル プロジェクトの 1 つであり、元の投稿は次のとおりです。
MainActivity.java のコードは次のとおりです。
package org.udoo.androidadkdemobidirect;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.udoo.androidadkdemobidirect.R;
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.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
public class MainActivity extends Activity implements Runnable{
private static final String TAG = "UDOO_AndroidADKFULL";
private static final String ACTION_USB_PERMISSION = "org.udoo.androidadkdemobidirect.action.USB_PERMISSION";
private UsbManager mUsbManager;
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
private Message m;
UsbAccessory mAccessory;
ParcelFileDescriptor mFileDescriptor;
FileInputStream mInputStream;
FileOutputStream mOutputStream;
private static ToggleButton btn_LED = null;
private static TextView tv_adResult = null;
private boolean running = false;
// Receive the USB attached intent
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 = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
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 = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null && accessory.equals(mAccessory)) {
closeAccessory();
}
}
}
};
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
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.activity_main);
btn_LED = (ToggleButton) findViewById(R.id.toggleButtonLED);
tv_adResult = (TextView) findViewById(R.id.adResult);
}
@SuppressWarnings("deprecation")
@Override
public Object onRetainNonConfigurationInstance() {
if (mAccessory != null) {
return mAccessory;
} else {
return super.onRetainNonConfigurationInstance();
}
}
@Override
public void onResume() {
super.onResume();
if (mInputStream != null && mOutputStream != null) {
running = true;
return;
}
//open the accessory from the accessory list
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");
}
}
@Override
public void onPause() {
running = false;
super.onPause();
}
@Override
public void onDestroy() {
running = false;
closeAccessory();
unregisterReceiver(mUsbReceiver);
super.onDestroy();
}
// open the accessory and open the input and output stream from the descriptor
// start also the thread that reads from Arduino
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(this, "UDOO_ADK_readfrom");
running = true;
thread.start();
Toast.makeText(getApplicationContext(), "Accessory connected", Toast.LENGTH_SHORT).show();
Log.i(TAG, "openaccessory");
}
else {
Toast.makeText(getApplicationContext(), "Accessory not connected", Toast.LENGTH_SHORT).show();
}
}
// close the accessory
private void closeAccessory() {
Log.i(TAG, "closeaccessory");
try {
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
} catch (IOException e) {
} finally {
mFileDescriptor = null;
mAccessory = null;
running = false;
}
}
// ToggleButton method - send message to Arduino
public void writeToAccessory(View v){
if (mAccessory != null) {
byte[] message = new byte[1];
message[0] = (byte) (btn_LED.isChecked()?1:0);
if (mOutputStream != null) {
try {
mOutputStream.write(message);
} catch (IOException e) {
Log.e(TAG, "write failed", e);
}
}
}
else
Toast.makeText(getApplicationContext(), "Accessory not connected", Toast.LENGTH_SHORT).show();
}
// Thread to read data from Arduino
public void run() {
int ret = 0;
byte[] buffer = new byte[4];
while (running) {
try {
ret = mInputStream.read(buffer);
} catch (IOException e) {
break;
}
m = Message.obtain(mHandler);
if (ret != 0) {
m.arg1 = (int) ((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff);
ret = 0;
}
mHandler.sendMessage(m);
}
}
static Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
final int temp = msg.arg1;
tv_adResult.setText(String.format("%4d (= %.2f V)", temp, 3.3/1024*temp));
}
};
}
また、この奇妙な動作が AOA プロトコルに基づく他のアプリでも持続することも確認しました。つまり、Galaxy Note 3 は出力メッセージをアクセサリに正しく送信しますが、そこから入力メッセージを読み取りません。
問題がどこにあるかを見つけることができません。StackOverflow コミュニティにヒントを求めます。
どんな助けでも大歓迎です。