0
votes

Looking at the various examples and questions regarding this, I simply want to make a connection programmatically to a previously paired bluetooth device. In all of the examples, it seems that you have to choose a profile. What I want to do is just like what happens when you go into settings>bluetooth and click on a paired device and it just connects. So far I can find the bonded device:

    BluetoothDevice result;

    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    Set<BluetoothDevice> devices = adapter.getBondedDevices();
    if (devices != null) {
        for (BluetoothDevice device : devices) {
            Log.i("TAG", "Device name:" + device.getName());
            if (deviceName.equals(device.getName())) {
                result = device;
                Log.i("TAG", "Found:" + result.getName() + " attempting to connect");
                break;
            }
        }
    }

Now I just want to attempt to connect to the device in the same manner as occurs from bluetooth settings page.

Jackabe, seems to be doing "something" here is what I get:

07-17 10:50:55.346 11494-11494/com.daford.autowificonnect I/BT: Attempting to connect to Protocol: 00001101-0000-1000-8000-00805f9b34fb
07-17 10:50:55.348 11494-11494/com.daford.autowificonnect W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
07-17 10:50:56.263 11494-11494/com.daford.autowificonnect W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
07-17 10:50:56.357 11494-11494/com.daford.autowificonnect I/messageFromSensor: AT+VGS=14

(here it hangs for a while then)

07-20 14:43:04.314 18793-28387/com.daford.bluetoothdetection I/BT: Attempting to connect to Protocol: 00001101-0000-1000-8000-00805f9b34fb
07-20 14:43:04.321 18793-28387/com.daford.bluetoothdetection W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
07-20 14:43:05.172 18793-28387/com.daford.bluetoothdetection W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
07-20 14:43:05.187 18793-28387/com.daford.bluetoothdetection W/BT: Fallback failed. Cancelling.
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:738)
at android.bluetooth.BluetoothSocket.waitSocketSignal(BluetoothSocket.java:697)
at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:379)
at com.daford.bluetoothdetection.ConnectThread$FallbackBluetoothSocket.connect(ConnectThread.java:199)
at com.daford.bluetoothdetection.ConnectThread.connect(ConnectThread.java:66)
at com.daford.bluetoothdetection.MainActivity.connectToDevice(MainActivity.java:53)
at com.daford.bluetoothdetection.MainActivity$1.run(MainActivity.java:37)
at java.lang.Thread.run(Thread.java:761)
07-20 14:43:05.188 18793-28387/com.daford.bluetoothdetection W/System.err: java.io.IOException: Could not connect to device: 44:5E:F3:9F:35:1D
07-20 14:43:05.188 18793-28387/com.daford.bluetoothdetection W/System.err:     at com.daford.bluetoothdetection.ConnectThread.connect(ConnectThread.java:80)
07-20 14:43:05.194 18793-28387/com.daford.bluetoothdetection W/System.err:     at com.daford.bluetoothdetection.MainActivity.connectToDevice(MainActivity.java:53)
07-20 14:43:05.196 18793-28387/com.daford.bluetoothdetection W/System.err:     at com.daford.bluetoothdetection.MainActivity$1.run(MainActivity.java:37)
07-20 14:43:05.196 18793-28387/com.daford.bluetoothdetection W/System.err:     at java.lang.Thread.run(Thread.java:761)
1

1 Answers

0
votes

At this point here:

BluetoothDevice device : devices

You now have your paired devices as device objects.

I assume you now have these displayed in a list of some sort. If you do then you need to get the specific device object you want to connect to. Do this by attaching an onClickListener to your list view using the int position.

To actually create a connection there is a lot more to do. You now have to work with sockets to open a channel between your phone device and the bluetooth device.

There are plenty of ways to do this, many demonstrated on this site. From past experience I create a separate class to handle these connections.

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;

import com.smart.app.smartremote.Messages.DeviceMessageListener;

