Reputation: 502
I'm trying to make an app that communicates with nearby devices. My app is composed of the main activity that asks to enable bluetooth and sets the discoverable mode, so it waits for a connection to be made.
The second activity takes care of finding nearby devices and making the pairing. After pairing pairing some configuration messages are exchanged and then both start a ThirdActivity that deals with the communication between the two devices.
I can successfully exchange these messages but the problem is that I need to pass the BluetoothService object (which keeps the communication information) to the Third Activity.
Since I don't think I can implement parcelable then I simply closed the connection without eliminating the pairing and then recreate AcceptThread and ConnectThread in the thirdActivity by creating a new BluetoothService object but always passing the same BluetoothDevice.
From the various logs what happens is that the AcceptThread waits on the accept(), while the ConnectThread fails the connect() reporting this error.
W/System.err: java.io.IOException: read failed, socket might closed or timeout, read ret: -1
at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:762)
at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:776)
at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:399)
at com.crossthebox.progetto.BluetoothService$ConnectThread.run(BluetoothService.java:118)
What can I do?
This is the BluetoothService Class
public class BluetoothService {
private UUID myid = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final String appName = "myapp";
private static final int STATE_NONE = 0; // we're doing nothing
private static final int STATE_LISTEN = 1; // now listening for incoming connections
private static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
private static final int STATE_CONNECTED = 3;
private static final int STATE_BUFFER_NOT_EMPTY = 4;
private String message ="";
private int mState;
private final BluetoothAdapter mBluetoothAdapter;
Context mContext;
private AcceptThread mAcceptThread;
private ConnectThread mConnectThread;
private BluetoothDevice mDevice;
private UUID deviceUUID;
private ConnectedThread mConnectedThread;
public BluetoothService(Context context) {
mContext = context;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
}
private class AcceptThread extends Thread {
private final BluetoothServerSocket bluetoothServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp = null;
try{
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(appName, myid);
}catch (IOException e){
}
bluetoothServerSocket = tmp;
mState = STATE_LISTEN;
}
public void run() {
BluetoothSocket socket = null;
try {
socket = bluetoothServerSocket.accept();
} catch (IOException e) {
}
if (socket != null) {
mState = STATE_CONNECTING;
connected(socket);
}
}
public void cancel() {
try {
bluetoothServerSocket.close();
} catch (IOException e) {
}
}
}
private class ConnectThread extends Thread {
private BluetoothSocket mSocket;
public ConnectThread(BluetoothDevice device, UUID uuid) {
mDevice = device;
deviceUUID = uuid;
}
public void run(){
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = mDevice.createRfcommSocketToServiceRecord(deviceUUID);
} catch (IOException e) {
}
mSocket = tmp;
mBluetoothAdapter.cancelDiscovery();
try {
mSocket.connect(); //this throws exception for socket close ( but only the second time)
} catch (IOException e) {
// Close the socket
try {
mSocket.close();
} catch (IOException e1) {
}
e.printStackTrace();
}
connected(mSocket);
}
public void cancel() {
try {
mSocket.close();
} catch (IOException e) {
}
}
}
public synchronized void start() {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
}
public void startClient(BluetoothDevice device,UUID uuid){
mConnectThread = new ConnectThread(device, uuid);
mConnectThread.start();
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mSocket;
private final InputStream mInStream;
private final OutputStream mOutStream;
public ConnectedThread(BluetoothSocket socket) {
mSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = mSocket.getInputStream();
tmpOut = mSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mInStream = tmpIn;
mOutStream = tmpOut;
}
public void run(){
byte[] buffer = new byte[1024];
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
// Read from the InputStream
try {
bytes = mInStream.read(buffer);
if(bytes != 0) {
String incomingMessage = new String(buffer, 0, bytes);
message = incomingMessage;
System.out.println("HO LETTO " + message);
mState = STATE_BUFFER_NOT_EMPTY;
}
} catch (IOException e) {
break;
}
}
}
//Call this from the main activity to send data to the remote device
public void write(byte[] bytes) {
try {
mOutStream.write(bytes);
} catch (IOException e) {
}
}
//termina la connessione
public void cancel() {
try {
mSocket.close();
} catch (IOException e) { }
}
}
private void connected(BluetoothSocket mSocket) {
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(mSocket);
mConnectedThread.start();
mState = STATE_CONNECTED;
}
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) {
return;}
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
public int getState(){
return mState;
}
public String getMessage(){
String tmp = null;
if(!message.equals("")){
tmp = message;
message = "";
}
mState = STATE_CONNECTED;
return tmp;
}
public void setState(int state){
this.mState = state;
}
public void cancel(){
if(mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
if(mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if(mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transition);
/* * */
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
/* * */
if(requestCode == DISCOVER_REQUEST){
if(resultCode == 120){
bluetoothService = new BluetoothService(this);
bluetoothService.start();
//after receiving some message correctly
Intent thirdActivity = new Intent(this, com.project.ThirdActivity.class);
bluetoothService.cancel();
this.startActivity(thirdActivity);
finish();
}
if(resultCode == RESULT_CANCELED){
finish();
}
}
}
}
SecondActivity the way I cancel the connection is pretty the same as MainActivity. I close the socket after some message and then start ThirdActivity
ThirdActivity
if(mode == CLIENT){
BluetoothDEvice bluetoothDevice = getIntent().getExtras().getParcelable("btdevice");
bluetoothService.startClient(bluetoothDevice,myid);
}else //SERVER
bluetoothService.start();
Upvotes: 1
Views: 1308
Reputation: 11
Possible solution:
A brilliant example is in the following link:
https://github.com/googlesamples/android-BluetoothChat
Upvotes: 1