Skip to content

Crash: SecurityException ao chamar métodos do BluetoothAdapter no Android 12+ #265

Description

@chesterbr

O que está acontecendo?

O aplicativo está crashando quando tenta acessar funcionalidades do Bluetooth em dispositivos com Android 12 ou superior. O erro ocorre porque o app chama métodos do BluetoothAdapter que requerem a permissão BLUETOOTH_CONNECT, mas essa permissão pode ter sido revogada pelo usuário enquanto o app estava em segundo plano.

Por que isso acontece?

A partir do Android 12 (API 31), o Google introduziu novas permissões de runtime para Bluetooth:

  • BLUETOOTH_CONNECT - necessária para conectar a dispositivos e acessar informações como nome do adaptador
  • BLUETOOTH_SCAN - necessária para descobrir dispositivos próximos

O problema: O app verifica essas permissões corretamente no onCreate() da activity Bluetooth. Porém, o usuário pode revogar a permissão nas configurações do sistema enquanto o app está em segundo plano. Quando o app retorna ao primeiro plano, ele tenta usar o Bluetooth sem re-verificar se ainda tem permissão, causando o crash.

Onde está o problema no código?

1. ServidorBluetoothActivity.java (linha 240)

// Em atualizaClientes(), chamado via postDelayed no onResume()
apelidos[0] = Jogador.sanitizaNome(btAdapter.getName());  // 💥 Crash aqui

2. ClienteBluetoothActivity.java (linha 304)

// Em listaDispositivosPareados()
dispositivosPareados.addAll(btAdapter.getBondedDevices());  // ⚠️ Potencial crash

Ambos os métodos (getName() e getBondedDevices()) requerem BLUETOOTH_CONNECT no Android 12+.

A anotação @SuppressLint("MissingPermission") presente nesses métodos apenas silencia o aviso do lint durante a compilação - ela não previne a exceção em tempo de execução.

Dados do Play Console (últimos 7 dias)

Métrica Valor
Usuários afetados 13
Eventos de crash 14
Versão do app 3.0.6 (30006)

Versões Android afetadas: 15, 14, 13, 12

Dispositivos: Samsung A15, POCO duchamp, Redmi sapphire, realme RE60TCL1

Stack Trace

java.lang.SecurityException: 
  at android.os.Parcel.createExceptionOrNull (Parcel.java:3057)
  at android.os.Parcel.createException (Parcel.java:3041)
  at android.os.Parcel.readException (Parcel.java:3024)
  at android.bluetooth.IBluetooth$Stub$Proxy.getName (IBluetooth.java:1426)
  at android.bluetooth.BluetoothAdapter.getName (BluetoothAdapter.java:1196)
  at me.chester.minitruco.android.bluetooth.ServidorBluetoothActivity.atualizaClientes (ServidorBluetoothActivity.java:240)

Como corrigir?

A solução é re-verificar a permissão antes de qualquer chamada que a exija, ou tratar a exceção graciosamente. Opções:

Opção 1: Verificação preventiva

private boolean temPermissaoBluetooth() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        return checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) 
               == PackageManager.PERMISSION_GRANTED;
    }
    return true; // Antes do Android 12, não precisa dessa permissão
}

Opção 2: Try-catch defensivo

String nome;
try {
    nome = btAdapter.getName();
} catch (SecurityException e) {
    // Permissão foi revogada - encerrar graciosamente
    finish();
    return;
}

Referências

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions