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.
L'étape suivante consiste à lister, dans le fichier de manifeste, les autorisations requises pour le bon fonctionnement de votre application. Trois autorisations sont requises :
android.permission.BLUETOOTH
: requise pour échanger des données par bluetooth.
android.permission.BLUETOOTH_ADMIN
: requise pour lancer un scan des périphériques disponibles.
android.permission.ACCESS_COARSE_LOCATION
: requise depuis les dernières versions d'Android.
Pour comprendre cette permission, il faut savoir qu'il est possible à une application de se localiser grâce à des balises bluetooth disposées en
différents points d'un environnement donné. Dès lors qu'on capte suffisamment de balises, on peut alors être localisé par triangulation en fonction
de la puissance des signaux reçues. Cela présuppose, bien entendu, que l'on connaisse la localisation des différentes balises.
En conséquence, la permission de localisation est requise.
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> |
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> |
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); } } } |
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(); } }; } |
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 :