I am working on a Bluetooth multiplayer game project.I followed the android Bluetooth overview https://developer.android.com/guide/topics/connectivity/bluetooth strictly.I used the following code to read and write data:-
public class MyBluetoothService {
private static final String TAG = "MY_APP_DEBUG_TAG";
private Handler handler; // 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 = handler.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 = handler.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 =
handler.obtainMessage(MessageConstants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString("toast",
"Couldn't send data to the other device");
writeErrorMsg.setData(bundle);
handler.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);
}
}
}
}
For writing data I am using the following code:-
String[] myString={"HI!","How Are YOU"};
mConnected.write(Arrays.toString(myString).getBytes());
But I see that inputstream.read() is receiving data quite late after another device is sending the data.I found some questions regarding this,but none of them seem to provide a satisfactory answer.Any suggestion will be highly helpful.
After
mmOutStream.write(bytes);
try to call:
mmOutStream.flush();
this will cause the bytes to be sent immediately.
https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#flush()
Related
I've been following a BluetoothChat app tutorial similar to the sample provided by Google. Link to reference here GoogleSource . I can successfully connect to other phone's Bluetooth when I have not implemented the class that handles the input and output streams. But when I implemented the class (ConnectedThread), it crashes the app with the null pointer exception at the run() method on "bytes = inputSream.read(buffer)" inside that class. Any idea on how to approach a fix? Been plaguing me for days. Help would be appreciated. Thanks!
ConnectedThread class
private class ConnectedThread extends Thread {
private final BluetoothSocket bluetoothsocket;
private final InputStream inputStream;
private final OutputStream outputStream;
public ConnectedThread(BluetoothSocket socket) {
bluetoothsocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = bluetoothsocket.getInputStream();
tmpOut = bluetoothsocket.getOutputStream();
} catch (IOException e) {
Log.e("ConnectedThrd->Cons", "Socket not created.");
}
inputStream = tmpIn;
outputStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
//App crashes here(?)
bytes = inputStream.read(buffer);
// Send the obtained bytes to the UI Activity
handler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e("ConnectedThrd->Run", "Connection Lost.", e);
e.printStackTrace();
connectionLost();
break;
}
}
}
public void write(byte[] buffer) {
try {
outputStream.write(buffer);
handler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e("ConnectedThread->Write", "Empty write stream.");
}
}
public void cancel() {
try {
bluetoothsocket.close();
} catch (IOException e) {
Log.e("ConnectedThread->Cancel", "Failed to close socket.");
}
}
}
The problem was that the BluetoothSocket was null when I try to send a data to the other device causing this error. Adding a condition to check whether a connection is established helped me handle the error.
I'm doing an application that comunicate with car by an OBD 2 port.
Now i'm working with bluetooth connection and i'm reading Android documentation and have some issues about connection and comunication with obd device.
I'm moving like this steps:
1)If bluetooth not active, activate the bluetooth
2)search device and show in a list
3)OnItemClick in the listview for connect with touched device (founded) with a client bluetooth connection
And here i have some problem to understand the Android documentation....
For the connection with device i use this code (like documentation)
foundedDeviceList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View view,
final int position, long id) {
mBluetoothAdapter.cancelDiscovery();
String deviceName = (String)adapter.getItemAtPosition(position);
Toast.makeText(getApplicationContext(), "Selezionato: " + deviceName,
Toast.LENGTH_LONG).show();
for(BluetoothDevice dv : deviceList){
if(dv.getName() != null && dv.getName().equals(deviceName)){
selectedDevice = dv;
}
}
ConnectThread connectThread = new ConnectThread(selectedDevice);
connectThread.run();
}
});
//Thread of bluetooth connection
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket
// because mmSocket is final.
BluetoothSocket tmp = null;
mmDevice = device;
try {
// Get a BluetoothSocket to connect with the given BluetoothDevice.
// MY_UUID is the app's UUID string, also used in the server code.
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
Log.i(TAG, "Socket's create() successfull");
} catch (IOException e) {
Log.e(TAG, "Socket's create() method failed", e);
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it otherwise slows down the connection.
mBluetoothAdapter.cancelDiscovery();
Log.i(TAG, "run() eseguito");
try {
// Connect to the remote device through the socket. This call blocks
// until it succeeds or throws an exception.
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and return.
try {
mmSocket.close();
} catch (IOException closeException) {
Log.e(TAG, "Could not close the client socket", closeException);
}
return;
}
// The connection attempt succeeded. Perform work associated with
// the connection in a separate thread.
//manageMyConnectedSocket(mmSocket);
}
// Closes the client socket and causes the thread to finish.
public void cancel() {
Log.i(TAG, "cancel() eseguito");
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the client socket", e);
}
}
}
I'm not sure about the connectThread.run() they don't explain the usage of method inside ConnectThread and i don't know how declare the manageMyConnectedSocket(mmSocket);
For the comunication i create a class MyBluetoothService.java and like documentation i write this code:
package com.tesi.ddz.obd_project;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Created by ddz on 24/04/17.
*/
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);
}
}
}
}
I would implement the method manageMyConnectedSocket(mmSocket); by calling the class MyBluetoothService.java and manage the connection as i understand the documentation....
They declare ConnectedThread as private so i can't call this method in the MainActivity.java.... so what is the best way to implement this connection?
Don't use MyBluetoothService and declare all to the MainActivity or keep working like that and maybe declare ConnectedThred public so i can use it in the MainActivity?
Especially i don't understand how use the class MyBluetoothService.java and the method manageMyConnectionSocket(mmsocket)
hello everybody i have been working on this app for so long now, and i think i almost finished but there is a problem and i tried a lot of different ways to solve it but i couldn't so any help i would appreciate .
the app is simple Bluetooth data sender to an Bluetooth module and it works just fine the problem occur if i wanted to close the connection from the app i couldn't close it and i have tried interrupt and the cancel method and putting a condition in a while loop but without any luck so can anyone help me please thank you.
this is my client thread (the same as android developer)
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private boolean x;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Log.i(tag, "construct");
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
}
catch (IOException e) {
// Log.i(tag, "get socket failed");
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
while (true) {
bluetoothAdapter.cancelDiscovery();
Log.i(tag, "connect - run");
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Log.i(tag, "connect - succeeded");
} catch (IOException connectException) {
Log.i(tag, "connect failed");
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) {
}
return;
}
// Do work to manage the connection (in a separate thread)
xHandler.obtainMessage(0, mmSocket).sendToTarget();
if(x==false){
break;
}
}
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
Log.i(tag,"cancel 1");
mmSocket.close();
x=false;
// mmDevice.close();
} catch (IOException e) { }
}
}
and this is my connected class
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private boolean x;
//private FileInputStream fis;
private int s;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
//s=x;
// 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() {
// if (s == 1) {
byte[] buffer;
// buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs}
//}
while (x) {
try {
// Read from the InputStream
buffer=new byte[1024];
// buffer = new byte[1024];
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
xHandler.obtainMessage(1, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
Log.i(tag,"write");
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
mmInStream.close();
mmOutStream.close();
x=false;
Log.i(tag,"cancel 2");
}
catch (IOException e) { }
}
}
and finally the handler:
public Handler xHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
Log.i(tag, "in handleeer");
super.handleMessage(msg);
switch(msg.what){
case 0:
// DO something
// if(omar==1){
//(BluetoothSocket)msg.obj
// bluetoothSocket=(BluetoothSocket).msg.obj;
connectedThread = new ConnectedThread((BluetoothSocket)msg.obj);
Toast.makeText(getApplicationContext(), "CONNECT", Toast.LENGTH_LONG).show();
//omar++;}
//String s = "79";
String s="h";
connectedThread.write(s.getBytes());
Log.i(tag, "connected");
break;
case 1:
byte[] readBuf = (byte[])msg.obj;
String string = new String(readBuf);
Toast.makeText(getApplicationContext(), string, Toast.LENGTH_LONG).show();
break;
}
}
};
I have a Raspberry Pi which I am using to read some sensor data and then trying to send that data through Bluetooth RFCOMM socket to Android phone. I can send data from the Android phone to the Raspberry Pi without problems but for some reason I am not able to read the sensor data with the Android phone sent by the Raspberry Pi.
The write function on the Raspberry Pi always returns the right amount of bytes that have been sent and on the Android side I have a thread reading the InputStream and there is a available function to check if there is any bytes to read but it almost every time returns nothing. However, it sometimes reads (maybe 1 time of 20) the sensor data and after the message handler has passed the data back to the another activity and printed the data on a text view, the program crashes.
Maybe someone could give me some explanation why the InputStream isn't receiving any data even though the Raspberry Pi sends the data. Huge thanks in advance!
Here is my BluetoothTransferThread class:
public class BluetoothTransferThread extends Thread {
private final BluetoothSocket connectedSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private Context context;
private final Handler threadHandler;
public BluetoothTransferThread(BluetoothSocket socket, Context context, Handler mHandler) {
this.context = context;
connectedSocket = socket;
threadHandler = mHandler;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
//Send a transfer thread created message to activity
threadHandler.obtainMessage(BluetoothClientActivity.TRANSFER_THREAD_CREATED).sendToTarget();
int[] buffer;
int readByte;
int i = 0, bytesAvailable;
/**
* Keep listening to the InputStream while connected
*/
while (true) {
try {
//Check if there is bytes available to read in the InputStream
bytesAvailable = mmInStream.available();
if(bytesAvailable > 0) {
buffer = new int[bytesAvailable];
Log.d(getClass().getName(), String.format("value = %d", bytesAvailable));
/*
* Read the stream byte at a time and store it to a buffer until we have received the end of the frame char
*/
do {
//readByte = dInputStream.readUnsignedByte();
readByte = mmInStream.read();
buffer[i] = readByte;
i++;
} while (readByte != 0xEE);
//Send the received data through handler back to activity
threadHandler.obtainMessage(BluetoothClientActivity.MESSAGE_READ, buffer).sendToTarget();
}
try {
currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Write to the connected OutStream.
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
Toast.makeText(this.context, "Wrote to the socket", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(this.context, "Couldn't write to the socket", Toast.LENGTH_SHORT).show();
}
}
/**
* Close the transfer thread
*/
public void cancel() {
try {
connectedSocket.close();
Toast.makeText(this.context, "Transfer thread socket closed", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(this.context, "Couldn't close the transfer thread socket", Toast.LENGTH_SHORT).show();
}
}
And here is the Raspberry Pi's side code snippet:
case READ_SENSOR_DATA:
/* Serialize the data and send it through the socket */
pthread_mutex_lock(&sensorData->mutex1);
pthread_mutex_lock(&sensorData->mutex5);
serializationLengthPtr = serializeStruct(sendBuffer, sensorData);
pthread_mutex_unlock(&sensorData->mutex1);
pthread_mutex_unlock(&sensorData->mutex5);
sendBuffer[8] = FRAME_END_CHAR;
bytes_sent = write(client, sendBuffer, serializationLengthPtr - sendBuffer + 1);
if(bytes_sent <= 0) {
perror("Write failed!\n");
socketCloseFlag = true;
break;
}
else {
printf("Bytes sent: %d\n", bytes_sent);
}
break;
I'am a newbie to android Bluetooth and I want to read and store the Bluetooth message in external android app(mine) using internal storage or sqlite. I have tried the android bluetooth-chat sample from GitHub but I don't know how to implement my idea.
Any help would be helpful and thanks
Exchange of bluetooth messages is covered in the android.bluetooth section of the api.
http://developer.android.com/guide/topics/connectivity/bluetooth.html#ManagingAConnection
Here is a basic example of managing a connection and sending/receiving messages:
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
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();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // 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);
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* 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) { }
}
}