获取蓝牙信号强度

问题描述 投票:0回答:5

我想获取连接到我手机的另一台设备的蓝牙信号强度,

如何获取蓝牙信号强度?

我尝试通过谷歌进行大量搜索,但没有找到任何答案。

有人知道我该如何实施吗?

这是我的活动:

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();
            }
        }
    };

}

我的清单文件中也有蓝牙权限。

java android
5个回答
48
投票

要获取信号,您可以检查蓝牙 RSSI,您可以读取已连接设备的 RSSI,或执行蓝牙发现以检查任何附近设备的 RSSI。

基本上,蓝牙发现是向范围内的所有站点广播以进行响应。当每个设备做出响应时,Android 会触发 ACTION_FOUND 意图。在此意图中,您可以获取额外的 EXTRA_RSSI 来获取 RSSI。

请注意,并非所有蓝牙硬件都支持 RSSI。

另相关:Android IRC 办公时间关于 Android 蓝牙 RSSI 的问题 这是一个经典蓝牙广播接收器示例

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();
        }
    }
};

36
投票

我认为你的代码没问题,但你需要实现

startDiscovery()
才能看到结果。

事实是,

BluetoothDevice.EXTRA_RSSI
仅适用于发现设备,当您连接到其中一个设备时,您将无法再获取其RSSI。

在这里,我开发了一个非常简单的活动示例,可以让您查看附近设备的 RSSI。您首先需要在布局中添加一个 TextView 和一个 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");
            }
        }
    };
}

看起来是这样的:

RSSI Detection - Android Example


13
投票

API 18(Android 4.3)中引入了必要的API。 您需要拨打

BluetoothGatt#readRemoteRssi()
发起请求。 响应显示在
BluetoothCallback#onReadRemoteRssi()
回调中。 (这是处理连接、发现、特征读取等的回调对象)

不再需要广播接收器的东西。


6
投票

您可以使用 RSSI 获取 BluetoothDevice 的信号强度。这可以使用 BluetoothAdapter 来获取绑定设备来完成。

一旦有了您感兴趣的,只需对其调用 connectGatt() 并定义一个新的 BluetoothGattCallback。这是一个提供很少方法来重写的接口。下面写的两个将允许您在每次连接状态发生变化时获得 rssi。

@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));
      }
    });
  }

}

注意:此示例需要在清单文件中声明以下权限

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

0
投票

这里是记录蓝牙 RSSI ble 设备并记录它们的完整代码,您也可以在文本视图中添加它们。进一步感谢 @memochipan 的代码,无需连接即可获取所有附近设备的 RSSI 值。

RSSI 记录器

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>

权限

<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" />
© www.soinside.com 2019 - 2024. All rights reserved.