簡體   English   中英

USB_DEVICE_ATTACHED Intent 未觸發

[英]USB_DEVICE_ATTACHED Intent not firing

有沒有人能夠讓 android.hardware.usb.action.USB_DEVICE_ATTACHED" 工作?

好的,所以我正在嘗試使用新的 usb 主機模式功能來檢測何時連接了 usb 設備。 出於我的目的,我希望在連接設備時收到通知。 我無法看到它發生。 我正在使用我知道有效的廣播接收器(當我讓它監聽其他事情時,例如按下主頁按鈕。無論我嘗試什么,我似乎都無法獲得觸發的意圖......所以讓事情變得更簡單我決定忘記我的項目並嘗試使用谷歌自己的示例代碼,看看我是否至少可以完成這項工作。我沒有導彈發射器之一,但我想我至少可以得到它的 USB_Device_Attached開火。沒有 go。我修改了代碼以適用於其他設備。首先我嘗試調整設備過濾器 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());

在簡歷中 function。 經過更多挖掘和刪除對 usb 的任何引用后,我發現我制作的每個應用程序都會在連接/分離鍵盤時調用簡歷(因此意圖:android.intent.action.MAIN 日志條目)。 現在我唯一能想到的是它是 android 源代碼中的一個錯誤。 順便說一句,我使用的是 os 3.1 的 wifi xoom。

我也有同樣的問題。 我終於發現在設備過濾器 xml 中我們應該添加以下行。

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

xxxxx 和 yyyyy 應該是十進制數。 不是十六進制代碼。 然后這一切都像宣傳的那樣工作。 我知道已經晚了,但我希望它有所幫助。

因此,我找到了解決問題的方法,並且學到了很多東西,希望它可以幫助其他人。

因此,首先關閉HID 設備不會啟動任何意圖 它們也不會出現在mUsbManager.getDeviceList()列表中。 然而其他的事情。 我給了一個 usb memory 棒一個 go 你知道什么設備列在設備列表中。 我還發現返回的設備沒有 class、子類或協議。 調試顯示父接口確實具有正確的類/子類/和協議。 此外,如果您必須有設備過濾器。 我最終得到了一個class=0008 (USB STORAGE)來滿足我的目的。 我猜其他課程也可以。

所以現在開始弄清楚意圖。 事實證明,意圖必須附加到啟動器活動。 我嘗試將它附加到服務或接收器不會產生任何結果。 因此,現在我打算觸發我現在在連接設備(usb memory 棒)時看到彈出通知,它要求我將我的應用程序設置為該設備的默認應用程序。 現在完美了,每次連接該設備時我的應用程序都會運行。 請注意,系統將提示您輸入每個唯一設備。 但只有一次。 它似乎像默認程序一樣注冊。

好吧,我認為這總結了我的發現。 太糟糕了,當連接鍵盤/鼠標時,您無法收到通知。 還有件事兒。 tiamat kernel 沒有任何問題,現在運行它沒有問題。

我最近發現了一個類似問題的解決方案。

正如有人已經指出的那樣, HID devices不會啟動意圖,我認為這是您的問題。

但是,一個相關的問題是,如果您的程序設置為在連接 USB 設備時運行,那么即使您的應用程序正在運行,您也無法捕獲USB_DEVICE_ATTACHED操作。 相反,系統會看到該意圖,並說“哦,這意味着該應用程序想要運行(如您的清單中聲明的那樣),然后它向您發送 android.intent.action.MAIN 操作而不是USB_DEVICE_ATTACHED操作,並調用onResume() 。即使您的應用程序正在運行。據我所知,如果您的清單聲明您的應用程序將在連接 USB 設備時運行,則您無法捕獲USB_DEVICE_ATTACHED意圖。您只需在onResume()中放入一些代碼onResume()檢查 USB 是否已連接。即使您的程序正在運行,當連接 USB 設備時,onResume 也會再次調用。

我在這里更詳細地記錄了我的解決方案: Android 3.1 USB-Host - BroadcastReceiver does not receive USB_DEVICE_ATTACHED

我有同樣的問題。 我的最終解決方案是使用老式的輪詢技術。 這是一個相當小的 class 解決了我滿意的問題。

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();
    }
}

另一種解決方法是使用

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

