我密切关注本教程:http ://assets.en.oreilly.com/1/event/68/Building%20Android%20Accessories%20using%20the%20Open%20Accessory%20Development%20Kit%20and%20Arduino%20Presentation%201 .pdf 但是,我进行了一些修改,以便在每次更新文本时发送 ASCII 值。我仍然无法连接我的 Android 设备(是的,我有多个,从 2.2.3 到 2.2.7 版本)。我一直在屏幕日志中收到输出流为空的错误。任何帮助将不胜感激!
OpenAccessoryTest.java
package org.simonmonk.duinodroid;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.android.future.usb.UsbAccessory;
import com.android.future.usb.UsbManager;
public class OpenAccessoryTest extends Activity implements Runnable {
private EditText mByteField;
private EditText mResponseField;
private Button mSendButton;
private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";
private UsbManager mUsbManager;
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
private UsbAccessory mAccessory;
private ParcelFileDescriptor mFileDescriptor;
private FileInputStream mInputStream;
private FileOutputStream mOutputStream;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mByteField = (EditText) findViewById(R.id.streamingTextView1);
mResponseField = (EditText) findViewById(R.id.arduinoresponse);
mSendButton = (Button) findViewById(R.id.sendButton);
// String valueStr = mByteField.getText().toString();
mSendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sendMessageToArduino();
}
});
setupAccessory();
}
@Override
public Object onRetainNonConfigurationInstance() {
if (mAccessory != null) {
return mAccessory;
} else {
return super.onRetainNonConfigurationInstance();
}
}
@Override
public void onResume() {
log("Resuming");
super.onResume();
if (mInputStream != null && mOutputStream != null) {
log("Resuming: streams were not null");
return;
}
log("Resuming: streams were null");
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("onResume:mAccessory is null");
}
}
@Override
public void onPause() {
log("Pausing");
super.onPause();
}
@Override
public void onDestroy() {
log("Destroying");
unregisterReceiver(mUsbReceiver);
super.onDestroy();
}
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
ValueMsg t = (ValueMsg) msg.obj;
log("Arduino sent: " + t.getFlag() + " " + t.getReading());
}
};
private void log(String string) {
String contents = mResponseField.getText().toString();
mResponseField.setText(contents + "\n" + string);
}
private void setupAccessory() {
log("In setupAccessory");
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);
}
}
private void openAccessory(UsbAccessory accessory) {
log("In openAccessory");
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, "OpenAccessoryTest");
thread.start();
alert("openAccessory: Accessory openned");
log("Attached");
} else {
log("openAccessory: accessory open failed");
}
}
private void closeAccessory() {
log("In closeAccessory");
try {
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
} catch (IOException e) {
} finally {
mFileDescriptor = null;
mAccessory = null;
}
}
private int composeInt(byte hi, byte lo) {
int val = hi & 0xff;
val *= 256;
val += lo & 0xff;
return val;
}
@Override
public void run() {
int ret = 0;
byte[] buffer = new byte[16384];
int i;
while (true) { // keep reading messages forever. There are prob lots of
// messages in the buffer, each 4 bytes
try {
ret = mInputStream.read(buffer);
} catch (IOException e) {
break;
}
i = 0;
while (i < ret) {
int len = ret - i;
if (len >= 2) {
Message m = Message.obtain(mHandler);
int value = composeInt(buffer[i], buffer[i + 1]);
m.obj = new ValueMsg('a', value);
mHandler.sendMessage(m);
}
i += 2;
}
}
}
public void sendMessageToArduino() {
String valueStr = mByteField.getText().toString();
try {
for (int x = 0; x < valueStr.length(); x++) {
sendCommand((byte) valueStr.charAt(x));
log("Sending to Arduino: " + (byte) valueStr.charAt(x));
}
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
alert("The Byte should be a number between 0 and 255");
}
}
public void sendCommand(byte value) {
log("Sent: " + value);
byte[] buffer = new byte[1];
buffer[0] = value;
if (mOutputStream != null) {
try {
mOutputStream.write(buffer);
} catch (IOException e) {
log("Send failed: " + e.getMessage());
}
} else {
log("Send failed: mOutStream was null");
}
}
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("USB permission denied");
}
}
} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (accessory != null && accessory.equals(mAccessory)) {
log("Detached");
closeAccessory();
}
}
}
};
public void alert(String message) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage(message);
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alertDialog.show();
}
}`
StreamingTextView.java
package org.simonmonk.duinodroid;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;
public class StreamingTextView extends EditText {
public StreamingTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public StreamingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public StreamingTextView(Context context) {
super(context);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
((OpenAccessoryTest) super.getContext()).sendCommand(toAscii(event));
return super.onKeyDown(keyCode, event);
}
private byte toAscii(KeyEvent event) {
byte ch = (byte) event.getUnicodeChar();
if (ch == 0) {
switch(event.getKeyCode()){
case KeyEvent.KEYCODE_DEL:
ch = 8;
break;
case KeyEvent.KEYCODE_ENTER:
ch = 10;
break;
}
}
return ch;
}
}
主要的.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:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Byte 0 (decimal)" />
<org.simonmonk.duinodroid.StreamingTextView
android:id="@+id/streamingTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="StreamingTextView" >
<requestFocus />
</org.simonmonk.duinodroid.StreamingTextView>
<Button
android:id="@+id/sendButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Send to Arduino" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Log" />
<EditText
android:id="@+id/arduinoresponse"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:editable="false"
android:lines="10" />
</LinearLayout>