Как у нас получился нативный модуль к React Native

    Если вы еще не знакомы с ReactJS или React Native, то очень рекомендуем ознакомиться, эти фреймворки уже сейчас оказывают значительное влияние на то, куда движется мир разработки мобильных и веб-приложений. Наша же статья о том, как дать возможность веб-разработчику делать приложения для iOS с аудио/видео звонками и другими прелестями платформы voximplant. Создание нативных модулей для React Native — это настолько обширная тема, что про нее можно писать бесконечно и материалов про нее в сети пока еще катастрофически мало. Мы при создании модуля опирались на ряд готовых примеров с github, которые очень помогли не закопаться с этим на века.



    Что такое React Native



    Подозреваю, что подавляющее большинство читателей хабра об этом знает. Но на всякий случа: это фреймворк от Facebook, который позволяет создавать native iOS приложения на javascript, при этом для создания пользовательского интерфейса используется не HTML, а ReactJS. Который, в свою очередь, создает “родные” виджеты операционной системы вместо HTML DOM. Более того, авторы обещают в будущем сделать то же самое и для Android.



    Что такое Native Modules



    В React Native есть уже ряд готовых модулей, которые идут в составе фреймворка и позволяют сделать очень много всего полезного, но, очевидно, далеко не все, что может захотеть разработчик мобильного приложения, и тут нам на помощь приходят native modules:

    “Sometimes an app needs access to platform API, and React Native doesn't have a corresponding module yet. Maybe you want to reuse some existing Objective-C, Swift or C++ code without having to reimplement it in JavaScript, or write some high performance, multi-threaded code such as for image processing, a database, or any number of advanced extensions.”


    Это именно наш случай, у нас в клиентском SDK voximplant есть множество штук, которые будут нормально работать только если написаны на достаточно низком уровне: видео/аудио кодеки, webrtc, srtp, ws и другие страшные слова. А разработчикам React Native приложений это все не очень интересно, они хотят иметь дело с понятным высокоуровневым javascript API, так как все их приложение это практиески сплошной javascript/jsx. Упаковка низкоуровневого кода в модуль React Native позволяет разработчикам фокусироваться на разработке приложений и не беспокоиться о магии под капотом.

    Архитектура нативного модуля



    Нативный модуль может содержать код на c/c++, на objective-c и на javascript. В низкоуровневый код мы вынесли сетевое взаимодействие с нашим облаком (c, c++, libwebrtc и небольшая кучка библиотек по мелочки) и отображение видео (objective-c). В высокоуровневый javascript код ушла обертка работы с облаком и два React виджета: один для предпросмотра собственного видео и второй для просмотра видео собеседника:



    Технически разделение на низкоуровневый и высокоуровневый код происходит следующим образом: вы создаете objective-c класс, наследуемый от предоставляемого React’ом класса RCTBridgeModule. Используя максросы вида RCT_EXPORT_METHOD вы задаете точки взаимодействия с javascript кодом, в то время как в objective-c коде можно взаимодействовать с операционной системой, c/c++ библиотеками, создавать “родные” iOS виджеты и делать другие нужные и полезные вещи.

    Готовый нативный модуль можно распространять разными способами, самый простой — это собрать исходники в виде .npm пакета и опубликовать его в репозитории. В таком случае для добавления модуля в свой проект достаточно сделать “npm install”, добавить .xcodeproj и собранную библиотеку (потому что пользователи ну явно не хотят собирать у себя libwebrtc с патчами — то еще удовольствие) и собрать свой проект.

    Функционал



    В нашем случае все просто — функционал модуля должен повторять функционал voximplant mobile sdk, то есть поддерживать как аудио, так и видео звонки через платформу, давать возможность включать/выключать громкий динамик, микрофон, менять камеру и т.д. В общем, никак не ограничивать разработчика из-за того, что он выбрал путь воина react native.





    Использование модуля в React Native приложении



    Инсталляция модуля выглядит достаточно просто, в директории проекта выполняем:

    npm install react-native-voximplant@latest --save
    


    После этого открываем свой проект в Xcode, в навигаторе проекта нажимаем правой кнопкой Add Files to, переходим в node_modules/react-native-voximplant и выбираем VoxImplant.xcodeproj.





    Далее в навигаторе проекта Xcode выбираем проект, переключаемся на закладку «Build Phases» и в разделе «Link Binary with Libraries» указываем GLKit.framework, libc++.dylib, libvoximplant.a и react-native-voximplant/VoxImplantSDK/libVoxImplantSDK.a





    В закладке «Build Settings» проверяем, что выбрано ‘All’ (а не ‘Basic’), находим Header Search Paths и удостовериваемся, что там есть $(SRCROOT)/../react-native/React и $(SRCROOT)/../../React и оба помечены как «recursive».

    Вот и все, дальше пишем свое приложение, которое использует подключенный модуль:

    немного кода
    var VoxImplant = require(‘react-native-voximplant’);
    
    // Adding SDK event listener
    RCTDeviceEventEmitter.addListener(
      'ConnectionSuccessful',
      () => {
       console.log('Connection successful');
      }
    );
    
    ...
    
    componentDidMount: function() {
        VoxImplant.SDK.connect();    
        VoxImplant.SDK.setCameraResolution(320,240);
      },
    
    …
    
    makeCall: function() {
        VoxImplant.SDK.createCall(number, settings_video, null, function(callId) {
          currentCallId = callId;      
          VoxImplant.SDK.startCall(callId);      
        });
    },
    
    ...
    



    Чтобы упростить задачу ознакомления с модулем мы сделали демо-приложение, которое можно взять с github и собрать, следуя инструкциям на странице. В результате получается:



    Заключение



    Многие критикуют React Native, говоря о производительности javascript относительно “родного” кода. На самом же деле такие технологии позволяют совместить лучшее из обоих миров: высокоуровневый и лаконичный javascript используется для кода логики приложения, в то время как низкоуровневый код на c/c++/objective-c используется для библиотек и критичных по скорости участков логики. Такой подход позволяет равномерно размазывать сложность по частям приложения, избегая ее скапливания в одном месте — что часто ведет к переусложненному и неподдерживаемому коду.

    Вопросы, комментарии, критика? Мы традиционно готовы общаться.
    • +20
    • 10,7k
    • 3
    Voximplant 125,32
    Облачная телеком-платформа
    Поделиться публикацией
    Комментарии 3
    • 0
      Хорошо, что вы трогаете новые технологии, это всегда полезно. Но я бы не делал ставку на React Native.

      высокоуровневый и лаконичный javascript

      тут я вообще могу спорить. Как по мне swift намного лаконичней и красивей. И компромиссов и скать не нужно.

      Я уверен, что у React Native будут свои поклонники, но не так и много.
      • 0
        Согласен, что делать ставку на что-то одно — это не очень перспективно. Поэтому мы стараемся предлагать наши решения для разных вариантов. Родные SDK для iOS и Android у нас тоже есть :)
      • +3
        А я просто оставлю это здесь.
        Учитывая компонентный подход, компоненты отрефайнят и будет нормальная кроссплатформенная JS тулза которой не стыдно пользоваться, по сравнению с Cordova которая имхо шлакъ.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое