USB_DEVICE_ATTACHED意图不解雇

时间:2011-05-28 19:16:44

标签: android usb

有没有人能够让android.hardware.usb.action.USB_DEVICE_ATTACHED“工作?”

好的,所以我正在尝试使用新的USB主机模式功能来检测何时连接USB设备。出于我的目的,我希望在设备连接时得到通知。我无法看到它发生。我正在使用我知道有效的广播接收器(当我听到其他东西时,例如按下主页按钮。无论我尝试什么,我似乎无法获得触发的意图......所以让事情更简单我决定忘记我的项目,并尝试使用谷歌自己的示例代码,看看我是否至少可以做到这一点。我没有一个导弹发射器,但我想我至少可以得到它USB_Device_Attached不用了。我修改了代码以适用于其他设备。首先我尝试调整设备过滤器xml。 我添加了我的设备(键盘):

<usb-device vendor-id="1050" product-id="0010" />

我从lsusb命令获得了供应商和产品。连接设备后,logcat会显示找到设备

D/EventHub(  144): No input device configuration file found for device 'Yubico Yubico Yubikey II'.
I/EventHub(  144): New device: id=43, fd=219, path='/dev/input/event8', name='Yubico Yubico Yubikey II', classes=0x80000003, configuration='', keyLayout='/system/usr/keylayout/Generic.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm', builtinKeyboard=false
I/InputReader(  144): Device added: id=43, name='Yubico Yubico Yubikey II', sources=0x00000101
I/ActivityManager(  144): Config changed: { scale=1.0 imsi=0/0 loc=en_US touch=3 keys=2/1/1 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=47}
D/MissileLauncherActivity(16191): intent: android.intent.action.MAIN
I/EventHub(  144): Removed device: path=/dev/input/event8 name=Yubico Yubico Yubikey II id=43 fd=219 classes=0x80000003
I/InputReader(  144): Device removed: id=43, name='Yubico Yubico Yubikey II', sources=0x00000101
I/ActivityManager(  144): Config changed: { scale=1.0 imsi=0/0 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=48}
D/dalvikvm(  144): GC_EXPLICIT freed 78K, 26% free 14717K/19719K, paused 3ms+3ms
D/MissileLauncherActivity(16191): intent: android.intent.action.MAIN

xoom确实找到了键盘,它可以在设备上使用(我可以在浏览器中使用它来输入字母)。意图类型的火(但它只触发android.intent.action.MAIN)我没有得到DEVICE_ATTACHED意图。日志条目来自示例代码:

Log.d(TAG, "intent: " + intent.getAction().toString());

在恢复功能中。在更多地挖掘并删除对usb的任何引用后,我发现每个应用程序都会在连接/分离键盘时调用简历(因此意图:android.intent.action.MAIN日志条目)。     现在我唯一可以想到的是它是android源码中的一个bug。 顺便说一下,我正在使用带有操作系统3.1的wifi xoom。

11 个答案:

答案 0 :(得分:21)

我也有同样的问题。我终于发现在设备过滤器xml中我们应该添加以下行。

<usb-device vendor-id-"xxxxx" product-id="yyyyy">

xxxxx和yyyyy应为十进制数。不是HEX代码。然后这一切都像宣传的那样工作! 我知道它已经晚了但我希望它有所帮助。

答案 1 :(得分:13)

所以我找到了解决问题的方法,并且我已经学到了很多东西,希望它可以帮助别人。

首先关闭 HID设备不会启动任何意图。它们也不会出现在mUsbManager.getDeviceList()列表中。然而其他事情。我给了一个usb记忆棒,你知道该设备列在设备列表中。我还发现返回的设备没有类,子类或协议。调试显示父接口确实具有适当的类/子类/协议。 此外,如果您必须有设备筛选器。我最终得到class=0008 (USB STORAGE)为我的目的工作。我猜其他课也可以。

所以现在要搞清楚意图。事实证明,意图必须附加到启动器活动。我试图将它附加到服务或接收器上的尝试不会有任何成果。所以现在我得到了解雇的意图我现在看到当我连接我的设备(usb记忆棒)时弹出通知它它要求我将我的应用程序设置为该设备的默认设置。现在完美我的应用程序每次连接该设备时都会运行。请注意,系统将提示您输入每个唯一的设备。但只有一次。它看起来很像默认程序。

嗯,我认为这总结了我发现的东西。当键盘/鼠标连接时,你无法收到通知。还有件事儿。 tiamat内核没有任何问题,现在运行它没有任何问题。

答案 2 :(得分:7)

我最近发现了类似问题的解决方案。

有人已经注意到,HID devices没有启动意图,我认为这是你的问题。

但是,相关的问题是,如果您的程序设置为在连接USB设备时运行,那么即使您的应用程序运行,您也无法捕获USB_DEVICE_ATTACHED操作。相反,系统会看到该意图,并说“哦,这意味着该应用程序想要运行(如清单中所声明的那样),然后它会向您发送android.intent.action.MAIN操作而不是USB_DEVICE_ATTACHED操作,并调用onResume()。即使您的应用程序正在运行。据我所知,如果您的清单声明您的应用程序将在连接USB设备时运行,则无法捕获USB_DEVICE_ATTACHED意图你只需要在onResume()中放一些代码来检查USB是否已连接。即使你的程序正在运行,当连接USB设备时,onResume也会再次被调用。

我在这里更详细地注意到我的解决方案:Android 3.1 USB-Host - BroadcastReceiver does not receive USB_DEVICE_ATTACHED

答案 3 :(得分:2)

枚举设备

如果您的应用程序有兴趣在应用程序运行时检查当前连接的所有USB设备,它可以枚举总线上的设备。使用getDeviceList()方法获取所有连接的USB设备的哈希映射。如果要从地图中获取设备,则哈希映射由USB设备的名称键入。

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();

如果需要,您还可以从哈希映射中获取迭代器并逐个处理每个设备:

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
    UsbDevice device = deviceIterator.next()
    //your code
}

