Как программно спарить 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
Ответы
Ответ 1
Мне удалось автоматически запросить процедуру сопряжения с клавиатурными устройствами через приложение, работающее как служба, проверяющее наличие определенного типа устройства и измененную версию приложения "Настройки".
Я должен сказать, что я работал над настраиваемым устройством под управлением 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, но в пользовательской среде он работает.
Я надеюсь, что это может быть полезно.
Ответ 2
Это мой ответ:
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
}
}
}
};
Ответ 3
К сожалению, я думаю, что лучшее, что вы собираетесь получить, это открыть настройки/Беспроводные сети и настройки Bluetooth для этого пользователя:
Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
startActivityForResult(intent, REQUEST_PAIR_DEVICE);
Ответ 4
Используя отражение, вы можете вызвать метод createBond из класса BluetoothDevice.
Смотрите это сообщение: Как отключить или удалить спаренное устройство bluetooth программно на Android?
Существует также решение для несанкционированного доступа.
Ответ 5
Отражение 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
Ответ 6
Может быть, вам нужно запуститьActivityForResult, а не только startActivity?
Другой вариант - изучить образец приложения BluetoothChat и запустить сокет соединения RFComm, как только вы запустите сокет, запрос на спаривание автоматически появится без необходимости отправки отдельного намерения для спаривания. Таким образом вам не придется обрабатывать сопряжение.
http://developer.android.com/resources/samples/BluetoothChat/index.html
Ответ 7
Я использую этот класс для связи между моим клиентским смартфоном и серверным устройством:
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 Developers.
Ответ 8
Я обнаружил, что использование разных значений для 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 использовать парные параметры перед использованием моего приложения.
Ответ 9
Вот как я это понимаю:
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);
Ответ 10
в дополнение к моему комментарию, кстати, даже если эти типы 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);