Как программно выполнить сопряжение устройства Bluetooth на Android - PullRequest
17 голосов
/ 14 февраля 2011

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

Мне нужно только поддерживать устройства с 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

Ответы [ 10 ]

10 голосов
/ 08 октября 2012

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

Я должен сказать, что я работал на пользовательском устройстве под управлением 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.Android.settings. Bluetooth Я нашел свой путь через

createDevicePreference(CachedBluetoothDevice cachedDevice) 

в DeviceListPreferenceFragment.

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

cachedDevice.startPairing();

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

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

4 голосов
/ 04 апреля 2016

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

в 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
            }
        }
    }
};
4 голосов
/ 14 января 2012

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

3 голосов
/ 22 января 2013

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

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

Существует также решение для несправедливых.

2 голосов
/ 11 декабря 2015

Отражение - это 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

0 голосов
/ 15 января 2015

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

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);
0 голосов
/ 05 марта 2014

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

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 для получения более подробной информации.

0 голосов
/ 21 октября 2011

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

Смотрите эту страницу: 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 перед использованием моего приложения.

0 голосов
/ 24 июня 2011
Между прочим,

в дополнение к моему комментарию, даже если эти типы ДЕЙСТВИЙ действительно существуют, вы не используете их. Вот пример:

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);
0 голосов
/ 24 апреля 2011

Может быть, вам нужно запуститьActivityForResult вместо только startActivity?

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...