Как программно спарить Bluetooth-устройство на Android

Для моего приложения я пытаюсь программно установить Bluetooth-устройство. Я могу показать диалог сопряжения для устройства, с которым я хочу соединиться, и я могу ввести pincode. Когда я нажимаю «Пара», диалог удаляется, и ничего не происходит.

Мне нужно только поддерживать устройства с Android 2.0 и новее.

В настоящее время я использую следующий код для запуска процесса спаривания:

public void pairDevice(BluetoothDevice device) { String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST"; Intent intent = new Intent(ACTION_PAIRING_REQUEST); String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE"; intent.putExtra(EXTRA_DEVICE, device); String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT"; int PAIRING_VARIANT_PIN = 0; intent.putExtra(EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } 

Перед запуском запроса на сопряжение я прекращаю сканирование для новых устройств.

Мое приложение имеет следующие разрешения Bluetooth:

  • android.permission.BLUETOOTH_ADMIN
  • android.permission.BLUETOOTH

Solutions Collecting From Web of "Как программно спарить Bluetooth-устройство на Android"

Мне удалось автоматически запросить процедуру сопряжения с клавиатурными устройствами через приложение, работающее в качестве службы, проверяющее наличие определенного типа устройства и измененную версию приложения «Настройки».

Я должен сказать, что я работал над настраиваемым устройством под управлением Android 4.0.3 без внешних элементов управления (нет кнопок «Назад / Главная / подтвердить»): соединение контроллера с загрузкой завершено без какого-либо взаимодействия до тех пор, пока не будет запрошен PIN-код.

Сначала я создал службу, запускающую активность при загрузке (с android.intent.action.BOOT_COMPLETED и android.permission.RECEIVE_BOOT_COMPLETED) которая периодически проверяет наличие устройства класса 1344 (клавиатура, единственный способ ввода данных по запросу) на Обратный вызов onReceive:

 public void onReceive(Context context, Intent intent) ... BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); ... if(dev.getBluetoothClass().getDeviceClass() == 1344){...} 

После фильтрации я выбираю первую доступную клавиатуру, а затем передаю адрес BT в приложение «Настройки»:

 Intent btSettingsIntent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS); btSettingsIntent.putExtra("btcontroller", dev.getAddress()); startActivityForResult(btSettingsIntent, 1); 

Трудная часть искала лучшее место для вызова процесса сопряжения. Используя только

 intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN); 

Привел меня к диалоговому окну, который когда-то закрыл, оставил меня с устройством в паре, но непригодным для использования.

Копаясь в классах com.ndroid.settings.Bluetooth, я нашел свой путь через

 createDevicePreference(CachedBluetoothDevice cachedDevice) 

В DeviceListPreferenceFragment.

Оттуда я сравнил свой ранее выбранный адрес BT с теми, которые были доступны, и один раз успешно совпадающий, я звоню

 cachedDevice.startPairing(); 

Я знаю, это сложно и требует доступа к исходному коду Android, но в пользовательской среде он работает.

Надеюсь, это может быть полезно.

К сожалению, я думаю, что лучшее, что вы собираетесь получить, это открыть Настройки / Беспроводные сети / Настройки Bluetooth для пользователя:

  Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS); startActivityForResult(intent, REQUEST_PAIR_DEVICE); 

Это мой ответ:

In onCreate () напишите:

  registerReceiver(incomingPairRequestReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST)); 

