NativeModules未包含在ReactNative中

时间:2018-01-05 22:56:25

标签: android react-native react-native-android create-react-native-app react-native-native-module

我刚刚使用create-react-native-app创建了一个新应用程序,并将其分离以便能够创建一个本机模块。

然后,我在包含我的包的SensorManagerPackage.java旁边创建了MainApplication.java。然后创建了一个满足ReactContextBaseJavaModule实现的模块。

但是当我启动react-native应用程序并尝试记录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;
    }

}

2 个答案:

答案 0 :(得分:0)

您是否更新了清单并完全链接了库?您没有为gradle设置添加任何示例代码,而是将其带入包中。

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

答案 1 :(得分:0)

我刚刚找到了解决这个问题的方法。问题来自于@ReactMethod类中声明了AbstractSensor

为了解决这个问题,我覆盖了我想在子类中公开的方法,并在其上添加了@ReactMethod注释。

然后,因为模块现在有一些公开的方法,现在它们在NativeModules对象中可见。