I have an application that will use 2 activities. The start or main activity sets up a bluetooth connection. When I switch to another activity I loose the bluetooth connection. Can a bluetooth connection be maintained when switching? Here is the OnResume() and onPause(). When I remove the btSocket.close() in the onPause The connection is maitained but will not communicate when onResume tries to connect.
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...");
BluetoothDevice device = btAdapter.getRemoteDevice(address);
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
}
btAdapter.cancelDiscovery();
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() + ".");
}
}
You should make your bluetooth connection independent of your activities. I would suggest that you put all your bluetooth code into a 'MyApp' class derived from Android Application class, or into a service. Using a service will be more complicated, but it will give you options to keep the app running even after the user closes the activities, e.g. if you want to finish your bluetooth communication.
You will find much written about both options, as they are common ways to structure your app - particularly when there is some form of network communication.
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
So there are many SO posts related to this issue -
java.io.IOException: [JSR82] accept: Connection is not created (failed or aborted)
java.io.IOException: [JSR82] while connecting to a bluetooth device
Other Posts -
http://android.2317887.n4.nabble.com/getting-exception-while-connecting-to-server-via-bluetooth-td11390.html
http://www.coderexception.com/Cbz1B31bPPQixWQQ/connection-is-not-created-failed-or-aborted-exception-thrown-during-bluetooth-connection-in-android
Tried everything from reflection to without reflection but none worked -
if(!mDeviceAddress.equals("") && BluetoothAdapter.checkBluetoothAddress(mDeviceAddress))
{
Log.i(TAG, "Remote Device Name "+mDeviceName);
bdDevice = mBluetoothAdapter.getRemoteDevice(mDeviceAddress);
getConnected(bdDevice);
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void getConnected(BluetoothDevice bdDevice)
{
if(bdDevice == null)
{
setSetting("STATUS", "Disconnected");
Toast.makeText(getActivity(),
"Unable to get Remote Device!", Toast.LENGTH_SHORT).show();
return;
}
else
{
Log.i(TAG, "Connecting Address--"+ bdDevice.getAddress());
boolean isConnected = createInsecureRfcommSocket(bdDevice, 1);
if(!isConnected)
{
for(int i=2;i<4;i++)
{
if(!isConnected)
isConnected = createInsecureRfcommSocket(bdDevice, i);
else
break;
}
}
if(isConnected)
{
Log.i(TAG, "Connected Socket");
setSetting("STATUS", "Connected");
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
timeSyncCommand();
mConnectedThread.writeByte(runCommand);
startTime = System.currentTimeMillis();
}
else
{
try
{
socket = bdDevice.
createInsecureRfcommSocketToServiceRecord(
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
}
catch(IOException io)
{
Toast.makeText(getActivity(), "Socket Create -"
+ io.toString() , Toast.LENGTH_SHORT).show();
}
try
{
mBluetoothAdapter.cancelDiscovery();
socket.connect();
}
catch(IOException io)
{
Log.i(TAG, "Socket Connect -"+io.toString());
}
if(socket.isConnected())
{
Log.i(TAG, "Connected Socket");
setSetting("STATUS", "Connected");
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
timeSyncCommand();
mConnectedThread.writeByte(runCommand);
startTime = System.currentTimeMillis();
}
else
{
Log.i(TAG, "Disconnected Socket");
setSetting("STATUS", "Disconnected");
}
}
}
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public boolean createInsecureRfcommSocket(BluetoothDevice bdDevice, int i)
{
try
{
Log.i(TAG,
"Creating RFCOMM socket using reflection with Object "+i);
//socket = bdDevice.createRfcommSocketToServiceRecord(my_UUID);
Method m = bdDevice.getClass().
getMethod("createInsecureRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(bdDevice, i);
mBluetoothAdapter.cancelDiscovery();
Log.i(TAG,"Attempt to connect to a remote device");
socket.connect();
}
catch(IOException e)
{
setSetting("STATUS", "Disconnected");
Log.i(TAG,"Exception raised "+e.getMessage());
try
{
socket.close();
Log.i(TAG,
"Cannot connect with address "+bdDevice.getAddress());
e.printStackTrace();
}
catch (IOException e1)
{
Log.i(TAG,"Socket not closed");
e1.printStackTrace();
}
}
catch (NoSuchMethodException e1)
{
Log.i(TAG,"NoSuchMethodException");
e1.printStackTrace();
}
catch (InvocationTargetException e2)
{
Log.i(TAG,"InvocationTargetException");
e2.printStackTrace();
}
catch (IllegalAccessException e3)
{
Log.i(TAG,"IllegalAccessException");
e3.printStackTrace();
}
catch (NullPointerException e4)
{
Log.i(TAG,"NullPointerException");
e4.printStackTrace();
}
}
If you see carefully to the above code then you notice -
1) Tried reflection with port 1
2) If 1 fails then tried reflection with port 2
3) If 2 fails then tried reflection with port 3
4) If 3 fails then tried without reflection
In short, used everything but none worked.
My exception trace -
Remote Device Name RN-IAP-E281
Connecting Address--00:06:68:4D:E2:81
Creating RFCOMM socket using reflection with Object 1
Attempt to connect to a remote device
Exception raised [JSR82] connect: Connection is not created (failed or aborted).
Cannot connect with address 00:06:68:4D:E2:81
Creating RFCOMM socket using reflection with Object 2
Attempt to connect to a remote device
Exception raised [JSR82] connect: Connection is not created (failed or aborted).
Cannot connect with address 00:06:68:4D:E2:81
Creating RFCOMM socket using reflection with Object 3
Attempt to connect to a remote device
Exception raised [JSR82] connect: Connection is not created (failed or aborted).
Cannot connect with address 00:06:68:4D:E2:81
Disconnected Socket
------onReceive BroadcastReceiver------
Received Bluetooth Disconnected Request
------Returned from broadcast after disconnect------
Any help will be appreciated!
I am trying with blue-tooth chat example for api-10, in my micromax pfhone.
When I scanning for devices it showing the list for both secure and non secure.
But When I try to connect it showing unable to connect.
And UUIDs are:
private static final UUID MY_UUID_SECURE = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final UUID MY_UUID_INSECURE =UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
I tried this post,
Service discovery failed exception using Bluetooth on Android , but no change.
Any ideas?
This is my code for connecting to a blue-tooth device while pairing. I got this code from android api-10 samples:
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
setName("ConnectThread" + mSocketType);
// 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) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " + mSocketType +
" socket during connection failure", e2);
}
connectionFailed();
return;
}
An obvious question, but still:
Did you register the 2 Bluetooth permissions in the Android manifest file?
I would like to develop an application for sending a message to multiple devices through blue tooth.I know blue tooth is a point to point communication even though i would like to connect and send a message as following steps:
1.Get the list of paired devices
2.Select a device from paired list
3.Connect to paired device , send a message to selected paired device
4.Disconnect from device
5.Get connection to another device and so on (one after another).
I am getting paired devices addresses list as follows:
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
pairedList.add(device.getAddress());
}
Log.v("11111111", "11111111111"+dev);
}
I am trying to connect to them and sending a message when user clicks on a button as follows:
((Button)findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String message = "Haiii";
for(int i=0;i<dev.size();i++){
Log.v("device", "111111 : "+pairedList.get(i));
mbService.connect(mBtAdapter.getRemoteDevice(pairedList.get(i)));
mbService.write(message.getBytes());
mbService.stop();
}
}
});
From the above code i am getting connection when loop pairedList.get(0).But the message is not sending to another device.In another device api sample application has installed.
If I use pairedList.get(i) it is not connecting to any devices even single device also.
please help me .
try to create separate threads for each connection - I had a similar issue and creating a new thread for each connection solved it nicely. By the way I even create a new thread to establish the connection - so establishing the connection does not block the UI. Got this from the BT sample code...
to create a new thread to establish a connection:
mConnectBluetoothThread = new ConnectBluetoothThread(device);
mConnectBluetoothThread.start();
where ConnectBluetoothThread is defined like:
public ConnectBluetoothThread(BluetoothDevice device) {
if (DEBUG)
Log.i(this.getClass().getSimpleName(),
this.getClass().getName()
+ " ->"
+ Thread.currentThread().getStackTrace()[2]
.getMethodName());
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
if (DEBUG)
Log.i(this.getClass().getSimpleName(),
this.getClass().getName()
+ " ->"
+ Thread.currentThread().getStackTrace()[2]
.getMethodName());
// TODO
setName("ConnectThread");
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.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(this.getClass().getSimpleName(),
"unable to close() socket during connection failure",
e2);
}
return;
}
// Reset the ConnectThread because we're done
synchronized (InterBT.this) {
mConnectBluetoothThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(),
"close() of connect socket failed", e);
}
}
}
public synchronized void connected(BluetoothSocket socket,
BluetoothDevice device) {
if (DEBUG)
Log.d(this.getClass().getSimpleName(), "connected");
// Cancel the thread that completed the connection
if (mConnectBluetoothThread != null) {
mConnectBluetoothThread.cancel();
mConnectBluetoothThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedBluetoothThread != null) {
mConnectedBluetoothThread.cancel();
mConnectedBluetoothThread = null;
}
// Cancel the accept thread because we only want to connect to one
// device
// if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread =
// null;}
// Start the thread to manage the connection and perform transmissions
mConnectedBluetoothThread = new ConnectionThreadBT(socket);
mConnectedBluetoothThread.start();
setState(STATE_CONNECTED);
}
and also create a new class ConnectionThreadBT that handles the connection to read and write:
public class ConnectionThreadBT extends ConnectionThreadBase {
private static final boolean DEBUG = true;
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
byte[] responseBuffer = new byte[4096 * 4];
int responseBufferLen = 0;
public ConnectionThreadBT(BluetoothSocket socket) {
if (DEBUG)
Log.i(this.getClass().getSimpleName(),
this.getClass().getName()
+ " ->"
+ Thread.currentThread().getStackTrace()[2]
.getMethodName());
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "temp sockets not created",
e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
if (DEBUG)
Log.i(this.getClass().getSimpleName(),
this.getClass().getName()
+ " ->"
+ Thread.currentThread().getStackTrace()[2]
.getMethodName());
//we have successfully connected to BT
//now inform UI
Home_Screen.sendMessageToHomeScreen(
Home_Screen.MESSAGE_INTERBT_CONNECTION_TESTED,
Home_Screen.CONNECTION_SUCCESS, true);
}
and then to write just call this method which is also defined within ConnectionThreadBT
public void sendMsg(MyBuffer buffer){
try {
mmOutStream.write(buffer);
mmOutStream.flush();
successfullyWritten = true;
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(),
"Exception during write", e);
successfullyWritten = false;
}
to read either do the same or start a monitoring loop in the run method which keeps reading as long as the connectedThread is alive and reports back any read information through a handler similar to the UI screen update
As the title explains I'm having a hard time sending some data via Bluetooth to my PC. I'm trying to establish a connection with my android phone as client and my PC as server. When I'm trying to actually establish a connection via BluetoothSocket.connect() my phone prompts for a pin. After entering it my PC also prompts for the same pin but before I can enter it, the connect() - method throws an IOException. I assume that the connect()-Method times out before I can enter the correct pin on my PC, but how can I get it to wait long enough for me to enter the PIN?
EDIT: After Re-Pairing the PC with my Phone it worked, because the pairing dialog doesn't appear in my app anymore. If I unpair the PC and start my app, the pairing dialog pops up but disappears after several seconds and the socket throws an exception ("connection reset by peer"). Apparently the connection is reset before the pairing is done, but why?
Here is my code:
private void connectToDevice(BluetoothDevice device)
{
mBluetoothAdapter.cancelDiscovery();
BluetoothSocket socket = null;
try
{
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101- 0000- 1000-8000-00805F9B34FB"));
}
catch (IOException e)
{
Log.e("HeliRemote", "Couldn't get socket.");
return;
}
try
{
socket.connect();
}
catch (IOException e)
{
try
{
socket.close();
}
catch (IOException e1)
{
Log.e("HeliRemote", "Couldn't close connection");
}
// That's the message I get in LogCat
Log.e("HeliRemote", "Couldn't connect to Socket.");
return;
}
Log.i("HeliRemote", "connected.");
}
I would be glad if somebody could give me any good words of advice regarding the problem.
Method m = mBluetoothDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
mBluetoothSocket = (BluetoothSocket) m.invoke(mBluetoothDevice, 1);
// mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(applicationUUID);
mBluetoothAdapter.cancelDiscovery();
mBluetoothSocket.connect();
}
catch (IOException eConnectException)
{
Log.d(TAG, "CouldNotConnectToSocket", eConnectException);
closeSocket(mBluetoothSocket);
return;
} catch (SecurityException e) {
Log.d(TAG, "CouldNotConnectToSocket", e);
closeSocket(mBluetoothSocket);
} catch (NoSuchMethodException e) {
Log.d(TAG, "CouldNotConnectToSocket", e);
closeSocket(mBluetoothSocket);
} catch (IllegalArgumentException e) {
Log.d(TAG, "CouldNotConnectToSocket", e);
closeSocket(mBluetoothSocket);
} catch (IllegalAccessException e) {
Log.d(TAG, "CouldNotConnectToSocket", e);
closeSocket(mBluetoothSocket);
} catch (InvocationTargetException e) {
Log.d(TAG, "CouldNotConnectToSocket", e);
closeSocket(mBluetoothSocket);
}
}
try this one...