這適用於某些 usb 設備(鍵盤、鼠標)

枚舉設備

如果您的應用程序有興趣在您的應用程序運行時檢查當前連接的所有 USB 設備,它可以枚舉總線上的設備。 使用 getDeviceList() 方法獲取所有連接的 USB 設備的 hash map。 hash map 由 USB 設備的名稱作為鍵,如果您想從 Z1D78DC1141214E5AEZB 獲取設備。

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

如果需要,您也可以只從 hash map 獲取迭代器,並逐個處理每個設備:

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
}

我將我的應用程序設置為launchMode="singleTop"並且在該模式下似乎getIntent().getAction()始終等於首次啟動應用程序的操作。

因此,如果您手動啟動應用程序然后插入設備(即使從該應用程序切換后),您將收到android.intent.action.MAIN

如果你殺死應用程序然后插入設備,你總是會得到android.hardware.usb.action.USB_DEVICE_ATTACHED ,即使是從切換到你的應用程序,甚至是旋轉設備

實際上,在拔出 USB 設備時,我奇怪地收到了意圖,我認為沒有記錄在案 - 但當然,當我的設備分離時,我會收到USB_DEVICE_ATTACHED

如果沒有singleTop ,它會按預期工作,但是如果您的應用程序已經打開並且您插入設備,那么您會得到另一個愚蠢的額外活動。

Android 的 API 再次出現問題,過於復雜且難以使用。

這就是我為檢測 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"/>

好的,更多的工作,更多的失敗,但有些進步。

我從 sdk 文檔中找到了更多信息。 看來您必須擁有設備過濾器才能使用意圖。 所以我決定嘗試使用 class 過濾器而不是供應商/產品 ID。 我認為它會更通用,並希望能抓住隱藏設備。 我使用 03h 作為 class id,我嘗試了各種格式,我嘗試了子類,我什至使用 lsusb 來發現,class,子類和我的設備的協議。 這些似乎根本沒有幫助。 所以我進一步研究了 sdk 文檔並決定嘗試枚舉所有設備以查看操作系統看到的類/子類/協議整數。 我復制了粘貼到點擊監聽器中的代碼並添加了 log.v 語句。 logcat 中沒有顯示任何內容。

看起來,美國系統沒有看到任何設備(即使該設備實際工作。)現在這非常表明 USB 設備連接意圖未觸發。 現在我必須說我在我的 xoom (tiamat) 中使用了自定義 kernel。 我認為這可能與前一段時間的問題有關,所以我恢復到股票 3.1。 現在仍然在進步。 現在這是不久前,在我嘗試枚舉之前,所以現在我將再次恢復並繼續使用庫存,直到我確定 kernel 不是問題。 當我發現更多信息時,我會回來查看。 成功或失敗。 當然,如果其他人比我更能理解這一點,請加入。最后一點,當我在文檔中看到這一點時,我非常擔心整個 otg 主機模式。請注意,即使它引用了兩種方法,coe 也是相同的枚舉。 可能只是文案作者的錯誤,但鑒於所有這些失敗,仍然有些擔心。

根據我的測試,Android可以在連接 HID 設備時觸發意圖。 (MissileLauncher 示例應用程序就是這樣做的。有關更多信息,請參閱示例源代碼。)

Missile Launcher (Dream Cheeky USB Missle Launcher) HID 設備的子類和協議設置為 0x00。 欲了解更多信息,請參閱: http://www.mattcutts.com/blog/playing-with-a-usb-missile-launcher/

需要注意的是,Android 並沒有專門針對鼠標和鍵盤設備(可能更多)。 但是,我可以檢測到 InterfaceClass = 0x03、InterfaceSubClass = 0x00、InterfaceProtocol = 0x00 的 HID 設備。 對於我的應用程序,我的 HID 設備是嵌入式 controller,因此設置子類和協議不是問題。

連接 Usb 鍵盤不會觸發USB_DEVICE_ATTACHED

相反,系統將觸發Intent.ACTION_CONFIGURATION_CHANGED 但是,由於有配置更改,系統會重新啟動 Activity。 您不會在 Activity 重新啟動時捕捉到該動作。 在這種情況下,您需要在 Android 清單中添加android:configChanges="keyboard|keyboardHidden"以便在連接外部鍵盤后不會重新啟動 Activity。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM