Voltar para o Blog

Android Permitira Configurar Roteador Wi-Fi Dual-Band: O Que Isso Significa Para Desenvolvedores IoT

Ola HaWkers, uma nova funcionalidade do Android esta prestes a facilitar significativamente a vida de quem desenvolve aplicacoes para Internet das Coisas (IoT) e smart home: o sistema operacional ganhara suporte nativo para configurar roteadores Wi-Fi com tecnologia dual-band diretamente pelo celular.

Se voce ja tentou criar um app que configura dispositivos IoT via Wi-Fi, sabe a dor de cabeca que e lidar com diferentes bandas de frequencia. Essa novidade pode mudar o jogo.

O Que Esta Chegando

O Google esta adicionando ao Android APIs nativas que permitirao que aplicativos configurem roteadores Wi-Fi dual-band de forma programatica. Isso significa que desenvolvedores poderao criar experiencias de setup muito mais fluidas para dispositivos conectados.

Funcionalidades Principais

O que sera possivel:

  • Configurar SSID e senha para bandas 2.4GHz e 5GHz separadamente
  • Alternar entre bandas automaticamente baseado em requisitos
  • Gerenciar configuracoes de QoS (Quality of Service)
  • Configurar redes para convidados
  • Integrar com Matter e Thread para smart home

APIs esperadas:

  • WifiNetworkConfigBuilder aprimorado
  • Novos intents para configuracao de roteador
  • Suporte a Wi-Fi Easy Connect (DPP 2.0)
  • Integracao com Local Network Access APIs

Por Que Isso Importa Para IoT

A configuracao de dispositivos IoT sempre foi um dos maiores pontos de friccao na experiencia do usuario. Com essas novas APIs, varios problemas comuns poderao ser resolvidos.

Problemas Atuais de Setup IoT

Dificuldades comuns:

  1. Dispositivos IoT so funcionam em 2.4GHz, mas celular conecta em 5GHz
  2. Usuario precisa trocar manualmente de rede durante setup
  3. Apps precisam de permissoes invasivas para gerenciar Wi-Fi
  4. Configuracao falha silenciosamente sem feedback claro
  5. Diferentes fabricantes usam protocolos proprietarios

Como as Novas APIs Resolvem

Problema Solucao com Novas APIs
Banda incorreta Selecao automatica de banda
Troca manual de rede API gerencia conexao temporaria
Permissoes invasivas Escopo mais limitado e seguro
Falhas silenciosas Callbacks detalhados de erro
Protocolos proprietarios Padrao unificado do Android

Impacto no Desenvolvimento de Apps

Para desenvolvedores mobile e IoT, essas mudancas trazem oportunidades significativas.

Novas Possibilidades

Apps de smart home:

  • Setup de dispositivos em segundos
  • Configuracao em lote de multiplos dispositivos
  • Migracao automatica entre redes
  • Diagnostico de problemas de conexao

Apps de configuracao de rede:

  • Controle parental mais granular
  • Priorizacao de dispositivos
  • Analise de qualidade de conexao
  • Otimizacao automatica de banda

Exemplo de Implementacao

Vamos ver como sera possivel usar essas novas APIs para configurar um dispositivo IoT:

Setup Basico de Dispositivo IoT

