Créer un scanner Bluetooth avec l'API Bluetooth d'Android

Le Bluetooth est devenu une technologie très populaire, en particulier sur les appareils mobiles. C'est une technologie permettant de découvrir et de transférer des données entre des appareils à proximité. Pratiquement tous les appareils mobiles modernes disposent de la technologie Bluetooth de nos jours. Si vous souhaitez créer une interface d'application avec un autre appareil compatible Bluetooth, allant des téléphones aux haut-parleurs, vous devez savoir comment utiliser l'API Bluetooth d'Android..

Dans ce tutoriel, nous allons créer une application similaire à l'application Bluetooth intégrée dans les paramètres d'Android. Il comprendra les fonctionnalités suivantes:

  • activer Bluetooth sur un appareil
  • afficher une liste d'appareils jumelés
  • découvrir et répertorier les périphériques Bluetooth à proximité

Nous allons également passer en revue les bases pour connecter et envoyer des données à un autre périphérique Bluetooth. J'ai créé un projet pour commencer, que vous pouvez télécharger à partir de GitHub. La capture d'écran ci-dessous illustre le projet de démarrage. Si vous êtes bloqué ou avez des problèmes, vous pouvez jeter un coup d'œil au projet terminé sur GitHub..

1. Activer Bluetooth

Avant de pouvoir activer Bluetooth sur un appareil Android, nous devons demander les autorisations nécessaires. Nous faisons cela dans le manifeste de l'application. le BLUETOOTH Cette autorisation permet à notre application de se connecter, de se déconnecter et de transférer des données avec un autre appareil Bluetooth. le BLUETOOTH_ADMIN l'autorisation permet à notre application de découvrir de nouveaux appareils Bluetooth et de modifier les paramètres Bluetooth de l'appareil.

  

Nous utiliserons l'adaptateur Bluetooth pour établir une interface avec Bluetooth. Nous instancions l'adaptateur dans le ListeActivité classe. Si l'adaptateur est nul, cela signifie que Bluetooth n'est pas pris en charge par l'appareil et que l'application ne fonctionnera pas sur l'appareil actuel. Nous gérons cette situation en affichant une boîte de dialogue d'alerte à l'utilisateur et en quittant l'application..

@Override protected void onCreate (Bundle savedInstanceState) … BTAdapter = BluetoothAdapter.getDefaultAdapter (); // Le téléphone ne prend pas en charge Bluetooth, informez-en l'utilisateur et quittez-le. if (BTAdapter == null) new AlertDialog.Builder (this) .setTitle ("Non compatible") .setMessage ("Votre téléphone ne prend pas en charge Bluetooth") .setPositiveButton ("Exit", nouvelle DialogInterface.OnClickListener () public void onClick (dialogue DialogInterface, int) System.exit (0);) .setIcon (android.R.drawable.ic_dialog_alert) .show (); 

Si Bluetooth est disponible sur l'appareil, nous devons l'activer. Pour activer Bluetooth, nous commençons une intention fournie par le SDK Android., BluetoothAdapter.ACTION_REQUEST_ENABLE. Cela présentera une boîte de dialogue à l'utilisateur, lui demandant l'autorisation d'activer Bluetooth sur l'appareil.. REQUEST_BLUETOOTH est un entier statique que nous avons défini pour identifier la demande d'activité.

public class ListActivity étend ActionBarActivity implémente DeviceListFragment.OnFragmentInteractionListener public static int REQUEST_BLUETOOTH = 1; ... void protégé onCreate startActivityForResult (enableBT, REQUEST_BLUETOOTH); 

2. Obtention d’une liste de périphériques jumelés

Au cours de cette étape, nous recherchons des appareils Bluetooth couplés et les affichons dans une liste. Dans le contexte d'un appareil mobile, un appareil Bluetooth peut être:

  • inconnu
  • jumelé
  • connecté

