Idan Rahamim
Idan Rahamim

Reputation: 607

Get bluetooth signal strength

I want to get the Bluetooth signal strength of an another device which connected to my phone,

How can I get the Bluetooth signal strength?

I tried to search a lot over google and did not find any answer.

Does someone know how can I implement it?

this is myActivity:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));


    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    private final BroadcastReceiver receiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();
            if(BluetoothDevice.ACTION_FOUND.equals(action)) {
                int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
                Toast.makeText(getApplicationContext(),"  RSSI: " + rssi + "dBm", Toast.LENGTH_SHORT).show();
            }
        }
    };

}

I also has a Bluetooth permission in my manifest file.

Upvotes: 48

Views: 91111

Answers (5)

Shubham Kumar Gupta
Shubham Kumar Gupta

Reputation: 1147

here is the full code for logging Bluetooth RSSI ble devices and log them, you can add those inside the text view as well. Thanks @memochipan further on its code to get the RSSI values for all the nearby devices without connecting to them.

RSSI Logger

class RSSILoggerActivity : AppCompatActivity() {
    private lateinit var binding: ActivityRssiBinding

    val BLUETOOTH_PERMISSION: Int = 101

    private val btAdapter: BluetoothAdapter by lazy {
        (applicationContext.getSystemService(
            BLUETOOTH_SERVICE
        ) as BluetoothManager).adapter
    }
    private val locationManager by lazy {
        applicationContext.getSystemService(
            LOCATION_SERVICE
        ) as LocationManager
    }

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityRssiBinding.inflate(layoutInflater)
        setContentView(binding.root)
        registerReceiver(
            receiver,
            IntentFilter(BluetoothDevice.ACTION_FOUND, BluetoothDevice.ACTION_UUID)
        )

        requestBluetoothPermission()
        requestLocationPermission()

        binding.buttonStart.setOnClickListener {
            if (ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.BLUETOOTH_SCAN,
                ) == PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.ACCESS_FINE_LOCATION
                ) == PackageManager.PERMISSION_GRANTED
            ) {
                if (btAdapter.isEnabled && isLocationEnabled()) {
                    // Start discovery
                    btAdapter.startDiscovery()
                } else {
                    // Prompt user to enable Bluetooth or location
                    Toast.makeText(this, "Some issue", Toast.LENGTH_SHORT).show()
                }

            } else {
                Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun isLocationEnabled(): Boolean {
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
                locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
    }

    fun requestLocationPermission() {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_BACKGROUND_LOCATION
                ),
                WRITE_PERMISSION
            )
        }
    }

    fun requestBluetoothPermission() {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.BLUETOOTH_SCAN
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(
                    Manifest.permission.BLUETOOTH_SCAN,
                    Manifest.permission.BLUETOOTH_ADMIN,
                    Manifest.permission.BLUETOOTH,
                    Manifest.permission.BLUETOOTH_CONNECT,
                ),
                BLUETOOTH_PERMISSION
            )
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String?>,
        grantResults: IntArray,
        deviceId: Int
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults, deviceId)
        if (requestCode == BLUETOOTH_PERMISSION) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (ContextCompat.checkSelfPermission(
                        this,
                        Manifest.permission.BLUETOOTH_SCAN
                    ) == PackageManager.PERMISSION_GRANTED
                ) {
                    Log.d("Permission", "Permission has been granted")
                }
            }
        }
    }

    private val receiver: BroadcastReceiver = object : BroadcastReceiver() {
        @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
        override fun onReceive(context: Context?, intent: Intent) {
            val action = intent.action
            when (action) {
                BluetoothDevice.ACTION_FOUND -> {
                    val rssi =
                        intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.Companion.MIN_VALUE)
                            .toInt()
                    val device: BluetoothDevice? =
                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                    if (device != null)
                        Log.d(
                            "Key:",
                            "${binding.tvRssi.text} ${device.name} : ${device.address} $rssi\n"
                        )
                }

                BluetoothDevice.ACTION_UUID -> {
                    val device: BluetoothDevice? =
                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                    val uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID)
                    if (uuidExtra != null) {
                        for (uuid in uuidExtra) {
                            Log.d("UUID", "Device: ${device?.name} ${device?.address} UUID: $uuid")
                        }
                    }
                }
            }
        }
    }
}

