I am attempting to use the MyBluetoothService class straight from the Android tutorials and call the write method from the main activity as suggested by the text. I would just like some guidance on how to pass a string from the main activity to the write method and send it to a connected Bluetooth device.
public class MyBluetoothService {
private static final String TAG = "MY_APP_DEBUG_TAG";
private Handler mHandler; // handler that gets info from Bluetooth service
// Defines several constants used when transmitting messages between the
// service and the UI.
private interface MessageConstants {
public static final int MESSAGE_READ = 0;
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_TOAST = 2;
// ... (Add other message types here as needed.)
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte[] mmBuffer; // mmBuffer store for the stream
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams; using temp objects because
// member streams are final.
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating input stream", e);
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating output stream", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
mmBuffer = new byte[1024];
int numBytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
numBytes = mmInStream.read(mmBuffer);
// Send the obtained bytes to the UI activity.
Message readMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_READ, numBytes, -1,
mmBuffer);
readMsg.sendToTarget();
} catch (IOException e) {
Log.d(TAG, "Input stream was disconnected", e);
break;
}
}
}
// Call this from the main activity to send data to the remote device.
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
// Share the sent message with the UI activity.
Message writtenMsg = mHandler.obtainMessage(
MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
writtenMsg.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Error occurred when sending data", e);
// Send a failure message back to the activity.
Message writeErrorMsg =
mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString("toast",
"Couldn't send data to the other device");
writeErrorMsg.setData(bundle);
mHandler.sendMessage(writeErrorMsg);
}
}
// Call this method from the main activity to shut down the connection.
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
}
}
this code will help you to find all the devices in the surrounding
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class DeviceList extends AppCompatActivity {
ListView blist;
Button b;
private BluetoothAdapter myBluetooth = null;
private Set<BluetoothDevice> pairedDevices;
public static String EXTRA_ADDRESS = "device_address";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_device_list);
b=(Button)findViewById(R.id.button);
blist=(ListView)findViewById(R.id.listView);
myBluetooth = BluetoothAdapter.getDefaultAdapter();
if(myBluetooth == null)
{
//Show a mensag. that the device has no bluetooth adapter
Toast.makeText(getApplicationContext(), "Bluetooth Device Not Available", Toast.LENGTH_LONG).show();
//finish apk
finish();
}
else if(!myBluetooth.isEnabled())
{
//Ask to the user turn the bluetooth on
Intent turnBTon = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnBTon,1);
}
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pairedDevices();
}
});
}
private void pairedDevices()
{
pairedDevices=myBluetooth.getBondedDevices();
ArrayList list=new ArrayList();
if(pairedDevices.size() > 0)
{
for(BluetoothDevice bt : pairedDevices)
{
list.add(bt.getName() + "\n" + bt.getAddress()); //Get the device's name and the address
}
}
else
{
Toast.makeText(getApplicationContext(), "No Paired Bluetooth Devices Found.", Toast.LENGTH_LONG).show();
}
final ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, list);
blist.setAdapter(adapter);
blist.setOnItemClickListener(myListClickListener); //Method called when the device from the list is clicked
}
private AdapterView.OnItemClickListener myListClickListener = new AdapterView.OnItemClickListener()
{
public void onItemClick (AdapterView<?> av, View v, int arg2, long arg3)
{
// Get the device MAC address, the last 17 chars in the View
String info = ((TextView) v).getText().toString();
String address = info.substring(info.length() - 17);
// Make an intent to start next activity.
Intent i = new Intent(DeviceList.this, ledControl.class);
//Change the activity.
i.putExtra(EXTRA_ADDRESS, address); //this will be received at ledControl (class) Activity
startActivity(i);
}
};
}
this code helps to send the message to the device connected
public class ledControl extends AppCompatActivity {
Button btnOn, btnOff, btnDis;
TextView lumn;
String address = null;
private ProgressDialog progress;
BluetoothAdapter myBluetooth = null;
BluetoothSocket btSocket = null;
private boolean isBtConnected = false;
//SPP UUID. Look for it
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent newint = getIntent();
address = newint.getStringExtra(DeviceList.EXTRA_ADDRESS); //receive the address of the bluetooth device
//view of the ledControl
setContentView(R.layout.activity_led_control);
//call the widgtes
btnOn = (Button) findViewById(R.id.button2);
btnOff = (Button) findViewById(R.id.button3);
btnDis = (Button) findViewById(R.id.button4);
lumn = (TextView) findViewById(R.id.lumn);
new ConnectBT().execute(); //Call the class to connect
//commands to be sent to bluetooth
btnOn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
turnOnLed();
//method to turn on
}
});
btnOff.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
turnOffLed(); //method to turn off
}
});
btnDis.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Disconnect(); //close connection
}
});
}
private void Disconnect()
{
if (btSocket!=null) //If the btSocket is busy
{
try
{
btSocket.close(); //close connection
}
catch (IOException e)
{ msg("Error");}
}
finish(); //return to the first layout
}
private void turnOffLed()
{
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("F".toString().getBytes());
//Log.e("message",)
}
catch (IOException e)
{
msg("Error");
}
}
}
private void turnOnLed()
{
if (btSocket!=null)
{
try
{
//Toast.makeText(ledControl.this,"oning",Toast.LENGTH_SHORT).show();
btSocket.getOutputStream().write("O".toString().getBytes());
Log.e("message",btSocket.toString());
}
catch (IOException e)
{
msg("Error");
}
}
}
// fast way to call Toast
private void msg(String s)
{
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
}
private class ConnectBT extends AsyncTask<Void, Void, Void> // UI thread
{
private boolean ConnectSuccess = true; //if it's here, it's almost connected
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(ledControl.this, "Connecting...", "Please wait!!!"); //show a progress dialog
}
#Override
protected Void doInBackground(Void... devices) //while the progress dialog is shown, the connection is done in background
{
try
{
if (btSocket == null || !isBtConnected)
{
myBluetooth = BluetoothAdapter.getDefaultAdapter();//get the mobile bluetooth device
BluetoothDevice dispositivo = myBluetooth.getRemoteDevice(address);//connects to the device's address and checks if it's available
btSocket = dispositivo.createInsecureRfcommSocketToServiceRecord(myUUID);//create a RFCOMM (SPP) connection
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
btSocket.connect();//start connection
}
}
catch (IOException e)
{
ConnectSuccess = false;//if the try failed, you can check the exception here
}
return null;
}
#Override
protected void onPostExecute(Void result) //after the doInBackground, it checks if everything went fine
{
super.onPostExecute(result);
if (!ConnectSuccess)
{
msg("Connection Failed. Is it a SPP Bluetooth? Try again.");
finish();
}
else
{
msg("Connected.");
isBtConnected = true;
}
progress.dismiss();
}
}
}
Related
I am trying to send data over bluetooth to stm32f411 board. I am using HC-05 v2 bluetooth module which communicates over UART interface. When I'm sending data from computer it works perfectly- data is sent and STM's response is received over UART in RealTerm. However switching to bluetooth module and sending and receiving data from android app doesn't work as expected. For now I want to send ASCII data (for now just 0 and 1, but the goal is to send integers from 0 to 100). Perhaps it has something to do with message length or app's baud rate.
I also tried to send data as byte not byte array but it didn't work- when I sent 0 it worked fine but when I sent 1 I got 120 decimal on STM, 2 I got 128, 3 I got 248. When I tried sending the same data back to app every message started with [B# followed by usually 7 characters.
My android studio code:
public class MainActivity extends AppCompatActivity {
Button someButton;
ListView pairedDevListView;
Switch bluetoothSwitch;
BluetoothAdapter myBluetoothAdapter;
Intent bluetoothEnablingIntent;
TextView connectionStatusText;
SeekBar rightEnSeekBar, leftEnSeekBar;
SendReceive sendReceive;
BluetoothDevice[] bluetoothPairedDevArray;
int REQUEST_ENABLE_BLUETOOTH = 1;
int requestCodeForEnable;
static final int STATE_LISTENING = 1;
static final int STATE_CONNECTING = 2;
static final int STATE_CONNECTED = 3;
static final int STATE_CONNECTION_FAILED = 4;
static final int STATE_MESSAGE_RECEIVED = 5;
private static final String APP_NAME = "STM32";
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
Handler handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(#NonNull Message message) {
switch (message.what){
case STATE_LISTENING:
connectionStatusText.setText("Listening");
break;
case STATE_CONNECTING:
connectionStatusText.setText("Connecting");
break;
case STATE_CONNECTED:
connectionStatusText.setText("Connected");
break;
case STATE_CONNECTION_FAILED:
connectionStatusText.setText("Connection failed");
break;
case STATE_MESSAGE_RECEIVED:
byte[] readBuff = (byte[]) message.obj;
//String tempMsg = new String(readBuff, 0 , message.arg1);
String tempMsg = null;
try {
tempMsg = new String(readBuff, "ASCII");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), String.valueOf(readBuff), Toast.LENGTH_SHORT).show();
connectionStatusText.setText(tempMsg);
break;
}
return true;
}
});
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothEnablingIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
requestCodeForEnable = 1;
if(!myBluetoothAdapter.isEnabled()){
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BLUETOOTH);
}
findViewByIds();
implementListeners();
}
private void findViewByIds() {
pairedDevListView = findViewById(R.id.pairedDevicesListView);
bluetoothSwitch = findViewById(R.id.btSwitch);
connectionStatusText = findViewById(R.id.statusTextView);
rightEnSeekBar = findViewById(R.id.rightSeekBar);
leftEnSeekBar = findViewById(R.id.leftSeekBar);
someButton = findViewById(R.id.button2);
}
private void implementListeners() {
//BLUETOOTH ENABLING SWITCH
bluetoothSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b){
if(myBluetoothAdapter == null){
Toast.makeText(getApplicationContext(),"Bluetooth is not supported on this device", Toast.LENGTH_LONG).show();
}
else{
if(!myBluetoothAdapter.isEnabled()){
startActivityForResult(bluetoothEnablingIntent, requestCodeForEnable);
}
}
}
else{
if(myBluetoothAdapter.isEnabled()){
myBluetoothAdapter.disable();
Toast.makeText(getApplicationContext(), "Bluetooth is disabled", Toast.LENGTH_LONG).show();
}
}
}
});
//CLICKING ON DEVICE FROM PAIRED DEVICE LIST
pairedDevListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
ClientClass clientClass = new ClientClass(bluetoothPairedDevArray[i]);
clientClass.start();
connectionStatusText.setText("Connecting");
}
});
someButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String string = "1";
try {
sendReceive.write(string.getBytes("ASCII"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
});
}
//SHOWING PAIRED DEVICES WHEN SWITCH IS CHECKED
private void showPairedDevices() {
Set<BluetoothDevice> btDevices = myBluetoothAdapter.getBondedDevices();
bluetoothPairedDevArray = new BluetoothDevice[btDevices.size()];
String[] deviceNames = new String[btDevices.size()];
int index = 0;
if(btDevices.size() > 0){
for(BluetoothDevice device: btDevices){
deviceNames[index] = device.getName();
bluetoothPairedDevArray[index] = device;
index++;
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, deviceNames);
pairedDevListView.setAdapter(arrayAdapter);
}
}
//SHOWING POP UP MESSAGE
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if(requestCode == requestCodeForEnable){
if(resultCode == RESULT_OK){
Toast.makeText(getApplicationContext(), "Bluetooth is enabled", Toast.LENGTH_LONG).show();
showPairedDevices();
}
else if(resultCode == RESULT_CANCELED){
Toast.makeText(getApplicationContext(), "Bluetooth enabling cancelled", Toast.LENGTH_LONG).show();
}
}
}
private class ClientClass extends Thread{
private BluetoothSocket socket;
private BluetoothDevice device;
public ClientClass(BluetoothDevice device1){
this.device = device1;
try {
socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run(){
myBluetoothAdapter.cancelDiscovery();
try {
socket.connect();
Message message = Message.obtain();
message.what = STATE_CONNECTED;
handler.sendMessage(message);
sendReceive = new SendReceive(socket);
sendReceive.start();
} catch (IOException e) {
e.printStackTrace();
Message message = Message.obtain();
message.what = STATE_CONNECTION_FAILED;
handler.sendMessage(message);
}
}
}
private class SendReceive extends Thread {
private final BluetoothSocket bluetoothSocket;
private final InputStream inputStream;
private final OutputStream outputStream;
public SendReceive(BluetoothSocket socket) {
bluetoothSocket = socket;
InputStream tempIn = null;
OutputStream tempOut = null;
try {
tempIn = bluetoothSocket.getInputStream();
tempOut = bluetoothSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
inputStream = tempIn;
outputStream = tempOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while (true) {
try {
bytes = inputStream.read(buffer);
handler.obtainMessage(STATE_MESSAGE_RECEIVED, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void write(byte[] bytes) {
try {
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
My STM code:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
switch (atoi(&Received)) {
case 0:
size = sprintf(Data, "STOP\n\r");
HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_LED_Pin, GPIO_PIN_RESET);
break;
case 1:
size = sprintf(Data, "START\n\r");
HAL_GPIO_WritePin(BLUE_LED_GPIO_Port, BLUE_LED_Pin, GPIO_PIN_SET);
break;
default:
size = sprintf(Data, "Odebrano nieznany znak: %c\n\r", Received);
break;
}
HAL_UART_Transmit_IT(&huart1, Data, size);
HAL_UART_Receive_IT(&huart1, &Received, 1);
HAL_GPIO_TogglePin(RED_LED_GPIO_Port, RED_LED_Pin);
}
So i'm making a OBDII Bluetooth app were the user can send commands such as voltage (in this case) and get data from the OBDII. So far i've managed to make a Bluetooth connection with my mobile device to my OBDII adapter work and now I need to send some basic commands and displaying them in Logcat (for the moment).
The problem i'm having is that it doesn't recognize my onClick method?
Could not find method onClick(View) in a parent or ancestor Context
for android:onClick attribute defined on view class
android.support.v7.widget.AppCompatButton with id 'getValue'
I'm sure that i've missed something in my code, but I dont know what.
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button b1;
BluetoothAdapter mAdapter;
FragmentHostCallback mHost;
BTHandler btHandler;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Constants.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BTHandler.STATE_CONNECTED:
//setContentView(R.layout.activity_connected);
Intent intent = new Intent(MainActivity.this, Connected.class);
startActivity(intent);
Toast.makeText(getApplicationContext(), R.string.title_connected_to, Toast.LENGTH_SHORT).show();
Log.v("Log", "Connected");
break;
case BTHandler.STATE_NONE:
Toast.makeText(getApplicationContext(), R.string.title_not_connected, Toast.LENGTH_SHORT).show();
break;
}
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btHandler = new BTHandler(MainActivity.this, mHandler);
b1 = (Button) findViewById(R.id.connect);
mAdapter = BluetoothAdapter.getDefaultAdapter();
//init();
if (mAdapter == null) {
Toast.makeText(getApplicationContext(), R.string.device_not_supported, Toast.LENGTH_LONG).show();
finish();
} else {
if (!mAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
}
}
//BTHandler btHandler = new BTHandler(MainActivity.this, mHandler);
//btHandler.connect("");
}
public void onClick(View v) {
int id = v.getId();
String sendMessage = ("AT RV");
switch (id) {
case R.id.connect:
onConnect(); //Operation
Log.v("Log", "Pressed onClick");
break;
case R.id.getValue:
btHandler.write(sendMessage);
Log.v("Log", "getValue" + sendMessage);
break;
}
}
BTHandler.java
public class BTHandler {
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
final ArrayList<String> devices = new ArrayList();
private final Handler mHandler;
private BluetoothAdapter mAdapter;
private BluetoothDevice device;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private BluetoothSocket socket;
private String status;
private int mState;
private boolean connectionStatus = false;
public BTHandler(Context context, Handler handler) { // Konstruktor
mAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = handler;
}
public void write(String s) {
mConnectedThread.sendRawCommand(s);
}
/*
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
*/
public void connect(String deviceAddress) {
mConnectThread = new ConnectThread(deviceAddress);
mConnectThread.start();
}
private void guiHandler(int what, int arg1, String obj) {
Message msg = mHandler.obtainMessage();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.sendToTarget();
}
private class ConnectThread extends Thread {
BluetoothSocket tmp = null;
private BluetoothSocket mmSocket;
public ConnectThread(String deviceAddress) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
device = mAdapter.getRemoteDevice(deviceAddress);
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
tmp = device.createRfcommSocketToServiceRecord(uuid);
//socket.connect();
//Log.v("connect", "connect");
} catch (IOException e) {
//e.printStackTrace();
//Log.v("exception", "e");
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mAdapter.cancelDiscovery();
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes;
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Log.v("connect", "connect");
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
Log.v("close", "close");
} catch (IOException closeException) {
}
guiHandler(Constants.TOAST, Constants.SHORT, "Connection Failed");
return;
}
guiHandler(Constants.CONNECTION_STATUS, Constants.STATE_CONNECTED, "");
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private ObdMultiCommand multiCommand;
public ConnectedThread(BluetoothSocket socket) {
connectionStatus = true;
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
try {
RPMCommand engineRpmCommand = new RPMCommand();
SpeedCommand speedCommand = new SpeedCommand();
ModuleVoltageCommand voltageCommand = new ModuleVoltageCommand();
while (!Thread.currentThread().isInterrupted()) {
engineRpmCommand.run(mmInStream, mmOutStream); //(socket.getInputStream(), socket.getOutputStream());
speedCommand.run(mmInStream, mmOutStream); //(socket.getInputStream(), socket.getOutputStream());
voltageCommand.run(mmInStream, mmOutStream); //(socket.getInputStream(), socket.getOutputStream());
// TODO handle commands result
Log.d("Log", "RPM: " + engineRpmCommand.getFormattedResult());
Log.d("Log", "Speed: " + speedCommand.getFormattedResult());
Log.v("Log", "Voltage: " + speedCommand.getFormattedResult());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
OBDcmds();
// Keep listening to the InputStream until an exception occurs
while (connectionStatus) {
sendMultiCommand();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// CALL this to MainActivity
public void sendRawCommand(String s) {
try {
//new ObdRawCommand();
} catch (Exception e) {
}
}
private void OBDcmds() { // execute commands
try {
new EchoOffCommand().run(socket.getInputStream(), socket.getOutputStream());
new LineFeedOffCommand().run(socket.getInputStream(), socket.getOutputStream());
new TimeoutCommand(125).run(socket.getInputStream(), socket.getOutputStream());
new SelectProtocolCommand(ObdProtocols.AUTO).run(socket.getInputStream(), socket.getOutputStream()); //ISO_15765_4_CAN
} catch (Exception e) {
Log.v("Log", "e");
// handle errors
}
}
/*
// Call this from the main activity to send data to the remote device
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
*/
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
public void sendMultiCommand() {
try {
// RUN some code here
} catch (Exception e) {
}
}
}
}
EDIT:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {...}
#Override
protected void onCreate(Bundle savedInstanceState) {
b1 = (Button) findViewById(R.id.connect);
b1.setOnClickListener(this);
}
Logcat:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.asabanov.powersupplytool, PID: 26570
java.lang.IllegalStateException: Could not find method onClick(View) in a parent or ancestor Context for android:onClick
attribute defined on view class
android.support.v7.widget.AppCompatButton with id 'getValue'
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatViewInflater.java:307)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:266)
at android.view.View.performClick(View.java:5226)
at android.view.View$PerformClick.run(View.java:21266)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:168)
at android.app.ActivityThread.main(ActivityThread.java:5845)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
W/System.err: com.github.pires.obd.exceptions.UnableToConnectException: Error
running 01 42, response: 0142...UNABLETOCONNECT
W/System.err: at java.lang.Class.newInstance(Native Method)
W/System.err: at com.github.pires.obd.commands.ObdCommand.checkForErrors(ObdCommand.java:203)
W/System.err: at com.github.pires.obd.commands.ObdCommand.readResult(ObdCommand.java:123)
W/System.err: at com.github.pires.obd.commands.ObdCommand.run(ObdCommand.java:77)
W/System.err: at com.example.asabanov.powersupplytool.BTHandler$ConnectedThread.(BTHandler.java:151)
W/System.err: at com.example.asabanov.powersupplytool.BTHandler$ConnectThread.run(BTHandler.java:117)
V/Log: e
EDIT:
private void onConnect() {
ArrayList deviceStrs = new ArrayList();
final ArrayList<String> devices = new ArrayList();
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
Set pairedDevices = mAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (Object device : pairedDevices) {
BluetoothDevice bdevice = (BluetoothDevice) device;
deviceStrs.add(bdevice.getName() + "\n" + bdevice.getAddress());
devices.add(bdevice.getAddress());
}
}
// show list
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.select_dialog_singlechoice,
deviceStrs.toArray(new String[deviceStrs.size()]));
alertDialog.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
String deviceAddress = devices.get(position);
btHandler.connect(deviceAddress);
//btHandler.write();
}
});
alertDialog.setTitle("Paired devices");
alertDialog.show();
}
You should set an onClickListener for your button.
For that, you need to implement OnClickListener interface as:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
When you create the button, set its OnClickListener as follows:
b1 = (Button) findViewById(R.id.connect);
b1.setOnClickListener(this);
This should get you to your onClick method, when the button is clicked.
Edit: i see you have two buttons. Just do the same for the other button. Don't forget to declare a member for b2, just like b1.
Button b2;
b2 = (Button)findViewById(R.id.getValue);
b2.setOnClickListener(this);
I want to send real time accelerometer data from my android phone to my laptop, so that I can do some further analysis using that data, but I am facing some challenges in doing so...I am not able to persist connection at the android side and getting
W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
03-20 23:30:19.881 10050-13445/com.accel.bluetoothconnect W/System.err: java.io.IOException: read failed, socket might closed or timeout, read ret: -1
03-20 23:30:19.881 10050-13445/com.accel.bluetoothconnect W/System.err: at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:1016)
03-20 23:30:19.881 10050-13445/com.accel.bluetoothconnect W/System.err: at android.bluetooth.BluetoothSocket.waitSocketSignal(BluetoothSocket.java:973)
03-20 23:30:19.881 10050-13445/com.accel.bluetoothconnect W/System.err: at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:662)
03-20 23:30:19.881 10050-13445/com.accel.bluetoothconnect W/System.err: at com.accel.bluetoothconnect.MainActivity$ConnectingThread.run(MainActivity.java:446)
03-20 23:30:19.951 10050-10050/com.accel.bluetoothconnect W/Accel Value(X)->: 0.0
03-20 23:30:19.951 10050-10050/com.accel.bluetoothconnect W/Accel Value(Y)->: 0.0
03-20 23:30:19.951 10050-10050/com.accel.bluetoothconnect W/Accel Value(Z)->: 10.289082
03-20 23:30:20.151 10050-10050/com.accel.bluetoothconnect W/Accel Value(X)->: 0.0
03-20 23:30:20.151 10050-10050/com.accel.bluetoothconnect W/Accel Value(Y)->: 0.0
03-20 23:30:20.151 10050-10050/com.accel.bluetoothconnect W/Accel Value(Z)->: 10.271125
03-20 23:30:20.351 10050-10050/com.accel.bluetoothconnect W/Accel Value(X)->: 0.0
03-20 23:30:20.351 10050-10050/com.accel.bluetoothconnect W/Accel Value(Y)->: 0.0
03-20 23:30:20.351 10050-10050/com.accel.bluetoothconnect W/Accel Value(Z)->: 10.289082
whereas, on the laptop side where bluecove code is running, it is able to connect and the thread waits for the data.
BlueCove version 2.1.1-SNAPSHOT on winsock
0000110100001000800000805f9b34fb
waiting for connection...
waiting for connection...
waiting for input
finish process
Codes that I am using,
For Android-
public class MainActivity extends Activity implements SensorEventListener {
private final static UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
private static final String TAG="BluetoothConnector";
private static final int REQUEST_ENABLE_BT = 1;
private static final int DISCOVERABLE_BT_REQUEST_CODE = 2;
private static final int DISCOVERABLE_DURATION = 300;
public static final int EXIT_CMD = -1;
int conn_flag = 0;
private Button onBtn;
private Button offBtn;
private Button listBtn;
private Button findBtn;
private TextView text;
private BluetoothAdapter myBluetoothAdapter;
private Set<BluetoothDevice> pairedDevices;
private ListView myListView;
private ArrayAdapter<String> BTArrayAdapter;
BluetoothDevice bluetoothDevice;
private float lastX, lastY, lastZ;
private SensorManager sensorManager;
private Sensor accelerometer;
private float deltaXMax = 0;
private float deltaYMax = 0;
private float deltaZMax = 0;
private float deltaX = 0;
private float deltaY = 0;
private float deltaZ = 0;
private float vibrateThreshold = 0;
private TextView currentX, currentY, currentZ, maxX, maxY, maxZ;
public Vibrator v;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// take an instance of BluetoothAdapter - Bluetooth radio
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(myBluetoothAdapter == null) {
onBtn.setEnabled(false);
offBtn.setEnabled(false);
listBtn.setEnabled(false);
findBtn.setEnabled(false);
text.setText("Status: not supported");
Toast.makeText(getApplicationContext(),"Your device does not support Bluetooth",
Toast.LENGTH_LONG).show();
} else {
text = (TextView) findViewById(R.id.text);
onBtn = (Button)findViewById(R.id.turnOn);
onBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
on(v);
}
});
offBtn = (Button)findViewById(R.id.turnOff);
offBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
off(v);
}
});
listBtn = (Button)findViewById(R.id.paired);
listBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
list(v);
}
});
findBtn = (Button)findViewById(R.id.search);
findBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
find(v);
}
});
myListView = (ListView)findViewById(R.id.listView1);
// create the arrayAdapter that contains the BTDevices, and set it to the ListView
BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
myListView.setAdapter(BTArrayAdapter);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// ListView Clicked item value
String itemValue = (String) myListView.getItemAtPosition(position);
String MAC = itemValue.substring(itemValue.length() - 17);
bluetoothDevice = myBluetoothAdapter.getRemoteDevice(MAC);
// Initiate a connection request in a separate thread
ConnectingThread t = new ConnectingThread(bluetoothDevice);
t.start();
}
});
}
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
// success! we have an accelerometer
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
vibrateThreshold = accelerometer.getMaximumRange() / 2;
} else {
// fai! we dont have an accelerometer!
}
//initialize vibration
v = (Vibrator) this.getSystemService(Context.VIBRATOR_SERVICE);
}
public void on(View view){
if (!myBluetoothAdapter.isEnabled()) {
Intent turnOnIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOnIntent, REQUEST_ENABLE_BT);
Toast.makeText(getApplicationContext(),"Bluetooth turned on" ,
Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(getApplicationContext(),"Bluetooth is already on",
Toast.LENGTH_LONG).show();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
if(requestCode == REQUEST_ENABLE_BT){
if(myBluetoothAdapter.isEnabled()) {
text.setText("Status: Enabled");
Toast.makeText(getApplicationContext(), "Ha! Bluetooth is now enabled." +
"\n" + "Scanning for remote Bluetooth devices...",
Toast.LENGTH_SHORT).show();
// To discover remote Bluetooth devices
discoverDevices();
// Make local device discoverable by other devices
makeDiscoverable();
// Start a thread to create a server socket to listen
// for connection request
ListeningThread t = new ListeningThread();
t.start();
} else {
text.setText("Status: Disabled");
}
}else if (requestCode == DISCOVERABLE_BT_REQUEST_CODE){
if (resultCode == DISCOVERABLE_DURATION){
Toast.makeText(getApplicationContext(), "Your device is now discoverable by other devices for " +
DISCOVERABLE_DURATION + " seconds",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Fail to enable discoverability on your device.",
Toast.LENGTH_SHORT).show();
}
}
}
protected void discoverDevices(){
// To scan for remote Bluetooth devices
if (myBluetoothAdapter.startDiscovery()) {
Toast.makeText(getApplicationContext(), "Discovering other bluetooth devices...",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Discovery failed to start.",
Toast.LENGTH_SHORT).show();
}
}
protected void makeDiscoverable(){
// Make local device discoverable
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, DISCOVERABLE_DURATION);
startActivityForResult(discoverableIntent, DISCOVERABLE_BT_REQUEST_CODE);
}
public void list(View view){
// get paired devices
pairedDevices = myBluetoothAdapter.getBondedDevices();
// put it's one to the adapter
for(BluetoothDevice device : pairedDevices)
BTArrayAdapter.add(device.getName()+ "\n" + device.getAddress());
Toast.makeText(getApplicationContext(),"Show Paired Devices",
Toast.LENGTH_SHORT).show();
}
final BroadcastReceiver bReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// add the name and the MAC address of the object to the arrayAdapter
BTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
BTArrayAdapter.notifyDataSetChanged();
}
else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
conn_flag=1;
}
}
};
public void find(View view) {
if (myBluetoothAdapter.isDiscovering()) {
// the button is pressed when it discovers, so cancel the discovery
myBluetoothAdapter.cancelDiscovery();
}
else {
BTArrayAdapter.clear();
myBluetoothAdapter.startDiscovery();
registerReceiver(bReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
}
public void off(View view){
myBluetoothAdapter.disable();
text.setText("Status: Disconnected");
Toast.makeText(getApplicationContext(),"Bluetooth turned off",
Toast.LENGTH_LONG).show();
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
// Register the BroadcastReceiver for ACTION_FOUND
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(bReceiver, filter);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
this.unregisterReceiver(bReceiver);
}
#Override
public void onSensorChanged(SensorEvent event) {
Log.w("Accel Value(X)->", String.valueOf(deltaX));
Log.w("Accel Value(Y)->", String.valueOf(deltaY));
Log.w("Accel Value(Z)->", String.valueOf(deltaZ));
if(conn_flag == 1) {
Log.w("Data Transfer", "Finally transferring data");
ConnectingThread ct = new ConnectingThread(bluetoothDevice);
ct.write((int) deltaX);
}
// get the change of the x,y,z values of the accelerometer
deltaX = Math.abs(lastX - event.values[0]);
deltaY = Math.abs(lastY - event.values[1]);
deltaZ = Math.abs(lastZ - event.values[2]);
// if the change is below 2, it is just plain noise
if (deltaX < 2)
deltaX = 0;
if (deltaY < 2)
deltaY = 0;
if ((deltaZ > vibrateThreshold) || (deltaY > vibrateThreshold) || (deltaZ > vibrateThreshold)) {
v.vibrate(50);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private class ListeningThread extends Thread {
private final BluetoothServerSocket bluetoothServerSocket;
public ListeningThread() {
BluetoothServerSocket temp = null;
try {
temp = myBluetoothAdapter.listenUsingRfcommWithServiceRecord(getString(R.string.app_name), uuid);
} catch (IOException e) {
e.printStackTrace();
}
bluetoothServerSocket = temp;
}
public void run() {
BluetoothSocket bluetoothSocket;
// This will block while listening until a BluetoothSocket is returned
// or an exception occurs
while (true) {
try {
bluetoothSocket = bluetoothServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection is accepted
if (bluetoothSocket != null) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "A connection has been accepted.",
Toast.LENGTH_SHORT).show();
}
});
// Code to manage the connection in a separate thread
/*
manageBluetoothConnection(bluetoothSocket);
*/
try {
bluetoothServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
// Cancel the listening socket and terminate the thread
public void cancel() {
try {
bluetoothServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class ConnectingThread extends Thread {
private BluetoothSocket bluetoothSocket;
private final BluetoothDevice bluetoothDevice;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectingThread(BluetoothDevice device) {
BluetoothSocket temp = null;
bluetoothDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
temp = bluetoothDevice.createRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
e.printStackTrace();
}
bluetoothSocket = temp;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = bluetoothSocket.getInputStream();
tmpOut = bluetoothSocket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
myBluetoothAdapter.cancelDiscovery();
try {
// This will block until it succeeds in connecting to the device
// through the bluetoothSocket or throws an exception
bluetoothSocket.connect();
} catch (IOException connectException) {
connectException.printStackTrace();
try {
Log.e("","trying fallback...");
bluetoothSocket =(BluetoothSocket) bluetoothDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(bluetoothDevice,1);
bluetoothSocket.connect();
Log.e("","Connected");
}
catch (Exception e2) {
Log.e("", "Couldn't establish Bluetooth connection!");
}
}
}
public void write(int out) {
try {
mmOutStream.write(out);
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
// Cancel an open connection and terminate the thread
public void cancel() {
try {
mmOutStream.write(EXIT_CMD);
bluetoothSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}}
Android manifest-
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.VIBRATE" />
For fallback code, I referred to- getBluetoothService() called with no BluetoothManagerCallback for Android Nexus 5
and laptop side (bluecove)-
WaitThread.java-
public class WaitThread implements Runnable{
/** Constructor */
public WaitThread() {
}
#Override
public void run() {
waitForConnection();
}
/** Waiting for connection from devices */
private void waitForConnection() {
// retrieve the local Bluetooth device object
LocalDevice local = null;
StreamConnectionNotifier notifier;
StreamConnection connection = null;
// setup the server to listen for connection
try {
local = LocalDevice.getLocalDevice();
local.setDiscoverable(DiscoveryAgent.GIAC);
//UUID uuid = new UUID("04c6093b00001000800000805f9b34fb", false);
UUID uuid = new UUID("0000110100001000800000805f9b34fb", false);
System.out.println(uuid.toString());
String url = "btspp://localhost:" + uuid.toString() + ";name=RemoteBluetooth";
notifier = (StreamConnectionNotifier)Connector.open(url);
} catch (BluetoothStateException e) {
System.out.println("Bluetooth is not turned on.");
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
// waiting for connection
while(true) {
try {
System.out.println("waiting for connection...");
connection = notifier.acceptAndOpen();
Thread processThread = new Thread(new ProcessConnectionThread(connection));
processThread.start();
} catch (Exception e) {
e.printStackTrace();
return;
}
}
}
}
and ProcessConnectionThread.java-
public class ProcessConnectionThread implements Runnable{
private StreamConnection mConnection;
// Constant that indicate command from devices
private static final int EXIT_CMD = -1;
private static final int KEY_RIGHT = 1;
private static final int KEY_LEFT = 2;
public ProcessConnectionThread(StreamConnection connection)
{
mConnection = connection;
}
#Override
public void run() {
try {
// prepare to receive data
InputStream inputStream = mConnection.openInputStream();
System.out.println("waiting for input");
while (true) {
int command = inputStream.read();
if (command == EXIT_CMD)
{
System.out.println("finish process");
break;
}
processCommand(command);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Process the command from client
* #param command the command code
*/
private void processCommand(int command) {
try {
System.out.println("Value sent is: "+command);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Right now i'm just trying to pass x axis data that too in int (just for the moment). Please help me in getting it resolved. Also, this is my first android app and i have tried to connect pieces from various websites, so requesting everyone to please go easy with me.
I am a newbie of Android. My application uses Voice Recognition, TextToSpeech and send data out via Bluetooth from Android phone (SAMSUNG Galaxy Note | OS: Android 4.1.2) to Arduino. It can send data out only once a time and after it can't send (it through IOException), so application finish(). Below is my code.
Android Code
package com.itcdroid.smarthome;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Locale;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements
TextToSpeech.OnInitListener {
//Tag for logging
private static final String TAG = "ITCDroid";
private static final int REQUEST_ENABLE_BT = 1;
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothSocket mBluetoothSocket = null;
private OutputStream outStream = null;
//MAC address of remote Bluetooth device
private final String address = "98:D3:31:B4:34:EE";
// UUID that specifies a protocol for generic bluetooth serial communication
//Well known SPP UUID
private static final UUID MY_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private TextToSpeech tts;
private String ttsText;
private TextView txtSpeechInput;
private ImageButton btnSpeak;
private final int REQ_CODE_SPEECH_INPUT = 100;
// Available commands
private static final String[] commands = {"on", "off", "turn on the light", "turn off the light"};
boolean foundCommand;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
checkBtState();
tts = new TextToSpeech(this, this);
txtSpeechInput = (TextView) findViewById(R.id.txtSpeechInput);
btnSpeak = (ImageButton) findViewById(R.id.btnSpeak);
// hide the action bar
//getActionBar().hide();
//mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//checkBtState();
btnSpeak.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
promptSpeechInput();
}
});
}
#Override
public void onResume() {
super.onResume();
Log.d(TAG, "...In onResume - Attempting client connect...");
//Set up a pointer to the remote node using it's address.
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. in this case we are using the UUID for SPP
try {
mBluetoothSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
}
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
mBluetoothAdapter.cancelDiscovery();
// Establish the connection. This will block until is connects.
Log.d(TAG, "...Connecting to Remote...");
try {
mBluetoothSocket.connect();
Log.d(TAG, "...Connection established and data link opened...");
} catch(IOException e) {
try {
mBluetoothSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onResume() and unable to close socket during connection failture" + e2.getMessage() + ".");
}
}
//Create a data stream so we can talk to server.
Log.d(TAG, "...Creating Socket...");
try {
outStream = mBluetoothSocket.getOutputStream();
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and output stream creation failture: " + e.getMessage() + ".");
}
}
#Override
public void onPause(){
super.onPause();
Log.d(TAG, "...In onPause()...");
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
}
}
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mBluetoothSocket.close();
} catch (IOException e) { }
}
private void checkBtState() {
// TODO Auto-generated method stub
//Check for Bluetooth support and then check to make sure it is turned on
if (mBluetoothAdapter == null) {
errorExit("Fatal Error", "Bluetooth Not supported. Aborting.");
} else {
if (mBluetoothAdapter.isEnabled()) {
Log.d(TAG, "...Bluetooth is enabled...");
} else {
//Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
}
/**
* Showing google speech input dialog
* */
private void promptSpeechInput() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
getString(R.string.speech_prompt));
try {
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT);
} catch (ActivityNotFoundException a) {
Toast.makeText(getApplicationContext(),
getString(R.string.speech_not_supported),
Toast.LENGTH_SHORT).show();
}
}
/**
* Receiving speech input
* */
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQ_CODE_SPEECH_INPUT: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> result = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
foundCommand = false;
for(String command : commands) {
if(result.contains(command)) {
foundCommand = true;
if(command == "on") {
txtSpeechInput.setText("You say -on-");
ttsText = "The light is turn on now.";
speakOut();
sentData("1");
}
else if(command == "off") {
txtSpeechInput.setText("You say -off-");
ttsText = "The light is turn off now.";
speakOut();
sentData("2");
}
else if(command == "turn on the light") {
txtSpeechInput.setText("You say -turn on the light-");
ttsText = "The light is turn on now.";
speakOut();
sentData("1");
}
else if(command == "turn off the light") {
txtSpeechInput.setText("You say -turn off the light-");
ttsText = "The light is turn off now.";
speakOut();
sentData("2");
}
}
}
if (!foundCommand) {
txtSpeechInput.setText("Unknown what you say");
ttsText = "I don't know what you want!";
speakOut();
}
//txtSpeechInput.setText(result.get(0));
}
break;
}
}
}
#Override
public void onDestroy() {
// Don't forget to shutdown!
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
#Override
public void onInit(int status) {
// TODO Auto-generated method stub
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.US);
// tts.setPitch(5); // set pitch level
// tts.setSpeechRate(2); // set speech speed rate
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "Language is not supported");
} else {
//btnSpeak.setEnabled(true);
speakOut();
}
} else {
Log.e("TTS", "Initilization Failed");
}
}
//#SuppressWarnings("deprecation")
private void speakOut() {
String text = ttsText;
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null);
}
private void sentData(String message) {
// TODO Auto-generated method stub
byte[] msgBuffer = message.getBytes();
Log.d(TAG, "...Sending data: " + message + "...");
try {
outStream.write(msgBuffer);
outStream.close();
reConnectBT();
} catch (IOException e) {
String msg = "In onResume() and an exception occurred during write:" + e.getMessage();
msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + "exists on server.\n\n";
errorExit("sentData IOException", msg);
}
}
private void reConnectBT() {
// TODO Auto-generated method stub
Log.d(TAG, "...In reConnectBT - Attempting client connect...");
//Set up a pointer to the remote node using it's address.
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. in this case we are using the UUID for SPP
try {
mBluetoothSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
}
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
mBluetoothAdapter.cancelDiscovery();
// Establish the connection. This will block until is connects.
Log.d(TAG, "...Connecting to Remote...");
try {
mBluetoothSocket.connect();
Log.d(TAG, "...Connection established and data link opened...");
} catch(IOException e) {
try {
mBluetoothSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onResume() and unable to close socket during connection failture" + e2.getMessage() + ".");
}
}
//Create a data stream so we can talk to server.
Log.d(TAG, "...Creating Socket...");
try {
outStream = mBluetoothSocket.getOutputStream();
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and output stream creation failture: " + e.getMessage() + ".");
}
}
private void errorExit(String title, String message) {
// TODO Auto-generated method stub
Toast msg= Toast.makeText(getBaseContext(),
title, Toast.LENGTH_SHORT);
msg.show();
finish();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
It seems that you're doing a lot of juggling with connecting and disconnecting from your bluetooth device, which can harm your performance. Another thing you're doing is managing all of the heavy Bluetooth processes directly in your UI thread, which will make your app lock up until the connections complete.
Here's a link to my project's repository, I'm doing simple Bluetooth connections in it and made a BluetoothConnection class as a wrapper for managing the connection state. Feel free to use the source code, but be wary that I'm always actively changing it. If you choose to use it your code, the implementation would go something like this:
InputStream mInputStream;
OutputStream mOutputStream;
BluetoothConnection mConnection = new BluetoothConnection("Connection Name", "98:D3:31:B4:34:EE");
mConnection.setOnConnectStatusChangedListener(this, new onConnectStatusChangedListener() {
#Override
public void onConnect() {
/*
* Connecting to bluetooth takes some time, it won't be ready immediately.
* Set some actions here that let your program know that the connection
* finished successfully. For example,
*/
mInputStream = mConnection.getInputStream();
mOutputStream = mConnection.getOutputStream();
//Use some method of your own to write data
sendDataToBluetoothDevice(mOutputStream);
}
#Override
public void onDisconnect() {
/*
* Same thing applies to disconnecting, set some actions to occur
* when the disconnect is confirmed.
*/
}
}
/*
* Internally, this launches an AsyncTask to handle connecting,
* which is why we need the onConnectStatusChangedListener
* callbacks.
*/
mConnection.connect();
//To disconnect:
mConnection.disconnect();
This should simplify things for you by handling all of the heavy lifting in background processes. As far as reading and writing more than once, as long as you use the InputStream and OutputStream correctly you should be golden.
I'm trying to build an android app that loops 5 MAC addresses because there's 5 devices being used but not at the same time but with the same functions.
Currently I'm using this to start the string:
private static String address = "00:06:66:0A:AD:98";
And this to connect that address to the bluetooth adapter:
BluetoothDevice device = btAdapter.getRemoteDevice(address);
I'm a bit of a noob but the rest of the app is working. It sends and receives data from a serial and displays it in a simple fashion.
Any help would be appreciated.
I've attached the whole code for your review, it's based off a tutorial.
package com.example.bluetooth2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.UUID;
import com.example.bluetooth2.R;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = "Arduino controller";
Button btnOn, btnOff, btnQ, btnTurbo;
TextView txtArduino,txtOther;
Handler h;
final int RECIEVE_MESSAGE = 1; // Status for Handler
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private StringBuilder sb = new StringBuilder();
private ConnectedThread mConnectedThread;
// SPP UUID service
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// MAC-address of Bluetooth module (you must edit this line)
private static String address = "00:06:66:0A:AD:98";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnQ = (Button) findViewById(R.id.btnQ); // button baton status
btnOn = (Button) findViewById(R.id.btnOn); // button LED ON
btnOff = (Button) findViewById(R.id.btnOff); // button LED OFF
btnTurbo = (Button) findViewById(R.id.btnTurbo); // button TURBO
txtArduino = (TextView) findViewById(R.id.txtArduino); // display battery life
txtOther = (TextView) findViewById(R.id.txtOther); // display other information
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
String[] parts = sbprint.split(" "); // split string
String batteryLife = parts[0]; // battery
String otherInfo = parts[1]; // other
sb.delete(0, sb.length()); // and clear
txtArduino.setText(batteryLife); // update TextView
txtOther.setText(otherInfo); // update textOther
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapter
checkBTState();
btnOn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
btnOn.setEnabled(false);
btnTurbo.setEnabled(true);
btnOff.setEnabled(true);
mConnectedThread.write("h"); // Send "1" via Bluetooth
//Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show();
}
});
btnOff.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
btnOff.setEnabled(false);
btnTurbo.setEnabled(true);
btnOn.setEnabled(true);
mConnectedThread.write("l"); // Send "0" via Bluetooth
//Toast.makeText(getBaseContext(), "Turn off LED", Toast.LENGTH_SHORT).show();
}
});
btnQ.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mConnectedThread.write("?"); // Send "0" via Bluetooth
//Toast.makeText(getBaseContext(), "Baton Status", Toast.LENGTH_SHORT).show();
}
});
btnTurbo.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
btnOff.setEnabled(true);
btnTurbo.setEnabled(false);
btnOn.setEnabled(true);
mConnectedThread.write("t"); // Send "t" via Bluetooth
//Toast.makeText(getBaseContext(), "Turbo mode", Toast.LENGTH_SHORT).show();
}
});
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
if(Build.VERSION.SDK_INT >= 10){
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
return (BluetoothSocket) m.invoke(device, MY_UUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
}
return device.createRfcommSocketToServiceRecord(MY_UUID);
}
#Override
public void onResume() {
super.onResume();
Log.d(TAG, "...onResume - try connect...");
// Set up a pointer to the remote node using it's address
Log.d(TAG, "...onResume - try connect...");
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = btAdapter.getRemoteDevice(address);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. In this case we are using the
// UUID for SPP.
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
}
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
btAdapter.cancelDiscovery();
// Establish the connection. This will block until it connects.
Log.d(TAG, "...Connecting...");
try {
btSocket.connect();
Log.d(TAG, "....Connection ok...");
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
}
}
// Create a data stream so we can talk to server.
Log.d(TAG, "...Create Socket...");
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
}
#Override
public void onPause() {
super.onPause();
Log.d(TAG, "...In onPause()...");
try {
btSocket.close();
} catch (IOException e2) {
errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
}
}
private void checkBTState() {
// Check for Bluetooth support and then check to make sure it is turned on
// Emulator doesn't support Bluetooth and will return null
if(btAdapter==null) {
errorExit("Fatal Error", "Bluetooth not support");
} else {
if (btAdapter.isEnabled()) {
Log.d(TAG, "...Bluetooth ON...");
} else {
//Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
}
}
private void errorExit(String title, String message){
Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
finish();
}
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(String message) {
Log.d(TAG, "...Data to send: " + message + "...");
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
Log.d(TAG, "...Error data send: " + e.getMessage() + "...");
}
}
}
}
String[] fiveMacAddresses = {"address1", "address2", "address3", "address4", "address5"};
List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>(fiveMacAddresses.length);
for (String address: fiveMacAddresses) {
devices.add(btAdapter.getRemoteDevice(address));
}
now you have array of devices.