ReactNative与Android交互详解

本文详细介绍了如何在ReactNative项目中,通过创建Android原生模块与ReactNative进行数据交换,包括创建继承自ReactContextBaseJavaModule的类、封装方法以便RN调用、以及如何在RN端接收和处理从Android传递的数据。
摘要由CSDN通过智能技术生成

前言:很多开发者使用ReactNative时候会遇到与Android之间的交互,本文将介绍Android如何传递值到ReactNative。

步骤:

1.用Android Studio打开一个已经存在的RN项目,即用AS打开 项目文件夹/android,如下图所示

2.在Android原生这边创建一个类继承ReactContextBaseJavaModule,这个类里边放我们需要被RN调用的方法,将其封装成一个原生模块。

MyNativeModule.java代码如下:

package com.awesomeproject;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.xiaomi.mipush.sdk.MiPushClient;
import org.json.JSONException;
import org.json.JSONObject;

public class PushModule extends ReactContextBaseJavaModule {
    private ReactApplicationContext reactContext;
    public PushModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "PushModule";
    }
    /**
     从RN界面里面调用该方法
     **/
    @ReactMethod
    public void getDeviceToken(){
        MainApplication.getReactPackage().mModule.sendDataToJS( MiPushClient.getRegId(MainApplication.getContext()));


    }
    
    public void sendDataToJS(String deviceToken){
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("deviceToken",deviceToken);
            jsonObject.put("deviceName","");

        } catch (JSONException e) {
            throw new RuntimeException(e);
        }

        this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("deviceToken",jsonObject.toString());
    }



}

本类中存放我们要复用的原生方法,继承了ReactContextBaseJavaModule类,并且实现了其getName()方法,构造方法也是必须的。按着Alt+Enter程序会自动提示。接着定义了一个方法,该方法必须使用注解@ReactMethod标明,说明是RN要调用的方法。

3.在Android原生这边创建一个类实现接口ReactPackage包管理器,并把第二步创建的类加到原生模块(NativeModule)列表里。

PushPackage.java代码如下:

package com.awesomeproject;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

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

public class PushPackage implements ReactPackage {
    public PushModule mModule;
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> list = new ArrayList<>();
        mModule = new PushModule(reactContext);
        list.add(mModule);
        return list;
    }

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

4.将第三步创建的包管理器添加到ReactPackage列表里(getPackage方法里)

MainApplication.java代码如下:

package com.awesomeproject;

import android.app.Application;
import android.content.Context;
import android.util.Log;

import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.soloader.SoLoader;
import com.awesomeproject.newarchitecture.MainApplicationReactNativeHost;
import com.vivo.push.IPushActionListener;
import com.vivo.push.PushClient;
import com.vivo.push.PushConfig;
import com.vivo.push.util.VivoPushException;
import com.xiaomi.channel.commonutils.logger.LoggerInterface;
import com.xiaomi.mipush.sdk.Logger;
import com.xiaomi.mipush.sdk.MiPushClient;

import java.lang.reflect.InvocationTargetException;
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() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          packages.add(mCommPackage);
          // Packages that cannot be autolinked yet can be added manually here, for example:
          // packages.add(new MyReactNativePackage());
          return packages;
        }

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

  private final ReactNativeHost mNewArchitectureNativeHost =
      new MainApplicationReactNativeHost(this);

  @Override
  public ReactNativeHost getReactNativeHost() {
    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
      return mNewArchitectureNativeHost;
    } else {
      return mReactNativeHost;
    }
  }


    static Context context;

    public static Context getContext() {
        return context;
    }
    private static final PushPackage mCommPackage = new PushPackage();
    public static PushPackage getReactPackage() {
        return mCommPackage;
    }



    @Override
  public void onCreate() {
    super.onCreate();
        context = this;
    // If you opted-in for the New Architecture, we enable the TurboModule system
    ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
    SoLoader.init(this, /* native exopackage */ false);
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());



        //初始化push

        try {
//PushConfig.agreePrivacyStatement属性及含义说明请参考接口文档
//使用方法
            PushConfig config = new PushConfig.Builder()
                    .agreePrivacyStatement(true)
                    .build();
            PushClient.getInstance(MainApplication.this).initialize(config);
        } catch (VivoPushException e) {
            Log.d("VivoPushException","-------------"+e.toString());
//此处异常说明是有必须的vpush配置未配置所致,需要仔细检查集成指南的各项配置。
            e.printStackTrace();
        }



