Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Scanner les périphériques bluetooth à proximité

Accès rapide :
Les permissions requises
Une interface graphique très simpliste
La définition d'un BroadcastReceiver
Le code de votre activité

Ce tuto vous montre comment trouver les périphériques bluetooth actifs à proximité. Commencez par créer un nouveau projet Android nommé BlueToothScanner et de type « Empty Activity ». Il nécessite une API minimale (paramètre minSdkVersion du fichier build.gradle) 23 et une API cible (paramètre targetSdkVersion) fixée à 26. Ce dernier paramètre est important si vous souhaitez déployer votre application sur le Play Store : il n'est plus autorisé de déployée des applications avec un targetSdkVersion inférieur à 26.

Les permissions requises

L'étape suivante consiste à lister, dans le fichier de manifeste, les autorisations requises pour le bon fonctionnement de votre application. Trois autorisations sont requises :

Voici le code complet de votre fichier de manifeste.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="fr.koor.bluetoothscanner">

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Votre fichier de manifeste

Une interface graphique très simpliste

Effectivement, notre interface graphique ne possédera qu'un seul bouton permettant de lancer un scan bluetooth. En voici son contenu.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnScan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        android:text="Scan Bluetooth"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    
</android.support.constraint.ConstraintLayout>
Définition de notre layout

La définition d'un BroadcastReceiver

L'étape suivante consiste à définir une classe dérivant de BroadcastReceiver. Cette classe nous permettra de définir une instance qui recevra les informations de chaque périphérique bluetooth qui sera détecté. La réception des informations se fera grâce à la méthode onReceive : il y aura, bien entendu, autant d'appels à cette méthode que de périphériques bluetooth détectés. Voici le code de cette classe. Il est à noter qu'on se contente d'afficher des informations sur chaque périphérique détecté dans un toast.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
package fr.koor.bluetoothscanner;

import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public class BluetoothReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            // Un récupère le périphérique bluetooth détecté durant le scan
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            // Et on affiche ses informations dans un toast et dans la fenêtre LogCat
            String message = device.getName() + "-" + device.getAddress();
            Toast.makeText(context, message, Toast.LENGTH_LONG).show();
            Log.i("DebugBluetooth", message);

        }

    }

}
Votre classe dérivant de BroadcastReceiver

Le code de votre activité

Il ne reste plus qu'à produire le code de l'activité qui démarrera un scan suite à un clic sur le bouton. Notez aussi que cette classe vérifie aussi quelques préalables au bon fonctionnement de l'application. En voici son code.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
 66 
 67 
 68 
 69 
 70 
 71 
 72 
 73 
 74 
 75 
 76 
 77 
 78 
 79 
 80 
 81 
 82 
 83 
 84 
 85 
 86 
 87 
package fr.koor.bluetoothscanner;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_ENABLE_BT = 456;
    private static final int REQUEST_ENABLE_LOCATION = 457;

    private BluetoothAdapter bluetoothAdapter = null;

    private Button btnScan;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // On cherche à récupérer l'interface bluetooth du périphérique Android
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // Si pas de module (d'interface) bluetooth sur le périphérique ...
        if ( bluetoothAdapter == null ) {
            Toast.makeText(
                    this,
                    "Bluetooth not supported on this deveice",
                    Toast.LENGTH_LONG).show();
            return;
        }

        // Si le bluetooth n'est pas activé, on propose de l'activer
        if ( ! bluetoothAdapter.isEnabled() ) {
            // Demande à activer l'interface bluetooth
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }

        // On vérifie les autorisations pour la localisation
        //     Cette permission est requise sur les versions récentes d'Android, car on
        //     peut se localiser par triangulation avec différentes bornes bluetooth en
        //     fonction de la puissance des signaux reçus.
        if ( checkSelfPermission( Manifest.permission.ACCESS_COARSE_LOCATION)
                                  != PackageManager.PERMISSION_GRANTED ) {
            requestPermissions(
                    new String[] {  android.Manifest.permission.ACCESS_COARSE_LOCATION  },
                    REQUEST_ENABLE_LOCATION );
        }

        // On enregistre un gestionnaire d'événements sur le bouton
        btnScan = findViewById( R.id.btnScan );
        btnScan.setOnClickListener( btnScanLister );
    }


    private View.OnClickListener btnScanLister = new View.OnClickListener() {
        private BluetoothReceiver bluetoothReceiver = null;

        @Override
        public void onClick(View view) {
            // On enregistre le "broadcast receiver" une unique fois
            if ( bluetoothReceiver == null ) {
                bluetoothReceiver = new BluetoothReceiver();
                IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
                registerReceiver(bluetoothReceiver, filter);
            }

            // Si un scan bluetooth est en cours, on le coupe
            if (bluetoothAdapter.isDiscovering()) {
                bluetoothAdapter.cancelDiscovery();
            }

            // On lance un nouveau scan bluetooth
            bluetoothAdapter.startDiscovery();
        }
    };

}
Le code de l'activité