activity_rssi.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RSSILoggerActivity">

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/tv_rssi"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_margin="20dp"
        android:background="#F2DEC9"
        android:padding="18dp"
        android:scrollbars="vertical"
        android:textSize="28sp"
        app:layout_constraintBottom_toTopOf="@id/buttonStart"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/buttonStart"
        android:layout_width="300dp"
        android:layout_height="48dp"
        android:layout_marginStart="54dp"
        android:layout_marginEnd="54dp"
        android:layout_marginBottom="32dp"
        android:background="#E6A25D"
        android:text="Start Measuring"
        android:textColor="#FFFFFF"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Permissions

<uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Upvotes: 0

Arvind
Arvind

Reputation: 1568

To get the signal you can check Bluetooth RSSI, you can read RSSI for connected devices, or perform a Bluetooth discovery to check the RSSI for any nearby devices.

Basically a Bluetooth discovery is a broadcast to all stations within range to respond back. As each devices responds back, Android fires off an ACTION_FOUND intent. Within this intent you can getExtra EXTRA_RSSI to obtain the RSSI.

Note that not all bluetooth hardware supports RSSI.

Also Related: Android IRC Office Hours Question About Android Bluetooth RSSI here is a Bluetooth Classic broadcast receiver example

private final BroadcastReceiver receiver = new BroadcastReceiver(){
    @Override
    public void onReceive(Context context, Intent intent) {

        String action = intent.getAction();
        if(BluetoothDevice.ACTION_FOUND.equals(action)) {
            short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
            Toast.makeText(getApplicationContext(),"  RSSI: " + rssi + "dBm", Toast.LENGTH_SHORT).show();
        }
    }
};

Upvotes: 49

Yoann.G
Yoann.G

Reputation: 283

You can get the signal strengh of a BluetoothDevice using its rssi. This can be done using BluetoothAdapter to get the bounded devices.

Once you have the one you are interested in, just call connectGatt() on it and define a new BluetoothGattCallback. This is an interface that provides few method to override. The two written below will allow you to have the rssi everytime the connection state changes.

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // Get the default bluetoothAdapter to store bonded devices into a Set of BluetoothDevice(s)
  BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  // It will work if your bluetooth device is already bounded to your phone
  // If not, you can use the startDiscovery() method and connect to your device
  Set<BluetoothDevice> bluetoothDeviceSet = bluetoothAdapter.getBondedDevices();

  for (BluetoothDevice bluetoothDevice : bluetoothDeviceSet) {
    bluetoothDevice.connectGatt(this, true, new BluetoothGattCallback() {
      @Override
      public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);
      }
      @Override
      public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
        if(status == BluetoothGatt.GATT_SUCCESS)
          Log.d("BluetoothRssi", String.format("BluetoothGat ReadRssi[%d]", rssi));
      }
    });
  }

}

NOTE : This sample requires a the following permission declared in your manifest file

<uses-permission android:name="android.permission.BLUETOOTH" />

Upvotes: 6

fadden
fadden

Reputation: 52313

The necessary API was introduced in API 18 (Android 4.3). You need to call BluetoothGatt#readRemoteRssi() to initiate the request. The response shows up on the BluetoothCallback#onReadRemoteRssi() callback. (That's the callback object that handles connect, discovery, characteristic reads, etc.)

The broadcast receiver stuff is no longer required.

Upvotes: 13

Memochipan
Memochipan

Reputation: 3465

I think your code is ok, but you need to implement startDiscovery() in order to see results.

The true is that BluetoothDevice.EXTRA_RSSI only works for discovering devices, when you connect to one of them you are not able any more to get its RSSI.

Here I developed a very simple sample of an Activity that permit you see the RSSI of the devices near to you. You first need to add a TextView and a Button to your layout, then enable the Bluetooth Adapter and then just click the button.

package com.in2apps.rssi;

import android.os.Bundle;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class RSSIActivity extends Activity {

    private BluetoothAdapter BTAdapter = BluetoothAdapter.getDefaultAdapter();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rssi);
        registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));

        Button boton = (Button) findViewById(R.id.button1);
        boton.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                BTAdapter.startDiscovery();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_rssi, menu);
        return true;
    }

    private final BroadcastReceiver receiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();
            if(BluetoothDevice.ACTION_FOUND.equals(action)) {
                int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
                String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
                TextView rssi_msg = (TextView) findViewById(R.id.textView1);
                rssi_msg.setText(rssi_msg.getText() + name + " => " + rssi + "dBm\n");
            }
        }
    };
}

It looks this way:

RSSI Detection - Android Example

Upvotes: 36

Related Questions