java - Android 3.1 USB-Host - BroadcastReceiver 不接收 USB_DEVICE_ATTACHED

标签 java android usb

我工作过 the description and samples for USB host at developer.android.com检测连接和分离的 USB 设备。

如果我在连接设备时在 list 文件中使用 Intent 过滤器来启动我的应用程序,它可以正常工作:插入,检测到设备,android 请求启动应用程序的权限,设备信息显示在一张 table 。

我正在开发的应用程序不应仅在连接/分离设备时启动/完成(例如数据管理目的)。如果应用程序已经在运行,我也不希望打开对话框弹出。因此,我决定如果连接了设备,则不直接启动 Activity ,而是注册一个 BroadcastReceiver,它(稍后)应该在设备处于/分离状态时通知 Activity 。这个接收器可以很好地识别分离 Action ,但不能识别附加 Action 。

我是否缺少权限或数据属性或类似的东西?教程和示例没有说明额外的必要属性。

这是 list 文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest 
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="de.visira.smartfdr"
  android:versionCode="1"
  android:versionName="1.0">

<uses-sdk android:minSdkVersion="12" />
<uses-feature android:name="android.hardware.usb.host" />

<application android:icon="@drawable/icon" android:label="@string/app_name">


    <receiver android:name=".usb.Detector">
        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
        </intent-filter>

        <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
            android:resource="@xml/device_filter" />
        <meta-data android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
            android:resource="@xml/device_filter" />
    </receiver>
</application>

接收者:

public class FDRDetector extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();

    Toast.makeText(context, "Action: " + action, 3).show();
            // pops up only if action == DETACHED
}

我不明白为什么相同的 Intent 过滤器可以工作,如果我在 Activity 上使用它们,但如果它们应用于接收器则不行?即使我在代码中设置了接收器和过滤器,也无法识别附件。

我的工作环境: IDE:带有 Android 插件的 Eclipse 3.7

设备:Acer Iconia Tab A500

安卓:3.1

提前致谢

最佳答案

啊哈!我想到了。我遇到了完全相同的问题。

它的要点是 - 如果您在插入设备时自动启动您的应用程序(使用 list 文件),那么看起来 Android 系统 获得了 ACTION_USB_DEVICE_ATTACHED Intent ,然后因为它知道您的应用程序想要在这种情况下运行,它实际上向您的应用程序发送 android.intent.action.MAIN Intent 。它从不向您的应用程序发送 ACTION_USB_DEVICE_ATTACHED 操作,因为它认为它已经知道您的应用程序在这种情况下想要做什么。

我刚刚发现了问题,我想我有一个解决方案,但我可以告诉你我发现了什么:

即使您的应用程序正在运行并且在前台,当您插入 USB 设备并且 Android 系统获取 ACTION_USB_DEVICE_ATTACHED Intent 时,它也会在您的 Activity 中调用 onResume()。

很遗憾,您不能这样做:

@Override
public void onResume() {
    super.onResume();

    Intent intent = getIntent();
    Log.d(TAG, "intent: " + intent);
    String action = intent.getAction();

    if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
        //do something
    } 
}

因为 Intent 将以 android.intent.action.MAIN 的形式返回,而不是 ACTION_USB_DEVICE_ATTACHED。

如果您只是离开应用程序,但不拔掉 USB,您会得到 android.intent.action.MAIN,这很烦人。我想让设备进入休眠状态并重新唤醒它会做同样的事情。

所以根据我的发现,您无法直接获得 Intent ,但似乎您可以依赖在插入 USB 设备时调用 onResume(),因此解决方案是检查以查看如果每次收到 onResume 时都连接了 USB。您还可以在 USB 断开连接时设置一个标志,因为 USB 断开连接 Intent 当然可以正常触发。

所以总的来说,您的广播接收器可能如下所示:

// BroadcastReceiver when remove the device USB plug from a USB port  
BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
         if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {                
        usbConnected=false;             
        }
    }
};

你会在 onCreate 里面有这个:

  // listen for new devices
 IntentFilter filter = new IntentFilter();
 filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
 registerReceiver(mUsbReceiver, filter);

这位于 list 中的 Activity 标签内:

        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
        </intent-filter>

        <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
            android:resource="@xml/device_filter" />

您的/res/xml/文件夹中将有一个 device_filter.xml 文件,如下所示:

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <usb-device vendor-id="1027" product-id="24577" />  
    <usb-device vendor-id="1118" product-id="688" /> 
</resources>

(当然可以使用您需要的任何供应商 ID 和产品 ID)

然后你的 onCreate 看起来像这样:

@Override
public void onResume() {
    super.onResume();

    Intent intent = getIntent();
    Log.d(TAG, "intent: " + intent);
    String action = intent.getAction();


    if (usbConnected==false ) {
        //check to see if USB is now connected
    } 
}

我没有用于检查 USB 是否已连接的特定代码,因为我实际上还没有深入研究。我正在使用一个可以连接的库,所以对于我的应用程序,我可以启动那个循环,我很好。

将 list 中 Activity 的启动模式设置为“singleTask”也很重要,以防止它在已经运行时再次运行,否则插入 USB 设备只会启动应用程序的第二个实例!

所以我的 list 中的整个 Activity 标签如下所示:

    <activity
        android:label="@string/app_name"
        android:name="com.awitness.common.TorqueTablet"
        android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen"
        android:screenOrientation="landscape"
        android:configChanges="orientation|keyboardHidden" 
        android:launchMode="singleTask"
        >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME"/>
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter> 

        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
        </intent-filter>

        <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
            android:resource="@xml/device_filter" />

    </activity>

无论如何,我希望这对某人有所帮助!我很惊讶我已经无法找到解决方案!

关于java - Android 3.1 USB-Host - BroadcastReceiver 不接收 USB_DEVICE_ATTACHED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6981736/

相关文章:

java - 将 MotionEvent 值存储在 ArrayList 中

linux - Docker 中的 Usbip

java - 为什么函数没有参数化的返回类型,因为它有参数化的输入?

java - 如何为模型中的每个元素生成编辑模式?

Java 运算符优先级示例

android - 路径像水平菜单按钮

java - Zbar 扫描仪错误 java.lang.RuntimeException : cancelAutoFocus failed

c# - 连接到数字秤(Mettler Toledo PS90)作为 HID 仅当电缆首次连接到计算机时运行 On Report

android - android adb "usb device not found"问题的原因?

java - IBM Watson 语音到文本的依赖性