Подтвердить что ты не робот

Как программно спарить 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
4b9b3361

Ответ 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);

Ответ 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);