USB_DEVICE_ATTACHED Intent not firing

2019-01-13 08:27发布

Has anyone out there been able to get the android.hardware.usb.action.USB_DEVICE_ATTACHED" to work?

Ok so i'm trying to use the new usb host mode features to detect when a usb device is attached. For my purposes i want to be notified any time a device is attached. I was not able to see it happen. I'm using a broadcast reciever that i know works (when i have it listen for other things such as the home button being pressed. No matter what i try i can't seem to get the intent to fire.... So to make things simpler i decided to forget about my project and attempt to use google's own sample code and see if i could at least make that work. I don't have one of the missle launcher but i figured i could at least get it the USB_Device_Attached to fire. No go. I adapted the code to work for other devices. First i tried adjusting the device filter xml. I added my device (a keyboard):

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

I got the vendor and product from an lsusb command. When the device is attached the logcat shows that the device is found

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

The xoom does find the keyboard and it is usable from the device (i can use it in the browser to type letters). And the intent sort of fires (but it only fires the android.intent.action.MAIN) i don't ever get the DEVICE_ATTACHED Intent. The log entry comes from the sample code:

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

In the resume function. After more digging and removing any reference to usb i found that every app i make get's the resume called when a keyboard is attached/detached (hence the intent: android.intent.action.MAIN log entry). Right now the only thing i can figure is that it's a bug in the android source. By the way i'm using a wifi xoom with os 3.1.

标签: android usb
11条回答
Melony?
2楼-- · 2019-01-13 08:41

Connect Usb Keyboard WONT fire USB_DEVICE_ATTACHED.

Instead, the System will fire Intent.ACTION_CONFIGURATION_CHANGED. However, as there is a configuration change, system will restart the Activity. You wont catch the action with the Activity restarted. In this case, you need to add android:configChanges="keyboard|keyboardHidden" in your Android Manifest so that the Activity wont be restarted once a external keyboard is connected.

查看更多
不美不萌又怎样
3楼-- · 2019-01-13 08:44

I also had the same problem. I finally figured out that in the device filter xml we should add following line.

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

the xxxxx and yyyyy should be decimal numbers. NOT HEX CODES. Then it all works as advertised! I know it is late but I hope it helps.

查看更多
劫难
4楼-- · 2019-01-13 08:52

So I found a solution to my problem and I've learned a lot hopefully it can help someone else.

So first off HID devices do not kick off any intent. Nor do they show up in the mUsbManager.getDeviceList() list. Other things however do. I gave a usb memory stick a go and what do you know the device is listed in the device list. I also found out that the device returned does not have the a class,subclass, or protocol. Debugging revealed that the parent interface did however have the proper class/subclass/and protocol. Also if you must have a device filter. I ended up with a class=0008 (USB STORAGE) to work for my purposes. I'm guessing other classes would work as well.

So now on to figuring out intents. Turns out that the intent must be attached to a launcher activity. My attempts to attach it to a service or receiver will not bear any fruits. So now that I'm getting intents to fire I now see notifications popup when I attach my device (usb memory stick) it asks me to set my app as the default for that device. Perfect now my app gets run every time I attach that device. Note that you will be prompted for each unique device. But only once. It seems to be registered much like default programs.

Well, I think that about sums up what I found. too bad you can't get notified when an keyboard/mouse gets attached. Oh and one more thing. There are not any problems with the tiamat kernel, running it right now and no problems.

查看更多
虎瘦雄心在
5楼-- · 2019-01-13 08:52

I recently discovered a solution to a similar issue.

As someone has already noted, HID devices do not kick off an intent, which I think was your issue.

However, a related issue is that, if your program is set to run when a USB device is connected, then even once your application is running, you can't capture the USB_DEVICE_ATTACHED action. Instead, the system sees that intent, and says "oh that means this application wants to run (as declared in your manifest) and then it sends you the android.intent.action.MAIN action instead of the USB_DEVICE_ATTACHED action, and it calls onResume(). Even if your app is running. So as far as I can tell, you CAN'T capture the USB_DEVICE_ATTACHED intent if your manifest declares that your app will run when USB devices are attached. You just have to put some code in onResume() to check to see if USB is connected. Even if your program is running, onResume will get called again when a USB device is attached.

I note my solution in more detail here: Android 3.1 USB-Host - BroadcastReceiver does not receive USB_DEVICE_ATTACHED

查看更多
倾城 Initia
6楼-- · 2019-01-13 08:52

I had the same problem. My ultimate solution was to use the old fashioned polling technique. Here is a fairly minimal class which solves the problem to my satisfaction.

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();
    }
}
查看更多
\"骚年 ilove
7楼-- · 2019-01-13 08:57

Another workaround is to use

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

which will work for some usb devices (keyboard, mouse)

查看更多
登录 后发表回答