How to know when bluetooth pairing completed - android

I want to listen for incoming messages through bluetooth when pairing totally completed. I can't call listen(can I?) before the pairing is completed and I can't know when it is completed.
I tried a lot of methods to pair between two devices like this one:
private void pairDevice() {
try {
BluetoothDevice device = bluetooth.getRemoteDevice(address);
Log.d("pairDevice()", "Start Pairing...");
Method m = device.getClass().getMethod("createBond", (Class[]) null);
m.invoke(device, (Object[]) null);
Log.d("pairDevice()", "Pairing finished.");
} catch (Exception e) {
Log.e("pairDevice()", e.getMessage());
}
}
this one works nice but it opens a popup to accept the pairing and theLog.d("pairDevice()", "Pairing finished."); is called before the popup dialog is being accepted and I need to do things only when the pairing is totally completed and the devices are now paired. here is my code for listening for messages:
public void run() {
final int BUFFER_SIZE = 1024;
byte[] buffer = new byte[BUFFER_SIZE];
int bytes = 0;
int b = BUFFER_SIZE;
while (true) {
try {
bytes = inStream.read(buffer, bytes, BUFFER_SIZE - bytes);
textview.setText(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
here is my code for sending the message(score):
private void init() throws IOException {
if (bluetooth != null) {
if (bluetooth.isEnabled()) {
Set<BluetoothDevice> bondedDevices = bluetooth.getBondedDevices();
if (bondedDevices.size() > 0) {
ParcelUuid[] uuids = device.getUuids();
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuids[0].getUuid());
socket.connect();
outputStream = socket.getOutputStream();
inStream = socket.getInputStream();
write(score);
}
Log.e("error", "No appropriate paired devices.");
} else {
Log.e("error", "Bluetooth is disabled.");
}
}
}
public void write(String s) throws IOException {
outputStream.write(s.getBytes());
}
I tried to pair two devices without user permission like in this answer -here- but it also asked for permissions i don't know why .. So actually I don't think I need pairing without permission I just need doing something when popup accepted. is it possible? thanks.

Related

Put BT in discoverable mode and Accept an SPP connection in Xamarin Droid

this is my first use of Bluetooth with Xamarin.
I need to activate the "discoverable mode" within my application and then accept the incoming connections from an external host device.
I have read some docs but I cannot understand well how to implement it.
Could someone point me in the right direction?
I found the way..
First open an intent to put bluetooth in discovery mode...
var intent = new Intent(BluetoothAdapter.ActionRequestDiscoverable);
StartActivityForResult(intent, 0);
Then, use ListenUsingInsecureRfcommWithServiceRecord to put BT in listening mode:
class BluetoothThread : Java.Lang.Thread
{
BluetoothServerSocket _btServerSocket;
BluetoothSocket _btSocket;
Stream _inStream;
Stream _outStream;
private static Java.Util.UUID uuid = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
public event EventHandler<String> OnStringReceived;
public bool Cancel { get; set; } = false;
public override void Run()
{
byte[] buffer = new byte[1024];
int bytes;
string _ReceivedStr;
try
{
_btServerSocket =
BluetoothAdapter.DefaultAdapter.ListenUsingInsecureRfcommWithServiceRecord("Test.Droid", uuid);
try
{
_btSocket = _btServerSocket.Accept();
if (_btServerSocket != null)
Log.Info("BluetoothThread", "CONNECTION SUCCEED!");
_inStream = _btSocket.InputStream;
_outStream = _btSocket.OutputStream;
}
catch (Java.IO.IOException e)
{
Log.Error("BluetoothThread", "accept() failed", e);
}
while (!Cancel)
{
// Read from the InputStream
bytes = _inStream.Read(buffer, 0, buffer.Length);
_ReceivedStr = Encoding.ASCII.GetString(buffer);
OnStringReceived?.Invoke(this, _ReceivedStr);
Log.Info("BluetoothThread", $"RECEIVED: {_ReceivedStr}");
}
}
catch (Java.IO.IOException e)
{
Log.Error("BluetoothThread", "listen() failed", e);
}
}
}

android Bluetooth crash when connection is stopped

I am writing an app on Android Studio.
I communicate from an Android device to an arduino board via Bluetooth.
For now everything works but i am starting a new Activity and i need to stop the actual BT connection. so i want to call a stop method.
The problem is that it crash when i call it.
here is the code
public class BtInterface {
private BluetoothDevice device = null;
private BluetoothSocket socket = null;
private InputStream receiveStream = null;
private OutputStream sendStream = null;
String GlobalBuff="";
String Right_Buff="";
private ReceiverThread receiverThread;
Handler handler;
public BtInterface(Handler hstatus, Handler h,String Device_Name) {
Set<BluetoothDevice> setpairedDevices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
BluetoothDevice[] pairedDevices = (BluetoothDevice[]) setpairedDevices.toArray(new BluetoothDevice[setpairedDevices.size()]);
for(int i=0;i<pairedDevices.length;i++) {
if(pairedDevices[i].getName().contains(Device_Name)) {
device = pairedDevices[i];
try {
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
receiveStream = socket.getInputStream();
sendStream = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
handler = hstatus;
receiverThread = new ReceiverThread(h);
}
public void sendData(String data) {
sendData(data, false);
}
public void sendData(String data, boolean deleteScheduledData) {
try {
sendStream.write(data.getBytes());
sendStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void connect() {
new Thread() {
#Override public void run() {
try {
socket.connect();
Message msg = handler.obtainMessage();
msg.arg1 = 1;
handler.sendMessage(msg);
receiverThread.start();
} catch (IOException e) {
Log.v("N", "Connection Failed : " + e.getMessage());
e.printStackTrace();
}
}
}.start();
}
public void close() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
socket=null; //???
}
public BluetoothDevice getDevice() {
return device;
}
private class ReceiverThread extends Thread {
Handler handler;
ReceiverThread(Handler h) {
handler = h;
}
#Override public void run() {
while(true) {
try {
if(receiveStream.available() > 0) {
byte buffer[] = new byte[1000];
int k = receiveStream.read(buffer, 0, 1000);
if(k > 0) {
byte rawdata[] = new byte[k];
for(int i=0;i<k;i++)
rawdata[i] = buffer[i];
String data = new String(rawdata);
GlobalBuff= GlobalBuff+data;
Right_Buff= GlobalBuff.substring(GlobalBuff.length()-1,GlobalBuff.length());
if(Right_Buff.equals("\n")){
Message msg = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("receivedData", GlobalBuff);
msg.setData(b);
handler.sendMessage(msg);
GlobalBuff="";
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
i try some extra code :
receiverThread.interrupt();
receiverThread=null;
if (receiveStream != null) {
try {receiveStream.close();} catch (Exception e) {}
receiveStream = null;
}
if (sendStream != null) {
try {sendStream.close();} catch (Exception e) {}
sendStream = null;
}
before closing but the result is the same , it crash.
The strange behavior is that it didn't crash immediately as it could happen with a type error or else ( i am talking of the behavior in debug mode...)
If anybody got an idea.
Googling this bring me to people with this issue but no solution that works for my case.
Thanks
UPDATE
what i found as a trace when it crash is that :
06-02 07:45:27.369 9025-9133/fr.icservice.sechage A/libc? Fatal signal 11 (SIGSEGV) at 0x00000008 (code=1), thread 9133 (Thread-1436)
I also made a test on a sony Z3 phone under 5.0.2 (compare to my T210 samsung galaxy tab3 under 4.4.2)and it not crash..!
maybe it's a ROM bug?! or a android version problem...
This is a known problem (or bug?) on Android. If you close the Bluetooth socket and then access it later on, some devices will crash with a segmentation fault (like yours). A common workaround is to check socket.isConnected() before or to synchronize the access to close(), write(), read(), ... by setting a flag like closeWasCalled = true and prevent any further calls to methods of this socket in your code after a close() call.
The problem comes with Socket Input/Output. I faced this problem when disconnecting with peer bluetooth device.
Reason :
From code, we are trying to read() , write() from socket object/connection which is closed.
Solution :
Add checking socket.isConnected() before above operations
You can read more about this problem on Stack Overflow question : Here

Can't send data to Arduino Due from Android via Bluetooth

I have written an Android app that's supposed to send data to Arduino Due via Bluetooth Module (ZS-040). Bluetooth connection is fine. However, Arduino doesn't seem to receive any data from Android. When I send data to Arduino through the Serial Monitor though, it works. I've looked into many stackoverflow questions and other guides online but can't seem to figure out what's wrong.
Here's some code:
Thread for connecting the two devices:
private class ConnectThread extends Thread {
private BluetoothDevice mmDevice;
private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
//uuid for Arduino bluetooth module
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
try {
tmp = mmDevice.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { };
socket = tmp;
}
public void run() {
mBluetoothAdapter.cancelDiscovery();
runOnUiThread(new Runnable() {
#Override
public void run() {
findBtn.setText("Search for devices");
}
});
try {
socket.connect();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), "Success", Toast.LENGTH_SHORT).show();
}
});
} catch (IOException connectionException) {
try {
socket.close();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), "An error has occured. Please try again.",
Toast.LENGTH_SHORT).show();
}
});
} catch (IOException closeException) { }
return;
}
}
}
Code for sending data to Arduino; function is called when a button is pressed.
public void sendData(View view) {
// write to OutputStream
OutputStream mmOutputStream = null;
try {
mmOutputStream = socket.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
e.printStackTrace();
}
// String message = "0";
// byte[] msgBuffer = message.getBytes();
try {
mmOutputStream.write('0');
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
e.printStackTrace();
}
}
Arduino code (directly copied from here):
char incomingByte; // incoming data
int LED = 12; // LED pin
void setup() {
Serial.begin(9600); // initialization
pinMode(LED, OUTPUT);
Serial.println("Press 1 to LED ON or 0 to LED OFF...");
}
void loop() {
if (Serial.available() > 0) { // if the data came
incomingByte = Serial.read(); // read byte
if(incomingByte == '0') {
digitalWrite(LED, LOW); // if 1, switch LED Off
Serial.println("LED OFF. Press 1 to LED ON!"); // print message
}
if(incomingByte == '1') {
digitalWrite(LED, HIGH); // if 0, switch LED on
Serial.println("LED ON. Press 0 to LED OFF!");
}
}
}
EDIT: Because it's a DUE with which I'm working, I can't use SoftwareSerial library. :(
I've figured it out after much debugging with both hardware and software. Serial refers to rx0 and tx0 on the Due board. However, when the board is powered by the computer via usb cable (usb-to-serial to be exact), rx0 receives data from the computer instead of the bluetooth even when it's connected. Changing it to other serial such as Serial1 (rx1 and tx1), Serial2 (rx2, tx2) and Serial3 (rx3, tx3) in the Arduino code prevents that from happening.

Application using bluetooth SPP profile not working after update from Android 4.2 to Android 4.3

I wrote a simple application based on bluetoothChat. I communicate between the phone and a bluetooth module using SPP profile. The phone always initiates the communication. The application worked pefectly on Android 4.2, using Nexus 3 and Samsung Galaxy 3.
After the update to Android 4.3, the application does not work anymore. I connect all the time, I can send an outpustream and receive the right data, but after the 1st outputstream command, the application always disconnected after around 6s.
As shown in the logcat below, it looks there is a timer issue on the inputstream.
08-23 14:10:00.726: D/mems(23193): STEVAL-MKI106V1
08-23 14:10:00.804: D/Main Activity(23193): firmware version*setdb106V1
08-23 14:10:00.812: D/Main Activity(23193): sent message*setdb106V1
08-23 14:10:00.812: D/BluetoothMEMSCommunication(23193): dans write3
08-23 14:10:00.812: D/BluetoothMEMSCommunication(23193): envoi stream
08-23 14:10:05.812: W/bt-btif(20368): dm_pm_timer expires
08-23 14:10:05.812: W/bt-btif(20368): dm_pm_timer expires 0
08-23 14:10:05.812: W/bt-btif(20368): proc dm_pm_timer expires
08-23 14:10:11.656: E/bt-btm(20368): btm_sec_disconnected - Clearing Pending flag
08-23 14:10:11.656: W/bt-btif(20368): invalid rfc slot id: 15
08-23 14:10:11.656: I/connection(23193): connectionlost
What is dm_pm_timer?
I tried to connect a different way, with secure and insecure rfcom. I know the bluetooth chat is not optimized to receive the buffer, so I modified it, not no effect. I used the flush command for the outpustream too, but no effect either.
package com.meneujj.memsbtbis;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
public class BluetoothMEMSCommunication {
// debugging
private static final String TAG = "BluetoothMEMSCommunication";
private static final boolean D = true;
// eMotion BT h as this standard UUID
private static final UUID STANDARD_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private int mState;
private int handlerCalling;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
// Constants they indicate the current connection state
public static final int STATE_NONE = 0;
public static final int STATE_CONNECTED = 3; // now connected to a remote device
// constructor. Prepares a new Bluetooth Connection
// context The UI Activity Context
// handler an Handler to send messages back to the UI Activity
public BluetoothMEMSCommunication(Context context, Handler handler, int i) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
handlerCalling = i;
}
private synchronized void setState(int state) {
mState = state;
Log.d(TAG, Integer.toString(mState));
mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
public synchronized void connect(BluetoothDevice device) {
// start the thread to connect with the given device
if (mConnectThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
Log.d(TAG,"routine connect lancee");
mConnectThread = new ConnectThread(device);
mConnectThread.start();
}
private void ConnectionLost() {
// Send a failure message back to the activity
Message msg = mHandler.obtainMessage(MainActivityMemsBT.CONNECTION_LOST_MESSAGE);
Bundle bundle = new Bundle();
bundle.putString(MainActivityMemsBT.TOAST_CONNECTION_LOST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);
Log.i("connection","connectionlost");
setState(STATE_NONE);
StopAllThreads();
}
public synchronized void StopAllThreads() {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(STATE_NONE);
}
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) {
// cancel the thread they completed the connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to manage the connection and perform transmission
mConnectedThread = new ConnectedThread(socket, socketType);
mConnectedThread.start();
// Send the name of the connected device back to the UI activity
Message msg = mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(MainActivityMemsBT.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
public void write(byte[] out) {
// create temporary object
ConnectedThread r;
Log.d(TAG,"dans write" + Integer.toString(mState));
// synchronize a copy of the ConnectedThread
synchronized (this) {
if (handlerCalling == 2) setState(STATE_CONNECTED);
if (mState != STATE_CONNECTED) {
Log.d(TAG, "different de STATE_CONNECTED");
Log.i(TAG, Integer.toString(handlerCalling));
return;}
r= mConnectedThread;
}
r.write(out);
}
Any idea is there is a workaround? Or any obvious mistake in my code
Thanks
// Thread runs while attempting to an an outgoing connection with a device.
// it runs straight through; the connection either succeeds or fails.
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(STANDARD_UUID);
//tmp = device.createInsecureRfcommSocketToServiceRecord(STANDARD_UUID);
/* try {
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
try {
tmp = (BluetoothSocket) m.invoke(device, 1);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} */
} catch (IOException e) {
}
mmSocket = tmp;
}
public void run () {
setName("ConnectThread" + mSocketType);
mAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException e) {
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " + mSocketType + "socket during connection failure", e2);
}
return;
}
// reset the CoonectThread because the job is over
synchronized (BluetoothMEMSCommunication.this) {
mConnectThread = null;
}
connected(mmSocket, mmDevice, mSocketType);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
// close connectThread class
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
ConnectionLost();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
// Thread to listen to input sockets
public void run() {
Log.i(TAG, "Begin mConnectedThread");
byte[] buffer = new byte[1024];
// int bytes;
int bytesRead = -1;
String message = "";
// keep listening to the InputStream while connected
while(true) {
try {
// read from the input stream
// bytesRead = mmInStream.read(buffer);
// message = message+ new String(buffer, 0, bytesRead);
// byte[] byteString = message.getBytes();
Log.i("info","pret a faire read");
bytesRead = mmInStream.read(buffer, 0, 1024);
if (bytesRead != -1 && handlerCalling == 1) {
mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_READ, bytesRead, -1, buffer).sendToTarget(); }
if (bytesRead !=-1 && handlerCalling == 2) {
mHandler.obtainMessage(DemoAccelerometer.MESSAGE_READ, bytesRead, -1, buffer).sendToTarget(); }
}
catch (IOException e) {
ConnectionLost();
break;
}
}
}
public void write(byte[] buffer) {
try{
mmOutStream.write(buffer);
// if (handlerCalling == 1) {
// mHandler.obtainMessage(MainActivityMemsBT.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
Log.d(TAG,"envoi stream");
// mmOutStream.flush();
// }
} catch (IOException e) {
}
}
public void cancel() {
try{
mmSocket.close();
} catch (IOException e) {
}
}
}
}
We can confirm the Bluetooth disconnect after 6 seconds when communicating from our Nexus 4 app to an external Bluetooth ECG (medical device) after upgrading from Android 4.2 to 4.3. This happens specifically during an ECG measurement with lots of inbound data (from ECG to the Android app) but no outbound data. "Normal" Bluetooth communication with some inbound and outbound data from time to time does not seem to be affected.
After 6 seconds we see the same adb log messages reported by JJM
dm_pm_timer expires
dm_pm_timer expires 0
proc dm_pm_timer expires
btm_sec_disconnected - Clearing Pending flag
This timer expiry on the Android side triggers something (closing output stream because no outbound data?) on the external Bluetooth ECG which in turn sends an ECG specific command we receive on the input stream that we never receive on the Nexus 4 with Android 4.2.
Changing the Android app implementation to occasionally send an arbitrary "keep alive" command to the ECG solves the problem. The timer expiry does not appear in the adb logs anymore and the ECG measurement now behaves the same as with Android 4.2.
Thanks to JJM for the hints.
I found a work around. It is disconnected if there is no streaming activity for a few seconds. I managed to have some output or input streaming several times per second, and it never disconnects now.
I found on StackOverflow an answer that helped me to fix the problem. I guess it has something to do with the inputStream and outputStream not being closed properly and nulled, as well as the bluetooth socket. After using this function:
* Reset input and output streams and make sure socket is closed.
* This method will be used during shutdown() to ensure that the connection is properly closed during a shutdown.
* #return
*/
private void resetConnection() {
setState(STATE_NONE);
Log.d(TAG, "reset connection");
if (mmInStream != null) {
try {
mmInStream.close();
} catch (Exception e) {
Log.d(TAG,"exception in closing inputstream - " + e.getMessage());
}
mmInStream = null;
}
if (mmOutStream != null) {
try {
mmOutStream.close();
} catch (Exception e) {
Log.d(TAG,"exception in closing outputstream - " + e.getMessage());
}
mmOutStream = null;
}
if (mmSocket != null) {
try {
mmSocket.close();
} catch (Exception e) {
Log.d(TAG,"exception in closing socket - " + e.getMessage());
}
mmSocket = null;
}
}
in ConnectedThread and call it when necessary, i removed that problem. It could be also a problem with reading from the inputStream, maybe because there was nothing in there when attempting to read.
I suggest that you do a boolean function readWrite() that whenever you write to outputStream you also read the inputStream and send the readBuffer to UI with mHandler. If both read and write are ok, than return true, if one of them went wrong than return false and use resetConection before closing your ConnectedThread.
It worked very nice for me.
UPDATE: (30-SEPT-2013)
I am running my app and I still get the hci_status = 36 after few minutes. I have an app, that connects to an external bluetooth device. I am sending data and receive data approx. 3 times / sec. I am using a Thread.sleep(300) between writes. In my tests I got this error after few minutes up to almost 30 minutes when running the app.
Any feedback is appreciated!

