Android Permettra de Configurer les Routeurs Wi-Fi Dual-Band : Ce Que Cela Signifie Pour les Développeurs IoT
Salut HaWkers, une nouvelle fonctionnalité d'Android est sur le point de faciliter significativement la vie de ceux qui développent des applications pour l'Internet des Objets (IoT) et la smart home : le système d'exploitation gagnera un support natif pour configurer les routeurs Wi-Fi avec technologie dual-band directement depuis le téléphone.
Si vous avez déjà essayé de créer une app qui configure des appareils IoT via Wi-Fi, vous connaissez le casse-tête de gérer différentes bandes de fréquence. Cette nouveauté peut changer la donne.
Ce Qui Arrive
Google ajoute à Android des APIs natives qui permettront aux applications de configurer des routeurs Wi-Fi dual-band de manière programmatique. Cela signifie que les développeurs pourront créer des expériences de configuration beaucoup plus fluides pour les appareils connectés.
Fonctionnalités Principales
Ce qui sera possible :
- Configurer SSID et mot de passe pour les bandes 2.4GHz et 5GHz séparément
- Basculer entre les bandes automatiquement selon les besoins
- Gérer les configurations QoS (Quality of Service)
- Configurer des réseaux invités
- Intégrer avec Matter et Thread pour la smart home
APIs attendues :
WifiNetworkConfigBuilderamélioré- Nouveaux intents pour la configuration de routeur
- Support Wi-Fi Easy Connect (DPP 2.0)
- Intégration avec Local Network Access APIs
Pourquoi C'est Important Pour l'IoT
La configuration des appareils IoT a toujours été l'un des plus grands points de friction dans l'expérience utilisateur. Avec ces nouvelles APIs, plusieurs problèmes courants pourront être résolus.
Problèmes Actuels de Setup IoT
Difficultés courantes :
- Les appareils IoT ne fonctionnent qu'en 2.4GHz, mais le téléphone se connecte en 5GHz
- L'utilisateur doit changer manuellement de réseau pendant le setup
- Les apps ont besoin de permissions invasives pour gérer le Wi-Fi
- La configuration échoue silencieusement sans feedback clair
- Différents fabricants utilisent des protocoles propriétaires
Comment les Nouvelles APIs Résolvent
| Problème | Solution avec Nouvelles APIs |
|---|---|
| Mauvaise bande | Sélection automatique de bande |
| Changement manuel de réseau | L'API gère la connexion temporaire |
| Permissions invasives | Scope plus limité et sécurisé |
| Échecs silencieux | Callbacks d'erreur détaillés |
| Protocoles propriétaires | Standard unifié d'Android |
Impact sur le Développement d'Apps
Pour les développeurs mobile et IoT, ces changements apportent des opportunités significatives.
Nouvelles Possibilités
Apps de smart home :
- Setup d'appareils en quelques secondes
- Configuration en lot de multiples appareils
- Migration automatique entre réseaux
- Diagnostic des problèmes de connexion
Apps de configuration réseau :
- Contrôle parental plus granulaire
- Priorisation d'appareils
- Analyse de qualité de connexion
- Optimisation automatique de bande
Exemple d'Implémentation
Voyons comment il sera possible d'utiliser ces nouvelles APIs pour configurer un appareil IoT :
Setup Basique d'Appareil IoT
// MainActivity.kt - Configuration d'appareil IoT
class IoTDeviceSetupActivity : AppCompatActivity() {
private lateinit var wifiManager: WifiManager
private lateinit var connectivityManager: ConnectivityManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_setup)
wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
setupIoTDevice()
}
private fun setupIoTDevice() {
// Configurer réseau spécifique pour IoT (2.4GHz)
val iotNetworkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(
WifiNetworkSpecifier.Builder()
.setSsid("IoT_Device_AP")
.setWpa2Passphrase("setup_password")
.setBand(WifiNetworkSpecifier.BAND_24GHZ) // Force 2.4GHz
.build()
)
.build()
// Callback pour la connexion
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
// Connecté à l'AP de l'appareil IoT
runOnUiThread {
showStatus("Connecté à l'appareil")
configureDeviceWifi(network)
}
}
override fun onUnavailable() {
super.onUnavailable()
runOnUiThread {
showError("Échec de connexion à l'appareil")
}
}
}
// Demander la connexion
connectivityManager.requestNetwork(iotNetworkRequest, networkCallback)
}
private fun configureDeviceWifi(network: Network) {
// Envoyer la configuration du réseau domestique à l'appareil
val homeNetworkConfig = HomeNetworkConfig(
ssid = "MonReseauWifi",
password = "mot_de_passe_securise",
preferredBand = Band.AUTO, // Laisser l'appareil choisir
securityType = SecurityType.WPA3
)
// Utiliser socket lié au network de l'appareil
network.bindSocket(socket)
// Envoyer configuration via HTTP/CoAP/MQTT
sendConfigToDevice(homeNetworkConfig)
}
private fun showStatus(message: String) {
binding.statusText.text = message
}
private fun showError(message: String) {
binding.statusText.text = "Erreur : $message"
}
}
// Data class pour la configuration
data class HomeNetworkConfig(
val ssid: String,
val password: String,
val preferredBand: Band,
val securityType: SecurityType
)
enum class Band { AUTO, BAND_24GHZ, BAND_5GHZ, BAND_6GHZ }
enum class SecurityType { WPA2, WPA3, OPEN }Découverte d'Appareils avec mDNS
// DeviceDiscoveryManager.kt
class DeviceDiscoveryManager(private val context: Context) {
private val nsdManager: NsdManager =
context.getSystemService(Context.NSD_SERVICE) as NsdManager
private val discoveredDevices = mutableListOf<IoTDevice>()
fun startDiscovery(onDeviceFound: (IoTDevice) -> Unit) {
val discoveryListener = object : NsdManager.DiscoveryListener {
override fun onDiscoveryStarted(regType: String) {
Log.d(TAG, "Découverte démarrée")
}
override fun onServiceFound(service: NsdServiceInfo) {
// Filtrer par type de service IoT
if (service.serviceType == SERVICE_TYPE) {
nsdManager.resolveService(service, createResolveListener(onDeviceFound))
}
}
override fun onServiceLost(service: NsdServiceInfo) {
discoveredDevices.removeIf { it.name == service.serviceName }
}
override fun onDiscoveryStopped(serviceType: String) {
Log.d(TAG, "Découverte arrêtée")
}
override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {
Log.e(TAG, "Échec du démarrage de découverte : $errorCode")
}
override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {
Log.e(TAG, "Échec de l'arrêt de découverte : $errorCode")
}
}
nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryListener)
}
private fun createResolveListener(
onDeviceFound: (IoTDevice) -> Unit
): NsdManager.ResolveListener {
return object : NsdManager.ResolveListener {
override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
Log.e(TAG, "Échec de résolution : $errorCode")
}
override fun onServiceResolved(serviceInfo: NsdServiceInfo) {
val device = IoTDevice(
name = serviceInfo.serviceName,
host = serviceInfo.host,
port = serviceInfo.port,
attributes = serviceInfo.attributes
)
discoveredDevices.add(device)
onDeviceFound(device)
}
}
}
companion object {
private const val TAG = "DeviceDiscovery"
private const val SERVICE_TYPE = "_iot._tcp."
}
}
data class IoTDevice(
val name: String,
val host: InetAddress,
val port: Int,
val attributes: Map<String, ByteArray>
)
Intégration avec Matter
// MatterDeviceSetup.kt
class MatterDeviceSetup(private val context: Context) {
private val commissioningClient: CommissioningClient =
Matter.getCommissioningClient(context)
suspend fun setupMatterDevice(
deviceInfo: MatterDeviceInfo,
wifiCredentials: WifiCredentials
): Result<CommissionedDevice> {
return try {
// Démarrer le processus de commissioning
val commissioningRequest = CommissioningRequest.builder()
.setCommissioningService(ComponentName(context, MatterCommissioningService::class.java))
.setWifiCredentials(
WifiCredentials.Builder()
.setSsid(wifiCredentials.ssid)
.setPassword(wifiCredentials.password)
.build()
)
.setOnboardingPayload(deviceInfo.qrCode)
.build()
val result = commissioningClient
.commissionDevice(commissioningRequest)
.await()
Result.success(result)
} catch (e: Exception) {
Result.failure(e)
}
}
// Service pour commissioning en arrière-plan
class MatterCommissioningService : Service() {
override fun onBind(intent: Intent): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// Traiter le commissioning
return START_NOT_STICKY
}
}
}
data class MatterDeviceInfo(
val qrCode: String,
val manualCode: String,
val vendorId: Int,
val productId: Int
)
data class WifiCredentials(
val ssid: String,
val password: String
)
Bonnes Pratiques Pour les Apps IoT
1. Gestion d'Erreurs Robuste
sealed class SetupError {
object NetworkNotFound : SetupError()
object AuthenticationFailed : SetupError()
object DeviceUnreachable : SetupError()
object ConfigurationFailed : SetupError()
data class Unknown(val message: String) : SetupError()
}
fun handleSetupError(error: SetupError): String {
return when (error) {
is SetupError.NetworkNotFound ->
"Réseau Wi-Fi non trouvé. Vérifiez le nom du réseau."
is SetupError.AuthenticationFailed ->
"Mot de passe incorrect. Réessayez."
is SetupError.DeviceUnreachable ->
"L'appareil ne répond pas. Redémarrez-le et réessayez."
is SetupError.ConfigurationFailed ->
"Échec de configuration. Réessayez dans quelques secondes."
is SetupError.Unknown ->
"Erreur : ${error.message}"
}
}2. UX de Setup Progressif
enum class SetupStep {
SCANNING,
CONNECTING_TO_DEVICE,
SENDING_CONFIG,
WAITING_DEVICE_CONNECT,
VERIFYING,
COMPLETE
}
@Composable
fun SetupProgressUI(currentStep: SetupStep) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = when (currentStep) {
SetupStep.SCANNING -> "Recherche de l'appareil..."
SetupStep.CONNECTING_TO_DEVICE -> "Connexion à l'appareil..."
SetupStep.SENDING_CONFIG -> "Envoi de la configuration..."
SetupStep.WAITING_DEVICE_CONNECT -> "Attente de connexion de l'appareil..."
SetupStep.VERIFYING -> "Vérification de la connexion..."
SetupStep.COMPLETE -> "Configuration terminée !"
},
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
LinearProgressIndicator(
progress = { (currentStep.ordinal + 1).toFloat() / SetupStep.entries.size },
modifier = Modifier.fillMaxWidth()
)
}
}Compatibilité et Prérequis
Versions Supportées
| Fonctionnalité | Android Minimum | API Level |
|---|---|---|
| Wi-Fi Network Suggestion | Android 10 | 29 |
| Wi-Fi Network Specifier | Android 10 | 29 |
| Wi-Fi Easy Connect | Android 10 | 29 |
| Dual-Band Config (nouveau) | Android 16 | 36 |
| Matter Integration | Android 13 | 33 |
Permissions Nécessaires
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- Pour Matter -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
Conclusion
Le support natif d'Android pour la configuration des routeurs Wi-Fi dual-band est une évolution importante pour l'écosystème IoT. Pour les développeurs, cela signifie moins de code boilerplate, une meilleure expérience utilisateur et un taux de succès plus élevé dans les setups d'appareils connectés.
Si vous travaillez dans le développement mobile ou IoT, cela vaut la peine de commencer à explorer ces APIs et de planifier comment les intégrer dans vos projets. L'avenir de la smart home dépend d'expériences de configuration sans friction.
Pour approfondir le développement mobile et IoT, je recommande de jeter un œil à l'article sur JavaScript et le Monde de l'IoT : Intégrer le Web à l'Environnement Physique où nous explorons comment utiliser JavaScript pour créer des solutions connectées.