Затем создать переменную

 private final BroadcastReceiver incomingPairRequestReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) { BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //pair from device: dev.getName() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { dev.setPairingConfirmation(true); //successfull pairing } else { //impossible to automatically perform pairing, //your Android version is below KITKAT } } } }; 

Используя отражение, вы можете вызвать метод createBond из класса BluetoothDevice.

См. Это сообщение: Как отключить или удалить парное устройство Bluetooth программно на Android?

Существует также решение для несанкционированного доступа.

Отражение DODGY, разные производители могут изменить эти базовые методы, как они пожелают! Я тестировал множество различных приложений на наших 10 устройствах, и этот метод отражения работает только на примерно 75% устройств. Если вы хотите, чтобы приложение, которое работает для всех, было очень осторожным при использовании рефлексии – попробуйте облачное тестирование, чтобы протестировать ваше приложение на более 100 устройствах и проверить частоту отказа.

В этом случае отражение вообще не требуется, так как API 19 (KitKat 4.4)

BluetoothDevice имеет новый метод CreateBond.

  private void pairDevice(BluetoothDevice device) { device.createBond(); } 

developer.android.com/reference/android/bluetooth/BluetoothDevice.html

Может быть, вам нужно startActivityForResult, а не только startActivity?

Другим вариантом является просмотр примера приложения BluetoothChat и запуск сокета соединения RFComm, как только вы запустите сокет, запрос на соединение будет автоматически появляться без необходимости отправки отдельного намерения для спаривания. Таким образом вам не придется обрабатывать сопряжение.

http://developer.android.com/resources/samples/BluetoothChat/index.html

Я использую этот класс для соединения между моим клиентским смартфоном и серверным устройством:

 private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final UUID WELL_KNOWN_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); public ConnectThread(BluetoothDevice device) { // Use a temporary object that is later assigned to mmSocket,because // mmSocket is final BluetoothSocket tmp = null; // Get a BluetoothSocket to connect with the given BluetoothDevice try { tmp = device.createRfcommSocketToServiceRecord(WELL_KNOWN_UUID); //This is the trick Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class }); tmp = (BluetoothSocket) m.invoke(device, 1); } catch (Exception e) { e.printStackTrace(); } mmSocket = tmp; } public void run() { DebugLog.i(TAG, "Trying to connect..."); // Cancel discovery because it will slow down the connection mBluetoothAdapter.cancelDiscovery(); try { // Connect the device through the socket. This will block // until it succeeds or throws an exception mmSocket.connect(); DebugLog.i(TAG, "Connection stablished"); } catch (IOException connectException) { // Unable to connect; close the socket and get out DebugLog.e(TAG, "Fail to connect!", connectException); try { mmSocket.close(); } catch (IOException closeException) { DebugLog.e(TAG, "Fail to close connection", closeException); } return; } } /** Will cancel an in-progress connection, and close the socket */ public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } } 

Во-первых, получите объект BluetoothDevice, который вы хотите подключить (список парных устройств или устройств обнаружения). Затем выполните:

 ConnectThread ct = new ConnectThread(device); ct.start(); 

Поскольку connect () является блокирующим вызовом, эта процедура подключения всегда должна выполняться в потоке отдельно от основного потока активности. Дополнительную информацию см. В разделе « Разработчики Android» .

Я обнаружил, что использование различных значений для PAIRING_VARIANT_PIN приводит к различным поведениям UI парного взаимодействия.

См. Эту страницу: http://code.google.com/p/backport-android-bluetooth/source/browse/trunk/backport-android-bluetooth201/src/backport/android/bluetooth/BluetoothDevice.java?spec=svn67&r= 67

Я подозреваю, что проблема заключается в том, что оба устройства Bluetooth 2.1, и в этом случае запрос на сопряжение должен приводить к отображению 6-значного ключа доступа на обоих устройствах.

Лучший результат, который я смог достичь, – это использовать PAIRING_VARIANT_PIN = 0. При появлении запроса от моего приложения я ввел вывод 1234, и на моем целевом устройстве появился 6-значный пароль. Интерфейс сопряжения завершен, и это все.

Либо вам нужно узнать, как инициировать запрос сопряжения Bluetooth 2.1, используя другой вариант сопряжения, либо вариант с парой вариантов соединения. Или вы не поймаете результат активности, которая работает правильно.

Учитывая количество времени, которое я пытался сделать это, я решил, что моим конечным пользователям просто нужно будет с помощью настроек Android установить соединение перед использованием моего приложения.

Вот как я это понимаю:

 Bluetooth device = mBtAdapter.getRemoteDevice(address); //address:11:23:FF:cc:22 Method m = device.getClass() .getMethod("createBond", (Class[]) null); m.invoke(device, (Object[]) null); // send pairing dialog request After pairing// connectDevice(address); 

В дополнение к моему комментарию, кстати, даже если эти типы ACTION существуют, вы не используете их. Вот пример:

 Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST); intent.putExtra(EXTRA_DEVICE, device); int PAIRING_VARIANT_PIN = 272; intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN); sendBroadcast(intent);