Bluetooth paired devices connection problems

I'm having issues with connecting. At first it works, than it does not, unless I unpair the devices.
I've gotten every possible exception that could happen, socket closed, pipe closed, connection refused, port already in use, etc.
I'm aware that there are issues with bluetooth on android pre 4.2 (https://code.google.com/p/android/issues/detail?id=37725).
Devices that I'm having problems with connecting these devices:
Htc one(android 4.2)
samsung galaxy s2(android 4.1.2)
nexus 4 (4.3)
samsung galaxy s4 (4.2)
Another minor issue is, that the paired devices are not stored (mostly on the nexus 4, and the sgs2).
Here is my code:
private static final UUID MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //this is the other one that I've tried: fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final String NAME = "BluetoothConnector";
public void listenForConnection() throws IOException, BluetoothException {
//first close the socket if it is open
closeSocket();
BluetoothServerSocket mServerSocket = null;
try {
mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID_SECURE); //ioexception here!
} catch (IOException e) {
if (Build.VERSION.SDK_INT >= 9) {
try { //this is a stupid hack, http://stackoverflow.com/questions/6480480/rfcomm-connection-between-two-android-devices
Method m = mBluetoothAdapter.getClass().getMethod("listenUsingRfcommOn", new Class[] { int.class });
mServerSocket = (BluetoothServerSocket) m.invoke(mBluetoothAdapter, PORT);
} catch (Exception ex) {
Log.e(ex);
throw e;
}
} else {
throw e;
}
}
while (!isCancelled) {
try {
socket = mServerSocket.accept();
} catch (IOException e) {
if (socket != null) {
try {
socket.close();
} finally {
socket = null;
}
}
throw e;
}
if (socket == null) {
throw new BluetoothException("Socket connection connected, but null");
} else {
isConnected = true;
break; // everything is ok
}
}
}
public void connect(String address) throws IOException, BluetoothException {
mBluetoothAdapter.cancelDiscovery();
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
try {
socket = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
} catch (IOException e1) {
Log.e(e1);
if (Build.VERSION.SDK_INT >= 9) {
try {
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
socket = (BluetoothSocket) m.invoke(device, PORT);
} catch (Exception e) {
Log.e(e);
throw e1;
}
} else {
throw e1;
}
}
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket.connect();
} catch (IOException e) {
Log.e(e);
// Close the socket
try {
socket.close();
} catch (IOException e2) {
Log.e(e2);
Log.wtf("unable to close() socket during connection failure");
}
throw e;
}
}
private void closeSocket() {
try {
if (socket != null) {
socket.close();
socket = null;
Log.d("Socket closed");
}
} catch (IOException e) {
Log.e(e);
Log.wtf("close() of connect socket failed");
}
}
I tried changing the uuid(random one also), tried looking at older sdk samples.
So what could be wrong here?
edit: trying to clarify: the problem usually comes up, when 2 devices that have been paired, connected, did some successful communication, get disconnected (by the user). After that, they can not be reconnected, unless they get rebooted, or unpaired manually.
You are trying to paired this manner:
private void TwitPairedDevice() {
buttonTwitPairDevice.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Set<BluetoothDevice> fetchPairedDevices=bluetooth.getBondedDevices();
Iterator<BluetoothDevice> iterator=fetchPairedDevices.iterator();
while(iterator.hasNext())
{
final BluetoothDevice pairBthDevice=iterator.next();
final String addressPairedDevice=pairBthDevice.getAddress();
AsyncTask<Integer, Void, Void> asynchPairDevice=new AsyncTask<Integer, Void, Void>() {
#Override
protected Void doInBackground(Integer... params) {
try {
socket=pairBthDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
};asynchPairDevice.execute();
}
}
});
}
Connect Pired Device:
private void FetchPairedDevices() {
Set<BluetoothDevice> pairedDevices=bluetooth.getBondedDevices();
for(BluetoothDevice pairedBthDevice:pairedDevices)
{
listPairedDevice.add(pairedBthDevice.getName());
}
listviewPairedDevice.setAdapter(adapterPairedDevice);
listviewPairedDevice.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Object listPairedName=arg0.getItemAtPosition(arg2);
String selectedPairedName=listPairedName.toString();
Set<BluetoothDevice> bthDeviceChecking=bluetooth.getBondedDevices();
for(final BluetoothDevice bthDevice:bthDeviceChecking)
{
if(bthDevice.getName().contains(selectedPairedName))
{
listPairDevice.clear();
listPairDevice.add(bthDevice);
final String addressPairedDevice=bthDevice.getAddress();
AsyncTask<Integer, Void, Void> asynTask=new AsyncTask<Integer,Void,Void>() {
#Override
protected Void doInBackground(Integer... params) {
try {
socket=bthDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
asynTask.execute(arg2);
}
}
}
});
}
It seems that at this point Bluetooth is broken on android.
There is no sure way of connecting 2 devices, that works all the time.
Some people are using an unofficial way to do it, but that does not work on all devices.
I did some in house testing, with the top 10 devices, that are on the market currently, so after around around 90 test runs, the hacked method worked 75% of the time, which is not good enough.
For example, the htc oneX will just handle incoming Bluetooth request, as a Bluetooth hands free device(it is connecting succesfully!), but makes messaging impossible.
After implementing full Bluetooth functionality, we decided to remove it from our app, and release it without it. We'll switch to wifi in some later release.

Categories

Resources