答案 4 :(得分:2)

我遇到了同样的问题。我的最终解决方案是使用老式的轮询技术。这是一个相当小的课程,它解决了我满意的问题。

package com.YourCompancy.YourProduct;

import android.app.*;
import android.content.*;

import android.hardware.usb.*;
import java.util.*;
import android.util.*;
import android.os.*;

public class UsbDeviceWatcher extends BroadcastReceiver
{   
    public void onReceive(Context context, Intent intent)
    {
        if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED))
        {
            UsbDevice d = (UsbDevice)
                intent.getExtras().get(UsbManager.EXTRA_DEVICE);

            DeviceConnect(d, false);
        }
    }

    public void DeviceConnect(UsbDevice device, boolean Attached)
    {
            if (Attached)
            {
                            // Some suggestions ...
                            //    play sound effect
                            //    notify consumer software
                            //    determine if interested in device
                            //    etc
                            Log.i("usb", "device attached");

            } else
            {
                Log.i("usb", "device detached");
            }

    }

    public UsbManager manager;
    public Handler handler;

    public UsbDeviceWatcher(Context context, Handler handle)
    {

        this.handler = handle;

        manager = (UsbManager) 
            context.getSystemService(Context.USB_SERVICE);

        IntentFilter dev = new IntentFilter();

        dev.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);

        context.registerReceiver(this, dev);    

        final UsbDeviceWatcher _this = this;

        Thread thread = new Thread(new Runnable()
        {
            public void run()
            {
                LinkedList<UsbDevice> seen = new LinkedList<UsbDevice>();
                LinkedList<UsbDevice> attached = new LinkedList<UsbDevice>();

                            //there is a need for multithread support here
                                //   so the thread can watch for an exit condition
                while (true)
                {

                    HashMap<String, UsbDevice>
                        D = manager.getDeviceList();

                    for (UsbDevice d : D.values())
                    {
                        if (!seen.contains(d))
                        {
                            if (!attached.contains(d))
                            {
                                final UsbDevice dev = d;

                                handler.post(new Runnable(){
                                    public void run()
                                    {
                                        DeviceConnect(dev, true);
                                    }
                                });
                            }

                            seen.add(d);
                        }
                    }

                    for (UsbDevice d : seen)
                    {
                        if (!D.values().contains(d)) seen.remove(d);
                    }

                    try
                    {
                        Thread.sleep(500);  
                    } catch (InterruptedException exception)
                    {
                        return; 
                    }
                }

            }
        });

        thread.start();
    }
}

