0


ReactNative与Android交互详解

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

步骤:

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

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

MyNativeModule.java代码如下:

  1. package com.awesomeproject;
  2. import com.facebook.react.bridge.ReactApplicationContext;
  3. import com.facebook.react.bridge.ReactContextBaseJavaModule;
  4. import com.facebook.react.bridge.ReactMethod;
  5. import com.facebook.react.modules.core.DeviceEventManagerModule;
  6. import com.xiaomi.mipush.sdk.MiPushClient;
  7. import org.json.JSONException;
  8. import org.json.JSONObject;
  9. public class PushModule extends ReactContextBaseJavaModule {
  10. private ReactApplicationContext reactContext;
  11. public PushModule(ReactApplicationContext reactContext) {
  12. super(reactContext);
  13. this.reactContext = reactContext;
  14. }
  15. @Override
  16. public String getName() {
  17. return "PushModule";
  18. }
  19. /**
  20. 从RN界面里面调用该方法
  21. **/
  22. @ReactMethod
  23. public void getDeviceToken(){
  24. MainApplication.getReactPackage().mModule.sendDataToJS( MiPushClient.getRegId(MainApplication.getContext()));
  25. }
  26. public void sendDataToJS(String deviceToken){
  27. JSONObject jsonObject = new JSONObject();
  28. try {
  29. jsonObject.put("deviceToken",deviceToken);
  30. jsonObject.put("deviceName","");
  31. } catch (JSONException e) {
  32. throw new RuntimeException(e);
  33. }
  34. this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
  35. .emit("deviceToken",jsonObject.toString());
  36. }
  37. }

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

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

PushPackage.java代码如下:

  1. package com.awesomeproject;
  2. import com.facebook.react.ReactPackage;
  3. import com.facebook.react.bridge.NativeModule;
  4. import com.facebook.react.bridge.ReactApplicationContext;
  5. import com.facebook.react.uimanager.ViewManager;
  6. import java.util.ArrayList;
  7. import java.util.Collections;
  8. import java.util.List;
  9. public class PushPackage implements ReactPackage {
  10. public PushModule mModule;
  11. @Override
  12. public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
  13. List<NativeModule> list = new ArrayList<>();
  14. mModule = new PushModule(reactContext);
  15. list.add(mModule);
  16. return list;
  17. }
  18. @Override
  19. public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  20. return Collections.emptyList();
  21. }
  22. }

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

