Как подружить React Native и Java код на Android

от автора

Необходимость работы с нативной частью приложения React Native обычно возникает тогда, когда какой-либо сервис не имеет специального api для RN. Таким образом, хороший разработчик должен уметь, как минимум, представление того, как работает нативная часть приложения. В данной статье будут приведены примеры работы взаимодействия приложения React Native c Android.

Нативный модуль

Для начала создадим новый класс в папке android/app/src/main/java класс CustomModule:

package com.awesomeproject; import android.widget.Toast; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod;  import java.util.Map; import java.util.HashMap;  public class CustomModule extends ReactContextBaseJavaModule {     CustomModule (ReactApplicationContext context) {         super(context);         reactContext = context;     }      @Override     public String getName() {         return "CustomModule";     }      private static ReactApplicationContext context; }

Данный класс содержит обязательный метод getName(). Именно по тому имени, который вернет данный метод можно получить доступ к нативному модулю из кода Javascript (об этом далее).
Обратим также внимание на то, что конструктор класса принимает контекст приложения в качестве аргумента. Контекст приложения необходим, когда мы хотим взаимодействуем с компонентами Android.

Создадим метод класса CustomModule, который будет вызываться из кода Javascript:

@ReactMethod     public void show(String message, int duration) {         Toast.makeText(context,"Hello world", Toast.LENGTH_LONG).show();     }

Заметим, что для того, чтобы метод был доступен в RN, необходимо использовать декоратор “@ReactMethod”.

Класс Toast — компонент Android, который может вызывать всплывающее сообщение снизу с помощью метода show().

Связь модуля с приложением Android

После того, как был создан модуль, его необходимо поместить в пакет (“package”).

Создадим пакет в том же пространстве имен:

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 CustomPackage implements ReactPackage {      @Override     public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {         return Collections.emptyList();     }      @Override     public List<NativeModule> createNativeModules(             ReactApplicationContext reactContext) {         List<NativeModule> modules = new ArrayList<>();         modules.add(new CustomModule(reactContext));         return modules;     }  }

Интерфейс “ReactPackage” содержит два обязательных метода: “createNativeModules” и “createViewManagers”. View manager в коде RN — это компонент. Наш модуль будет использовать функции и не является ui компонентом Android и поэтому помещен в метод “createNativeModules”.

Примечание: один пакет может содержать несколько модулей.

Дальше, пакет необходимо связать с приложением Android следующим образом:

    //MainApplication.java  @Override     protected List<ReactPackage> getPackages() {       @SuppressWarnings("UnnecessaryLocalVariable")       List<ReactPackage> packages = new PackageList(this).getPackages();       packages.add(new CustomPackage());       return packages;     }

Использование модуля в коде Javascript

Теперь попробуем вызвать метод “show()” в приложении RN:

const App = () => {   NativeModules.ToastExample.show();   return (     <>       <StatusBar barStyle="dark-content" />       <SafeAreaView>         <ScrollView           contentInsetAdjustmentBehavior="automatic"           style={styles.scrollView}>           <Text>text</Text>         </ScrollView>       </SafeAreaView>     </>   ); };

Результат:

Обмен данными между приложениями RN и Android

Теперь, осуществим обмен данными между приложениями. Создадим в классе CustomModule два новых метода, для нахождения суммы:

      @ReactMethod     public void sum(int a, int b, Promise res) {         try {             res.resolve(a+b);         } catch (IllegalViewOperationException e) {             res.resolve(e);         }     }

@ReactMethod     public void sum(float a, float b, Callback success, Callback fail) {         try {             success.invoke((a+b));         } catch (IllegalViewOperationException e) {             fail.invoke(e.getMessage());         }     }

Переменные “a” и “b” будут приходить из кода Javascript и необходимо помнить про соответствие типов данных между Java и JS:

Примечание: так как типу Number соответствует сразу несколько типов из Java мы используем перегрузку, создав два метода с одним названием, но разными типами параметров.

Чтобы вернуть данные в код JS модуль com.facebook.react.bridge содержит типы Promise и CallBack.

Теперь используем метод в Js:

const showRes = async () => { const res = NativeModules.SendDataToRN.sum(400, 250);    alert(res); };  const App = () => {    React.useEffect(() => { 	showRes();    }, [])    return (     <>       <StatusBar barStyle="dark-content" />       <SafeAreaView>         <ScrollView           contentInsetAdjustmentBehavior="automatic"           style={styles.scrollView}>           <Text>text</Text>         </ScrollView>       </SafeAreaView>     </>   ); }; 

Результат:

Заключение

Материалы статьи можно использовать во всех ситуациях, когда api для rn еще не написано. Как видно из примеров, обмен данными между приложениями — достаточно простая операция, не требующая глубоких знаний программирования на Java.

ссылка на оригинал статьи https://habr.com/ru/post/511212/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *