Android 4.3 Bluetooth Low Energy instável

189

Atualmente, estou desenvolvendo um aplicativo que utilizará o Bluetooth Low Energy (teste no Nexus 4). Depois de começar com as APIs oficiais do BLE no Android 4.3, notei que, depois de conectar um dispositivo pela primeira vez, raramente consigo conectar / me comunicar com esse dispositivo ou com qualquer outro dispositivo.

Seguindo o guia aqui , posso conectar-me com êxito a um dispositivo, verificar serviços e características e ler / gravar / receber notificações sem problemas. No entanto, após desconectar e reconectar, muitas vezes não consigo verificar os serviços / características ou não consigo concluir uma leitura / gravação. Não consigo encontrar nada nos logs para indicar por que isso está acontecendo.

Quando isso acontece, tenho que desinstalar o aplicativo, desativar o Bluetooth e reiniciar o telefone antes que ele comece a funcionar novamente.

Sempre que um dispositivo é desconectado, lembre-se de chamar close () no objeto BluetoothGatt e defina-o como nulo. Alguma ideia?


EDIT:
Despejos de log: para esses logs, enraíquei meu telefone e aumentamos os níveis de rastreamento de itens relacionados no /etc/bluetooth/bt_stack.conf

Conexão bem-sucedida - Primeira tentativa após reiniciar o telefone e instalar o aplicativo. Sou capaz de conectar, descobrir todos os serviços / características e ler / escrever.

Tentativa com falha 1 - Esta é a próxima tentativa após desconectar da conexão bem-sucedida acima. Parece que fui capaz de descobrir características, mas a primeira tentativa de leitura retornou um valor nulo e foi desconectada logo depois.

Tentativa com falha 2 - Um exemplo em que eu nem consigo descobrir serviços / características.


EDIT 2:
O dispositivo ao qual estou tentando conectar é baseado no chip CC2541 da TI. Eu obtive uma TI SensorTag (também baseada no CC2541) para brincar e descobri que a TI lançou um aplicativo Android para a SensorTag ontem. No entanto, este aplicativo tem o mesmo problema. Eu testei isso em outros dois Nexus 4s com o mesmo resultado: A conexão com o SensorTag foi bem-sucedida na primeira ou na segunda vez, mas (de acordo com os registros) falha ao descobrir serviços a partir de então, causando todos os tipos de falhas. Estou começando a me perguntar se é um problema com esse chip específico?

sa.shadow
fonte
Publique os logs completos do seu telefone desde a inicialização até enfrentar o problema.
AAnkit
3
Estou usando o Samsung Galaxy S4 com o vazado Google edition Android 4.3 instalado; após inúmeras tentativas de conexão / desconexão, quando descobrir serviços, receberei aleatoriamente 129 (GATT_INTERNAL_ERROR) e receberei um onConnectionStateChange com status 133 (GATT_ERROR), estado = BluetoothProfile.DEVICE_DISCONNECTED.
reTs 7/08/13
1
Por uma ou duas vezes, recebi vários retornos de chamada de status 129 e 133 em um curto período de tempo e nunca recebi nenhum retorno de chamada no BluetoothGattCallback até reiniciar o dispositivo (mas a digitalização é boa).
RETS
1
Esqueça de dizer que estou testando com cerca de dez dispositivos usando chips de TI (desculpe, eu não conheço os modelos deles) e um dispositivo com chips nórdicos. O dispositivo com fichas nórdicos nunca relatório de erro (não o suficiente para provar o problema é TI específico, embora).
RETS
1
Posso confirmar que esta questão ainda é existir no Samsung Galaxy S5 (Ambos G900VVRU2BOG5 e G900VVRU2BOA8 versão de compilação). Se eu limpar os dados de Configurações> Gerenciador de aplicativos >> Todos >> Bluetooth , eles funcionarão por um momento.
27515 IronBlossom

Respostas:

184

Dicas importantes de implementação

(Talvez algumas dessas dicas não sejam mais necessárias devido a atualizações do sistema operacional Android.)

  1. Alguns dispositivos como o Nexus 4 com Android 4.3 levam mais de 45 segundos para se conectar usando uma instância existente do gatt . Solução alternativa: sempre feche instâncias gatt ao desconectar e crie uma nova instância de gatt em cada conexão.
  2. Não se esqueça de ligar android.bluetooth.BluetoothGatt#close()
  3. Inicie um novo thread dentro onLeScan(..) e conecte-se. Motivo: BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)sempre falha, se chamado dentro LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)do mesmo encadeamento no Samsung Galaxy S3 com Android 4.3 (pelo menos para a compilação JSS15J.I9300XXUGMK6)
  4. A maioria dos dispositivos filtra publicidade
  5. Melhor não usar android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) com o parâmetro para filtrar determinados UUIDs de serviço, porque isso é completamente quebrado no Samsung Galaxy S3 com Android 4.3 e não funciona para UUIDs de 128 bits em geral.
  6. Gatt sempre pode processar um comando de cada vez . Se vários comandos forem chamados brevemente após o outro, o primeiro será cancelado devido à natureza síncrona da implementação do gatt.
  7. Costumo ver, mesmo em dispositivos modernos com Android 5, que o Wifi interfere no bluetooth e vice-versa. Como último recurso, desligue o wifi para estabilizar o bluetooth.