import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class ConnectThread {

    private BluetoothSocketWrapper bluetoothSocket;
    private BluetoothDevice device;
    private boolean secure;
    private BluetoothAdapter adapter;
    private List<UUID> uuidCandidates;
    private int candidate;
    private DeviceMessageListener messageListener;

    /**
     * @param device the device
     * @param secure if connection should be done via a secure socket
     * @param adapter the Android BT adapter
     * @param uuidCandidates a list of UUIDs. if null or empty, the Serial PP id is used
     */

    /**
     * This class runs on a new thread and handles communication between the phone and bluetooth device.
     * We attempt to open a socket, and if that fails, open a backup socket.
     * The methods to send and recieve data are also handled here.
     * */
    public ConnectThread(BluetoothDevice device, boolean secure, BluetoothAdapter adapter,
                         List<UUID> uuidCandidates) {
        this.device = device;
        this.secure = secure;
        this.adapter = adapter;
        this.uuidCandidates = uuidCandidates;
        this.messageListener = new DeviceMessageListener();

        if (this.uuidCandidates == null || this.uuidCandidates.isEmpty()) {
            this.uuidCandidates = new ArrayList<UUID>();
            this.uuidCandidates.add(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
        }
    }

    public BluetoothSocketWrapper connect() throws IOException {
        boolean success = false;
        while (selectSocket()) {
            adapter.cancelDiscovery();
            try {
                bluetoothSocket.connect();
                success = true;
                break;
            } catch (IOException e) {
                //try the fallback
                try {
                    bluetoothSocket = new FallbackBluetoothSocket(bluetoothSocket.getUnderlyingSocket());
                    Thread.sleep(500);
                    bluetoothSocket.connect();
                    success = true;
                    break;
                } catch (FallbackException e1) {
                    Log.w("BT", "Could not initialize FallbackBluetoothSocket classes.", e);
                } catch (InterruptedException e1) {
                    Log.w("BT", e1.getMessage(), e1);
                } catch (IOException e1) {
                    Log.w("BT", "Fallback failed. Cancelling.", e1);
                }
            }
        }

        if (!success) {
            throw new IOException("Could not connect to device: "+ device.getAddress());
        }

        receiveData(bluetoothSocket);
        return bluetoothSocket;
    }

    private boolean selectSocket() throws IOException {
        if (candidate >= uuidCandidates.size()) {
            return false;
        }

        BluetoothSocket tmp;
        UUID uuid = uuidCandidates.get(candidate++);

        Log.i("BT", "Attempting to connect to Protocol: "+ uuid);
        if (secure) {
            tmp = device.createRfcommSocketToServiceRecord(uuid);
        } else {
            tmp = device.createInsecureRfcommSocketToServiceRecord(uuid);
        }
        bluetoothSocket = new NativeBluetoothSocket(tmp);

        return true;
    }

    public static interface BluetoothSocketWrapper {

        InputStream getInputStream() throws IOException;

        OutputStream getOutputStream() throws IOException;

        String getRemoteDeviceName();

        void connect() throws IOException;

        String getRemoteDeviceAddress();

        void close() throws IOException;

        BluetoothSocket getUnderlyingSocket();

    }

    public static class NativeBluetoothSocket implements BluetoothSocketWrapper {

        private BluetoothSocket socket;

        public NativeBluetoothSocket(BluetoothSocket tmp) {
            this.socket = tmp;
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return socket.getInputStream();
        }

        @Override
        public OutputStream getOutputStream() throws IOException {
            return socket.getOutputStream();
        }

        @Override
        public String getRemoteDeviceName() {
            return socket.getRemoteDevice().getName();
        }

        @Override
        public void connect() throws IOException {
            socket.connect();
        }

        @Override
        public String getRemoteDeviceAddress() {
            return socket.getRemoteDevice().getAddress();
        }

        @Override
        public void close() throws IOException {
            socket.close();
        }

        @Override
        public BluetoothSocket getUnderlyingSocket() {
            return socket;
        }

    }

    public class FallbackBluetoothSocket extends NativeBluetoothSocket {

        private BluetoothSocket fallbackSocket;

        public FallbackBluetoothSocket(BluetoothSocket tmp) throws FallbackException {
            super(tmp);
            try
            {
                Class<?> clazz = tmp.getRemoteDevice().getClass();
                Class<?>[] paramTypes = new Class<?>[] {Integer.TYPE};
                Method m = clazz.getMethod("createRfcommSocket", paramTypes);
                Object[] params = new Object[] {Integer.valueOf(1)};
                fallbackSocket = (BluetoothSocket) m.invoke(tmp.getRemoteDevice(), params);
            }
            catch (Exception e)
            {
                throw new FallbackException(e);
            }
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return fallbackSocket.getInputStream();
        }

        @Override
        public OutputStream getOutputStream() throws IOException {
            return fallbackSocket.getOutputStream();
        }


        @Override
        public void connect() throws IOException {
            fallbackSocket.connect();
        }


        @Override
        public void close() throws IOException {
            fallbackSocket.close();
        }

    }

    public static class FallbackException extends Exception {

        /**
         *
         */
        private static final long serialVersionUID = 1L;

        public FallbackException(Exception e) {
            super(e);
        }

    }

    /**
     * This method sends InfraRed command as JsonObjects
     * */
    public void sendData(JSONObject object) throws IOException{
        String jsonStr = object.toString();
        OutputStream socketOutputStream =  bluetoothSocket.getOutputStream();
        socketOutputStream.write(jsonStr.toString().getBytes("utf-8"));
        Log.i("sending", jsonStr);
    }

    /**
     * This method sends RF commands as Hex strings.
     * */
    public void sendRadio(String string) throws IOException{
        OutputStream socketOutputStream =  bluetoothSocket.getOutputStream();
        socketOutputStream.write(string.getBytes("utf-8"));
        Log.i("sending", string);
    }

    /**
     * This method handles messages being sent from the bluetooth device.
     * We log the messages and also send them to a message receiver so we can evaluate them.
     * The checkMessages() methods do this.
     * */
    public boolean receiveData(BluetoothSocketWrapper socket) throws IOException{
        InputStream socketInputStream =  socket.getInputStream();
        byte[] buffer = new byte[1024];
        int bytes;

        // Keep looping to listen for received messages
        while (true) {
            try {
                bytes = socketInputStream.read(buffer);            //read bytes from input buffer
                String readMessage = new String(buffer, 0, bytes);
                messageListener.checkMessages(readMessage);
                Log.i("messageFromSensor", readMessage);

            } catch (IOException e) {
                break;
            }
        }
        return false;
    }

    /**
     * This method should be called when we no longer need the connection.
     * */
    public void close() throws IOException {
        bluetoothSocket.close();
    }

You can instantiate this class as I do below and call methods such as .connect() and .sendData() to communicate with the device.

public void connectToDevice(final BluetoothDevice device) {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        uuidCandidates = new ArrayList<>();
        uuidCandidates.add(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
        connectThread = new ConnectThread(device, true, mBluetoothAdapter, uuidCandidates);
        connectThread.connect();

    }