Il est important de connaître la différence entre un périphérique Bluetooth couplé et connecté. Les appareils jumelés sont conscients de l'existence de l'autre et partagent une clé de lien, qui peut être utilisée pour s'authentifier et créer une connexion. Les appareils sont automatiquement appariés une fois la connexion cryptée établie.

Les appareils connectés partagent un canal RFCOMM, leur permettant d'envoyer et de recevoir des données. Un appareil peut avoir plusieurs appareils jumelés, mais il ne peut être connecté qu'à un appareil à la fois..

Les appareils Bluetooth sont représentés par le BluetoothDevice objet. Vous pouvez obtenir une liste des appareils jumelés en appelant le getBondedDevices () méthode, qui retourne un ensemble de BluetoothDevice objets. Nous invoquons le getBondedDevices () méthode dans le DeviceListFragmentde onCreate () méthode.

public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); Log.d ("DEVICELIST", "Super a appelé pour DeviceListFragment onCreate \ n"); deviceItemList = new ArrayList(); Ensemble pairedDevices = bTAdapter.getBondedDevices (); 

Nous utilisons le getName () et getAddress ()  méthodes pour obtenir plus d'informations sur les périphériques Bluetooth. le getName () La méthode retourne l'identifiant public de l'appareil alors que getAddress () La méthode retourne l'adresse MAC du périphérique, un identifiant identifiant uniquement le périphérique..

Maintenant que nous avons une liste des appareils jumelés, nous créons un DeviceItem objet pour chaque BluetoothDevice objet. Nous ajoutons ensuite chaque DeviceItem objet à un tableau nommé deviceItemList. Nous allons utiliser cette matrice pour afficher la liste des appareils Bluetooth couplés dans notre application. Le code pour afficher la liste des DeviceItem les objets sont déjà présents dans le projet de démarrage.

if (pairedDevices.size ()> 0) pour (périphérique BluetoothDevice: pairedDevices) DeviceItem newDevice = new DeviceItem (device.getName (), device.getAddress (), "false"); deviceItemList.add (newDevice); 

3. Découvrir les appareils Bluetooth à proximité

L'étape suivante consiste à découvrir les périphériques avec lesquels le périphérique n'est pas encore associé., inconnu périphériques, et les ajouter à la liste des périphériques couplés. Nous faisons cela lorsque l'utilisateur appuie sur le bouton de numérisation. Le code pour gérer cela se trouve dans DeviceListFragment.

Nous devons d’abord faire un BroadcastReceiver et remplacer le onReceive () méthode. le onReceive () La méthode est appelée chaque fois qu'un périphérique Bluetooth est détecté..

le onReceive () La méthode prend une intention comme deuxième argument. Nous pouvons vérifier quel type d’intention diffuse en invoquant getAction (). Si l'action est BluetoothDevice.ACTION_FOUND, alors nous savons que nous avons trouvé un appareil Bluetooth. Lorsque cela se produit, nous créons un DeviceItem objet en utilisant le nom du périphérique et l'adresse MAC. Enfin, nous ajoutons le DeviceItem objecter à la ArrayAdapter pour l'afficher dans notre application.

