简体   繁体   中英

Bluetooth in react-native in new Android 12 and above

I am trying to scan Bluetooth Devices but startDiscovery just won't work, I have tried some old solutions of this but still no solution is working here. I have tried using some packages but they don't provide the solution I want.

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

This is the code I have written to startDiscovery() of Bluetooth Device but it is not discovering any devices. I have made the other device discoverable.

I have added below permissions:

<!--  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" />

are you shure your app has granted these permissions? I don't see perm-asking-code, and Android 12 new permissions are runtime ones

The BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, and BLUETOOTH_SCAN permissions are runtime permissions. Therefore, you must explicitly request user approval in your app before you can look for Bluetooth devices, make a device discoverable to other devices, or communicate with already-paired Bluetooth devices.

HERE you can find some examples how to implement

I solved the issue I was getting... The problem was in my Log message in ACTION_FOUND Broadcast receiver I had Log.d("TAG",device.getName()); of non-string value, so I change it to Log.d("TAG",String.valueOf(device.getName()));

And there is some WritableMap issue in the above code where I solved the initialisation using Aruguments.createMap();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM