How to Android
then connect to Arduino
through a Bluetooth module to Arduino
receive data. I just need to understand what part of Android
would be a Bluetooth Serial.
I found this code in the Internet it realizes if connection with the module, well I would like to know how to communicate with grbl 0.9 that is in Arduino
, because I put that code to send m3
but Arduino
does not respond.
ConnectionThread class
package br.com.dragaosemchama.supercounter;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Message;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.UUID;
public class ConnectionThread extends Thread{
BluetoothSocket btSocket = null;
BluetoothServerSocket btServerSocket = null;
InputStream input = null;
OutputStream output = null;
String btDevAddress = null;
String myUUID = "00001101-0000-1000-8000-00805F9B34FB";
boolean server;
boolean running = false;
boolean isConnected = false;
/* Este construtor prepara o dispositivo para atuar como servidor.
*/
public ConnectionThread() {
this.server = true;
}
/* Este construtor prepara o dispositivo para atuar como cliente.
Tem como argumento uma string contendo o endereço MAC do dispositivo
Bluetooth para o qual deve ser solicitada uma conexão.
*/
public ConnectionThread(String btDevAddress) {
this.server = false;
this.btDevAddress = btDevAddress;
}
/* O método run() contem as instruções que serão efetivamente realizadas
em uma nova thread.
*/
public void run() {
/* Anuncia que a thread está sendo executada.
Pega uma referência para o adaptador Bluetooth padrão.
*/
this.running = true;
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
/* Determina que ações executar dependendo se a thread está configurada
para atuar como servidor ou cliente.
*/
if(this.server) {
/* Servidor.
*/
try {
/* Cria um socket de servidor Bluetooth.
O socket servidor será usado apenas para iniciar a conexão.
Permanece em estado de espera até que algum cliente
estabeleça uma conexão.
*/
btServerSocket = btAdapter.listenUsingRfcommWithServiceRecord("Super Counter", UUID.fromString(myUUID));
btSocket = btServerSocket.accept();
/* Se a conexão foi estabelecida corretamente, o socket
servidor pode ser liberado.
*/
if(btSocket != null) {
btServerSocket.close();
}
} catch (IOException e) {
/* Caso ocorra alguma exceção, exibe o stack trace para debug.
Envia um código para a Activity principal, informando que
a conexão falhou.
*/
e.printStackTrace();
toMainActivity("---N".getBytes());
}
} else {
/* Cliente.
*/
try {
/* Obtem uma representação do dispositivo Bluetooth com
endereço btDevAddress.
Cria um socket Bluetooth.
*/
BluetoothDevice btDevice = btAdapter.getRemoteDevice(btDevAddress);
btSocket = btDevice.createRfcommSocketToServiceRecord(UUID.fromString(myUUID));
/* Envia ao sistema um comando para cancelar qualquer processo
de descoberta em execução.
*/
btAdapter.cancelDiscovery();
/* Solicita uma conexão ao dispositivo cujo endereço é
btDevAddress.
Permanece em estado de espera até que a conexão seja
estabelecida.
*/
if (btSocket != null) {
btSocket.connect();
}
} catch (IOException e) {
/* Caso ocorra alguma exceção, exibe o stack trace para debug.
Envia um código para a Activity principal, informando que
a conexão falhou.
*/
e.printStackTrace();
toMainActivity("---N".getBytes());
}
}
/* Pronto, estamos conectados! Agora, só precisamos gerenciar a conexão.
...
*/
if(btSocket != null) {
/* Envia um código para a Activity principal informando que a
a conexão ocorreu com sucesso.
*/
this.isConnected = true;
toMainActivity("---S".getBytes());
try {
/* Obtem referências para os fluxos de entrada e saída do
socket Bluetooth.
*/
input = btSocket.getInputStream();
output = btSocket.getOutputStream();
/* Permanece em estado de espera até que uma mensagem seja
recebida.
Armazena a mensagem recebida no buffer.
Envia a mensagem recebida para a Activity principal, do
primeiro ao último byte lido.
Esta thread permanecerá em estado de escuta até que
a variável running assuma o valor false.
*/
while(running) {
/* Cria um byte array para armazenar temporariamente uma
mensagem recebida.
O inteiro bytes representará o número de bytes lidos na
última transmissão recebida.
O inteiro bytesRead representa o número total de bytes
lidos antes de uma quebra de linha. A quebra de linha
representa o fim da mensagem.
*/
byte[] buffer = new byte[1024];
int bytes;
int bytesRead = -1;
/* Lê os bytes recebidos e os armazena no buffer até que
uma quebra de linha seja identificada. Nesse ponto, assumimos
que a mensagem foi transmitida por completo.
*/
do {
bytes = input.read(buffer, bytesRead+1, 1);
bytesRead+=bytes;
} while(buffer[bytesRead] != '\n');
/* A mensagem recebida é enviada para a Activity principal.
*/
toMainActivity(Arrays.copyOfRange(buffer, 0, bytesRead-1));
}
} catch (IOException e) {
/* Caso ocorra alguma exceção, exibe o stack trace para debug.
Envia um código para a Activity principal, informando que
a conexão falhou.
*/
e.printStackTrace();
toMainActivity("---N".getBytes());
this.isConnected = false;
}
}
}
/* Utiliza um handler para enviar um byte array à Activity principal.
O byte array é encapsulado em um Bundle e posteriormente em uma Message
antes de ser enviado.
*/
private void toMainActivity(byte[] data) {
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putByteArray("data", data);
message.setData(bundle);
MainActivity.handler.sendMessage(message);
}
/* Método utilizado pela Activity principal para transmitir uma mensagem ao
outro lado da conexão.
A mensagem deve ser representada por um byte array.
*/
public void write(byte[] data) {
if(output != null) {
try {
/* Transmite a mensagem.
*/
output.write(data);
} catch (IOException e) {
e.printStackTrace();
}
} else {
/* Envia à Activity principal um código de erro durante a conexão.
*/
toMainActivity("---N".getBytes());
}
}
/* Método utilizado pela Activity principal para encerrar a conexão
*/
public void cancel() {
try {
running = false;
this.isConnected = false;
btServerSocket.close();
btSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
running = false;
this.isConnected = false;
}
public boolean isConnected() {
return this.isConnected;
}
}
Main Activity
package br.com.dragaosemchama.supercounter;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
/* Definição dos objetos que serão usados na Activity Principal
statusMessage mostrará mensagens de status sobre a conexão
counterMessage mostrará o valor do contador como recebido do Arduino
connect é a thread de gerenciamento da conexão Bluetooth
*/
static TextView statusMessage;
static TextView counterMessage;
ConnectionThread connect;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Link entre os elementos da interface gráfica e suas
representações em Java.
*/
statusMessage = (TextView) findViewById(R.id.statusMessage);
counterMessage = (TextView) findViewById(R.id.counterMessage);
/* Teste rápido. O hardware Bluetooth do dispositivo Android
está funcionando ou está bugado de forma misteriosa?
Será que existe, pelo menos? Provavelmente existe.
*/
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
statusMessage.setText("Que pena! Hardware Bluetooth não está funcionando :(");
} else {
statusMessage.setText("Ótimo! Hardware Bluetooth está funcionando :)");
}
/* A chamada do seguinte método liga o Bluetooth no dispositivo Android
sem pedido de autorização do usuário. É altamente não recomendado no
Android Developers, mas, para simplificar este app, que é um demo,
faremos isso. Na prática, em um app que vai ser usado por outras
pessoas, não faça isso.
*/
btAdapter.enable();
/* Definição da thread de conexão como cliente.
Aqui, você deve incluir o endereço MAC do seu módulo Bluetooth.
O app iniciará e vai automaticamente buscar por esse endereço.
Caso não encontre, dirá que houve um erro de conexão.
*/
connect = new ConnectionThread("00:16:13:19:43:54");
connect.start();
/* Um descanso rápido, para evitar bugs esquisitos.
*/
try {
Thread.sleep(1000);
} catch (Exception E) {
E.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public static Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
/* Esse método é invocado na Activity principal
sempre que a thread de conexão Bluetooth recebe
uma mensagem.
*/
Bundle bundle = msg.getData();
byte[] data = bundle.getByteArray("data");
String dataString= new String(data);
/* Aqui ocorre a decisão de ação, baseada na string
recebida. Caso a string corresponda à uma das
mensagens de status de conexão (iniciadas com --),
atualizamos o status da conexão conforme o código.
*/
if(dataString.equals("---N"))
statusMessage.setText("Ocorreu um erro durante a conexão D:");
else if(dataString.equals("---S"))
statusMessage.setText("Conectado :D");
else {
/* Se a mensagem não for um código de status,
então ela deve ser tratada pelo aplicativo
como uma mensagem vinda diretamente do outro
lado da conexão. Nesse caso, simplesmente
atualizamos o valor contido no TextView do
contador.
*/
counterMessage.setText(dataString);
}
}
};
/* Esse método é invocado sempre que o usuário clicar na TextView
que contem o contador. O app Android transmite a string "restart",
seguido de uma quebra de linha, que é o indicador de fim de mensagem.
*/
//Está parte que alterei para enviar m3 para testar
public void restartCounter(View view) {
connect.write("m3".getBytes());
}
}