Bluetooth
A plataforma Android inclui suporte para a pilha de rede Bluetooth, que permite que um dispositivo troque dados com outros dispositivos Bluetooth. A estrutura do framework fornece acesso à funcionalidade Bluetooth através do Bluetooth Android APIs. Essas APIs permitem que as aplicações estabeleção comunicação sem fio com outros dispositivos Bluetooth.
Usando as APIs de Bluetooth, uma aplicação Android pode executar o seguinte:
- Verificar se há outros dispositivos Bluetooth
- Consultar o adaptador Bluetooth local para dispositivos Bluetooth emparelhados
- Estabelecer canais RFCOMM
- Conectar a outros dispositivos através do serviço de descoberta
- Transferir dados para e de outros dispositivos
- Gerenciar conexões múltiplas
Abaixo vamos mostrar algumas funcionalidades como a busca de dispositivos.
Buscando dispositivos
Antes de tudo, lembre-se de inserir as permissões no seu Manifest.xml. A primeira permissão é para a busca de dispositivos e outras coisas relacionadas ao bluetooth (como transferência). A segunda permissão é utilizada para controle do dispositivo, ex: ativar o bluetooth.
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
Como o exemplo vai ser bem simples, vamos mostrar os itens em um ListView, assim teremos apenas um Layout “main.xml”
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+idMain/listview" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
Agora vamos mostrar a classe responsável por TUDO a Bluetooth.java, essa classe extende BroadcastReceiver porque ela vai ser um receiver do sistema, vamos definir alguns filtros sobre o que ela vai “ouvir” e implementar o que vamos fazer com isso. Caso você não saiba o que é um Broadcast tentem ler algo sobre pois vai facilitar o entendimento.
public class Bluetooth extends BroadcastReceiver { [...] private BluetoothListener listener; private ArrayList lista; private BluetoothAdapter dispositivo; private Bluetooth(BluetoothListener listener) { this.listener = listener; lista = new ArrayList(); } [...] }
Como a classe é muito grande vou explica-la por partes para nao ficar muito confuso. No final do topico vou inserir um link do projeto tambem.
Tudo que irei mostrar vai estar dentro da classe Bluetooth.
Abaixo defini um listener que vai ser responsável em informar as ações da busca.
public static interface BluetoothListener { public static final String ACTION_DISCOVERY_STARTED = BluetoothAdapter.ACTION_DISCOVERY_STARTED; public static final String ACTION_FOUND = BluetoothDevice.ACTION_FOUND; public static final String ACTION_DISCOVERY_FINISHED = BluetoothAdapter.ACTION_DISCOVERY_FINISHED; public void action(String action); }
No método abaixo é realizado o registro dos broadcast para ler as ações do bluetooth e iniciar a busca.
public static Bluetooth startFindDevices(Context context, BluetoothListener listener) throws IOException { Bluetooth bluetooth = new Bluetooth(listener); //Pego o adapter bluetooth.dispositivo = BluetoothAdapter.getDefaultAdapter(); // verifico se o bluetooth esta desabilitado, se tiver habilito //retorno null pois esta ação demora para ser concluida. (tratar) if (!bluetooth.dispositivo.isEnabled()) { bluetooth.dispositivo.enable(); return null; } // Registro os Broadcast necessarios para a busca de dispositivos IntentFilter filter = new IntentFilter(BluetoothListener.ACTION_FOUND); IntentFilter filter2 = new IntentFilter(BluetoothListener.ACTION_DISCOVERY_FINISHED); IntentFilter filter3 = new IntentFilter(BluetoothListener.ACTION_DISCOVERY_STARTED); context.registerReceiver(bluetooth, filter); context.registerReceiver(bluetooth, filter2); context.registerReceiver(bluetooth, filter3); //inicio a busca e retorno o objeto que vai te ralista de dispositivos bluetooth.dispositivo.startDiscovery(); return bluetooth; }
Beleza, estamos iniciando a busca, mas como vamos descubrir o que está chegando? você deve sobrescrever o método onReceive do BroadcastReceiver. Abaixo vamos tratar cada Broadcast que foi registrado e chamar o listener para informar o que está acontecendo.
@Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); //caso encontre um dispositivo: if (action.compareTo(BluetoothDevice.ACTION_FOUND) == 0) { //pega as o dispositivo encontrado: BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //se a lista já tiver esse dispositivo eu retorno para o proximo //isso permite que sejá mostrado somente uma vez meu dispositivo //problema muito comum em exemplos if (lista.contains(device)) { return; } //adiciono o dispositivo na minha lista: lista.add(device); } else if (action.compareTo(BluetoothAdapter.ACTION_DISCOVERY_FINISHED) == 0) { //caso o discovery chegue ao fim eu desregistro meus broadcasts //SEMPRE FAÇA ISSO quando terminar de usar um broadcast //(aqueles IntentFilter que criei anteriormente) context.unregisterReceiver(this); } if (listener != null) { //se foi definido o listener eu aviso a quem ta gerenciando. listener.action(action); } }
Pronto, agora como usar essa classe ?
abaixo temos a Main do projeto:
Resumindo, implementei o Listener da classe Bluetooth para que podemos ler a ação, no onCreate damos o start na busca e definimos um adapter para o listview.
no método do listener (action) vamos tratar as ações do Bluetooth. quando chega no fim da busca pegamos os dispositivos da classe bluetooth e exibimos no listview.
public class MainActivity extends Activity implements Bluetooth.BluetoothListener { private static final String TAG = "BuscaBluetooth"; private Bluetooth bluetooth; private ArrayAdapter arrayAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { bluetooth = Bluetooth.startFindDevices(this, this); } catch (Exception e) { Log.e(TAG, "Erro: ", e); } arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1); ListView listView = (ListView) findViewById(R.idMain.listview); listView.setAdapter(arrayAdapter); } public void action(String action) { if (action.compareTo(ACTION_DISCOVERY_STARTED) == 0) { arrayAdapter.add("-Busca iniciada"); } else if (action.compareTo(ACTION_DISCOVERY_FINISHED) == 0) { preencherLista(); arrayAdapter.add("-Fim de busca."); } } private void preencherLista() { for (BluetoothDevice device : bluetooth.getDispositivos()) { arrayAdapter.add(device.getName() + "n" + device.getAddress()); } } }
Se rodarmos a aplicação veremos algo como:
Como opcional inseri um método na classe Bluetooth que pega os dispositivos já pareados.
public static Bluetooth getBondedDevices(Context applicationContext) throws IOException { Bluetooth bluetooth = new Bluetooth(null); // Pega o dispositivo bluetooth.dispositivo = BluetoothAdapter.getDefaultAdapter(); if (!bluetooth.dispositivo.isEnabled()) { bluetooth.dispositivo.enable(); } // Pega a lista de dispositivos pareados Set pairedDevices = bluetooth.dispositivo.getBondedDevices(); // Adiciono na lista e depois retorno a mesma. if (pairedDevices.size() > 0) { for (BluetoothDevice device : pairedDevices) { bluetooth.lista.add(device); } } return bluetooth; }
Talvez para leigos(ou nao) fica um pouco complicado para entender o conceito do listener dos Broadcasts e da minha pouca explicação, no link abaixo coloquei o projeto completo.
LINK DO PROJETO (DropBox)
Fonte: http://goo.gl/D7ekO
Mais uma vez parabéns pelo post, uma dúvida: O que acontece para que haja o retorno quando vamos verificar se o adaptador está ativo? Percebi que esta operação demora muito para ser concluída dando a impressão que está travado. O que pode ser feito para otimizar tal item?
Acredito que a melhor opção seja rodar em uma AsyncTask. Assim o processamento fica em Thread e você controla o feedback para o usuario. (usando um ProgressDialog.)