Bluetooth é um protocolo padrão de comunicação primariamente projetado para baixo consumo de energia e com baixo alcance.

A plataforma Android inclui suporte para a rede Bluetooth, permitindo que dispositivos troquem dados em uma rede sem fio. O Android Bluetooth API fornece acesso a várias funcionalidades do dispositivo, permitindo a comunicação entre eles ponto-a-ponto e multiponto.

Uma aplicação Android usando esta API pode desfrutar dos recursos:

  • 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.

Neste artigo veremos como realizar uma busca e pegar o objeto referente ao dispositivo, através desse objeto podemos estabilizar uma conexão direta e realizar varias tarefas.

Lista de dispositivos encontrados em uma busca
Figura 1. Lista de dispositivos encontrados em uma busca

Codificando

Para utilizar os recursos do Bluetooth em seu aplicativo, o Android pede para você declarar as seguintes permissões dependendo do uso: BLUETOOTH e BLUETOOTH_ADMIN.

A permissão BLUETOOTH é necessária para realizar qualquer comunicação entre dispositivos, como solicitar uma conexão, aceitar ou transferir dados.

A BLUETOOTH_ADMIN é necessária para iniciar a descoberta de dispositivos ou manipular suas configurações. A maioria dos aplicativos precisa dessa permissão pelo simples fato de buscar dispositivos. Caso você utilize essa permissão você também deve declarar a permissão BLUETOOTH.


<manifest ... >
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
  <uses-permission android:name="android.permission.BLUETOOTH" />
  ...
</manifest>
Listagem 1. Declaração das permissões no Manifest.xml

O Exemplo de busca é bem simples, vamos ter somente um layout “main.xml” que deve conter um ListView para inserirmos as informações decorrente ao processo de busca.


<?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>
Listagem 2. Arquivo main.xml

Já temos nossa estrutura, declaramos as permissões e construímos nosso layout. O próximo passo é desenvolver a classe Bluetooth.java para tratar nossa busca. Ela deve estender a classe BroadcastReceiver, que trata tudo o que for enviado pelo broadcast registrado na activity como se fosse um “listener”. Caso fique com duvidas sobre o que é um Broadcast verifique na documentação do Android, para facilitar o entendimento.

Vamos explicar tudo por partes para que não fique confuso. Na classe Bluetooth vamos ter 3 atributos, uma interface (que será o listener), um método para iniciar a busca e outro método sobrescrito da nossa super classe (que recebera as respostas do broadcast).

Nosso construtor privado deve receber somente um parâmetro que é o BluetoothListener ele vai ser criado dentro dessa mesma classe com o intuito de notificar a busca.


public class Bluetooth extends BroadcastReceiver {
[...]
    private BluetoothListener listener;
    private ArrayList lista;
    private BluetoothAdapter dispositivo;

    private Bluetooth(BluetoothListener listener) {
        this.listener = listener;
        lista = new ArrayList();
    }
[...]
//métodos gets e sets
[...]
}
Listagem 3. A classe Bluetooth.java estrutura

Na interface vamos definir um método action() e três ações para que tenhamos o controle do que está ocorrendo. Essas ações estão interligadas com as ações do Android Bluetooth API das classes BluetoothAdapter e BluetoothDevice.


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);
}
Listagem 4. Interface de notificação BluetoothListener

No método abaixo vamos instanciar nossa classe tratar se o bluetooth está desativado, registrar os broadcasts referentes ao nosso listener e iniciar a busca de dispositivos.


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 (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 a classe instanciada.
    bluetooth.dispositivo.startDiscovery();
    return bluetooth;
} 
Listagem 5. Método principal responsável por tratar e iniciar a busca

Você já deve ter sobrescrito 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
        context.unregisterReceiver(this);
    }

    if (listener != null) {
        //se foi definido o listener eu aviso a quem ta gerenciando.
        listener.action(action);
    }
}
Listagem 6. Implementação do método onReceive() do BroadcastReceiver

A classe Bluetooth.java está pronta para ser utilizada. Agora Vamos trabalhar em cima da MainActivity.java.

Primeiramente será definida a interface da classe Bluetooth para lermos as ações da busca. No método onCreate() vamos chamar o método estático da classe Bluetooth para iniciar a busca e definir um adaptador para o ListView.

Em nosso action() que foi sobrescrito de nossa interface implementada serão tratadas todas as ações da busca de dispositivos e assim que chegar no fim vamos popular o ListView com a lista de dispositivos.


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());
        }
    }
}
Listagem 7. Utilização da classe Bluetooth.java

Como um opcional também foi inserido um método na classe Bluetooth.java que permite pegar os dispositivos já pareados ao seu aparelho, porém de uma maneira direta sem a necessidade de utilizar o listener, pois não é realizada uma busca. Veja na listagem abaixo.


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;
}
Listagem 8. Método opcional para pegar dispositivos já pareados

Conclusão

A busca de dispositivos é sempre utilizada quando você tem uma aplicação que necessita de uma comunicação com outro dispositivo Bluetooth, através dessa consulta vamos obter os dados como nome e endereço dos dispositivos, assim podem estabelecer uma comunicação com os recursos do Android Bluetooth API, para a troca de informação.

Com isso finalizo esse artigo. No link “código fonte”, no topo dessa página, está o projeto que foi utilizado como exemplo. Até o próximo, um grande abraço e obrigado.

Referências