Вопрос:

Нативные модули не включены в ReactNative

android react-native react-native-android create-react-native-app react-native-native-module

503 просмотра

2 ответа

141 Репутация автора

Я только что создал новое приложение create-react-native-appи отключил его, чтобы иметь возможность создать собственный модуль.

Затем я создал SensorManagerPackage.javaрядом с MainApplication.javaмоим пакетом. А затем создал модуль, удовлетворяющий ReactContextBaseJavaModuleреализацию.

Но когда я запускаю свое реактивное приложение и пытаюсь записать содержимое NativeModules, в результате получается пустой объект. У вас есть идеи, почему он не загружается?

MainApplication.java

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
              new MainReactPackage(),
              new SensorManagerPackage()
      );
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

SensorManagerPackage.java

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.farmingapp.sensors.AmbientTemperatureSensor;
import com.farmingapp.sensors.LightSensor;
import com.farmingapp.sensors.PressureSensor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SensorManagerPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new AmbientTemperatureSensor(reactContext));
        modules.add(new LightSensor(reactContext));
        modules.add(new PressureSensor(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

AbstractSensor

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.annotation.Nullable;
import android.util.Log;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
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 com.facebook.react.modules.core.DeviceEventManagerModule;

public abstract class AbstractSensor extends ReactContextBaseJavaModule implements SensorEventListener {
    private final ReactApplicationContext reactContext;
    private final SensorManager sensorManager;
    private final Sensor sensor;
    private final int sensorId;
    private double lastReading = (double) System.currentTimeMillis();
    private int interval;

    public AbstractSensor(ReactApplicationContext reactContext, int sensorId) {
        super(reactContext);
        this.sensorId = sensorId;
        this.reactContext = reactContext;
        this.sensorManager = (SensorManager)reactContext.getSystemService(reactContext.SENSOR_SERVICE);
        this.sensor = this.sensorManager.getDefaultSensor(sensorId);
    }

    // RN Methods
    @ReactMethod
    public void setUpdateInterval(int newInterval) {
        this.interval = newInterval;
    }

    @ReactMethod
    public void startUpdates(Promise promise) {
        if (this.sensor == null) {
            // No sensor found, throw error
            promise.reject(new RuntimeException("No sensor found"));
            return;
        }
        promise.resolve(null);
        // Milisecond to Microsecond conversion
        sensorManager.registerListener(this, sensor, this.interval * 1000);
    }

    @ReactMethod
    public void stopUpdates() {
        sensorManager.unregisterListener(this);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }

    protected void sendEvent(String eventName, @Nullable WritableMap params) {
        try {
            this.reactContext
                    .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                    .emit(eventName, params);
        } catch (RuntimeException e) {
            Log.e("ERROR", "java.lang.RuntimeException: Trying to invoke Javascript before CatalystInstance has been set!");
        }
    }

    protected abstract WritableMap convertEvent(SensorEvent sensorEvent, WritableMap map);

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {
        double tempMs = (double) System.currentTimeMillis();
        if (tempMs - lastReading >= interval){
            lastReading = tempMs;

            WritableMap map = Arguments.createMap();

            if (sensorEvent.sensor.getType() == this.sensorId) {
                map.putDouble("timestamp", (double) System.currentTimeMillis());
                sendEvent(this.getName(), this.convertEvent(sensorEvent, map));
            }
        }
    }

}

LightSensor.java

import android.hardware.Sensor;
import android.hardware.SensorEvent;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.WritableMap;

public class LightSensor extends AbstractSensor {
    public LightSensor(ReactApplicationContext reactContext) {
        super(reactContext, Sensor.TYPE_AMBIENT_TEMPERATURE);
    }

    @Override
    public String getName() {
        return "Light";
    }

    protected WritableMap convertEvent(SensorEvent sensorEvent, WritableMap map) {
        map.putDouble("value", sensorEvent.values[0]);
        return map;
    }

}
Автор: Jeremie Источник Размещён: 05.01.2018 10:56

Ответы (2)


0 плюса

388 Репутация автора

Вы обновили свой манифест и полностью связали библиотеку? Вы не включили пример кода для своих настроек gradle и того, что вы вносите его в свои пакеты.

https://cmichel.io/how-to-create-react-native-android-library/

Автор: Chanoch Размещён: 06.01.2018 11:23

0 плюса

141 Репутация автора

Решение

Я только что нашел решение этой проблемы. Проблема возникла из-за того, что @ReactMethodбыли объявлены в AbstractSensorклассе.

Чтобы исправить это, я переопределил методы, которые хотел показать в дочернем классе, и добавил к ним @ReactMethodаннотацию.

И потом, поскольку у модулей теперь есть какой-то открытый метод, они теперь видны в NativeModulesобъекте.

Автор: Jeremie Размещён: 07.01.2018 08:24
Вопросы из категории :
32x32