MainApplication.java代码如下:

  1. package com.awesomeproject;
  2. import android.app.Application;
  3. import android.content.Context;
  4. import android.util.Log;
  5. import com.facebook.react.PackageList;
  6. import com.facebook.react.ReactApplication;
  7. import com.facebook.react.ReactInstanceManager;
  8. import com.facebook.react.ReactNativeHost;
  9. import com.facebook.react.ReactPackage;
  10. import com.facebook.react.config.ReactFeatureFlags;
  11. import com.facebook.soloader.SoLoader;
  12. import com.awesomeproject.newarchitecture.MainApplicationReactNativeHost;
  13. import com.vivo.push.IPushActionListener;
  14. import com.vivo.push.PushClient;
  15. import com.vivo.push.PushConfig;
  16. import com.vivo.push.util.VivoPushException;
  17. import com.xiaomi.channel.commonutils.logger.LoggerInterface;
  18. import com.xiaomi.mipush.sdk.Logger;
  19. import com.xiaomi.mipush.sdk.MiPushClient;
  20. import java.lang.reflect.InvocationTargetException;
  21. import java.util.List;
  22. public class MainApplication extends Application implements ReactApplication {
  23. private final ReactNativeHost mReactNativeHost =
  24. new ReactNativeHost(this) {
  25. @Override
  26. public boolean getUseDeveloperSupport() {
  27. return BuildConfig.DEBUG;
  28. }
  29. @Override
  30. protected List<ReactPackage> getPackages() {
  31. @SuppressWarnings("UnnecessaryLocalVariable")
  32. List<ReactPackage> packages = new PackageList(this).getPackages();
  33. packages.add(mCommPackage);
  34. // Packages that cannot be autolinked yet can be added manually here, for example:
  35. // packages.add(new MyReactNativePackage());
  36. return packages;
  37. }
  38. @Override
  39. protected String getJSMainModuleName() {
  40. return "index";
  41. }
  42. };
  43. private final ReactNativeHost mNewArchitectureNativeHost =
  44. new MainApplicationReactNativeHost(this);
  45. @Override
  46. public ReactNativeHost getReactNativeHost() {
  47. if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
  48. return mNewArchitectureNativeHost;
  49. } else {
  50. return mReactNativeHost;
  51. }
  52. }
  53. static Context context;
  54. public static Context getContext() {
  55. return context;
  56. }
  57. private static final PushPackage mCommPackage = new PushPackage();
  58. public static PushPackage getReactPackage() {
  59. return mCommPackage;
  60. }
  61. @Override
  62. public void onCreate() {
  63. super.onCreate();
  64. context = this;
  65. // If you opted-in for the New Architecture, we enable the TurboModule system
  66. ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
  67. SoLoader.init(this, /* native exopackage */ false);
  68. initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  69. //初始化push
  70. try {
  71. //PushConfig.agreePrivacyStatement属性及含义说明请参考接口文档
  72. //使用方法
  73. PushConfig config = new PushConfig.Builder()
  74. .agreePrivacyStatement(true)
  75. .build();
  76. PushClient.getInstance(MainApplication.this).initialize(config);
  77. } catch (VivoPushException e) {
  78. Log.d("VivoPushException","-------------"+e.toString());
  79. //此处异常说明是有必须的vpush配置未配置所致,需要仔细检查集成指南的各项配置。
  80. e.printStackTrace();
  81. }
  82. // 打开push开关, 关闭为turnOffPush,详见api接入文档
  83. PushClient.getInstance(this).turnOnPush(new IPushActionListener() {
  84. @Override
  85. public void onStateChanged(int state) {
  86. // TODO: 开关状态处理, 0代表成功,获取regid建议在state=0后获取;
  87. Log.d("vivo初始化------","开关状态处理, 0代表成功,获取regid建议在state=0后获取----"+state);
  88. }
  89. });
  90. //小米初始化push推送服务
  91. MiPushClient.registerPush(this, "2882303761517520571", "5841752092571");
  92. //打开Log
  93. LoggerInterface newLogger = new LoggerInterface() {
  94. @Override
  95. public void setTag(String tag) {
  96. Log.d("MainApplication-------",tag);
  97. // ignore
  98. }
  99. @Override
  100. public void log(String content, Throwable t) {
  101. Log.d("MainApplication-------",content+"-----"+t.toString());
  102. }
  103. @Override
  104. public void log(String content) {
  105. Log.d("MainApplication-------",content);
  106. }
  107. };
  108. Logger.setLogger(this, newLogger);
  109. }
  110. /**
  111. * Loads Flipper in React Native templates. Call this in the onCreate method with something like
  112. * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  113. *
  114. * @param context
  115. * @param reactInstanceManager
  116. */
  117. private static void initializeFlipper(
  118. Context context, ReactInstanceManager reactInstanceManager) {
  119. if (BuildConfig.DEBUG) {
  120. try {
  121. /*
  122. We use reflection here to pick up the class that initializes Flipper,
  123. since Flipper library is not available in release mode
  124. */
  125. Class<?> aClass = Class.forName("com.awesomeproject.ReactNativeFlipper");
  126. aClass
  127. .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
  128. .invoke(null, context, reactInstanceManager);
  129. } catch (ClassNotFoundException e) {
  130. e.printStackTrace();
  131. } catch (NoSuchMethodException e) {
  132. e.printStackTrace();
  133. } catch (IllegalAccessException e) {
  134. e.printStackTrace();
  135. } catch (InvocationTargetException e) {
  136. e.printStackTrace();
  137. }
  138. }
  139. }
  140. }

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

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

App.js代码如下:

  1. 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 代码如下

  1. package com.awesomeproject;
  2. import com.facebook.react.bridge.ReactApplicationContext;
  3. import com.facebook.react.bridge.ReactContextBaseJavaModule;
  4. import com.facebook.react.bridge.ReactMethod;
  5. import com.facebook.react.modules.core.DeviceEventManagerModule;
  6. import com.xiaomi.mipush.sdk.MiPushClient;
  7. import org.json.JSONException;
  8. import org.json.JSONObject;
  9. public class PushModule extends ReactContextBaseJavaModule {
  10. private ReactApplicationContext reactContext;
  11. public PushModule(ReactApplicationContext reactContext) {
  12. super(reactContext);
  13. this.reactContext = reactContext;
  14. }
  15. @Override
  16. public String getName() {
  17. return "PushModule";
  18. }
  19. /**
  20. 从RN界面里面调用该方法
  21. **/
  22. @ReactMethod
  23. public void getDeviceToken(){
  24. MainApplication.getReactPackage().mModule.sendDataToJS( MiPushClient.getRegId(MainApplication.getContext()));
  25. }
  26. public void sendDataToJS(String deviceToken){
  27. JSONObject jsonObject = new JSONObject();
  28. try {
  29. jsonObject.put("deviceToken",deviceToken);
  30. jsonObject.put("deviceName","2882303761517520571");
  31. } catch (JSONException e) {
  32. throw new RuntimeException(e);
  33. }
  34. this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
  35. .emit("deviceToken",jsonObject.toString());
  36. }
  37. }

步骤:

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

  1. NativeModules.PushModule.getDeviceToken();

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

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

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


本文转载自: https://blog.csdn.net/weixin_42193246/article/details/137545752
版权归原作者 Tom!!! 所有, 如有侵权,请联系我们删除。

“ReactNative与Android交互详解”的评论:

还没有评论