Tutorial para iniciantes

Um bom ponto de entrada para os novatos pode ser este tutorial em vídeo: Desenvolvendo aplicativos inteligentes Bluetooth para Android http://youtu.be/x1y4tEHDwk0

O problema e a solução alternativa descritos abaixo provavelmente foram corrigidos agora pelas atualizações do sistema operacional

Solução alternativa: eu poderia "estabilizar" meu aplicativo fazendo isso ...

  1. Eu forneço ao usuário uma configuração "Reiniciar Bluetooth". Se essa configuração estiver ativada, reinicio o Bluetooth em alguns pontos que indicam o início da pilha BLE se tornando instável. Por exemplo, se startScan retornar false. Um bom ponto também pode ser se serviceDiscovery falhar. Acabei de ligar e desligar o Bluetooth.
  2. Eu forneço outra configuração "Desligar o WiFi". Se essa configuração estiver ativada, meu aplicativo desativará o Wi-Fi quando o aplicativo estiver em execução (e o ativará posteriormente)

Esta solução alternativa é baseada em experiências a seguir ...

  • Reiniciar o Bluetooth ajuda a corrigir problemas com o BLE na maioria dos casos
  • Se você desligar o Wifi, a pilha BLE fica muito mais estável. No entanto, ele também funciona bem na maioria dos dispositivos com o wifi ativado.
  • Se você desligar o Wifi, reiniciar o Bluetooth recupera totalmente a pilha BLE sem a necessidade de reiniciar o dispositivo na maioria dos casos.
Um mundo
fonte
33
Google, você precisa corrigir isso agora. Essa solução (eu fiz mais porque funciona) é ridícula.
Chris Herbert
4
Às vezes, a descoberta de serviço será bem-sucedida com o status 0 (supondo que não haja problemas), mas as leituras de características produzirão valores NULL porque, na verdade, não estão realmente conectados ou as características não foram descobertas (vejo isso no log: 11-01 18:37: 32,131: AVISO / BluetoothGatt (20119): excepção não tratada: java.lang.NullPointerException)
Lo-Tan
2
@ Lo-Tan Sempre verifico após a descoberta do serviço, se meu serviço esperado está incluído. Você também nunca pode ter certeza, se a descoberta do serviço der algum resultado. Às vezes, não recebo retorno de chamada. Então, apliquei um tempo limite para descoberta de serviço.
OneWorld 25/11
2
Minha experiência é: Samsung S3 (4.3) reconectado com sucesso após o fechamento de um cliente Gatt, conforme descrito no parágrafo 2 acima; usando Nexus 4 & 7 (4.4.2) que não poderia novamente após ligação caiu, mesmo reiniciando adaptador BL, mas pode ser restabelecida automaticamente depois de 2 min
Konstantin Konopko
1
Alguém pode confirmar se android.bluetooth.BluetoothGatt pode lidar apenas com uma operação GATT pendente POR DISPOSITIVO , POR PROCESSO ou PERÍODO (ou seja: em todos os processos). Presumo que seja POR DISPOSITIVO, mas esse problema é tão grave que não me surpreenderia se fosse o contrário. Se a limitação for apenas POR DISPOSITIVO, o sistema operacional / dispositivo capaz de lidar com várias operações simultâneas estará comprovando que esse problema se deve a alguma implementação ingênua e fraca na instância BluetoothAdapter que o sistema operacional realiza em cada processo (que eu supusera que fosse um singleton em todos os processos).
swooby
18

DESLIGANDO WIFI:

Também posso confirmar que desativar o WIFI torna o Bluetooth 4.0 mais estável, especialmente no Google Nexus (eu tenho um Nexus 7).

O problema

é que a aplicação que estou desenvolvendo precisa tanto Wi-Fi e contínuo de varredura Bluetooth LE . Então, desligar o Wi-Fi não era uma opção para mim.

Além disso, percebi que a varredura contínua do Bluetooth LE pode realmente matar a conexão WIFI e tornar o adaptador WIFI incapaz de se reconectar a qualquer rede WIFI até que a varredura BLE esteja ativada. (Não tenho certeza sobre redes móveis e internet móvel).
Isso definitivamente aconteceu nos seguintes dispositivos:

  • Nexus 7
  • Motorola Moto G

No entanto, a digitalização BLE com WIFI ativado parecia bastante estável em:

  • Samsung S4
  • HTC One

Minha solução alternativa

