web-dev-qa-db-fra.com

Comment coupler par programme un périphérique Bluetooth sur Android

Pour mon application, j'essaie de coupler par programme un périphérique Bluetooth. Je peux afficher la boîte de dialogue de couplage du périphérique que je souhaite coupler et saisir un code PIN. Lorsque j'appuie sur "Pair", la boîte de dialogue est supprimée et rien ne se passe.

Je n'ai besoin que de prendre en charge les appareils avec Android 2.0 et plus récent.

Actuellement, j'utilise le code suivant pour démarrer la progression du jumelage:


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);
    }

Avant de lancer une demande d'association, j'arrête de rechercher de nouveaux périphériques.

Mon application dispose des autorisations Bluetooth suivantes:

  • Android.permission.BLUETOOTH_ADMIN
  • Android.permission.BLUETOOTH
17
FireFly

J'ai réussi à demander automatiquement une procédure de couplage avec des périphériques dotés d'un clavier via une application fonctionnant comme un service vérifiant la présence d'un type spécifique de périphérique et d'une version modifiée de l'application Paramètres.

Je dois dire que je travaillais sur un appareil personnalisé exécutant Android 4.0.3 sans contrôles externes (pas de boutons Précédent/Accueil/Confirmer): le couplage d'un contrôleur au démarrage est terminé sans aucune interaction jusqu'à ce que la demande de PIN soit obligatoire.

J'ai d'abord créé un service démarrant une activité au démarrage (avec Android.intent.action.BOOT_COMPLETED et Android.permission.RECEIVE_BOOT_COMPLETED) qui vérifie périodiquement la présence d'un périphérique de classe 1344 (un clavier, seul moyen de saisir des données sur demande) sur le rappel onReceive:

public void onReceive(Context context, Intent intent) 
...
    BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
...
if(dev.getBluetoothClass().getDeviceClass() == 1344){...}

Une fois filtré, je choisis le premier clavier disponible, puis je passe l'adresse BT à l'application Paramètres:

Intent btSettingsIntent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
btSettingsIntent.putExtra("btcontroller", dev.getAddress());
startActivityForResult(btSettingsIntent, 1);

La partie délicate était de chercher la meilleure position pour appeler le processus d’appariement. En utilisant seulement le

intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN);

m'a conduit à un dialogue de couplage qui une fois fermé m'a laissé l'appareil jumelé, mais inutilisable.

Creuser dans les classes de com.Android.settings.Bluetooth j'ai trouvé mon chemin à travers le 

createDevicePreference(CachedBluetoothDevice cachedDevice) 

dans DeviceListPreferenceFragment.

À partir de là, j’ai comparé l’adresse de BT que j’avais choisie précédemment avec celles qui étaient disponibles et j’appelle

cachedDevice.startPairing();

Je sais, c'est compliqué et nécessite un accès au code source Android, mais cela fonctionne dans un environnement personnalisé.

J'espère que cela pourrait être utile.

10
DvD

C'est ma réponse:

dans onCreate () écrivez ceci:

    registerReceiver(incomingPairRequestReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST));

puis créer une variable

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

Malheureusement, je pense que le mieux que vous obteniez est d'ouvrir Paramètres/Sans fil et réseaux/Paramètres Bluetooth pour l'utilisateur, comme ceci:

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

En utilisant la réflexion, vous pouvez appeler la méthode createBond à partir de la classe BluetoothDevice.

Voir cet article: Comment dissocier ou supprimer un périphérique Bluetooth couplé par programme sur Android?

Il existe également une solution pour le découplage.

3
Derzu

Reflection is DODGY, différents fabricants peuvent modifier ces méthodes sous-jacentes comme ils le souhaitent! J'ai testé de nombreuses applications différentes sur nos 10 appareils ici et cette méthode de réflexion ne fonctionne pleinement que sur environ 75% des appareils. Si vous souhaitez une application qui convient à tout le monde, soyez très prudent lorsque vous utilisez la réflexion. Essayez de tester votre cloud pour tester votre application sur plus de 100 appareils et vérifiez le taux d'échec.

Dans ce cas, aucune réflexion n'est nécessaire depuis API 19 (KitKat 4.4)

BluetoothDevice a une nouvelle méthode CreateBond.

 private void pairDevice(BluetoothDevice device) {

            device.createBond();
    }

developer.Android.com/reference/Android/bluetooth/BluetoothDevice.html

2
aiden_fry

Peut-être vous avez besoin de démarrerActivityForResult au lieu de seulement startActivity?

Une autre option consiste à examiner l'exemple d'application BluetoothChat et à démarrer un socket de connexion RFComm. Dès que vous démarrez le socket, une demande d'association apparaît automatiquement sans qu'il soit nécessaire d'envoyer une intention de couplage distincte. De cette façon, vous n'aurez pas besoin de gérer le jumelage.

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

0
Rahul Choudhary

J'utilise cette classe pour établir une connexion entre mon smartphone client et le périphérique serveur:

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)
        {
        }
    }
}

Commencez par obtenir l’objet BluetoothDevice que vous souhaitez connecter (liste des périphériques couplés ou des périphériques de détection). Alors fais:

ConnectThread ct = new ConnectThread(device);
ct.start();

Etant donné que connect () est un appel bloquant, cette procédure de connexion doit toujours être effectuée dans un thread distinct du thread d'activité principal. Voir Développeurs Android pour des informations plus détaillées.

0
DragonT