USB_DEVICE_ATTACHED Намерение не срабатывает
Кто-нибудь смог заставить работать android.hardware.usb.action.USB_DEVICE_ATTACHED"?
Итак, я пытаюсь использовать новые функции режима хоста USB, чтобы обнаружить, когда USB-устройство подключено. Для моих целей я хочу получать уведомления в любое время, когда устройство подключено. Я не смог увидеть это. Я использую вещательный приемник, который, как я знаю, работает (когда он у меня есть, слушаю другие вещи, такие как нажатие кнопки "Домой". Независимо от того, что я пытаюсь, у меня не получается получить намерение сработать.... чтобы все упростить, я решил забыть о своем проекте и попытаться использовать собственный пример кода Google и посмотреть, смогу ли я хотя бы сделать это. У меня нет одного из ракетных пусковых установок, но я решил, что по крайней мере смогу получить его 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 я обнаружил, что каждое приложение, которое я создаю, получает резюме, вызываемое при подключении / отключении клавиатуры (отсюда запись в журнале intent: android.intent.action.MAIN). Прямо сейчас, единственное, что я могу понять, это то, что это ошибка в источнике Android. Кстати, я использую Wi-Fi Xoom с ОС 3.1.
11 ответов
У меня тоже была такая же проблема. Я наконец понял, что в фильтре устройств xml мы должны добавить следующую строку.
<usb-device vendor-id-"xxxxx" product-id="yyyyy">
xxxxx и yyyyy должны быть десятичными числами. НЕ шестнадцатеричные коды. Тогда все работает как рекламируется! Я знаю, что уже поздно, но я надеюсь, что это поможет.
Поэтому я нашел решение своей проблемы и многому научился, надеюсь, он может помочь кому-то еще.
Поэтому сначала отключите HID-устройства, не создавайте никаких намерений. И при этом они не обнаруживаются в mUsbManager.getDeviceList()
список. Другие вещи, однако, делают. Я дал карту памяти USB, и что вы знаете, устройство указано в списке устройств. Я также обнаружил, что возвращаемое устройство не имеет класса, подкласса или протокола. Отладка показала, что родительский интерфейс действительно имел надлежащий класс / подкласс / и протокол. Также, если вы должны иметь фильтр устройства. Я закончил с class=0008 (USB STORAGE)
работать в моих целях. Я предполагаю, что другие классы также подойдут.
Итак, теперь выясним намерения. Оказывается, что намерение должно быть связано с активностью запуска. Мои попытки прикрепить его к услуге или получателю не принесут никаких плодов. Итак, теперь, когда я собираюсь запустить, теперь я вижу всплывающие уведомления, когда я подключаю свое устройство (карту памяти USB), он просит меня установить приложение по умолчанию для этого устройства. Отлично, теперь мое приложение запускается каждый раз, когда я подключаю это устройство. Обратите внимание, что вам будет предложено для каждого уникального устройства. Но только один раз. Кажется, что он зарегистрирован как программы по умолчанию.
Ну, я думаю о том, что подводит итог тому, что я нашел. Жаль, что вы не можете получить уведомление, когда подключается клавиатура / мышь. Да, и еще одна вещь. Нет проблем с ядром tiamat, запустив его прямо сейчас и никаких проблем.
Недавно я обнаружил решение аналогичной проблемы.
Как кто-то уже заметил, HID devices
не начинайте намерение, которое, я думаю, было вашей проблемой.
Однако связанная с этим проблема заключается в том, что если ваша программа настроена на запуск при подключении устройства USB, то даже после запуска приложения вы не сможете перехватить USB_DEVICE_ATTACHED
действие. Вместо этого система видит это намерение и говорит: "О, это означает, что это приложение хочет работать (как объявлено в вашем манифесте), а затем отправляет вам действие android.intent.action.MAIN вместо USB_DEVICE_ATTACHED
действие, и это вызывает onResume()
, Даже если ваше приложение работает. Так что, насколько я могу судить, вы не можете захватить USB_DEVICE_ATTACHED
намерение, если ваш манифест заявляет, что ваше приложение будет работать при подключении USB-устройств. Вы просто должны поместить некоторый код в onResume()
проверить, подключен ли USB. Даже если ваша программа запущена, onResume будет вызываться снова, когда подключено USB-устройство.
Я отмечу мое решение более подробно здесь: Android 3.1 USB-Host - BroadcastReceiver не получает USB_DEVICE_ATTACHED
Перечисляющие устройства
Если ваше приложение заинтересовано в проверке всех устройств 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
}
У меня такая же проблема. Моим окончательным решением было использовать старомодную технику опроса. Вот довольно минимальный класс, который решает проблему к моему удовлетворению.
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-устройств (клавиатура, мышь)
Мое приложение установлено как launchMode="singleTop"
и в этом режиме кажется, что getIntent().getAction()
всегда равно действию, которое первым запустило приложение.
Таким образом, если вы запустите приложение вручную, а затем подключите устройство (даже после отключения от этого приложения), вы получите android.intent.action.MAIN
,
Если вы убьете приложение, а затем подключите устройство, вы всегда получите android.hardware.usb.action.USB_DEVICE_ATTACHED
даже от выключения и возврата к вашему приложению, или даже для вращения устройства.
Я на самом деле странно получаю намерения, когда отключаю USB-устройство, которое я не думаю, что задокументировано - но, конечно, я получаю USB_DEVICE_ATTACHED
когда мое устройство отсоединено.
Без singleTop
, он работает вроде как ожидалось, но затем вы получаете еще одну глупую дополнительную активность, если ваше приложение уже открыто и вы подключаете устройство.
Еще раз, API-интерфейс Android глючит, чрезмерно сложен и сложен в использовании.
Это то, что я сделал, чтобы обнаружить 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. Похоже, что вы должны иметь фильтр устройства, чтобы использовать намерения. поэтому я решил попробовать использовать фильтр классов вместо идентификаторов поставщиков / продуктов. Я полагаю, что это было бы более общим и, надеюсь, поймать скрытое устройство. Я использовал 03h в качестве идентификатора класса, я пробовал различные форматы, я пробовал подклассы, я даже использовал lsusb для обнаружения, класса, подкласса и протокола моего устройства. похоже, это совсем не помогло. поэтому я пошел дальше к документации sdk и решил попробовать перечислить все устройства, чтобы увидеть, что операционная система видит целые числа класса / подкласса / протокола. Я скопировал код, вставил его в прослушиватель кликов и добавил операторы log.v. ничего не показывает в logcat.
Похоже, что американская система не видит ни одного устройства (даже если устройство действительно работает). Теперь это очень показательно для намерения подключенного USB-устройства не срабатывать. Теперь я должен сказать, что я использую собственное ядро в моем xoom (tiamat). Я думал, что это может быть как-то связано с проблемой некоторое время назад, поэтому я вернулся к стоковой версии 3.1. и до сих пор прогресс. это было некоторое время назад, до того, как я попытался перечислить, так что теперь я вернусь к agaian и продолжу работать с запасом, пока не буду уверен, что проблема не в ядре. Я вернусь, когда узнаю больше. успех или неудача. Конечно, если кто-то еще понимает это лучше меня, пожалуйста, включите. Последнее замечание. Я очень обеспокоен всем режимом хоста otg, когда я увидел это в документации. Обратите внимание, что коэффициент идентичен, даже если он ссылается на два метода: перечисление. возможно, это просто ошибка авторов переписки, но некоторые все равно переживают в связи со всей этой неудачей.
Подключите USB-клавиатуру НЕ БУДЕТ огонь USB_DEVICE_ATTACHED.
Вместо этого система запустит Intent.ACTION_CONFIGURATION_CHANGED. Однако при изменении конфигурации система перезапустит действие. Вы не поймаете действие при перезапуске Activity. В этом случае вам нужно добавить android:configChanges="keyboard|keyboardHidden" в свой манифест Android, чтобы действие не было перезапущено после подключения внешней клавиатуры.
Из моего тестирования Android может запустить намерение, когда подключено устройство HID. (Пример приложения MissileLauncher делает именно это. См. Пример исходного кода для получения дополнительной информации.)
Устройство HID для Missile Launcher (Dream Cheeky USB Missle Launcher) имеет свой подкласс и протокол, настроенный на 0x00. Для получения дополнительной информации см.: http://www.mattcutts.com/blog/playing-with-a-usb-missile-launcher/
Предостережение заключается в том, что Android не бросает намерение специально для устройств с мышью и клавиатурой (возможно, больше). Однако я могу обнаружить устройства HID, у которых InterfaceClass = 0x03, InterfaceSubClass = 0x00, InterfaceProtocol = 0x00. Для моего приложения мое HID-устройство является встроенным контроллером, поэтому настройка подкласса и протокола не является проблемой.