我在使用上传 Blink.ino(其他示例)的Arduino Due处理 Android 附件工作时遇到问题。问题是我无法从UsbManager
get fromgetSystemService("USB_SERVICE")
中检测到任何 USB 附件(或列表),无论是附加还是分离。
我的代码如下。
1. 表现
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.signalhello"
android:versionCode="1"
android:versionName="1.0" >
<!-- <uses-feature android:name="android.hardware.usb.accessory" />
<uses-feature android:name="android.hardware.usb.host" /> -->
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.signalhello.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
<action android:name="android.hardware.usb.action.USB_ACCESSORY_DETACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
</activity>
</application>
</manifest>
2. res/xml/中的accessory-filter.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-accessory manufacturer="Arduino-er"/> // I tried other options like <usb- accessory vendor-id="9025" product-id="62"/>
<usb-device vendor-id="9025" product-id="62"/>
<usb-accessory vendor-id="2341" product-id="003e"/>
<usb-device vendor-id="2341" product-id="003e"/>
</resources>
3. 主要活动
package com.example.signalhello;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import android.annotation.TargetApi;
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.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public class MainActivity extends Activity {
private static final String ACTION_USB_PERMISSION =
"net.hardroid.adk.example.action.USB_PERMISSION";
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
// USB가 감지되었을 때의 이벤트를 받음.
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("onReceive", "action: " + action);
tv01.setText("action: " + action);
if (ACTION_USB_PERMISSION.equals(action)) {
// 사용자에게 Android Accessory Protocol을 구현한 장비가 연결되면
// 수락할 것인지 문의한 다이얼로그에 대한 사용자의 선택 결과를 받는다.
synchronized (this) {
Log.d("onReceive", "Getting UsbAccessory...");
UsbAccessory accessory = intent
.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
Log.d("onReceive", "Accessory is null ? " + (accessory == null) + ", Device is null ? " + (usbDevice == null));
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
Log.d("onReceive", "Connected USB ...");
// 수락했을 경우
showMessage("receiver : USB Host 연결됨.");
}
else {
Log.d("onReceive", "Permission denied....");
Log.d(MainActivity.class.getName(),
"permission denied for accessory " + accessory);
showMessage("permission denied.");
}
openAccessory(accessory);
UsbManager manager = null;
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager
.getDeviceList();
Iterator<UsbDevice> deviceIter = deviceList.values()
.iterator();
while (deviceIter.hasNext()) {
UsbDevice device = deviceIter.next();
// Device's class...
int count = device.getInterfaceCount();
tv01.setText("count:" + count);
for (int i = 0; i < count; i++) {
UsbInterface iface = device.getInterface(i);
tv02.setText(tv02.getText() + "," + iface.getId());
}
}
// 연결 수락 결과를 받았음을 표시
mPermissionRequestPending = false;
tv04.setText("3");
}
}
else
if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
// Android Accessory Protocol을 구현한 장비의 연결이 해제되었을 때
UsbAccessory accessory = intent
.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
// 앱이 사용하고 있는 장비와 같은 것인지 확인
if (accessory != null && accessory.equals(mAccessory)) {
showMessage("USB Host 연결 해제됨.");
closeAccessory();
}
tv04.setText("4");
}
tv04.setText("5");
}
};
private TextView tv01;
private TextView tv02;
private TextView tv03;
private TextView tv04;
/*static class IncomingHandler extends Handler {
private final WeakReference<UDPListenerService> mService;
IncomingHandler(UDPListenerService service) {
mService = new WeakReference<UDPListenerService>(service);
}
@Override
public void handleMessage(Message msg)
{
UDPListenerService service = mService.get();
if (service != null) {
service.handleMessage(msg);
}
}
}*/
/*Handler mIncomingHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
}
});*/
static Handler uiHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.d("handleMessage", "msg.what: " + msg.what + ", msg.obj: " + msg.obj);
switch (msg.what) {
case 1:
}
}
};
private UsbAccessory mAccessory;
private AdkHandler handler;
private static UsbManager mUsbManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv01 = (TextView) findViewById(R.id.tv01);
tv02 = (TextView) findViewById(R.id.tv02);
tv03 = (TextView) findViewById(R.id.tv03);
tv04 = (TextView) findViewById(R.id.tv04);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
Log.d("onCreate", "Permission intent getting...");
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);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
Log.d("onCreate", "registering Receiver..");
Log.d("onCreate", "receiver is null ? " + (mUsbReceiver == null));
registerReceiver(mUsbReceiver, filter);
Log.d("onCreate", "registered Receiver..");
Log.d("onCreate", "Got permission intent...");
tv04.setText("1");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/** 액티비티가 화면에 보일 때 호출 */
@Override
public void onResume() {
super.onResume();
Log.d("onResume", "Getting device list");
// 앱이 화면에 보일 때 안드로이드 장비에 Android Accessory Protocol을
// 구현한 USB Host가 연결되어 있는지 확인
HashMap<String, UsbDevice> devices = mUsbManager.getDeviceList();
Log.d("onResume", "Getting UsbAccessory");
UsbAccessory accessory = getIntent().getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null) { // Android Accessory Protocol를 구현한 장비를 찾았을 경우
Log.d("onResume", "Got accessory");
if (mUsbManager.hasPermission(accessory)) {
Log.d("onResume", "Got permission");
showMessage("onresume : USB Accessory 연결됨.");
openAccessory(accessory);
}
else {
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
mUsbManager.requestPermission(accessory,
mPermissionIntent); // USB 연결을 통해 장비에 연결해도 되는지 사용자에게 문의
mPermissionRequestPending = true; // 연결권한을 물어보드 코드를 실행했음을 표시
}
}
}
}
else {
String device = "";
if (devices != null) {
Set<String> keys = devices.keySet();
for (String key : keys) {
device += key + ": " + devices.get(key).getDeviceName();
}
}
showMessage("mAccessory is null, devices: " + (devices == null ? "null" : device));
Log.d(MainActivity.class.getName(), "mAccessory is null");
}
tv04.setText("2");
}
// 액티비티가 소멸될 때 호출
@Override
protected void onDestroy() {
// 브로드캐스트 리시버를 제거
unregisterReceiver(mUsbReceiver);
super.onDestroy();
}
private void showMessage(String msg){
Log.d("showMessage", msg);
tv03.setText("message: " + msg);
}
private void openAccessory(UsbAccessory accessory){
mAccessory = accessory;
if(handler == null){
Log.d("openAccessory", "Instanciating AdkHandler");
handler = new AdkHandler();
Log.d("openAccessory", "Setting UI Handler to AdkHandler");
handler.setUiHandler(uiHandler);
}
Log.d("openAccessory", "Openning AdkHandler");
handler.open(mUsbManager, mAccessory);
}
private void closeAccessory(){
if(handler != null && handler.isConnected())
handler.close();
mAccessory = null;
}
}
3-1.AdkHandler.java
package com.example.signalhello;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import android.annotation.TargetApi;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
/**
*
* @author Chun, Young-yil. at IBS Inc.
* @since ADK 4.0
* @date 2013. 5. 15.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public class AdkHandler implements Runnable {
private ParcelFileDescriptor mFileDescriptor;
private FileInputStream mInputStream;
private FileOutputStream mOutputStream;
private Handler uiHandler;
private boolean running;
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
Log.d("run", "start");
int ret = 0;
byte[] buffer = new byte[16384];
int i;
while (ret >= 0 && running) {
try {
ret = mInputStream.read(buffer);
Log.d("run", "" + ret);
}
catch (Exception e) {
e.printStackTrace();
break;
}
i = 0;
Log.d("run", "i: " + i + ", ret: " + ret);
while ( i < ret && running) {
int len = ret - i;
Log.d("run", "buffer[" + i + "]: " + buffer[i]);
switch (buffer[i]) {
case 0x1:
if (len >= 3) {
Message m = Message.obtain(uiHandler, 1);
int value = composeInt(buffer[i = 1], buffer[i + 2]);
m.obj = value;
uiHandler.sendMessage(m);
Log.d("value", "" + value);
}
i += 3;
break;
default :
Log.d("default", "unknown msg:" + buffer[i]);
i = len;
break;
}
}
}
}
/**
* @param b
* @param c
* @return
*/
private int composeInt(byte high, byte low) {
int val = (int) high & 0xff;
val *= 256;
val += (int) low & 0xff;
return val;
}
public void open(UsbManager usbManager, UsbAccessory accessory) {
Log.d("open", "Getting FileDescriptor");
mFileDescriptor = usbManager.openAccessory(accessory);
if (mFileDescriptor == null) {
Log.d("open", "Failed to get ParcelFileDescriptor");
Log.d("보드연결", "실패");
Message msg = Message.obtain(uiHandler, -1);
msg.obj = "보드연결 실패";
Log.d("open", "Sending fail message to UI Handler...");
uiHandler.sendMessage(msg);
}
else
{
Log.d("open", "Succeeded in getting ParcelFileDescriptor");
Log.d("open", "Getting FileDescriptor from ParcelFileDescriptor");
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
Log.d("open", "Getting FileInputStream...");
mInputStream = new FileInputStream(fd);
Log.d("open", "New Threading..");
Thread thread = new Thread(null, this, "ADK Example");
running = true;
Log.d("open", "Starting thread...");
thread.start();
Log.d("보드연결", "성공");
}
}
public void close() {
Log.d("close", "Closing...");
running = false;
}
/**
* 멤버 uiHandler 을 회수
* @return the uiHandler
*/
public Handler getUiHandler() {
return uiHandler;
}
/**
* sets the uiHandler of this instance to given uiHandler.
* 멤버속성 uiHandler 을 인수 uiHandler 으로 세팅.
* @param uiHandler the uiHandler to set
*/
public void setUiHandler(Handler uiHandler) {
this.uiHandler = uiHandler;
}
/**
* @return
*/
public boolean isConnected() {
return (mInputStream != null && mOutputStream != null);
}
}
_4。活动主.xml_
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/ll01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:orientation="vertical" >
<TextView
android:id="@+id/tv01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="장비미인식" />
<TextView
android:id="@+id/tv02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-1" />
<TextView
android:id="@+id/tv03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-1" />
<TextView
android:id="@+id/tv04"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-1" />
</LinearLayout>
</RelativeLayout>
5. logcat(在root MPgio minipad中使用adbwireless)
- 05-31 12:16:12.728: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
- 05-31 12:16:15.298: W/PowerUI(207): 未知意图: Intent { act=android.intent.action.ACTION_POWER_CONNECTED flg=0x10000010 }
- 05-31 12:16:15.488: I/WindowManager(140): MediaPlayer.is not PlayingVideo
- 05-31 12:16:15.728: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
- 05-31 12:16:16.088: I/WindowManager(140): MediaPlayer.is not PlayingVideo
- 05-31 12:16:17.218: I/USB3G(86): 事件 {'add', '/devices/platform/sw_hcd_host0/usb1/1-1', 'usb', '', 189, 15 }
- 05-31 12:16:17.218:I/USB3G(86):路径:'/sys/devices/platform/sw_hcd_host0/usb1/1-1'
- 05-31 12:16:17.218: I/USB3G(86): VID:size 5,vid_path '/sys/devices/platform/sw_hcd_host0/usb1/1-1/idVendor',VID '2341
- 05-31 12:16:17.218:I/USB3G(86):'。
- 05-31 12:16:17.218: I/USB3G(86): PID :size 5,Pid_path '/sys/devices/platform/sw_hcd_host0/usb1/1-1/idProduct',PID '003e
- 05-31 12:16:17.218:I/USB3G(86):'。
- 05-31 12:16:17.218: I/USB3G(86): cmd=/system/etc/usb_modeswitch.sh /system/etc/usb_modeswitch.d/2341_003e &,
- 05-31 12:16:17.228: E/EventHub(140): 无法获得 /dev/input/mouse0 的驱动程序版本,不是打字机
- 05-31 12:16:17.228: D/EventHub(140): 找不到设备“Arduino LLC Arduino Due”的输入设备配置文件。
- 05-31 12:16:17.248: I/EventHub(140): 新设备: id=15, fd=247, path='/dev/input/event4', name='Arduino LLC Arduino Due', classes=0x8000000b , configuration='', keyLayout='/system/usr/keylayout/Generic.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm', builtinKeyboard=false
- 05-31 12:16:17.298: I/USB3G(86): excute ret : 0,err:No such file or directory
- 05-31 12:16:17.318: I/InputReader(140): 设备添加: id=15, name='Arduino LLC Arduino Due', sources=0x00002103
- 05-31 12:16:17.318:I/ActivityManager(140):配置更改:{1.3 0mcc0mnc ko_KR layoutdir=0 sw640dp w1066dp h592dp lrg land finger qwerty/v/v -nav/h s.33}
- 05-31 12:16:17.338:D/OpenGLRenderer(1631):刷新缓存(模式 0)
- 05-31 12:16:17.478: D/Activity(1631): pckname = com.example.signalhello mComponent = com.example.signalhello.MainActivity
- 05-31 12:16:17.538: I/StatusBar.HeightReceiver(207): 调整状态栏大小插入=假高度=36 旧=36
- 05-31 12:16:17.658: D/onCreate(1631): 权限意图获取...
- 05-31 12:16:17.658: D/onCreate(1631): 注册接收器..
- 05-31 12:16:17.668: D/onCreate(1631): 接收者为空?错误的
- 05-31 12:16:17.668: D/onCreate(1631): 注册接收者..
- 05-31 12:16:17.668: D/onCreate(1631): 获得许可意图...
- 05-31 12:16:17.698: D/onResume(1631): 获取设备列表
- 05-31 12:16:17.698: D/onResume(1631): 获取 UsbAccessory
- 05-31 12:16:17.698: D/showMessage(1631): mAccessory 为空,设备:
- 05-31 12:16:17.698: D/com.example.signalhello.MainActivity(1631): mAccessory 为空
- 05-31 12:16:17.728: D/ViewRootImpl(1631): pckname = com.example.signalhello
- 05-31 12:16:18.138: I/WindowManager(140): MediaPlayer.is not PlayingVideo
- 05-31 12:16:18.738: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
- 05-31 12:16:20.068: D/dalvikvm(140): GC_EXPLICIT 释放 267K, 24% 释放 8736K/11399K, 暂停 8ms+13ms
- 05-31 12:16:21.738: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
我对上述情况感到非常困惑。
Arduino 板与我的笔记本电脑(编程端口)相连。(我认为它为电路板提供电源,不是吗?)因为需要电源,我没有其他电源。
而且,我编译Blink.ino
了从 Arduino 网站下载的内容。(我测试过其他草图。但没有消息。)
并且,当通过 Arduino 代码编写工具上传时,板子会闪烁。但是,当我通过 USB 电缆将板连接(连接)到 Android 设备 MPgio MiniPad 时,上面的代码没有检测到任何迹象。
只是system_process
发出一些奇怪的消息(包括在 logcat 消息上方),例如' 05-31 12:16:17.228: E/EventHub(140): could not get driver version for /dev/input/mouse0, Not a typewriter' 或' 05-31 12:16:17.228: D/EventHub(140): 找不到设备“Arduino LLC Arduino Due ”的输入设备配置文件。
但是,就在这些下方,它会打印来自 system_process 的 EventHub 标签的“新设备:id ......”。
我只想检测我的 Arduino 板。