Android 3.1 USB-хост – BroadcastReceiver не получает USB_DEVICE_ATTACHED

Я проработал описание и образцы для хоста USB на сайте developer.android.com для обнаружения подключенных и отсоединенных USB-устройств.

Если я использую фильтр намерения в файле манифеста для запуска приложения при подключении устройства, он отлично работает: подключится, обнаружено устройство, андроид запрашивает разрешение на запуск приложения, информация об устройстве отображается в таблице.

Разработанное приложение не должно запускаться / завершаться, только если устройство подключено / отсоединено (например, в целях управления данными). Кроме того, я не хочу, чтобы открытое диалоговое окно появлялось, если приложение уже запущено. Поэтому я решил не запускать деятельность напрямую, если устройство подключено, но зарегистрировать BroadcastReceiver, который (позже) должен уведомить об этом, если устройство находится в состоянии / отсоединено. Этот приемник прекрасно распознает отрыв-действие, но не прилагается.

У меня отсутствует атрибут разрешения или данных или что-то в этом роде? Учебник и примеры ничего не говорят о дополнительных необходимых атрибутах.

Вот файл манифеста:

              

И приемник:

 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 } 

Я не понимаю, почему работает тот же фильтр-намерение, если я использую их для активности, но не если они применяются к получателю? Даже если я настрою приемник и фильтрую код, атташе не распознается.

Моя рабочая среда: IDE: Eclipse 3.7 с Android Plugin

Устройство: Acer Iconia Tab A500

Android: 3.1

заранее спасибо

Ага! Я понял. У меня была такая же проблема.

Суть его заключается в том, что если вы запускаете приложение автоматически, когда устройство подключено (используя файл манифеста), то появляется система Android, которая получает намерение ACTION_USB_DEVICE_ATTACHED, а затем, поскольку оно знает, что ваше приложение хочет работать в этой ситуации , он фактически отправляет вашему приложению намерение android.intent.action.MAIN. Он никогда не отправляет действие ACTION_USB_DEVICE_ATTACHED в ваше приложение, поскольку он считает, что он уже знает, что ваше приложение хочет сделать в этой ситуации.

Я только что определил проблему, и я думаю, что у меня есть решение, но я могу сказать вам, что я нашел:

Даже если ваше приложение работает и на переднем плане, когда вы подключаете USB-устройство, а система Android получает намерение ACTION_USB_DEVICE_ATTACHED, он будет вызывать 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 } } 

Потому что намерение вернется как android.intent.action.MAIN, а не ACTION_USB_DEVICE_ATTACHED.

Досадно, вы также получите android.intent.action.MAIN, если вы просто покинете приложение, но не отключите USB. Я полагаю, что устройство должно спать, и его пробуждение будет делать то же самое.

Таким образом, из того, что я нашел, вы не можете получить намерение напрямую, но, похоже, вы можете полагаться на onResume (), вызываемый при подключении USB-устройства, поэтому решение должно просто проверить, не является ли USB каждый раз, когда вы получаете onResume. Вы также можете установить флаг, когда USB отсоединен, потому что, конечно, огонь USB отключен.

Таким образом, ваш вещательный приемник может выглядеть так:

 // 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); 

Это входит в тег активности в вашем манифесте:

      

У вас будет файл device_filter.xml в папке / res / xml /, который выглядит так:

      

(конечно, с любыми идентификаторами поставщиков и идентификаторами продуктов, которые вам нужны)

И тогда ваш 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, поскольку я на самом деле еще не вникал в это. Я использую библиотеку, которая будет просто подключаться, если это возможно, поэтому для моего приложения я могу просто начать этот цикл, и я в порядке.

Его также, вероятно, важно, чтобы установить режим запуска вашей активности в манифесте на «singleTask», чтобы он не запускался снова, когда он уже запущен, или же подключение USB-устройства просто запустит второй экземпляр вашего приложения!

Итак, весь мой тег активности в моем манифесте выглядит так:

              

Во всяком случае, я надеюсь, что это поможет кому-то! Я был удивлен, что я не смог найти решение для этого уже!

Просто следовать за проницательным комментарием @ Гусдора (+1): я внедрил check onNewIntent() который, как указывает @Gusdor, вызывается, когда ваш launchMode задан как singleTask или singleTop . Затем вместо проверки булевых флагов, как предполагает принятый ответ, просто передайте намерение вашему приемнику вещания USB с помощью LocalBroadcastManager . Например,

 @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(intent.getAction())) { LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } } 

Затем, где бы вы ни регистрировали существующий (системный) приемник широковещательной передачи USB, просто зарегистрируйте один и тот же приемник с локальным экземпляром диспетчера вещания,

 @Override protected void onResume() { super.onResume(); myContext.registerReceiver(myUsbBroadcastReceiver, myIntent); // system receiver LocalBroadcastManager.getInstance(myContext).registerReceiver(myUsbBroadcastReceiver, intent); // local receiver } @Override protected void onPause() { super.onResume(); myContext.unregisterReceiver(myUsbBroadcastReceiver); // system receiver LocalBroadcastManager.getInstance(myContext).unregisterReceiver(myUsbBroadcastReceiver); // local receiver } 

Вы можете отправить другую систему, а не локальную широковещательную рассылку, но я не думаю, что вы сможете использовать действие UsbManager.ACTION_USB_ACCESSORY_ATTACHED (система увидит это как потенциальный риск для безопасности), поэтому вам нужно будет определить свою собственную действие. Ничего страшного, но зачем беспокоиться, тем более что на местных вещаниях нет IPC.

Создание широковещательного приемника внутри приложения, а не манифеста, позволяет вашему приложению обрабатывать отдельные события во время его работы. Таким образом, отдельные события отправляются только в приложение, которое в настоящее время запущено и не транслируется во все приложения.

  • как сделать свою функцию swap в java?
  • java.lang.ClassNotFoundException: Не нашел class на пути: dexpathlist
  • Ошибка: выполнение выполнено для задачи ': app: processDebugResources'. > java.io.IOException: не удалось удалить папку "" в андроид-студии
  • Как вернуть несколько значений?
  • java.util.ConcurrentModificationException при добавлении другого объекта
  • Создайте PDU для Android, который работает с SmsMessage.createFromPdu () (GSM 3gpp)
  • Как анализировать XML с помощью анализатора SAX
  • Что такое использование BaseColumns в Android?
  • Почему имена переменных часто начинаются с буквы «m»?
  • Может ли int быть пустым в Java?
  • настраиваемый метод getView адаптера listview, который вызывается несколько раз и не имеет когерентного порядка
  • Interesting Posts

    На OS X, как я могу запустить Cacoa emacs * и * перенести его на передний план?

    Представление валютных ценностей в Java

    Вывод мусора: MediaPlayer завершился без выпуска

    Как вы сравниваете структуры для равенства в C?

    Ничто в панели задач не работает или не открывается, запускает WerFault.exe, если что-либо нажато

    Выход из разделителя в двойных кавычках, в awk

    Почему после выхода из системы кнопка «Назад» на странице отображает содержимое предыдущей страницы?

    Убедитесь, что приложение находится на первом запуске

    Как написать настраиваемый stream ввода в C ++

    Генерация распределенного порядкового номера?

    Как реализовать пользовательскую проверку подлинности в ASP.NET MVC 5

    Разрешен ли объект сущности для запроса HTTP DELETE?

    Петля только повторяет один раз с помощью `ssh` в теле

    Сколько раз я отпускаю выделенный или сохраненный объект?

    Разница между getAttribute () и getParameter ()

    Давайте будем гением компьютера.