// MainActivity.kt - Configuracao de dispositivo 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() {
        // Configurar rede especifica para 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) // Forca 2.4GHz
                    .build()
            )
            .build()

        // Callback para conexao
        val networkCallback = object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                super.onAvailable(network)
                // Conectado ao AP do dispositivo IoT
                runOnUiThread {
                    showStatus("Conectado ao dispositivo")
                    configureDeviceWifi(network)
                }
            }

            override fun onUnavailable() {
                super.onUnavailable()
                runOnUiThread {
                    showError("Falha ao conectar ao dispositivo")
                }
            }
        }

        // Solicitar conexao
        connectivityManager.requestNetwork(iotNetworkRequest, networkCallback)
    }

    private fun configureDeviceWifi(network: Network) {
        // Enviar configuracao da rede domestica para o dispositivo
        val homeNetworkConfig = HomeNetworkConfig(
            ssid = "MinhaRedeWifi",
            password = "senha_segura",
            preferredBand = Band.AUTO, // Deixar dispositivo escolher
            securityType = SecurityType.WPA3
        )

        // Usar socket bound ao network do dispositivo
        network.bindSocket(socket)

        // Enviar configuracao via HTTP/CoAP/MQTT
        sendConfigToDevice(homeNetworkConfig)
    }

    private fun showStatus(message: String) {
        binding.statusText.text = message
    }

    private fun showError(message: String) {
        binding.statusText.text = "Erro: $message"
    }
}

// Data class para configuracao
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 }

Descoberta de Dispositivos com 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, "Descoberta iniciada")
            }

            override fun onServiceFound(service: NsdServiceInfo) {
                // Filtrar por tipo de servico 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, "Descoberta parada")
            }

            override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {
                Log.e(TAG, "Falha ao iniciar descoberta: $errorCode")
            }

            override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {
                Log.e(TAG, "Falha ao parar descoberta: $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, "Falha ao resolver: $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>
)

Integracao com 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 {
            // Iniciar processo 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 para commissioning em background
    class MatterCommissioningService : Service() {
        override fun onBind(intent: Intent): IBinder? = null

        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
            // Processar 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
)

Boas Praticas Para Apps IoT

1. Tratamento de Erros Robusto

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 ->
            "Rede Wi-Fi nao encontrada. Verifique o nome da rede."
        is SetupError.AuthenticationFailed ->
            "Senha incorreta. Tente novamente."
        is SetupError.DeviceUnreachable ->
            "Dispositivo nao responde. Reinicie-o e tente novamente."
        is SetupError.ConfigurationFailed ->
            "Falha ao configurar. Tente novamente em alguns segundos."
        is SetupError.Unknown ->
            "Erro: ${error.message}"
    }
}

2. UX de Setup Progressivo

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 -> "Procurando dispositivo..."
                SetupStep.CONNECTING_TO_DEVICE -> "Conectando ao dispositivo..."
                SetupStep.SENDING_CONFIG -> "Enviando configuracao..."
                SetupStep.WAITING_DEVICE_CONNECT -> "Aguardando dispositivo conectar..."
                SetupStep.VERIFYING -> "Verificando conexao..."
                SetupStep.COMPLETE -> "Configuracao completa!"
            },
            style = MaterialTheme.typography.headlineSmall
        )

        Spacer(modifier = Modifier.height(16.dp))

        LinearProgressIndicator(
            progress = { (currentStep.ordinal + 1).toFloat() / SetupStep.entries.size },
            modifier = Modifier.fillMaxWidth()
        )
    }
}

Compatibilidade e Requisitos

Versoes Suportadas

Funcionalidade Android Minimo 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 (novo) Android 16 36
Matter Integration Android 13 33

Permissoes Necessarias

<!-- 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" />

<!-- Para Matter -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

Conclusao

O suporte nativo do Android para configuracao de roteadores Wi-Fi dual-band e uma evolucao importante para o ecossistema IoT. Para desenvolvedores, isso significa menos codigo boilerplate, melhor experiencia de usuario e maior taxa de sucesso em setups de dispositivos conectados.

Se voce trabalha com desenvolvimento mobile ou IoT, vale a pena comecar a explorar essas APIs e planejar como integra-las em seus projetos. O futuro da smart home depende de experiencias de configuracao sem friccao.

Para se aprofundar em desenvolvimento mobile e IoT, recomendo dar uma olhada no artigo sobre JavaScript e o Mundo do IoT: Integrando a Web ao Ambiente Fisico onde exploramos como usar JavaScript para criar solucoes conectadas.

Bora pra cima! 🦅

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário