蓝牙在新安卓12及以上版本中反应原生



我正在尝试扫描蓝牙设备,但startDiscovery不起作用,我已经尝试了一些旧的解决方案,但仍然没有解决方案。我试过使用一些软件包,但它们没有提供我想要的解决方案。

package com.bt67;
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.util.Log;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import java.util.ArrayList;
import java.util.Objects;
public class discover extends ReactContextBaseJavaModule {
ReactApplicationContext reactContext;
ArrayList<BluetoothDevice> discoveredDevices;
WritableMap reactDiscoveredDevices;
BluetoothAdapter bluetoothAdapter;
@NonNull
@Override
public String getName() {
return "discover";
}
discover(ReactApplicationContext reactApplicationContext){
super(reactApplicationContext);
reactContext = reactApplicationContext;
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
discoveredDevices = new ArrayList<>();
IntentFilter intentActionFound = new IntentFilter(BluetoothDevice.ACTION_FOUND);
reactContext.registerReceiver(discoveryReceiver,intentActionFound);
IntentFilter scanIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
reactContext.registerReceiver(scanModeReceiver,scanIntentFilter);
}
BroadcastReceiver discoveryReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, @NonNull Intent intent) {
String action = intent.getAction();
Log.d(Constants.TAG,"in discoveryReceiver");
if(BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
discoveredDevices.add(device);
Log.d(Constants.TAG,"Found: "+device.getName());
reactDiscoveredDevices.putString(device.getAddress(), device.getName());
}
}
};
BroadcastReceiver scanModeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, @NonNull Intent intent) {
String action = intent.getAction();
if(action.equals(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)) {
int modeValue = intent.getIntExtra(
BluetoothAdapter.EXTRA_SCAN_MODE,BluetoothAdapter.ERROR);
if (modeValue == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
Log.d(Constants.TAG,"Device can receive connection");
} else if (modeValue == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Log.d(Constants.TAG,"Device is Discoverable and can receive connection");
} else if (modeValue == BluetoothAdapter.SCAN_MODE_NONE) {
Log.d(Constants.TAG,
"Device is NOT Discoverable and can't receive connection");
} else {
Log.d(Constants.TAG,"ERROR");
}
}
}
};
@ReactMethod
public void doDiscovery(@NonNull Callback callback) {
// If we're already discovering, stop it
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
// Request discover from BluetoothAdapter
bluetoothAdapter.startDiscovery();
callback.invoke("Started Discovery");
}
@ReactMethod
public void getDiscoveredDevices(@NonNull Callback callback) {
callback.invoke(reactDiscoveredDevices);
}
@ReactMethod
public void makeDeviceDiscoverable(int duration, @NonNull Callback callback) {
Intent intentDiscoverable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intentDiscoverable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,duration);
Objects.requireNonNull(getCurrentActivity()).startActivity(intentDiscoverable);
callback.invoke("Device is discoverable for "+duration+" seconds");
}
}

这是我为蓝牙设备的startDiscovery((编写的代码,但它没有发现任何设备。我已经发现了另一个设备。

我添加了以下权限:

<!--  For Android 11 or lower  -->
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
android:maxSdkVersion="28"/>
<!--  For Android Q  -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!--  For Android 12 or higher  -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

您是否确定您的应用程序已授予这些权限?我没有看到perm请求代码,并且Android 12的新权限是运行时的

BLUETOOTH_AVERTISE、BLUETOTH_CONNECT和BLUETOATH_SCAN权限是运行时权限。因此,在查找蓝牙设备、使设备可被其他设备发现或与已配对的蓝牙设备通信之前,您必须在应用程序中明确请求用户批准。

在这里你可以找到一些如何实现的例子

我解决了我遇到的问题。。。问题出现在我在ACTION_FOUND广播接收器中的日志消息中我有非字符串值的Log.d("TAG",device.getName());,所以我将其更改为Log.d("TAG",String.valueOf(device.getName()));

在上面的代码中有一些WritableMap问题,我使用Aruguments.createMap();解决了初始化问题