I want to receive data from a hardware device through Bluetooth in Android 5.1, but I got the following errors:
W/System.err: java.io.IOException: bt socket connect failed
W/System.err: at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:317)
W/System.err: at com.pda.bt.ConnectThread.run(ConnectThread.java:54)
E/error: bt socket connect failed
It just shows the error of bt socket connect failed. I tried to resolve the problem with various methods, but didn't work.
This is my code for connect:
public class ConnectThread extends Thread {
private final BluetoothAdapter mAdapter;
private final BluetoothDevice mDevice;
private final BluetoothSocket mySocket;
private static final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
public ConnectThread(BluetoothDevice device, BluetoothAdapter adapter) {
int sdk = Build.VERSION.SDK_INT;
BluetoothSocket _mySocket = null;
if (sdk >= 10) {
try {
_mySocket = device.createInsecureRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
Log.e("error", "Error creating socket");
}
} else {
try {
_mySocket = device.createRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
Log.e("error", "Error creating socket");
}
}
mDevice = device;
mAdapter = adapter;
mySocket = _mySocket;
Log.e("info", "=====>"+mDevice.getName());
Log.e("info", "=====>"+mDevice.getUuids());
}
public void run() {
mAdapter.cancelDiscovery();
try {
mySocket.connect();
} catch (IOException e) {
e.printStackTrace();
Log.e("error", e.getLocalizedMessage());
try {
mySocket.close();
} catch (Exception ee) {
Log.e("error", ee.getMessage());
}
}
}
public void cancel () {
try {
mySocket.close();
} catch (IOException e) {
Log.e("error", e.getMessage());
}
}
}
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
java.io.IOException: bt socket closed, read return: -1
08-14 20:30:11.519 30608-1676/com.example.lg.scoreboardapp W/System.err: at android.bluetooth.BluetoothSocket.read(BluetoothSocket.java:434)
08-14 20:30:11.519 30608-1676/com.example.lg.scoreboardapp W/System.err: at android.bluetooth.BluetoothInputStream.read(BluetoothInputStream.java:96)
08-14 20:30:11.519 30608-1676/com.example.lg.scoreboardapp W/System.err: at java.io.InputStreamReader.read(InputStreamReader.java:231)
08-14 20:30:11.519 30608-1676/com.example.lg.scoreboardapp W/System.err: at java.io.BufferedReader.fillBuf(BufferedReader.java:145)
08-14 20:30:11.519 30608-1676/com.example.lg.scoreboardapp W/System.err: at java.io.BufferedReader.readLine(BufferedReader.java:397)
08-14 20:30:11.519 30608-1676/com.example.lg.scoreboardapp W/System.err: at com.example.lg.scoreboardapp.MainActivity$ConnectThread.run(MainActivity.java:336)
Sometimes in my app, client unexpectedly closed.
I don't know why......
I have three diveces. one devices is server. others are client.
They are connected well, but one client was closed. other client is still open.
Please give me the solution...!!
It's MainActivitity.. 336Lineenter code here
while(socket != null){
i++;
Log.d("MAinActivity","-----------------"+i+"-----------------------------");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
final String str1 = in.readLine(); //<<---Line 336
Log.d("MainActivity","--------------------------------------"+str1+i);
json1 = str1;
parse();
}
It's ConnectThread client
private class ConnectThread extends Thread {
private BluetoothSocket socket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Toast.makeText(MainActivity.this, "연결에 실패하였습니다.\n다시 시도하여 주세요", Toast.LENGTH_SHORT).show();
e.printStackTrace();
//mkmsg("Client connection failed: "+e.getMessage().toString()+"\n");
}
socket = tmp;
}
public void run() {
// mkmsg("Client running\n");
// 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
socket.connect();
} catch (IOException e) {
//mkmsg("Connect failed\n");
e.printStackTrace();
try {
socket.close();
socket = null;
} catch (IOException e2) {
//mkmsg("unable to close() socket during connection failure: "+e2.getMessage().toString()+"\n");
socket = null;
e2.printStackTrace();
}
// Start the service over to restart listening mode
}
// If a connection was accepted
if (socket != null) {
//mkmsg("Connection made\n");
//mkmsg("Remote device address: "+socket.getRemoteDevice().getAddress().toString()+"\n");
//Note this is copied from the TCPdemo code.
try {
int i=0;
while(socket != null){
i++;
Log.d("MAinActivity","-----------------"+i+"-----------------------------");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
final String str1 = in.readLine();
Log.d("MainActivity","--------------------------------------"+str1+i);
json1 = str1;
parse();
}
Log.d("MainActivity_341Line","socket is null.......... check this");
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"MainActivity_341Line socket is null.......... check this",Toast.LENGTH_LONG);
}
});
} catch(Exception e) {
//mkmsg("Error happened sending/receiving\n");
e.printStackTrace();
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"Error happened sending/receiving\\n",Toast.LENGTH_LONG);
Log.d("MainActivity_341Line","Error happened sending/receiving");
}
});
try {
socket.close();
socket = null;
} catch (IOException e2) {
//mkmsg("unable to close() socket during connection failure: "+e2.getMessage().toString()+"\n");
socket = null;
Log.d("MainActivity_341Line","Error happened "+e2);
e2.printStackTrace();
}
}
} else {
//mkmsg("Made connection, but socket is null\n");
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"Made connection, but socket is null\\n",Toast.LENGTH_LONG);
}
});
}
}
public void cancel() {
try {
socket.close();
Toast.makeText(MainActivity.this, "채점기기와의 연결이 끝났습니다", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(MainActivity.this, "채점기기와의 연결이 끝났습니다", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
Try to replace your run() method in your ConnectThread to this:
public void run()
{
Log.e(TAG, "BEGIN mConnectThread");
setName("ConnectThread");
mAdapter.cancelDiscovery();
try
{
mmSocket.connect();
}
catch (IOException e)
{
try
{
Log.e(TAG,"Trying fallback...");
mmSocket = (BluetoothSocket)
mmDevice.getClass()
.getMethod("createRfcommSocket", new Class[] {int.class}).invoke(mmDevice, 2);
mmSocket.connect();
Log.e(TAG,"Connected");
}
catch (Exception e2)
{
Log.e(TAG, "Couldn't establish Bluetooth connection!");
try
{
mmSocket.close();
}
catch (IOException e3)
{
Log.e(TAG, "unable to close() " + " socket during connection failure", e3);
}
connectionFailed();
return;
}
}
synchronized (BluetoothHelper.this)
{
mConnectThread = null;
}
connected(mmSocket, mmDevice);
}
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 implemented the following BluetoothService, it is from the official
Android BluetoothChatService example:
public class BluetoothService extends Thread {
private static final String TAG = BluetoothService.class.getSimpleName();
private static final String NAME_SECURE = TAG + "Secure";
private static final String NAME_INSECURE = TAG + "Insecure";
private static final UUID MY_UUID_SECURE = UUID.fromString("a6fb84f6-20b3-477f-9160-bcd028bddc99");
private static final UUID MY_UUID_INSECURE = UUID.fromString("7dd8441a-1d4b-42f1-9996-a7d507548dfc");
public static final int STATE_NONE = 0;
public static final int STATE_LISTEN = 1;
public static final int STATE_CONNECTING = 2;
public static final int STATE_CONNECTED = 3;
private BluetoothAdapter bluetoothAdapter = null;
private Handler handler = null;
private AcceptThread secureAcceptThread = null;
private AcceptThread insecureAcceptThread = null;
private ConnectThread connectThread = null;
private ConnectedThread connectedThread = null;
private int bluetoothState = STATE_NONE;
public BluetoothService(Handler handler) {
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
this.bluetoothState = STATE_NONE;
this.handler = handler;
}
public synchronized void startConnection() {
Log.d(TAG, "start");
if (this.connectThread != null) {
this.connectThread.cancel();
this.connectThread = null;
}
if (this.connectedThread != null) {
this.connectedThread.cancel();
this.connectedThread = null;
}
this.setBluetoothState(STATE_LISTEN);
if (this.secureAcceptThread == null) {
this.secureAcceptThread = new AcceptThread(true);
this.secureAcceptThread.start();
}
if (this.insecureAcceptThread == null) {
this.insecureAcceptThread = new AcceptThread(false);
this.insecureAcceptThread.start();
}
}
public synchronized void connect(BluetoothDevice device, boolean secure) {
if (this.bluetoothState == STATE_CONNECTING) {
if (this.connectThread != null) {
this.connectThread.cancel();
this.connectThread = null;
}
}
if (this.connectedThread != null) {
this.connectedThread.cancel();
this.connectedThread = null;
}
this.connectThread = new ConnectThread(device, secure);
this.connectThread.start();
this.setBluetoothState(STATE_CONNECTING);
}
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType) {
if (this.connectThread != null) {
this.connectThread.cancel();
this.connectThread = null;
}
if (this.connectedThread != null) {
this.connectedThread.cancel();
this.connectedThread = null;
}
if (this.secureAcceptThread != null) {
this.secureAcceptThread.cancel();
this.secureAcceptThread = null;
}
if (this.insecureAcceptThread != null) {
this.insecureAcceptThread.cancel();
this.insecureAcceptThread = null;
}
this.connectedThread = new ConnectedThread(socket, socketType);
this.connectedThread.start();
Message msg = this.handler.obtainMessage(Globals.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(Globals.DEVICE_NAME, device.getName());
msg.setData(bundle);
this.handler.sendMessage(msg);
this.setBluetoothState(STATE_CONNECTED);
}
public synchronized void stopConnection() {
if (this.connectThread != null) {
this.connectThread.cancel();
this.connectThread = null;
}
if (this.connectedThread != null) {
this.connectedThread.cancel();
this.connectedThread = null;
}
if (this.secureAcceptThread != null) {
this.secureAcceptThread.cancel();
this.secureAcceptThread = null;
}
if (this.insecureAcceptThread != null) {
this.insecureAcceptThread.cancel();
this.insecureAcceptThread = null;
}
this.setBluetoothState(STATE_NONE);
}
public void write(byte[] out) {
ConnectedThread connectedThread = null;
synchronized (this) {
if (this.bluetoothState != STATE_CONNECTED) {
return;
}
connectedThread = this.connectedThread;
}
connectedThread.write(out);
}
private void connectionFailed() {
Message msg = this.handler.obtainMessage(Globals.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Globals.TOAST, "Unable to connect device");
msg.setData(bundle);
this.handler.sendMessage(msg);
BluetoothService.this.start();
}
private void connectionLost() {
Message msg = this.handler.obtainMessage(Globals.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Globals.TOAST, "Device connection was lost");
msg.setData(bundle);
this.handler.sendMessage(msg);
BluetoothService.this.start();
}
public synchronized int getBluetoothState() {
return this.bluetoothState;
}
private synchronized void setBluetoothState(int bluetoothState) {
this.bluetoothState = bluetoothState;
}
private class AcceptThread extends Thread {
private BluetoothServerSocket serverSocket = null;
private String socketType = null;
public AcceptThread(boolean secure) {
BluetoothServerSocket tempServerSocket = null;
this.socketType = secure ? "Secure" : "Insecure";
try {
if (secure) {
tempServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE);
} else {
tempServerSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + socketType + "listen() failed", e);
}
this.serverSocket = tempServerSocket;
}
public void run() {
this.setName("AcceptThread" + socketType);
BluetoothSocket socket = null;
while (bluetoothState != STATE_CONNECTED) {
try {
socket = this.serverSocket.accept();
} catch (IOException e) {
break;
}
if (socket != null) {
synchronized (BluetoothService.this) {
switch (bluetoothState) {
case STATE_LISTEN:
case STATE_CONNECTING:
connected(socket, socket.getRemoteDevice(), socketType);
break;
case STATE_NONE:
case STATE_CONNECTED:
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
}
public void cancel() {
try {
this.serverSocket.close();
} catch (IOException e) {
Log.e(TAG, "Socket Type" + socketType + "close() of server failed", e);
}
}
}
private class ConnectThread extends Thread {
private BluetoothSocket bluetoothSocket = null;
private BluetoothDevice bluetoothDevice = null;
private String socketType = null;
public ConnectThread(BluetoothDevice bluetoothDevice, boolean secure) {
this.bluetoothDevice = bluetoothDevice;
this.socketType = secure ? "Secure" : "Insecure";
BluetoothSocket tempBluetoothSocket = null;
try {
if (secure) {
tempBluetoothSocket = this.bluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
} else {
tempBluetoothSocket = this.bluetoothDevice.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + this.socketType + "create() failed", e);
}
this.bluetoothSocket = tempBluetoothSocket;
}
public void run() {
Log.i(TAG, "BEGIN mConnectThread");
this.setName("ConnectThread");
bluetoothAdapter.cancelDiscovery();
try {
this.bluetoothSocket.connect();
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
connectionFailed();
try {
this.bluetoothSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() socket during connection failure", e2);
}
return;
}
synchronized (BluetoothService.this) {
connectThread = null;
}
connected(this.bluetoothSocket, this.bluetoothDevice, this.socketType);
}
public void cancel() {
try {
this.bluetoothSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
private class ConnectedThread extends Thread {
private BluetoothSocket bluetoothSocket = null;
private InputStream inputStream = null;
private OutputStream outputStream = null;
public ConnectedThread(BluetoothSocket bluetoothSocket, String socketType) {
Log.d(TAG, "create ConnectedThread");
this.bluetoothSocket = bluetoothSocket;
InputStream tempInputStream = null;
OutputStream tempOutputStream = null;
try {
tempInputStream = this.bluetoothSocket.getInputStream();
tempOutputStream = this.bluetoothSocket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
this.inputStream = tempInputStream;
this.outputStream = tempOutputStream;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes = 0;
while (true) {
try {
bytes = this.inputStream.read(buffer);
handler.obtainMessage(Globals.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
BluetoothService.this.start();
break;
}
}
}
public void write(byte[] buffer) {
try {
this.outputStream.write(buffer);
handler.obtainMessage(Globals.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
this.bluetoothSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
}
When i now want to connect to a BluetoothDevice with this code:
private void connectDevice(Intent data, boolean secure) {
String address = data.getExtras().getString(BluetoothFragment.EXTRA_DEVICE_ADDRESS);
BluetoothDevice device = this.bluetoothAdapter.getRemoteDevice(address);
this.bluetoothService.connect(device, secure);
}
I get the following Error:
02-07 12:47:15.633: E/BluetoothService(17671): read failed, socket might closed or timeout, read ret: -1
02-07 12:47:15.633: E/BluetoothService(17671): java.io.IOException: read failed, socket might closed or timeout, read ret: -1
02-07 12:47:15.633: E/BluetoothService(17671): at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:512)
So everything i do is exactly like the example which android is providing.
You can download the sample code of the BluetoothChat in the Android
Studio sample codes.
The only thing im curious about is the uuid. I dont know how to create them and if it is important to use a special uuid. I just used a uuid generator which i downloaded from the Android Play Store and did the following:
private static final UUID MY_UUID_SECURE = UUID.fromString("a6fb84f6-20b3-477f-9160-bcd028bddc99");
private static final UUID MY_UUID_INSECURE = UUID.fromString("7dd8441a-1d4b-42f1-9996-a7d507548dfc");
So the question is: How can i connect to a BluetoothDevice?
Addition
I use a Nexus 7 and a Nexus 4 with the latest Android Version.
I downloaded several bluetooth connection apps and all of these
apps arent able to build a connection between my devices. So
maybe it isnt a problem with the code? Is it a Nexus or Android
5.0.1 bug?
Can you try this code?
You can pass the string to the BT device by calling
BluetoothPrinterHelper.BT.send(context, data)
Note: The code assumes that you have connected and paired to the BT device and is the only device in the paired list. You can change this behaviour in the findDevice(BluetoothAdapter) method.
Also, the UUID can be generated in Java itself by calling UUID.randomUUID().toString(), but in this case UUID plays a different role. This identifies the profile the target BT device is running. You check more about that here BT-UUID
package com.example.bt;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.AsyncTask;
public enum class BluetoothPrinterHelper {
BT;
private BluetoothDevice device;
private static BluetoothSocket socket;
private BluetoothSocket tmp;
private BluetoothAdapter adapter;
private String deviceName;
public void send(Context ctx, String data) {
mTryConnect = new TryConnect();
mTryConnect.execute();
boolean isConnected = false;
try {
Log.d(TAG, "Establishing connection to device");
isConnected = mTryConnect.get();
} catch (InterruptedException e) {
Log.e(TAG, "Error connecting to device");
return;
} catch (ExecutionException e) {
Log.e(TAG, "Error connecting to device");
return;
}
if (isConnected) {
Log.d(TAG, "Connection to device successfully established");
mTrySend = new TrySend(data);
mTrySend.execute();
} else {
Toast.makeText(ctx, "No BT device connected", Toast.LENGTH_LONG).show();
}
}
private BluetoothDevice findDevice(BluetoothAdapter adapter) {
Log.d(TAG, "Finding BT devices");
Set<BluetoothDevice> pairedDevices = null;
try {
pairedDevices = adapter.getBondedDevices();
} catch (NullPointerException e) {
Log.e(TAG, "Error retrieving paired devices");
}
if (pairedDevices != null && pairedDevices.size() == 1) {
Log.d(TAG, "Found 1 paired device");
for (BluetoothDevice bluetoothDevice : pairedDevices) {
return bluetoothDevice;
}
} else {
Log.w(TAG, "Many/No paired BT devices found");
}
return null;
}
private class TryConnect extends AsyncTask<Void, Void, Boolean> {
public TryConnect() {
adapter = BluetoothAdapter.getDefaultAdapter();
}
#Override
protected Boolean doInBackground(Void... params) {
// Check bonded devices list
device = findDevice(adapter);
if (adapter.isDiscovering()) {
adapter.cancelDiscovery();
}
// Create a socket for the device connection
if (device != null) {
try {
deviceName = device.getName();
Log.d(TAG, "Creating socket");
tmp = device.createRfcommSocketToServiceRecord(DEVICE_UUID);
} catch (NoSuchMethodException e) {
Log.e(TAG, "Printing - NoSuchMethodException", e);
return false;
} catch (IllegalArgumentException e) {
Log.e(TAG, "Printing - IllegalArgumentException", e);
return false;
} catch (IllegalAccessException e) {
Log.e(TAG, "Printing - IllegalAccessException", e);
return false;
} catch (InvocationTargetException e) {
Log.e(TAG, "Printing - InvocationTargetException", e);
return false;
}
}
socket = tmp;
// Connect to the created socket and device
try {
Log.d(TAG, "Creating connection to: " + deviceName);
socket.connect();
} catch (IOException e) {
Log.e(TAG, "Unable to connect. Closing connection", e);
try {
socket.close();
} catch (IOException e1) {
Log.e(TAG, "Unable to close connection during connection failure", e1);
}
return false;
} catch (NullPointerException e) {
Log.e(TAG, "NPE during BT socket connection");
}
return true;
}
}
private class TrySend extends AsyncTask<Void, Void, Boolean> {
byte[] out;
public TrySend(String data) {
try {
out = data.getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
Log.w(TAG, "UnsupportedEncodingException");
}
}
#Override
protected Boolean doInBackground(Void... params) {
try {
// Get the output stream and ready for write
try {
Log.d(TAG, "Creating output stream");
outStream = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Socket not created", e);
return false;
} catch (NullPointerException e) {
Log.e(TAG, "NPE retreiving socket stream");
return false;
}
// Write data to the socket for printing
try {
Log.d(TAG, "Write to output stream");
// Write format
outStream.write(command);
// Write data to print
DataOutputStream dataOutputStream = new DataOutputStream(outStream);
dataOutputStream.write(out);
dataOutputStream.flush();
} catch (IOException e) {
Log.e(TAG, "Exception during BT write to device", e);
return false;
} catch (NullPointerException e) {
Log.e(TAG, "NPE during socket write");
} finally {
try {
outStream.close();
} catch (IOException e) {
Log.e(TAG, "Exception during closing outstream", e);
} catch (NullPointerException e) {
Log.e(TAG, "NPE during BT socket close");
}
}
// Close the socket and cleanup
try {
Log.d(TAG, "Closing socket");
socket.close();
} catch (IOException e) {
Log.e(TAG, "Socket closing exception", e);
return false;
} catch (NullPointerException e) {
Log.e(TAG, "NPE during BT socket close");
}
} finally {
adapter = null;
device = null;
socket = null;
outStream = null;
}
return true;
}
}
}
UPDATE: Can you try this code:
Method m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] { int.class });
tmp = (BluetoothSocket) m.invoke(device, 1);
instead of
tmp = device.createRfcommSocketToServiceRecord(DEVICE_UUID);
I'm trying to send data from an android device to a remote bluetooth device supporting Serial Port Profile(SPP). I notice whenever I open and close a socket after each press of a button, it is too slow. What socket commands should be executed in the Run() and Onclick() functions? The following is a class which does Bluetooth IO:
public class Selecteddevice extends Activity implements OnClickListener {
private static final String TAG = "THINBTCLIENT";
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothDevice device;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private static final UUID MY_UUID =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
public static String address;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.selecteddevice);
findViewById(R.id.toggleButton1).setOnClickListener(this);
findViewById(R.id.toggleButton2).setOnClickListener(this);
findViewById(R.id.toggleButton3).setOnClickListener(this);
}
#Override
public void onStart() {
super.onStart();
String address = getIntent().getStringExtra("address");
TextView tv1 = (TextView) findViewById(R.id.textView_address);
tv1.setText(" DEVICE ADDRESS: " + address);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
device = mBluetoothAdapter.getRemoteDevice(address);
run();
}
public void run(){
mBluetoothAdapter.cancelDiscovery();
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e)
{
Log.e(TAG, "ON START: Socket creation failed.", e);
}
try {
btSocket.connect();
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: Socket connection failed.", e);
}
}
public void sendTestString(String s){
try {
outStream = btSocket.getOutputStream();
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: OutputStream creation failed.", e);
}
try {
outStream.write(s.getBytes());
Log.d(TAG, "sendTestByte: OutputStream write succeeded.");
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: OutputStream writefailed.", e);
}
}
public void onClick(View v){
switch(v.getId())
{
case R.id.toggleButton1:
this.sendTestString("1");
break;
case R.id.toggleButton2:
this.sendTestString("2");
break;
case R.id.toggleButton3:
this.sendTestString("3");
break;
}
}
#Override
public void onPause() {
super.onPause();
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e5)
{
Log.e(TAG, "ON PAUSE: Couldn't flush output stream.", e5);
}
}
try {
btSocket.close();
} catch (IOException e6)
{
Log.e(TAG, "ON PAUSE: Unable to close socket.", e6);
}
}
#Override
public void onStop() {
super.onStop();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
My program crashes after pairing with the error message:
07-27 13:00:57.483: E/THINBTCLIENT(7855): sendTestByte: OutputStream writefailed.
07-27 13:00:57.483: E/THINBTCLIENT(7855): java.io.IOException: socket closed
07-27 13:00:57.483: E/THINBTCLIENT(7855): at
android.bluetooth.BluetoothSocket.write(BluetoothSocket.java:331)
...
What am I doing wrong?
Thanks.
If you are sure the connection is established without any error and you can get the socket, try assigning your OutputStream member in run() method as follows:
public void run()
{
mBluetoothAdapter.cancelDiscovery();
try
{
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e)
{
Log.e(TAG, "ON START: Socket creation failed.", e);
}
try
{
btSocket.connect();
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: Socket connection failed.", e);
}
try
{
outStream = btSocket.getOutputStream();
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: OutputStream creation failed.", e);
}
}
public void sendTestString(String s)
{
try
{
outStream.write(s.getBytes());
outSttream.flush(); // <-- Try flush to force sending data in buffer
Log.d(TAG, "sendTestByte: OutputStream write succeeded.");
} catch (IOException e)
{
Log.e(TAG, "sendTestByte: OutputStream writefailed.", e);
}
}
You are not actually closing socket but this should work. Make sure connection with master device is not lost before write() call