как программно выполнить сопряжение устройства bluetooth на android

<p>для моего приложения я пытаюсь программно подключить устройство bluetooth. я могу показать диалог сопряжения для устройства, которое хочу связать, и могу ввести пин-код. когда я нажимаю «pair», диалог удаляется и ничего не происходит.</p><p>мне нужно только поддерживать устройства с android 2.0 и новее.</p><p>в настоящее время я использую следующий код для запуска процесса сопряжения:</p><pre><code> 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); } </code></pre><p>перед запуском запроса на сопряжение я прекращаю поиск новых устройств.</p><p>мое приложение имеет следующие разрешения bluetooth:</p><ul> <li>android.permission.bluetooth\_admin</li> <li>android.permission.bluetooth</li> </ul>

<p>мне удалось автоматически запросить процедуру сопряжения с устройствами с клавиатурой через приложение, работающее в качестве службы, которая проверяет наличие определенного типа устройства и измененную версию приложения «настройки».</p><p>я должен сказать, что я работал на пользовательском устройстве под управлением android 4.0.3 без внешних элементов управления (без кнопок возврата/возврата домой/подтверждения): подключение контроллера при загрузке завершено без какого-либо взаимодействия, пока запрос pin не стал обязательным.</p><p>сначала я создал службу, запускающую действие при загрузке (с <code>android.intent.action.boot\_completed</code> и <code>android.permission.receive\_boot\_completed)</code>, которая периодически проверяет наличие устройства класса 1344 (клавиатура, единственный способ ввода данных по запросу) в обратном вызове onreceive:</p><pre><code>public void onreceive(context context, intent intent) ... bluetoothdevice dev = intent.getparcelableextra(bluetoothdevice.extra\_device); ... if(dev.getbluetoothclass().getdeviceclass() == 1344){...} </code></pre><p>после фильтрации я выбираю первую доступную клавиатуру, а затем передаю bt-адрес приложению «настройки»:</p><pre><code>intent btsettingsintent = new intent(settings.action\_bluetooth\_settings); btsettingsintent.putextra("btcontroller", dev.getaddress()); startactivityforresult(btsettingsintent, 1); </code></pre><p>сложная часть искала лучшую позицию для вызова процесса сопряжения. используя только</p><pre><code>intent.putextra(bluetoothdevice.extra\_pairing\_variant, pairing\_variant\_pin); </code></pre><p>привел меня к диалоговому окну очистки, которое когда-то закрылось, оставило меня с сопряженным устройством, но непригодным для использования.</p><p>копаясь в классах com.android.settings. bluetooth я нашел свой путь через </p><pre><code>createdevicepreference(cachedbluetoothdevice cacheddevice) </code></pre><p>в devicelistpreferencefragment.</p><p>оттуда я сравнил свой ранее выбранный bt-адрес с доступным, и после успешного сопоставления я звоню</p><pre><code>cacheddevice.startpairing(); </code></pre><p>я знаю, это сложно и требует доступа к исходному коду android, но в пользовательской среде это работает.</p><p>я надеюсь, что это может быть полезно.</p>

<p>это мой ответ:</p><p>в oncreate () напишите это:</p><pre><code> registerreceiver(incomingpairrequestreceiver, new intentfilter(bluetoothdevice.action\_pairing\_request)); </code></pre><p>затем создайте переменную</p><pre><code>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 } } } }; </code></pre>

<p>к сожалению, я думаю, что лучшее, что вы получите, - это открыть настройки/беспроводная связь и сети/настройки bluetooth для пользователя, например, так:</p><pre><code> intent intent = new intent(settings.action\_bluetooth\_settings); startactivityforresult(intent, request\_pair\_device); </code></pre>

<p>используя рефлексию, вы можете вызвать метод createbond из класса bluetoothdevice.</p><p>смотрите этот пост: <a href="https://stackoverflow.com/questions/9608140/how-to-unpair-or-delete-paired-bluetooth-device-programmatically-on-android/11147911#11147911">как программно отключить или удалить сопряженное устройство bluetooth на android?</a> </p><p>существует также решение для несправедливости.</p>

<p>отражение dodgy, разные производители могут изменить эти основные методы, как они хотят! я протестировал много разных приложений на наших 10 устройствах здесь, и этот метод отражения полностью работает только примерно на 75% устройств. если вы хотите, чтобы приложение, которое работает для всех, было очень осторожным при использовании отражения - попробуйте провести некоторое облачное тестирование, чтобы протестировать ваше приложение на 100+ устройствах и проверить частоту отказов.</p><p>в этом случае отражение вообще не требуется, поскольку api 19 (kitkat 4.4)</p><p>у bluetoothdevice появился новый метод createbond.</p><pre><code> private void pairdevice(bluetoothdevice device) { device.createbond(); } </code></pre><p>developer.android.com/reference/android/bluetooth/bluetoothdevice.html</p>

<p>может быть, вам нужно запустить activityforresult вместо того, чтобы только запустить activity?</p><p>другой вариант - просмотреть пример приложения bluetoothchat и запустить сокет подключения rfcomm, как только вы запустите сокет, автоматически появится запрос на сопряжение, не отправляя отдельное намерение для сопряжения. таким образом, вам не нужно обрабатывать сопряжение.</p><p> <a href="http://developer.android.com/resources/samples/bluetoothchat/index.html">http://developer.android.com/resources/samples/bluetoothchat/index.html</a> </p>

<p>я использую этот класс для связи между моим клиентским смартфоном и серверным устройством:</p><pre><code>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) { } } } </code></pre><p>сначала получите <a href="http://developer.android.com/reference/android/bluetooth/bluetoothdevice.html">bluetoothdevice</a> объект, который вы хотите подключить (перечисление сопряженных устройств или устройств обнаружения). затем сделайте:</p><pre><code>connectthread ct = new connectthread(device); ct.start(); </code></pre><p>поскольку <a href="http://developer.android.com/reference/android/bluetooth/bluetoothsocket.html#connect%28%29">connect ()</a> является блокирующим вызовом, эту процедуру соединения всегда следует выполнять в потоке, отдельном от основного потока действия. смотрите <a href="http://developer.android.com/guide/topics/connectivity/bluetooth.html">android developers</a> для более подробной информации.</p>