dotintent / react-native-ble-plx

React Native BLE library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

πŸ› Error when create BleManager instance

Santa0727 opened this issue Β· comments

Prerequisites

  • I checked the documentation and FAQ without finding a solution
  • I checked to make sure that this issue has not already been filed

Expected Behavior

Hello,
I want to create a new BleManager instance using the following code.

const bleManager = useMemo(() => new BleManager(), []);

function useBLE(): BluetoothLowEnergyApi {
  const bleManager = useMemo(() => new BleManager(), []);
  .....
}

I want the above code to be working on expo 50.

Current Behavior

const bleManager = useMemo(() => new BleManager(), []);

Currently, the above code makes the following error:

ERROR  TypeError: Cannot read property 'createClient' of null
This error is located at:
    in App (at withDevTools.js:18)
    in withDevTools(App) (at renderApplication.js:57)
    in RCTView (at View.js:116)
    in View (at AppContainer.js:127)
    in RCTView (at View.js:116)
    in View (at AppContainer.js:155)
    in AppContainer (at renderApplication.js:50)
    in main(RootComponent) (at renderApplication.js:67), js engine: hermes
 ERROR  TypeError: Cannot read property 'createClient' of null

This is the dependencies in my package.json file:

"dependencies": {
    "@shopify/react-native-skia": "0.1.221",
    "expo": "~50.0.14",
    "expo-device": "~5.9.4",
    "expo-splash-screen": "~0.26.4",
    "expo-status-bar": "~1.11.1",
    "react": "18.2.0",
    "react-native": "0.73.6",
    "react-native-base64": "^0.2.1",
    "react-native-ble-plx": "^3.1.2"
  },

Library version

^3.1.2

Device

Android 10, Platform API Level 29

Environment info

I am using expo

Steps to reproduce

  1. Create fresh typescript expo project
  2. Create useBLE.ts file and then copy the following code
import { useMemo, useState } from "react";
import { PermissionsAndroid, Platform } from "react-native";
import { BleManager, Device } from "react-native-ble-plx";
import * as ExpoDevice from "expo-device";

interface BluetoothLowEnergyApi {
  requestPermissions(): Promise<boolean>;
  scanForPeripherals(): void;
  allDevices: Device[];
  connectToDevice: (deviceId: Device) => Promise<void>;
  connectedDevice: Device | null;
}

function useBLE(): BluetoothLowEnergyApi {
  const bleManager = useMemo(() => new BleManager(), []);

  const [allDevices, setAllDevices] = useState<Device[]>([]);
  const [connectedDevice, setConnectedDevice] = useState<Device | null>(null);

  const requestAndroid31Permissions = async () => {
    const bluetoothScanPermissions = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN, {
      title: "Scan Permission",
      message: "App requires Bluetooth Scanning",
      buttonPositive: "OK",
    });

    const bluetoothConnectPermissions = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
      {
        title: "Connecting Permission",
        message: "App requires Bluetooth Connecting",
        buttonPositive: "OK",
      }
    );

    const bluetoothFineLocationPermissions = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      {
        title: "Fine Location",
        message: "App requires Fine Location",
        buttonPositive: "OK",
      }
    );

    return (
      bluetoothScanPermissions === "granted" &&
      bluetoothConnectPermissions === "granted" &&
      bluetoothFineLocationPermissions === "granted"
    );
  };

  const requestPermissions = async () => {
    if (Platform.OS === "android") {
      if ((ExpoDevice.platformApiLevel ?? -1) < 31) {
        const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, {
          title: "Location Permission",
          message: "Bluetooth requires Location",
          buttonPositive: "OK",
        });

        return granted === PermissionsAndroid.RESULTS.GRANTED;
      } else {
        const isAndroid31PermissionsGranted = await requestAndroid31Permissions();
        return isAndroid31PermissionsGranted;
      }
    } else {
      return true;
    }
  };

  const isDuplicatedDevice = (devices: Device[], nextDevice: Device) =>
    devices.some((device) => device.id === nextDevice.id);

  const scanForPeripherals = () => {
  };

  const connectToDevice = async (device: Device) => {
  };

  return { scanForPeripherals, requestPermissions, allDevices, connectToDevice, connectedDevice };
}

