Android 如何与USB设备通信?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10183794/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to communicate with a USB device?
提问by Andres
I am trying to establish USB communication as host. I am following the examples here http://developer.android.com/guide/topics/usb/host.htmlbut I cannot get this working. Here is my code:
我正在尝试建立作为主机的 USB 通信。我正在关注http://developer.android.com/guide/topics/usb/host.html 中的示例,但我无法使其正常工作。这是我的代码:
private static final String ACTION_USB_PERMISSION = "com.multitools.andres.LCView";
UsbDevice device;
//Pide permisos al usuario para comunicacion con el dispositivo USB
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) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
//call method to set up device communication
}
}
else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(DEBUG) Log.i(TAG, "onCreate() -> MainMenu");
actionBar = getActionBar(); //obtengo el ActionBar
actionBar.setDisplayHomeAsUpEnabled(true); //el icono de la aplicacion funciona como boton HOME
//Menu
setListAdapter(new ArrayAdapter<String>(MainMenu.this, android.R.layout.simple_list_item_1, MenuNames));
//USB
if(DEBUG) Log.i(TAG, "Setting UsbManager -> MainMenu");
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
PendingIntent mPermissionIntent;
if(DEBUG) Log.i(TAG, "Setting PermissionIntent -> MainMenu");
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
if(DEBUG) Log.i(TAG, "Setting IntentFilter -> MainMenu");
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
if(DEBUG) Log.i(TAG, "Setting registerReceiver -> MainMenu");
registerReceiver(mUsbReceiver, filter);
if(DEBUG) Log.i(TAG, "Setting requestPermission -> MainMenu");
mUsbManager.requestPermission(device, mPermissionIntent);
}
I get the Force Close dialog when I uncomment the line mUsbManager.requestPermission(device, mPermissionIntent);
If I comment it, I don't get the force close but it doesnt work. I think the problem is in:
当我取消注释该行时,我会收到“强制关闭”对话框mUsbManager.requestPermission(device, mPermissionIntent);
如果我对其进行注释,我不会强制关闭,但它不起作用。我认为问题在于:
private static final String ACTION_USB_PERMISSION = "com.multitools.andres.LCView";
On Google's example it is as:
在谷歌的例子中,它是这样的:
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
But I dont know what exactly I have to put there and i could not find any explanation about that. What i have to put there or where is my error ? Here is the LogCat i am getting when i start my application:
但我不知道我到底要放什么,我找不到任何解释。我必须在那里放什么或我的错误在哪里?这是我启动应用程序时得到的 LogCat:
04-17 00:57:50.944: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:51.331: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:51.981: I/(1362): onCreate() -> MainMenu
04-17 00:57:52.013: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:52.151: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:52.570: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:52.731: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:53.122: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:53.231: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:53.390: I/(1362): Setting UsbManager -> MainMenu
04-17 00:57:53.451: I/(1362): Setting PermissionIntent -> MainMenu
04-17 00:57:53.470: I/(1362): Setting IntentFilter -> MainMenu
04-17 00:57:53.470: I/(1362): Setting registerReceiver -> MainMenu
04-17 00:57:53.511: I/(1362): Setting requestPermission -> MainMenu
04-17 00:57:53.660: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:53.791: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:54.311: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:54.401: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:54.531: I/(1362): onCreateOptionsMenu() -> MainMenu
04-17 00:57:54.683: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:54.772: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:55.186: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:55.291: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:55.661: I/dalvikvm(1362): threadid=3: reacting to signal 3
04-17 00:57:55.751: I/dalvikvm(1362): Wrote stack traces to '/data/anr/traces.txt'
04-17 00:57:55.791: D/gralloc_goldfish(1362): Emulator without GPU emulation detected.
04-17 01:11:47.323: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:47.720: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
04-17 01:11:48.124: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:48.291: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
04-17 01:11:48.452: I/(1459): onCreate() -> MainMenu
04-17 01:11:48.691: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:48.813: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
04-17 01:11:49.172: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:49.321: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
04-17 01:11:49.653: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:49.821: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
04-17 01:11:49.901: I/(1459): Setting UsbManager -> MainMenu
04-17 01:11:49.931: I/(1459): Setting PermissionIntent -> MainMenu
04-17 01:11:50.021: I/(1459): Setting IntentFilter -> MainMenu
04-17 01:11:50.031: I/(1459): Setting registerReceiver -> MainMenu
04-17 01:11:50.051: I/(1459): Setting requestPermission -> MainMenu
04-17 01:11:50.071: D/AndroidRuntime(1459): Shutting down VM
04-17 01:11:50.133: W/dalvikvm(1459): threadid=1: thread exiting with uncaught exception (group=0x409c01f8)
04-17 01:11:50.231: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:50.331: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
04-17 01:11:50.401: E/AndroidRuntime(1459): FATAL EXCEPTION: main
04-17 01:11:50.401: E/AndroidRuntime(1459): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.multitools.andres/com.multitools.andres.MainMenu}: java.lang.NullPointerException
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.app.ActivityThread.access0(ActivityThread.java:123)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.os.Handler.dispatchMessage(Handler.java:99)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.os.Looper.loop(Looper.java:137)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.app.ActivityThread.main(ActivityThread.java:4424)
04-17 01:11:50.401: E/AndroidRuntime(1459): at java.lang.reflect.Method.invokeNative(Native Method)
04-17 01:11:50.401: E/AndroidRuntime(1459): at java.lang.reflect.Method.invoke(Method.java:511)
04-17 01:11:50.401: E/AndroidRuntime(1459): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
04-17 01:11:50.401: E/AndroidRuntime(1459): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
04-17 01:11:50.401: E/AndroidRuntime(1459): at dalvik.system.NativeStart.main(Native Method)
04-17 01:11:50.401: E/AndroidRuntime(1459): Caused by: java.lang.NullPointerException
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.os.Parcel.readException(Parcel.java:1333)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.os.Parcel.readException(Parcel.java:1281)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.hardware.usb.IUsbManager$Stub$Proxy.requestDevicePermission(IUsbManager.java:535)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.hardware.usb.UsbManager.requestPermission(UsbManager.java:361)
04-17 01:11:50.401: E/AndroidRuntime(1459): at com.multitools.andres.MainMenu.onCreate(MainMenu.java:80)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.app.Activity.performCreate(Activity.java:4465)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
04-17 01:11:50.401: E/AndroidRuntime(1459): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
04-17 01:11:50.401: E/AndroidRuntime(1459): ... 11 more
04-17 01:11:50.751: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:50.851: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
04-17 01:11:51.331: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:51.403: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
04-17 01:11:51.774: I/dalvikvm(1459): threadid=3: reacting to signal 3
04-17 01:11:51.961: I/dalvikvm(1459): Wrote stack traces to '/data/anr/traces.txt'
Thanks you :)
谢谢 :)
回答by chandsie
That string is just a marker so you recognize the intent that is returned when you call registerReceiver(mUsbReceiver, filter);
. That isn't the problem.
该字符串只是一个标记,因此您可以识别调用时返回的意图registerReceiver(mUsbReceiver, filter);
。那不是问题。
I think the problem is here:
我认为问题出在这里:
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
This line is supposed to get you your USB Manager, but as far as I recall not all phones have to support the Android USB Accessory API. This line is probably just assigning null
to mUsbManager
which then causes you NullPointerException
when you call a method on it further down in the code. Trying checking if that isn't null
before making a call on it.
这条线应该让你得到你的 USB 管理器,但据我所知,并不是所有的手机都必须支持 Android USB 配件 API。这一行可能只是分配null
给mUsbManager
它,然后NullPointerException
当您在代码中进一步调用它的方法时会导致您。null
在打电话之前尝试检查这是否不是。
For more info, checkout these links:
有关更多信息,请查看以下链接:
- http://developer.android.com/guide/topics/usb/index.html
- http://developer.android.com/guide/topics/usb/accessory.html
- http://developer.android.com/guide/topics/usb/index.html
- http://developer.android.com/guide/topics/usb/accessory.html
EDIT:
编辑:
I think I see what the issue is now. You're right, it's not the USB Manager. It's the UsbDevice object (device
). It is never initialized anywhere in your code. In this line :
我想我现在明白问题所在了。你是对的,这不是 USB 管理器。它是 UsbDevice 对象 ( device
)。它永远不会在您的代码中的任何地方初始化。在这一行:
mUsbManager.requestPermission(device, mPermissionIntent);
you're basically firing off an intent to ask the user if it's okay for you to work with the device represented by the UsbDevice object device
. However when this call gets fired device
has not yet been initialized (and therefore has the default value of null
). So when you try to request permission you end up getting a NullPointerException
instead of the expected result. To fix this you need to figure out which device you want to connect to and assign it to device
. Look in here, under "Enumerating devices" to figure out different ways to do that. One way, if you know the name of the device you want to connect to, is to make the following calls after you retrieve the Usb Manager:
您基本上是在激发询问用户是否可以使用 UsbDevice 对象表示的设备的意图device
。然而,当这个调用被触发时还device
没有被初始化(因此具有默认值null
)。因此,当您尝试请求许可时,您最终会得到一个NullPointerException
而不是预期的结果。要解决此问题,您需要确定要连接的设备并将其分配给device
. 看看这里,在“枚举设备”下找出不同的方法来做到这一点。一种方法是,如果您知道要连接的设备的名称,则在检索 Usb 管理器后进行以下调用:
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
device = deviceList.get("<deviceName>");
(Obviously, you would replace <deviceName>
with the actual name of the device.
(显然,您将替换<deviceName>
为设备的实际名称。
回答by dajun
minSdkVersion
must >= 12
minSdkVersion
必须 >= 12
To enable USB host API support you should add a file named android.hardware.usb.host.xml and containing the following lines:
要启用 USB 主机 API 支持,您应该添加一个名为 android.hardware.usb.host.xml 并包含以下行的文件:
<permissions>
<feature name="android.hardware.usb.host"/>