October 22, 2024
Chicago 12, Melborne City, USA
Android

How do I automatically connect to all discoverable devices over Bluetooth that are within n RSSI range and running the same application?


I am creating an app on android that automatically connects to other devices running the same app over bluetooth(e.g. no prompts whatsoever) within n RSSI range. It then proceeds to send a file.

I currently have the devices successfully "advertising" and "discovering" simoultaneously, but the application does not discover itself and never connects. Here is the class I am using to call it.

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothServerSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@SuppressLint("MissingPermission")
public class BluetoothConnectionManager {

    private static final String TAG = "BluetoothConnManager";
    private static final UUID APP_UUID = UUID.fromString("29f9fac1-db57-4a3f-b91e-98f2a1139a16"); // Generate a unique UUID
    private static final String APP_NAME = "MyBluetoothApp"; // Your app name

    private BluetoothAdapter bluetoothAdapter;
    private BluetoothSocket bluetoothSocket;
    private BluetoothServerSocket serverSocket;
    private Context context;

    public BluetoothConnectionManager(Context context) {
        this.context = context;
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // Register for Bluetooth scan results (for RSSI)
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        context.registerReceiver(receiver, filter);
    }

    // Start discovering devices
    public void startDeviceDiscovery() {
        if (bluetoothAdapter != null && bluetoothAdapter.isEnabled()) {
            bluetoothAdapter.startDiscovery();
            Toast toast = Toast.makeText(context, "Discovery Started", Toast.LENGTH_SHORT);
            toast.show();
        }
    }

    // BroadcastReceiver to handle discovered devices and RSSI
    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice and RSSI
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);

                Log.d(TAG, "Device found: " + device.getName() + " RSSI: " + rssi);

                // Check the RSSI and if it's strong enough, attempt to connect
                if(rssi > -75) {
                    connectToDevice(device);
                    BluetoothFileTransfer bluetoothFileTransfer = new BluetoothFileTransfer(bluetoothSocket, context);
                    File fileToSend = new File(context.getFilesDir(), "contact.json");
                    File fileToRecieve = new File(context.getFilesDir(), "recievedContact.json");
                    bluetoothFileTransfer.startFileTransfer(fileToSend,fileToRecieve);
                    try {
                        wait(10000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    closeConnection();
                    cleanup();
                }
            }
        }
    };

    // Establish connection with a device
    private void connectToDevice(BluetoothDevice device) {
        try {
            bluetoothSocket = device.createRfcommSocketToServiceRecord(APP_UUID);
            bluetoothAdapter.cancelDiscovery(); // Cancel discovery as it impacts performance

            // Try to connect
            bluetoothSocket.connect();
            Log.d(TAG, "Connected to " + device.getName());
            Toast toast = Toast.makeText(context, "Connected to device", Toast.LENGTH_SHORT);
            toast.show();
        } catch (IOException e) {
            Log.e(TAG, "Connection failed", e);
            closeConnection();
        }
    }

    // Close connection if any
    public void closeConnection() {
        try {
            if (bluetoothSocket != null) {
                bluetoothSocket.close();
            }
        } catch (IOException e) {
            Log.e(TAG, "Failed to close connection", e);
        }
    }

    // Set up server socket to listen for connections
    public void startServer() {
        new Thread(() -> {
            try {
                serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(APP_NAME, APP_UUID);
                Log.d(TAG, "Server started");
                bluetoothSocket = serverSocket.accept(); // Blocking call
                Log.d(TAG, "Server accepted connection");

            } catch (IOException e) {
                Log.e(TAG, "Failed to start server", e);
            }
        }).start();
    }

    // Stop discovery and unregister receiver
    public void cleanup() {
        bluetoothAdapter.cancelDiscovery();
        try {
            serverSocket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        context.unregisterReceiver(receiver);
    }
}

I have yet to understand no connection is occuring as both servers successfully start and stop and devices are discoverable. I completely acknoledge that one similar post exists. However, this post does not seem to appeal to my question, as it is only questioning the method of connecting, not advertising as well.



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video