I am just trying to open socket with RN-41 microchip, as far as I know the chip listens for incoming connections all the time, is discoverable, etc.. Why do socket gets always closed directly?
private class Connect extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public Connect(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString("EB46DDA9-0D00-4C34-9365-D6AA6C111D1C"));
Log.v("SOCKET SUCCESS", "HAST SOCKET");
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
try {
mmSocket.connect();
Log.v("SOCKET SUCCESS", "VERBUNDEN");
} catch (IOException connectException) {
Log.v("SOCKET SUCCESS", "KEINE VERBINDUNG");
try {
mmSocket.close();
Log.v("SOCKET SUCCESS", "SOCKET CLOSED");
} catch (IOException closeException) {
Log.v("SOCKET SUCCESS", "SOCKET CLOSE FAIL");
}
return;
}
}
I've been googling all day long and got things work. Unfortunately I still dont know why and how it works, but it works perfectly. I changed my Connect class constructor code like this:
public Connect(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
//try {
// MY_UUID is the app's UUID string, also used by the server code
//ParcelUuid[] ids = device.getUuids();
//UUID deviceID = ids[0].getUuid();
//tmp = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));//deviceID);//UUID.fromString("EB46DDA9-0D00-4C34-9365-D6AA6C111D1C"));
Method m = null;
try {
m = mmDevice.getClass().getMethod("createInsecureRfcommSocket", new Class[] { int.class });
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
tmp = (BluetoothSocket)m.invoke(mmDevice, Integer.valueOf(1));
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.v("SOCKET SUCCESS", "HAST SOCKET");
//} catch (IOException e) { }
mmSocket = tmp;
}
Source:
Android Bluetooth SPP with Galaxy S3
P.s. If somebody would have a bit time to explain code above, I would appreciate it a lot. Thank you.
Related
We are about to release the new version of our software, and for the version afterward, our goal is to make the connection process for our Bluetooth SPP connections more reliable. We use the RN42 module in our products, and currently, at times it may take more than one try to connect to our boards.
Here is my current code:
class ConnectThread extends Thread {
BluetoothDevice mDevice;
public ConnectThread(BluetoothDevice device) throws SecurityException, NoSuchMethodException {
mDevice = device;
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
btSocket = mDevice.createInsecureRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
Log.e("Error", "Could not create socket!");
}
}
public void cancel() {
interrupt();
try {
Log.i("Treadmill", "in connect thread cancellation");
btSocket.close();
} catch (IOException localIOException) {
Log.e("Treadmill", "exception + " + localIOException.getMessage());
}
}
public void run() {
btAdapter.cancelDiscovery();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e("whatever", "InterruptedException: " + e.getMessage(), e);
}
try {
btSocket.connect();
Log.i("Treadmill", "After Connect");
} catch (IOException ioe) {
Log.i("Treadmill", "Trying Fallback");
try {
Method m;
try {
btSocket.close();
m = mDevice.getClass().getMethod("createInsecureRfcommSocket", new Class[]{int.class});
btSocket = (BluetoothSocket) m.invoke(mDevice, 1);
Thread.sleep(500);
btSocket.connect();
} catch (IllegalArgumentException e) {
Log.e("whatever", "IllegalArgumentException: " + e.getMessage(), e);
} catch (IllegalAccessException e) {
Log.e("whatever", "IllegalAccessException: " + e.getMessage(), e);
} catch (InvocationTargetException e) {
Log.e("whatever", "InvocationTargetException: " + e.getMessage(), e);
} catch (NoSuchMethodException e) {
Log.e("whatever", "NoSuchMethodException: " + e.getMessage(), e);
} catch (InterruptedException e) {
Log.e("whatever", "InterruptedException: " + e.getMessage(), e);
}
} catch (IOException ioe2) {
Log.e("Treadmill", "Failed to connect to Bluetooth device: " + ioe2.getMessage());
eventHandler.obtainMessage(MESSAGE_ERRORCONNECT, 0, 0, getResources().getString(R.string.connerr) + ": " + ioe2.getMessage()).sendToTarget();
try {
btSocket.close();
} catch (IOException localIOException2) {
Log.e("Error", "IO Exception!");
}
return;
}
}
eventHandler.obtainMessage(MESSAGE_CONNECT, 0, 0, "").sendToTarget();
synchronized (this) {
connectThread = null;
}
manageConnectedSocket(btSocket);
}
}
Even with the fallback to reflection the connection intermittently fails on some devices. I get the following error:
find_rfc_slot_by_id unable to find RFCOMM slot id: XX (XX being a number that increments on each attempted connection).
followed by this:
Failed to connect to Bluetooth device: read failed, socket might closed or timeout, read ret: -1
Does anyone know how to avoid these errors.
Interestingly, for comparison. I am testing on two tablets. One tablet, the Samsung Galaxy Tab 4 seems to work extremely well, while another, the Astro Tab A10, seems to be a bit more intermittent unless you wait several seconds between connecting and disconnecting.
For more reliable connection means even app was closed, Bluetooth should be keep connected in the background.
Below is the working solution I followed in my app to keep Bluetooth connection background.
First create a class which extends service, because service runs in the background even app closed until you call stopService or stopSelf methods
while starting BluetoothService class pass Bluetooth Mac address to connect and run in the background.
Sample code:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null){
String deviceg = intent.getStringExtra("bluetooth_device");
if (deviceg != null){
connectToDevice(deviceg);
}
}
return START_STICKY;
}
Below is the connect to device method which identifies mac Address into Bluetooth Device.
public synchronized void connectToDevice(String macAddress){
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
if (mConnectedThread != null){
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectThread = new ConnectBtThread(device);
toast("connecting");
mConnectThread.start();
}
This is my Thread class inside BluetoothService which runs in a separate thread
Code:
private class ConnectBtThread extends Thread{
private final BluetoothSocket mSocket;
private final BluetoothDevice mDevice;
public ConnectBtThread(BluetoothDevice device){
mDevice = device;
BluetoothSocket socket = null;
try {
socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(B_UUID));
} catch (IOException e) {
e.printStackTrace();
}
mSocket = socket;
}
#Override
public void run() {
if (mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
try {
mSocket.connect();
Log.d("service","Bluetooth one running (connected)");
} catch (IOException e) {
try {
mSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
connected(mSocket);
}
public void cancel(){
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
It works perfectly fine for our app.
If you want to access service methods bind this service to your activity
I'm trying to use bluetoothSocket to connect between my computer and my Android app on my phone
private void ConnectThread_BT(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
showToast("connectthread");
try {
tmp = device.createRfcommSocketToServiceRecord(uuid);
} catch (IOException e) { }
mmSocket = tmp;
showToast(mmSocket.toString());
}
public void run_BT() {
//btAdapter.cancelDiscovery();
showToast("runbt");
try {
mmSocket.connect();
showToast("connect");
} catch (IOException connectException) {
try {
mmSocket.close();
showToast(connectException.getMessage());
} catch (IOException closeException) { }
return;
}
I get the exception "failed socket might closed or timeout, read ret :-1"... Has anyone ever fixed this problem?
Thanks. Have a Nice day
I'm working in reading data via Motorola Bluetooth barcode scanner(CS3070).Actually, my original barcode data is : 1PCS3070-SR10007WW but i'm getting as two string example
1P as first string and CS3070-SR10007WW as second string. Getting as two string happen to all scanned barcode via reading through bluetooth. I hope now you may understand my problem. Same code as used from developer link
Here is my code of connecting and reading data in thread via bluetooth:
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
Method m;
try {
m = device.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
try {
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
mmSocket = tmp;
}
public void run() {
setName("ConnectThread");
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
connectionFailed();
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG,
"unable to close() socket during connection failure",
e2);
}
// Start the service over to restart listening mode
BluetoothService.this.start();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothService.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
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 BluetoothSocket input and output streams
try {
tmpIn = mmSocket.getInputStream();
tmpOut = mmSocket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes = 0;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(ScanningActivity.MESSAGE_READ,
bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
/**
* Write to the connected OutStream.
*
* #param buffer
* The bytes to write
*/
public void write(String buffer) {
try {
mmOutStream.write((buffer + "\n").getBytes());
// Share the sent message back to the UI Activity
mHandler.obtainMessage(ScanningActivity.MESSAGE_WRITE, -1, -1,
buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
mmInStream.close();
mmOutStream.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
Let me know if anybody have answer for it. Thanks in advance
I am developing a code to communicate to custom bluetooth circuit from Micromax Tab. Till socket creation it works fine. But when i try to connect it fails saying either Service discovery failed or host is down. I tried all the possible posts referring to this topic mentioning same problem. But end up getting same errors. I tried to change UUID but nothing works. Any clues?
Below is my code:
final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth not found",Toast.LENGTH_LONG).show();
}
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
if(device.getName().equals("linvor"))
{
mmDevice = device;
Toast.makeText(this, "Name: " + device.getName() + " And Address: " + device.getAddress(),Toast.LENGTH_LONG).show();
}
}
}
mBluetoothAdapter.cancelDiscovery();
BluetoothSocket tmp = null;
// UUID uuid = UUID.fromString("00001105-0000-1000-8000-00805F9B34FB");
// MY_UUID is the app's UUID string, also used by the server code
// tmp = mmDevice.createRfcommSocketToServiceRecord(uuid);
Method m = null;
try {
m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
try {
tmp = (BluetoothSocket) m.invoke(mmDevice, 1);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_LONG).show();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_LONG).show();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_LONG).show();
}
} catch (NoSuchMethodException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
tmp = (BluetoothSocket) m.invoke(mmDevice, 1);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_LONG).show();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_LONG).show();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_LONG).show();
}
Toast.makeText(getBaseContext(), "Created socket",Toast.LENGTH_LONG).show();
mmSocket = tmp;
mBluetoothAdapter.cancelDiscovery();
Toast.makeText(getBaseContext(), "Discovery cancelled",Toast.LENGTH_LONG).show();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
Toast.makeText(getBaseContext(), "Connected",Toast.LENGTH_LONG).show();
} catch (IOException e1) {
// Unable to connect; close the socket and get out
Toast.makeText(getBaseContext(), e1.getMessage(),Toast.LENGTH_LONG).show();
try {
mmSocket.close();
} catch (IOException e) {
Toast.makeText(getBaseContext(), e.getMessage(),Toast.LENGTH_LONG).show();
}
}
You are using this one to send image...
#Override
protected void onPostExecute(Void result) {
if(selectedImageURI!=null)
{
ContentValues values = new ContentValues();
values.put(BluetoothShare.URI, selectedImageURI.toString());
Toast.makeText(getBaseContext(), "URi : " + selectedImageURI,
Toast.LENGTH_LONG).show();
values.put(BluetoothShare.DESTINATION, addressPairedDevice);
values.put(BluetoothShare.DIRECTION,
BluetoothShare.DIRECTION_OUTBOUND);
Long ts = System.currentTimeMillis();
values.put(BluetoothShare.TIMESTAMP, ts);
getContentResolver().insert(BluetoothShare.CONTENT_URI,
values);
}
BluetoothShare.java is in the link
How to send file using bluetooth on android programatically?
How to send file from Android device to other device through Bluetooth by code
So I have this Android Bluetooth Project and I get a really annoying problem;
Let me describe the context:
The two phones wich are to be connected aquire their BluetoothSockets using the exact method described in the bluetooth documentation on the android developers site (here);
So, I use the following threads for the connection:
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(socket);
try {
mmServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
That is the acceptthread and,
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;
// 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) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// 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)
manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
that is the ConnectThread;(you might notice that they really are copied from the upper link);
The problem is that when trying to connect, the connectthread actually returns a socket(calls managesocket()), but the accepting thread remains at socket = mmServerSocket.accept(), as if nothing would have happened;
But Something is acually happening in the AcceptThread, since as I initiate a Connection from the other device (the one with a ConnectThread) the logcat of the accepting device is being updated;
Sometimes the connection is actually properly created, but only after some force closing, disabling->enabling bluetoothh, etc.
here is an interesting line in the logcat(generated by the .accept() call, I supose):
07-19 18:04:47.484: D/BLZ20_WRAPPER(3143): btlif_signal_event: ### event BTLIF_BTS_RFC_CON_IND not matched ###
So what could be the problem?