An open source library recommended for learning RN native module development—react-native-ble-manager

For example, the development of RN's native modules/Native Modules is a very important skill, but the examples on RN's official website are relatively simple, and then I came into contact with and used it recently, and read part of the source code of react-native-ble- manager , I found that it completely contains the knowledge points/technical points involved in a Native Modules, so I recommend it to everyone to learn and communicate together.
react-native-ble-manager currently has 1.8K stars
insert image description here
as shown below, react-native-ble- Manager is a Bluetooth low-power library in the RN development environment, used for programming of low-power Bluetooth communication functions in RN applications
insert image description here

Code structure of react-native-ble-manager

The amount of code is not much, if there is a foundation for Bluetooth development/API under the native platform, it will be easier to read
insert image description here

Understanding native modules based on layered thinking

For example, the guidelines for Android native modules
insert image description here
are as follows. During the development of the RN project, in most cases, my business logic and basic libraries are basically organized and written with JS/TS codes, but in fact most of the RN modules we use All three aspects are SDKs in the form of native modules. It is easier for us to add a native module to the project than to build an SDK in the form of a native module. The SDK also needs to deal with building and packaging. The following is my understanding of native modules based on the idea of ​​layered architecture. As the name suggests, the native module is a module that needs to rely on and use the API or functions of the native platform. This module is an ordinary JS module for the upper-level business, so the native module actually has two sub-modules, one is the JS module , the other is the platform layer module, the JS module directly serves the upper layer JS business module, which is called the interface module, and then the platform layer module is an internal implementation module, using the platform layer language to directly use the functional characteristics of the platform layer. How does the JS code of the native module communicate/interact with the platform layer code? This kind of scene needs to introduce a glue layer to deal with, but we don’t need to spend a lot of energy to build the glue layer like Android jni development, because the RN framework has already provided the function of this glue layer, so I will use the RN native module Developed specifications to build and write related code on the line
insert image description here

Understanding native modules from a role perspective

insert image description here

Look at native modules through react-native-ble-manager

Introduce the Android platform as the main

main file

insert image description here

main class diagram

insert image description here

Look at the interaction between JS and native from the scan interface

From the scan interface of JS to the scan interface of the Java layer, you can roughly understand the conversion of parameter types, and the callback processing after JS calls the native method, using the callback method
insert image description here

//js代码调scan,RN框架会帮忙代到并调到对应native层的scan方法,同时调用该方法时会做js数据类型到java数据类型的转换
 bleManager.scan(
        serviceUUIDs,
        seconds,
        allowDuplicates,
        scanningOptions,
        //下面这个就是一个js function对应到java就是一个callback类型
        (error: string | null) => {
    
    
          if (error) {
    
    
            reject(error);
          } else {
    
    
            fulfill();
          }
        }
      );
    });
//如下是java代码,BleManager.java类中scan方法
 @ReactMethod
    public void scan(ReadableArray serviceUUIDs, final int scanSeconds, boolean allowDuplicates, ReadableMap options,
                     Callback callback) {
    
    
        Log.d(LOG_TAG, "scan");
        if (getBluetoothAdapter() == null) {
    
    
            Log.d(LOG_TAG, "No bluetooth support");
            callback.invoke("No bluetooth support");
            return;
        }
        if (!getBluetoothAdapter().isEnabled()) {
    
    
            return;
        }

        synchronized (peripherals) {
    
    
            for (Iterator<Map.Entry<String, Peripheral>> iterator = peripherals.entrySet().iterator(); iterator
                    .hasNext(); ) {
    
    
                Map.Entry<String, Peripheral> entry = iterator.next();
                if (!(entry.getValue().isConnected() || entry.getValue().isConnecting())) {
    
    
                    iterator.remove();
                }
            }
        }

        if (scanManager != null)
            scanManager.scan(serviceUUIDs, scanSeconds, options, callback);
    }

Pay attention to the parameters of the scan method in the above JS code, and then look at the code for the relationship between the JS data type and the JAVA data type below.
In particular, it is important to understand the mapping between callback and function, because callback is often used when the native method calls back js. Let’s take a look at the
insert image description here
case where native actively interacts with js. Currently, the EventEmitter mechanism is used for interaction. That is, JS needs to register events, and then the native side can send corresponding events. The glue layer RN from Jvmruntime to Js runtime has helped us realize this event, just call the corresponding emmiter component. The following
is the code for registering the event on the JS side

const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);
//注删事件ID是一个String,如下面的 BleManagerDiscoverPeripheral,然后我们去native端的代码去搜索BleManagerDiscoverPeripheral
....
 const listeners = [
      bleManagerEmitter.addListener(
        'BleManagerDiscoverPeripheral',
        handleDiscoverPeripheral,
      ),
      bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan),
      bleManagerEmitter.addListener(
        'BleManagerDisconnectPeripheral',
        handleDisconnectedPeripheral,
      ),
      bleManagerEmitter.addListener(
        'BleManagerDidUpdateValueForCharacteristic',
        handleUpdateValueForCharacteristic,
      ),
    ];

//通过BleManagerDiscoverPeripheral看到native的有这样的代码, 
private void onDiscoveredPeripheral(final ScanResult result) {
    
    
        .....

        WritableMap map = peripheral.asWritableMap();
        bleManager.sendEvent("BleManagerDiscoverPeripheral", map);
    }

 public void sendEvent(String eventName, @Nullable WritableMap params) {
    
    
      getReactApplicationContext().getJSModule(RCTNativeAppEventEmitter.class).emit(eventName, params);
 }

Summarize

1. The native side uses RCTNativeAppEventEmitter to send events, and the js side uses NativeEventEmitter to register events, that is, the lower layer can actively communicate with the upper layer. 2.
Callback is often used as the normal operation of returning the call result of the native method to the JS runtime, that is, the method call and The result is returned, a two-way operation back and forth.

suggestion

1. Use webstorm to open the entire target, easy to read js/ts code
2. Use AS to open the Android directory, easy to read java code
3. Use xcode or appcode to open the ios directory, easy to read ios code

Guess you like

Origin blog.csdn.net/SCHOLAR_II/article/details/131966172