Classe publique DeviceListFragment extend Fragment implémente AbsListView.OnItemClickListener … final broadcastReceiver privé bReciever = new BroadcastReceiver () public void onReceive (contexte de contexte, intention de l'intention) String action = intent.getAction (); if (BluetoothDevice.ACTION_FOUND.equals (action)) BluetoothDevice device = intent.getParcelableExtra (BluetoothDevice.EXTRA_DEVICE); // Créer un nouvel élément de périphérique DeviceItem newDevice = new DeviceItem (device.getName (), device.getAddress (), "false"); // Ajoutez-le à notre adaptateur mAdapter.add (newDevice); ; 

Lorsque le bouton de numérisation est activé, nous devons simplement enregistrer le récepteur que nous venons de créer et appeler le startDiscovery () méthode. Si le bouton de numérisation est désactivé, nous annulons l'enregistrement du destinataire et invoquons cancelDiscovery (). Gardez à l'esprit que la découverte prend beaucoup de ressources. Si votre application se connecte à un autre périphérique Bluetooth, vous devez toujours annuler la découverte avant la connexion..

Nous effaçons également le ArrayAdapter objet, mAdapter, quand la découverte commence. Lorsque nous commençons à numériser, nous ne voulons pas inclure les anciens périphériques qui ne sont peut-être plus à portée de l'appareil..

public View onCreateView (inflater LayoutInflater, conteneur ViewGroup, Bundle savedInstanceState) View view = inflater.inflate (R.layout.fragment_deviceitem_list, conteneur, false); ToggleButton scan = (ToggleButton) view.findViewById (R.id.scan);… scan.setOnCheckedChangeListener (nouveau CompoundButton.OnCheckedChangeListener (1)) ; if (isChecked) mAdapter.clear (); getActivity (). registerReceiver (bReciever, filter); bTAdapter.startDiscovery (); autre getActivity (). ) 

C'est tout. Nous avons fini notre scanner Bluetooth.

4. Connexion à un appareil

Les connexions Bluetooth fonctionnent comme n'importe quelle autre connexion. Il existe un serveur et un client, qui communiquent via des sockets RFCOMM. Sur Android, les sockets RFCOMM sont représentés par un Prise Bluetooth objet. Heureusement pour nous, l'essentiel du code technique pour les serveurs est géré par le SDK Android et disponible via l'API Bluetooth..

Se connecter en tant que client est simple. Votre première obtention de la prise RFCOMM à partir de la BluetoothDevice en appelant createRfcommSocketToServiceRecord (), en passant un UUID, une valeur de 128 bits que vous créez. L'UUID est similaire à un numéro de port.

Par exemple, supposons que vous créez une application de discussion utilisant Bluetooth pour dialoguer avec d'autres utilisateurs à proximité. Pour rechercher d'autres utilisateurs avec lesquels discuter, vous souhaitez rechercher d'autres appareils avec votre application de chat installée. Pour ce faire, nous recherchons l'UUID dans la liste des services des périphériques à proximité. L'utilisation d'un UUID pour écouter et accepter les connexions Bluetooth ajoute automatiquement cet UUID à la liste de services du téléphone ou au protocole de découverte de service..

Une fois la Prise Bluetooth est créé, vous appelez relier() sur le Prise Bluetooth. Ceci initialisera une connexion avec le BluetoothDevice via la prise RFCOMM. Une fois que notre appareil est connecté, nous pouvons utiliser la prise pour échanger des données avec l'appareil connecté. Cela est similaire à n'importe quelle implémentation de serveur standard.

Le maintien d'une connexion Bluetooth est coûteux, nous devons donc fermer la prise lorsque nous n'en avons plus besoin. Pour fermer le socket, on appelle Fermer() sur le Prise Bluetooth.

L’extrait de code suivant montre comment se connecter avec un utilisateur donné. BluetoothDevice:

Classe publique ConnectThread étend Thread private BluetoothSocket bTSocket; connexion booléenne publique (BluetoothDevice bTDevice, UUID mUUID) BluetoothSocket temp = null; try temp = bTDevice.createRfcommSocketToServiceRecord (mUUID);  catch (IOException e) Log.d ("CONNECTTHREAD", "Impossible de créer le socket RFCOMM:" + e.toString ()); retourne faux;  try bTSocket.connect ();  catch (IOException e) Log.d ("CONNECTTHREAD", "Connexion impossible:" + e.toString ()); try bTSocket.close ();  catch (IOException close) Log.d ("CONNECTTHREAD", "Impossible de fermer la connexion:" + e.toString ()); retourne faux;  return true;  public boolean cancel () try bTSocket.close ();  catch (IOException e) Log.d ("CONNECTTHREAD", "Impossible de fermer la connexion:" + e.toString ()); retourne faux;  return true; 