答案 5 :(得分:2)

另一种解决方法是使用

new FileObserver("/dev/input") {
  @Override public void onEvent(int event, String path) {
     //gets called on input device insert / remove
  }
};

适用于某些USB设备(键盘,鼠标)

答案 6 :(得分:1)

确定更多工作,更多失败,但取得了一些进展。

我从sdk文档中发现了更多信息。您似乎必须拥有设备过滤器才能使用意图。所以我决定尝试使用类过滤器而不是供应商/产品ID。我认为这将是更一般的,并希望抓住隐藏设备。我使用03h作为类ID,我尝试了各种格式,我尝试了子类,我甚至使用lsusb来发现我的设备的类,子类和协议。这些似乎没有任何帮助。所以我进一步研究了sdk文档,并决定尝试枚举所有设备,看看os看到了类/子类/协议整数。我将粘贴的代码复制到click侦听器并添加了log.v语句。 logcat中没有显示任何内容。

它看起来像美国系统没有看到任何设备(即使设备实际工作。)现在这非常表明USB设备连接意图没有触发。现在我必须说我在我的xoom(tiamat)中使用自定义内核。我以为这可能与前一段时间的问题有关,所以我恢复了库存3.1。现在还在进步现在这是在我尝试枚举之前,所以现在我将恢复agaian并继续使用库存,直到我确定内核不是问题。当我发现更多时,我会回来查看。成功与失败。当然,如果有其他人比我更好地解读这个请求。 最后一点说明当我在文档中看到这个时,我非常担心整个otg主机模式。请注意,即使它参考两种枚举方法,coe也是相同的。可能只是一个复制作者的错误,但仍然担心所有这些失败。

答案 7 :(得分:1)

我的应用设置为launchMode="singleTop",在该模式下,似乎getIntent().getAction()始终等于首次启动应用的操作。

因此,如果您手动启动应用程序并然后插入设备(即使在离开该应用程序后),您将收到android.intent.action.MAIN

如果你杀了应用程序然后插入设备,你将永远得到android.hardware.usb.action.USB_DEVICE_ATTACHED,即使是切换回你的应用程序,甚至旋转设备。 / p>

我实际上在拔掉USB设备时非常奇怪地接受了意图,我认为这些设备没有记录 - 当然,当我的设备被拆卸时,我会收到USB_DEVICE_ATTACHED

如果没有singleTop,它会按预期工作,但如果您的应用已经打开并插入设备,那么您将获得另一项愚蠢的额外活动。

Android的API再次出现问题,过于复杂且难以使用。

答案 8 :(得分:1)

这是我检测USB / Media Connect的方法。

清单文件

    <receiver
            android:name=".UsbReceiver"
            android:enabled="true" >
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_MOUNTED"/>
            <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
            <data android:scheme="file"/>
        </intent-filter>
    </receiver>

我没有在活动和接收器中做任何事情。

看起来这条线正在做的事情。

<data android:scheme="file"/>

答案 9 :(得分:0)

根据我的测试,Android 可以在连接HID设备时触发意图。 (MissileLauncher示例应用程序就是这样做的。有关详细信息,请参阅示例源代码。)

Missile Launcher(Dream Cheeky USB Missle Launcher)HID Device的子类和协议设置为0x00。有关详细信息,请参阅:http://www.mattcutts.com/blog/playing-with-a-usb-missile-launcher/

需要注意的是,Android并没有特别针对鼠标和键盘设备(可能更多)。但是,我可以检测到其InterfaceClass = 0x03,InterfaceSubClass = 0x00,InterfaceProtocol = 0x00的HID设备。对于我的应用程序,我的HID设备是嵌入式控制器,因此设置子类和协议不是问题。

答案 10 :(得分:0)

连接Usb键盘 WONT 触发 USB_DEVICE_ATTACHED

相反,系统将触发 Intent.ACTION_CONFIGURATION_CHANGED 。但是,由于存在配置更改,系统将重新启动Activity。在重新启动Activity时,您不会捕获该操作。在这种情况下,您需要在Android Manifest中添加 android:configChanges =“keyboard | keyboardHidden”,以便在连接外部键盘后不会重新启动Activity。