Intereting Posts
Как обновить эмуляторы Google Play для Android Studio 2.2? Что такое Android Native Development Kit (NDK)? Как преобразовать BitmapDescriptor в drawable в android для просмотра изображений Плагин ADT «Загрузка данных для Android XXX» при каждом открытии файлов XML Не может установить свойство overflow 'null Как скрыть последний вид активности в недавнем списке андроидов? Использование реализации экрана блокиратора SharedPreferences не обновляется В чем разница между ADT и Android SDK? Как я могу реализовать разрешения на работу с Android 6.0 Runtime в существующем приложении Эмулятор Nexus 7 использует папку макета, а не layout-sw600dp Пользовательское расширение файла в Android Мне нужно сравнить координаты широты и долготы, которые скажут пользователю GPS, что ресторан Hooters ближе всего к его текущему положению Сбой в работе GMS Данные навигации и сохраненных экземпляров Правильный способ использования переменных среды системы в gradle с помощью Android Studio

BluetoothAdapter.getDefaultAdapter () бросает RuntimeException, а не в действие

Когда я пытаюсь получить адаптер bluetooth по умолчанию, пока я НЕ в TimerTask , но в TimerTask (созданный внутри Service ), используя:

 BluetoothAdapter.getDefaultAdapter(); 

Я получаю следующее исключение:

 Exception while invoking java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 

У моего приложения нет активности – так есть ли возможность отключить этот адаптер от Activity?

Это похоже на ошибку в Android и все еще существует в Android 4.0 (Ice Cream Sandwich)

Чтобы обойти это и иметь возможность вызвать BluetoothAdapter.getDefaultAdapter() из рабочего потока (например, AsyncTask), все, что вам нужно сделать, это вызвать BluetoothAdapter.getDefaultAdapter() один раз в основном потоке пользовательского интерфейса (например, внутри onCreate() вашего текущего Мероприятия).

RuntimeException генерируется только во время инициализации, а BluetoothAdapter.getDefaultAdapter() только инициализирует первый раз, когда вы его вызываете. Последующие вызовы к ней будут успешными даже в фоновом потоке.

Вызов BluetoothAdapter.getDefaultAdapter() в потоке UI работает, но не очень практичен. Я пробовал обходной путь с поддельной Activity, но, так как я ненавижу такие обходные пути, я решил прочитать, что сообщение об ошибке действительно говорит, и это не более того, что поток не вызывал Looper.prepare() .

Поэтому вызов Looper.prepare() перед вызовом BluetoothAdapter.getDefaultAdapter() должен решить проблему где угодно, а не только в потоке пользовательского интерфейса.

Пока работает для меня отлично.

Не уверен, насколько это правильно, но я добавил эту функцию обертки:

 static boolean m_calledLooperAlready = false; BluetoothAdapter getDefaultBluetoothAdapter() { if ( !m_calledLooperAlready ) { try { android.os.Looper.prepare(); } catch ( RuntimeException e ) { e.printStackTrace(); } m_calledLooperAlready = true; } return BluetoothAdapter.getDefaultAdapter(); } 

… и заменил все вхождения BluetoothAdapter.getDefaultAdapter() с помощью getDefaultBluetoothAdapter() . Это работает нормально для меня: 2.2.1, 2.3.3, 4.0.4, 4.3

Остерегайтесь gotcha, который существует в 2.3.x, но который исправлен в 4.x: если вы вызываете BluetoothAdapter.getDefaultAdapter() в любом потоке, отличном от основного потока приложений, этот поток должен вызывать Looper.prepare() а также Впоследствии Looper.loop() .

В противном случае будет возникать хотя бы одна проблема, с которой я столкнулся: accept() будет успешным при первом подключении, но затем не будет успешным при последовательных попытках даже после использования close() на ServerSocket.

Это происходит потому, что в старой версии BluetoothAdapter очистка записи SDP происходит путем сообщения, отправленного обработчику, созданному в потоке, где вызывается getDefaultAdapter() .

Привет, Kocus, нет никакого метода, называемого getDefault() в BluetoothAdapter calss . Это должен быть BluetoothAdapter.getDefaultAdapter();

Перейдите по этой ссылке для получения дополнительной информации.