0

I'm working on a app that will connect to a OBD2 device through Bluetooth, but I haven't yet figured out how to connect to a Bluetooth device.

I followed a video tutorial, and am currently following this tutorial with hopefully better luck, but I don't really understand how to implement the code since I can't see the full code (I'm a beginner).

Any help is appreciated!

Image:

(Here's where I want to press on a device and connect to it.)

BluetoothActivity:

package com.example.asabanov.powersupplytool;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;

public class BluetoothActivity extends AppCompatActivity implements OnItemClickListener {

    public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    protected static final int SUCCESS_CONNECT = 0;
    protected static final int MESSAGE_READ = 1;
    ArrayAdapter<String> listAdapter;
    ListView listView;
    BluetoothAdapter btAdapter;
    Set<BluetoothDevice> devicesArray;
    ArrayList<String> pairedDevices;
    ArrayList<BluetoothDevice> devices;
    IntentFilter filter;
    BroadcastReceiver receiver;
    //String tag = "debugging";

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case SUCCESS_CONNECT:
                    //do something
                    ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket) msg.obj);
                    Toast.makeText(getApplicationContext(), "Connect", Toast.LENGTH_SHORT).show();
                    String s = "Successfully connected";
                    connectedThread.write(s.getBytes());
                    break;
                case MESSAGE_READ:
                    byte[] readBuf = (byte[]) msg.obj;
                    String string = new String(readBuf);
                    Toast.makeText(getApplicationContext(), "Connect", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bluetooth);

        init(); //initiate Bluetooth
        if (btAdapter == null) {
            Toast.makeText(getApplicationContext(), "No bluetooth detected on this device", Toast.LENGTH_SHORT).show();
            finish();
        } else {
            if (!btAdapter.isEnabled()) {
                turnOnBT();
            }

            pairedDevices=getPairedDevices();
            startDiscovery();
        }


    }

    private void startDiscovery() {
        btAdapter.cancelDiscovery();
        btAdapter.startDiscovery();

    }

    private void turnOnBT() {
        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(intent, 1);
    }

    private ArrayList getPairedDevices() {
        devicesArray = btAdapter.getBondedDevices();
        if (devicesArray.size() > 0) {
            //add devices in array to list array
            for (BluetoothDevice device : devicesArray) {
                pairedDevices.add(device.getName() + "\n" + device.getAddress());
            }
        }
        return pairedDevices;
    }

    private void init() {
        listView = (ListView) findViewById(R.id.listView);
        listView.setOnItemClickListener(this);
        listAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 0);
        listView.setAdapter(listAdapter);
        btAdapter = BluetoothAdapter.getDefaultAdapter();
        pairedDevices = new ArrayList<String>();
        filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        devices = new ArrayList<BluetoothDevice>();
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                    devices.add(device);
                    String s = "";

                    for (int a = 0; a < pairedDevices.size(); a++) {
                        if (device.getName().equals(pairedDevices.get(a))) {
                            s = "Paired";
                            break;
                        }
                    }
                    // matt-hp (paired)
                    listAdapter.add(device.getName() + " " + s + " " + "\n" + device.getAddress());
                } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
                    //run some code


                } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                    //run some code

                } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                    if (btAdapter.getState() == btAdapter.STATE_OFF) {
                        turnOnBT();
                    }
                }
            }
        };
        registerReceiver(receiver, filter);
        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        registerReceiver(receiver, filter);
        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(receiver, filter);
        filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(receiver, filter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(receiver, filter);

    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Bluetooth must be enabled to continue", Toast.LENGTH_SHORT).show();
            finish();
        }
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (btAdapter.isDiscovering()) {
            btAdapter.cancelDiscovery();
        }

        if (listAdapter.getItem(position).contains("Paired")) {

            BluetoothDevice selectedDevice = devices.get(position);
            ConnectThread connect = new ConnectThread(selectedDevice);
            connect.start();
            Toast.makeText(getApplicationContext(), "Device is paired", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getApplicationContext(), "Device is not paired", Toast.LENGTH_SHORT).show();
        }
    }

    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mmDevice = device;

            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                // MY_UUID is the app's UUID string, also used by the server code
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
            }
            mmSocket = tmp;
        }

        public void run() {
            // Cancel discovery because it will slow down the connection
            btAdapter.cancelDiscovery();

            try {
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();
            } catch (IOException connectException) {
                // Unable to connect; close the socket and get out
                try {
                    mmSocket.close();
                } catch (IOException closeException) {
                }
                return;
            }

            // Do work to manage the connection (in a separate thread)
            mHandler.obtainMessage(SUCCESS_CONNECT, mmSocket).sendToTarget();
        }


        /**
         * Will cancel an in-progress connection, and close the socket
         */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
            }
        }
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            byte[] buffer;   // buffer store for the stream
            int bytes; // bytes returned from read()

            // Keep listening to the InputStream until an exception occurs
            while (true) {
                try {
                    // Read from the InputStream
                    buffer = new byte[1024];
                    bytes = mmInStream.read(buffer);
                    // Send the obtained bytes to the UI activity
                    mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget();

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

        /* Call this from the main activity to send data to the remote device */
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) {
            }
        }

        /* Call this from the main activity to shutdown the connection */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
            }
        }
    }
}
swess
  • 171
  • 19
  • Which bluetooth stack are you using? bluez or bluedroid? – Shark Feb 22 '16 at 13:13
  • I'm using my phone for trying to connect, if that's what you mean? – swess Feb 22 '16 at 13:20
  • No, what I meant was "at some point in android (around ICS/JB) it's bluetooth stack (bluedroid) stopped working for some LE cases/devices, so while I was working as an embedded engineer, one of my tasks was to completely replace the broken `bluedroid` with `bluez` and that got our STBs to recognize the remotes". Perhaps it's busted in your version of Android, perhaps I'm just talking crap. But first, really make sure your phone is able to connect to **any** LE device and that will verify that it's not up to the bluetooth stack, but a problem in the code. – Shark Feb 22 '16 at 13:24
  • Additionally, make sure you read [THIS link here](http://developer.android.com/guide/topics/connectivity/bluetooth-le.html) – Shark Feb 22 '16 at 13:26
  • 1
    I've added a image to the post. I'm using a HTC One (M8) 6.0 M. I can connect to a LE device through the system settings on my phone, but I want to be able to connect to a device through the app's Bluetooth listview menu. – swess Feb 22 '16 at 13:32
  • You're not referencing LE devices anywhere in your code nore scan for them. Where are you using the [startLeScan()](http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback)) method ? – Shark Feb 22 '16 at 13:35
  • Oh no, my bad. I thought you meant something different when saying LE devices, sorry for my ignorance, didn't check the link you posted. How would I go about for using the LE Scan method in my code and connecting through the app? – swess Feb 22 '16 at 13:38
  • Well, I read the link you posted, and that link states that OBDII is a BLE (bluetooth low energy) device. So you would need to scan for LE devices, and be prepared for a shitstorm if the bluetooth stack deep in the SDK is broken :) I'd initialize the LE scan in your `startDiscovery()` or `init()` methods and see where that takes you. – Shark Feb 22 '16 at 13:41
  • Connection is a whole different thing; first thing's first - lets verify that the phone can actually see your car's on-board computer/device first, and when that's out of the way - then we'll figure something out to connect to it. – Shark Feb 22 '16 at 13:42
  • The guide I posted didn't use LE tough? Quote: _"It seems that Bluetooth Low Energy API is just the thing we should use. However, since it is now supported only by several devices, it is too early to use it."_ – swess Feb 22 '16 at 13:45
  • oooh, my bad. Then I guess the onboard computer is just a regular bluetooth device and the code they showed in the tutorial should work and connect to it, no? – Shark Feb 22 '16 at 13:48
  • Yes, that's correct. I really don't know how to use the code tough since the whole project file is not showed. Also they're using a AlertDialog to connect to a device. Is it possible to connect through the app by just clicking on a found device on the Listview (Image above)? – swess Feb 22 '16 at 14:00
  • IF you see it, find it, pair with it OR add it to adapter - then yes. the ListView is just fed data from the `BluetoothAdapter btAdapter` – Shark Feb 22 '16 at 14:02
  • Because when i'm trying to connect to my boss's phone for example, it doesn't pair, it just toasts the message "Device not paired" which I have written in the code. How would I go about to pairing to a device? (Also thank you for helping and explaining everything to me!) – swess Feb 22 '16 at 14:05
  • No real idea; I didn't mess around much with Bluetooth in Java-land. Much more in C/C++ under the hood :) But the tutorial you pasted has a workaround - instead of pairing the normal way, they do this `BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid); socket.connect();` and connect as if they paired/bonded the regular way. – Shark Feb 22 '16 at 14:12

0 Answers0