// 打开push开关, 关闭为turnOffPush,详见api接入文档
        PushClient.getInstance(this).turnOnPush(new IPushActionListener() {
            @Override
            public void onStateChanged(int state) {
                // TODO: 开关状态处理, 0代表成功,获取regid建议在state=0后获取;
                Log.d("vivo初始化------","开关状态处理, 0代表成功,获取regid建议在state=0后获取----"+state);
            }
        });


        //小米初始化push推送服务

        MiPushClient.registerPush(this, "2882303761517520571", "5841752092571");

        //打开Log
        LoggerInterface newLogger = new LoggerInterface() {

            @Override
            public void setTag(String tag) {
                Log.d("MainApplication-------",tag);
                // ignore
            }

            @Override
            public void log(String content, Throwable t) {
                Log.d("MainApplication-------",content+"-----"+t.toString());

            }

            @Override
            public void log(String content) {
                Log.d("MainApplication-------",content);
            }
        };
        Logger.setLogger(this, newLogger);
  }

  /**
   * Loads Flipper in React Native templates. Call this in the onCreate method with something like
   * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
   *
   * @param context
   * @param reactInstanceManager
   */
  private static void initializeFlipper(
      Context context, ReactInstanceManager reactInstanceManager) {
    if (BuildConfig.DEBUG) {
      try {
        /*
         We use reflection here to pick up the class that initializes Flipper,
        since Flipper library is not available in release mode
        */
        Class<?> aClass = Class.forName("com.awesomeproject.ReactNativeFlipper");
        aClass
            .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
            .invoke(null, context, reactInstanceManager);
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      } catch (NoSuchMethodException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
    }
  }

}

5.在RN中去调用原生模块,必须import NativeModule模块。

修改App.js文件,需要从‘react-native’中引用‘NativeModules’,

App.js代码如下:

NativeModules.PushModule.getDeviceToken();

来分析一下程序运行流程:

(1)在配置文件AndroidManifest.xml中,android:name=".MainApplication",则MainApplication.java会执行。

(2)在MainApplication.java中,有我们创建的包管理器对象。程序加入PushPackage.java中。

(3)在PushPackage.java中,将我们自己创建的模块加入了原生模块列表中,程序进入PushModule.java中。

(4)在PushModule.java中,提供RN 调用的方法getDeviceToken

实现数据从Android原生回调到RN前端界面

我们都知道,要被RN调用的方法必须是void 类型,即没有返回值,但是项目中很多地方都需要返回数据。那怎么实现呢?

步骤:

1.在Android原生这边创建一个类继承ReactContextBaseJavaModule,这个类里边放我们需要被RN调用的方法,将其封装成一个原生模块。

在上面的PushModule中已经继承了ReactContextBaseJavaModule

我们需要调用sendDataToJS将数据传到RN 层。

PushModule.java 代码如下

package com.awesomeproject;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.xiaomi.mipush.sdk.MiPushClient;
import org.json.JSONException;
import org.json.JSONObject;

public class PushModule extends ReactContextBaseJavaModule {
    private ReactApplicationContext reactContext;
    public PushModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "PushModule";
    }
    /**
     从RN界面里面调用该方法
     **/
    @ReactMethod
    public void getDeviceToken(){
        MainApplication.getReactPackage().mModule.sendDataToJS( MiPushClient.getRegId(MainApplication.getContext()));


    }

    public void sendDataToJS(String deviceToken){
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("deviceToken",deviceToken);
            jsonObject.put("deviceName","2882303761517520571");

        } catch (JSONException e) {
            throw new RuntimeException(e);
        }

        this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("deviceToken",jsonObject.toString());
    }



}

步骤:

1、在RN 中调用原生的方法

NativeModules.PushModule.getDeviceToken();

2、原生提供对应的方法,将数据传递

3、RN 接收原生传递的数据

至此,我们实现了RN复用原生代码,即将原生模块封装成一个接口,在RN中调用。并且可以封装更加复杂的方法,同时实现了数据回调,即将数据从原生模块中传递到RN前端。

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值