export default useBLE;
  1. Copy the following code into App.tsx file
import { SafeAreaView, StyleSheet, Text, TouchableOpacity, View } from "react-native";
import useBLE from "./useBLE";
import { useState } from "react";
import DeviceModal from "./DeviceConnectionModal";

const App = () => {
  const { requestPermissions } = useBLE();
  const [visible, setVisible] = useState(false);
  const connectedDevice = false;

  const scanForDevices = async () => {
  };
  const openModal = () => {
    scanForDevices();
    setVisible(true);
  };

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.heartRateTitleWrapper}>
        {connectedDevice ? (
          <>
            <Text style={styles.heartRateTitleText}>Your Heart Rate Is:</Text>
            {/* <Text style={styles.heartRateText}>{heartRate} bpm</Text> */}
          </>
        ) : (
          <Text style={styles.heartRateTitleText}>Please Connect to a Heart Rate Monitor</Text>
        )}
      </View>
      <TouchableOpacity
        // onPress={connectedDevice ? disconnectFromDevice : openModal}
        onPress={openModal}
        style={styles.ctaButton}
      >
        <Text style={styles.ctaButtonText}>{connectedDevice ? "Disconnect" : "Connect"}</Text>
      </TouchableOpacity>
      {/* <DeviceModal
        closeModal={() => setVisible(false)}
        visible={visible}
        connectToPeripheral={connectToDevice}
        devices={allDevices}
      /> */}
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#f2f2f2",
  },
  heartRateTitleWrapper: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
  },
  heartRateTitleText: {
    fontSize: 30,
    fontWeight: "bold",
    textAlign: "center",
    marginHorizontal: 20,
    color: "black",
  },
  heartRateText: {
    fontSize: 25,
    marginTop: 15,
  },
  ctaButton: {
    backgroundColor: "#FF6060",
    justifyContent: "center",
    alignItems: "center",
    height: 50,
    marginHorizontal: 20,
    marginBottom: 5,
    borderRadius: 8,
  },
  ctaButtonText: {
    fontSize: 18,
    fontWeight: "bold",
    color: "white",
  },
});

export default App;

Formatted code sample or link to a repository

import { BleManager } from 'react-native-ble-plx'

export const manager = new BleManager()

Relevant log output

ERROR  TypeError: Cannot read property 'createClient' of null

This error is located at:
    in App (created by withDevTools(App))
    in withDevTools(App) (at renderApplication.js:57)
    in RCTView (at View.js:116)
    in View (at AppContainer.js:127)
    in RCTView (at View.js:116)
    in View (at AppContainer.js:155)
    in AppContainer (at renderApplication.js:50)
    in main(RootComponent) (at renderApplication.js:67), js engine: hermes
 ERROR  TypeError: Cannot read property 'createClient' of null

Additional information

No response

Hi @Santa0727
Thank you for raising the issue; we'll verify it and get back to you soon.

@Santa0727
It works for me :D
It looks like you used the standard "expo start" app launch, but this package uses native code that needs to be prebuilt.
Check

Btw.
You should have only one BLE instance, in your case a new one will be created every time you use the useBLE hook.

Hi @dominik-czupryna-withintent ,
Thank you for your response!

You are right, I used standard expo-managed flow without ejecting.
Is it impossible to use this library inside the expo without eject?

commented

@Santa0727 Use Expo Development Build. eject Expo is not a thing any more.

Hi @Santa0727
Is your issue is still relevant, do you need any help?

Hi @Santa0727
Do you still need help with the issue?

Closing due to inactivity