I have problem working on an Android accessory job with Arduino Due which is uploaded Blink.ino (other samples too). The problem is that I couldn't detect any USB accessory (or List) from UsbManager
got from getSystemService("USB_SERVICE")
in any case with attaching or detaching.
My code is below.
1. manifest
<?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. accessory-filter.xml in res/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. MainActivity
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. acivity_main.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 ( using adbwireless in rooting MPgio minipad )
- 05-31 12:16:12.728: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
- 05-31 12:16:15.298: W/PowerUI(207): unknown intent: 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): event { 'add', '/devices/platform/sw_hcd_host0/usb1/1-1', 'usb', '', 189, 15 }
- 05-31 12:16:17.218: I/USB3G(86): path : '/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): could not get driver version for /dev/input/mouse0, Not a typewriter
- 05-31 12:16:17.228: D/EventHub(140): No input device configuration file found for device 'Arduino LLC Arduino Due '.
- 05-31 12:16:17.248: I/EventHub(140): New device: 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): Device added: id=15, name='Arduino LLC Arduino Due ', sources=0x00002103
- 05-31 12:16:17.318: I/ActivityManager(140): Config changed: {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): Flushing caches (mode 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): Resizing status bar plugged=false height=36 old=36
- 05-31 12:16:17.658: D/onCreate(1631): Permission intent getting...
- 05-31 12:16:17.658: D/onCreate(1631): registering Receiver..
- 05-31 12:16:17.668: D/onCreate(1631): receiver is null ? false
- 05-31 12:16:17.668: D/onCreate(1631): registered Receiver..
- 05-31 12:16:17.668: D/onCreate(1631): Got permission intent...
- 05-31 12:16:17.698: D/onResume(1631): Getting device list
- 05-31 12:16:17.698: D/onResume(1631): Getting UsbAccessory
- 05-31 12:16:17.698: D/showMessage(1631): mAccessory is null, devices:
- 05-31 12:16:17.698: D/com.example.signalhello.MainActivity(1631): mAccessory is null
- 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 freed 267K, 24% free 8736K/11399K, paused 8ms+13ms
- 05-31 12:16:21.738: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
I'm very confused with my situation with above things.
The Arduino board is connected with my notebook PC (programming port). (I think it provides power to the board, doesn't it?) Because the power supply is needed, no other power supplier I have.
And, I compiled Blink.ino
which I downloaded from Arduino's site. (I have tested other sketches. But no news.)
And, the board works blinking when uploaded by the Arduino code writing tool. But when I attached (connected) the board by USB cable to Android device MPgio MiniPad, I have no sign of detection with my codes above.
Just system_process
issues some strange messages (which are included above logcat messages) like '05-31 12:16:17.228: E/EventHub(140): could not get driver version for /dev/input/mouse0, Not a typewriter' or '05-31 12:16:17.228: D/EventHub(140): No input device configuration file found for device 'Arduino LLC Arduino Due '.
But, just below those, it prints 'New device: id......' which is from system_process's EventHub Tag.
I want to just detect my Arduino board.