it-swarm-ru.tech

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

Для моего приложения я пытаюсь программно подключить устройство 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
17
FireFly

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

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

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

10
DvD

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

в 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
Nikytee

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

    Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
    startActivityForResult(intent, REQUEST_PAIR_DEVICE);
4
sky-dev

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

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

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

3
Derzu

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

2
aiden_fry

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

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

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

0
Rahul Choudhary

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

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
DragonT