Eu digitalizo o BLE por um curto período de tempo 3 a 4 segundos, depois desligo a digitalização por 3-4 segundos . Depois ligue novamente.

  • Obviamente, sempre desativo a digitalização do BLE quando estou conectando a um dispositivo BLE.
  • Quando eu desconecto um dispositivo, reinicio o BLE (desligue e ligue o adaptador) para redefinir a pilha antes de iniciar a digitalização novamente.
  • Também redefino o BLE ao descobrir services ou characteristicsfalhar.
  • Quando obtenho dados de anúncio de um dispositivo ao qual o aplicativo deve se conectar (digamos 500 vezes sem poder se conectar - são cerca de 5 a 10 segundos de publicidade), redefino o BLE novamente.
benka
fonte
Você disse que eu reinicio o BLE depois que um dispositivo é desconectado. Suponha, se o usuário estava transferindo o arquivo pela conexão bluetooth. Você fará com que a transferência do bluetooth falhe a qualquer momento.
Rahul Rastogi
1
o que você quer dizer com "desligue e ligue o adaptador"?
Marian Paździoch 19/03/2015
Concordo, Wi-Fi e Bluetooth em conjunto está matando o desempenho aplicativo em Moto G.
Nigilan
@ MarianPaździoch, por "virar adaptador OFF e depois em" @ Benka significa BluetoothAdapter
Anup
9

Verifique se o seu Nexus está emparelhado com o dispositivo. Não consigo verificar se a comunicação funciona ou não corretamente, mas você poderá se conectar mais de uma vez sem uma reinicialização. Parece que a primeira conexão não está exigindo emparelhamento, mas todas as tentativas subseqüentes o fazem.

Atualizarei esta resposta em alguns dias quando testar a descoberta de serviço e solicitar solicitações de leitura e gravação sem necessidade de reinicialização.

EDIT: Acontece que eu estava testando em uma versão de firmware de desenvolvimento (nosso sensor) que estava causando problemas se não emparelhado. Nossa versão mais recente do firmware de produção funciona bem nos 2540s e 2541s.

EDIT: notei que no Nexus 7 2013, as conexões são mais estáveis ​​quando o Wi-Fi está desativado. Eu gostaria de saber se isso ajuda alguém.

EDIT: Eu pareço tê-lo ao contrário com o emparelhamento. Tudo funciona bem quando não está emparelhado. Após o emparelhamento, estou apresentando exatamente os mesmos sintomas do OP. Ainda não se sabe se isso está relacionado ao nosso firmware ou à API BLE do Android. Tenha cuidado ao testar isso porque, uma vez emparelhado, talvez não seja possível desemparelhar devido a um bug explicado em 3b desta postagem .

Mikt25
fonte
Estou sempre conectando e reconectando a um dispositivo CC2541 sem nenhum tipo de emparelhamento manual ou reinicialização.
dgel
Na minha opinião, não há emparelhamento necessário. Os documentos oficiais também não comentam o emparelhamento. Também pude realizar gravação, leitura, notificação de alteração de característica sem qualquer emparelhamento. No entanto, apenas por um curto período de tempo. Agora está instável novamente ... O SAMSUNG BLE SKD v2.0 também não exigiu emparelhamento e funcionou muito bem.
OneWorld
3
Posso confirmar, é mais estável depois de desligar o Wifi. Todo mundo deveria tentar isso.
OneWorld
1
Se o emparelhamento é necessário ou não, depende da implementação do dispositivo. Os dispositivos nrf8002 requerem emparelhamento e as APIs Samsung 2.0 e 1.2 suportam isso. Parece que o suporte oficial da API está tendo problemas com o aspecto de emparelhamento, pois depois de emparelhar um dispositivo ble, parece impossível desemparelhar!
Chris Herbert
2
Eu tenho um trabalho em torno de ser incapaz de desemparelhar. 1) vá para o menu bt, selecione desemparelhar, remova o dispositivo ble da área ou depower-o, selecione o dispositivo ble no menu bt e ele tentará emparelhar e falhar e redefinir o bluetooth. Após a redefinição, o dispositivo não será pareado.
Chris Herbert
7

Em alguns modelos, há um defeito: https://code.google.com/p/android/issues/detail?id=180440

Por outro lado, no meu caso, o problema era que minha conexão não estava corretamente fechada no método onDestroy. Após o fechamento correto, o problema para mim não existe, não importa se o wifi está ativado ou desativado.

btGatt.disconnect();
btGatt.close();
Krystian
fonte
Por que é closenecessário?
IgorGanapolsky
3
O procedimento de fechamento correto é a Chave quando você deseja conectar o Bluetooth várias vezes. Na minha experiência, funciona melhor se você executar sua conexão Ble em um serviço UNBOUND separado, para poder iniciar e parar manualmente. E que você chama mConnectedGatt.disconnect (); ble_device = null; no seu inDestroy (). No meu caso, esse padrão funciona estável sem problemas.
medTech
4

Eu estava enfrentando um problema semelhante. Minha correção foi

if (Build.VERSION.SDK_INT >= 23) {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}

e chamando fechar após desconectar.

Sam Reyes
fonte