Se connecter en tant que serveur est légèrement plus difficile. Tout d'abord, de votre BluetoothAdapter, vous devez obtenir un BluetoothServerSocket, qui sera utilisé pour écouter une connexion. Ceci est utilisé uniquement pour obtenir le socket RFCOMM partagé de la connexion. Une fois la connexion établie, le socket du serveur n’est plus nécessaire et peut être fermé en appelant Fermer() dessus.

Nous instancions un socket serveur en appelant listenUsingRfcommWithServiceRecord (Nom de la chaîne, UUID mUUID). Cette méthode prend deux paramètres, un nom de type Chaîne et un identifiant unique de type UUID. Le paramètre name est le nom que nous donnons au service lorsqu'il est ajouté à l'entrée SDP (Service Discovery Protocol) du téléphone. L'identifiant unique doit correspondre à l'UUID utilisé par le client essayant de se connecter..

Nous appelons ensuite Acceptez() sur le nouvellement obtenu BluetoothServerSocket attendre une connexion. Quand le Acceptez() appel retourne quelque chose qui n'est pas nul, nous l'attribuons à notre Prise Bluetooth, que nous pouvons ensuite utiliser pour échanger des données avec le périphérique connecté.

L'extrait de code suivant montre comment accepter une connexion en tant que serveur:

Classe publique ServerConnectThread étend Thread private BluetoothSocket bTSocket; public ServerConnectThread ()  public void acceptConnect (BluetoothAdapter bTAdapter, UUID mUUID) BluetoothServerSocket temp = null; try temp = bTAdapter.listenUsingRfcommWithServiceRecord ("Nom_service", mUUID);  catch (IOException e) Log.d ("SERVERCONNECT", "Impossible d'obtenir un BluetoothServerSocket:" + e.toString ());  while (true) try bTSocket = temp.accept ();  catch (IOException e) Log.d ("SERVERCONNECT", "Impossible d'accepter une connexion entrante."); Pause;  if (bTSocket! = null) try temp.close ();  catch (IOException e) Log.d ("SERVERCONNECT", "Impossible de fermer ServerSocket:" + e.toString ());  Pause;  public void closeConnect () try bTSocket.close ();  catch (IOException e) Log.d ("SERVERCONNECT", "Impossible de fermer la connexion:" + e.toString ()); 

La lecture et l'écriture sur la connexion se font à l'aide de flux, Flux d'entrée et OutputStream. Nous pouvons obtenir une référence à ces flux en appelant getInputStream () et getOutputStream () sur le Prise Bluetooth. Pour lire et écrire dans ces flux, nous appelons lis() et écrire() respectivement.

L'extrait de code suivant montre comment procéder pour un entier unique:

Classe publique ManageConnectThread étend Thread public ManageConnectThread ()  public void sendData (BluetoothSocket socket, int data) lève l'IOException ByteArrayOutputStream output = new ByteArrayOutputStream (4); output.write (data); OutputStream outputStream = socket.getOutputStream (); outputStream.write (output.toByteArray ());  public int receiveData (socket BluetoothSocket) lève l'IOException byte [] buffer = new byte [4]; ByteArrayInputStream input = new ByteArrayInputStream (tampon); InputStream inputStream = socket.getInputStream (); inputStream.read (tampon); retourne input.read (); 

Vous pouvez trouver les deux exemples dans le projet terminé sur GitHub.

Conclusion

Nous avons réussi à fabriquer notre propre scanner Bluetooth et avons appris ce qui suit:

  • demander les autorisations Bluetooth nécessaires
  • activer Bluetooth sur votre téléphone
  • obtenir une liste des appareils jumelés
  • numériser et afficher une liste des périphériques Bluetooth à proximité
  • établir une connexion Bluetooth entre deux appareils
  • envoyer et recevoir des données via une connexion Bluetooth

N'hésitez pas à utiliser le code dans le projet fini sur GitHub et à le modifier dans vos propres applications.