Статьи

API доступа к платформе с помощью собственных модулей React

Эта статья была рецензирована Верной Анчетой . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!

React Native от Facebook — это дополнение к популярной библиотеке React JavaScript для создания собственных мобильных приложений. Он оказался более популярным, производительным и функциональным, чем другие фреймворки, но бывают случаи, когда его набор функций не хватает. В настоящее время React Native предлагает отличный способ создания собственных модулей для доступа к Native API, который еще не поддерживается. В этом уроке я покажу вам, как создавать модули React Native, которые предоставляют API Android MediaPlayer для реакции на Native.

Вы можете найти полный код проекта на GitHub .

Начало работы с React Native

SitePoint имеет полное руководство по установке React Native, доступное здесь . После установки создайте новый проект с помощью следующей команды:

 react-native init ReactNativeModuleTutorial 

Это создаст новую папку с именем ReactNativeModuleTutorial в вашем текущем рабочем каталоге. Перейдите в папку и запустите новый проект на своем устройстве или эмуляторе, используя следующую команду.

Примечание . Если вы используете эмулятор Android, вы должны запустить эмулятор перед запуском команды.

 react-native run-android 

Это создаст все необходимые файлы и папки в проекте, и вы должны увидеть следующий экран в вашем эмуляторе.

Скриншот приложения

Создание собственного модуля React Native для Android

Теперь, когда вы настроили проект, пришло время создать модуль React Native. Создайте новую папку с именем myaudiomodule в следующем каталоге:

ReactNativeModuleTutorial / Android / приложение / SRC / главная / Java / COM / reactnativemoduletutorial

Структура каталогов

Для создания простого нативного модуля вам нужно как минимум два файла.

  1. Реактивный пакет
  2. Java-класс, который расширяет ReactContextBaseJavaModule

Файл React Package обеспечивает упаковку различных модулей в один файл для последующего использования в коде JavaScript. Создайте файл с именем MyAudioPlayerPackage.java внутри папки myaudioplayer . Вам не нужно обращать особого внимания на этот файл, поскольку важной частью является добавление модуля (который вы вскоре создадите) в пакет внутри метода createNativeModules . Если вы решите создать несколько файлов модулей, вам нужно будет добавить и их здесь.

Добавьте следующее в MyAudioPlayerPackage.java :

 package com.reactnativemoduletutorial.myaudioplayer; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; 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 MyAudioPlayerPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new MyAudioPlayerModule(reactContext)); // adding the module to package return modules; } @Override public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } } 

Пришло время перейти к захватывающей части написания модуля, который вы будете использовать позже в коде JavaScript. Создайте другой файл в той же папке с именем MyAudioPlayerModule.java . В этом файле вы реализуете всю логику модуля и получите доступ к API-интерфейсам Android, которые еще не доступны в React Native.

 package com.reactnativemoduletutorial.myaudioplayer; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Callback; import java.util.Map; // these classes are required for playing the audio import android.media.MediaPlayer; import android.media.AudioManager; public class MyAudioPlayerModule extends ReactContextBaseJavaModule { private static MediaPlayer mediaPlayer = null; public MyAudioPlayerModule(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "MyAudioPlayer"; } } 

Пакет com.reactnativemoduletutorial.myaudioplayer поскольку вы находитесь в папке myaudioplayer . Вы также можете создать эти файлы в любом месте внутри папки responsenativemoduletutorial, если вы измените пакет соответствующим образом.

Сначала код импортирует все классы, необходимые для создания функциональности, которая нужна модулю. Каждый класс модуля расширяет ReactContextBaseJavaModule а для ReactContextBaseJavaModule требуется метод getName . Метод позволяет установить имя для модуля, используемого внутри кода JavaScript для доступа к модулю.

 @Override public String getName() { return "MyAudioPlayer"; } 

Методы, аннотированные @ReactMethod будут доступны в коде JavaScript, и эти методы моста всегда имеют возвращаемый тип void . Вы должны объявить каждый метод, который вы хотите использовать в коде JavaScript таким образом.

Я создал пару методов для воспроизведения аудио файла в модуле, но реализация аудио плеера зависит от вас, не стесняйтесь написать свой собственный код для плеера.

 @ReactMethod public void preparePlayer(String url) { try{ if (mediaPlayer != null) { mediaPlayer.release(); mediaPlayer = null; } mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(url); mediaPlayer.setLooping(true); mediaPlayer.prepareAsync(); }catch(Exception e){ } } @ReactMethod public void play() { try{ if (mediaPlayer != null) { if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } } }catch(Exception e){} } @ReactMethod public void pause(){ try{ if (mediaPlayer != null) { if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } }catch(Exception e){} } 

Код достаточно понятен, поскольку есть способы настройки аудиоплеера, воспроизведения и приостановки с использованием класса MediaPlayer доступного в Android.

Важной частью написания нативного модуля является создание методов, которые принимают методы обратного вызова, вызываемые после определенных задач. Вот как вы можете передавать значения из Java в JavaScript.

Создайте новый метод с именем setOnPreparedCallback который примет метод обратного вызова в качестве аргумента и вызовет этот обратный вызов, когда аудиофайл будет готов к воспроизведению.

 @ReactMethod public void setOnPreparedCallback(Callback onPrepared){ final Callback onPreparedCallback = onPrepared; try{ mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer player) { try{ onPreparedCallback.invoke(mediaPlayer.getDuration()); // invoking the callback with duration as argument }catch(Exception e){} } }); }catch(Exception e){} } 

Последний шаг — рассказать React Native о пакете. Отредактируйте файл MainApplication.java в ReactNativeModuleTutorial / android / app / src / main / java / com / реагировать на модуляцию /, чтобы импортировать MyAudioPlayerPackage.java из папки myaudioplayer .

 import com.reactnativemoduletutorial.myaudioplayer.MyAudioPlayerPackage; 

Обновите метод getPackages следующим образом:

 return Arrays.<ReactPackage>asList( new MainReactPackage() new MyAudioPlayerPackage() // the line added ); 

Теперь вы можете использовать модуль в приложении React Native. Откройте index.android.js в корне проекта и вставьте следующий код, заменив все, что уже есть. Я разработал простое приложение, которое имеет кнопки воспроизведения и паузы с 3 индикаторами текущего состояния приложения.

 import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, ToastAndroid, View, NativeModules, TouchableHighlight } from 'react-native'; var MyAudioPlayer = NativeModules.MyAudioPlayer; var buttonStyles = { marginTop: 8, backgroundColor: '#dddddd', padding: 10 }; var statStyle = { flex: 0.5, backgroundColor: '#cccccc', padding: 8, borderColor: '#ffffff', borderWidth: 1, margin: 2 }; class ReactNativeModuleTutorial extends Component { constructor(props){ super(props); this.state = { mp3Url: 'http://www.example.com/audio.mp3', prepared: false, playing: false, duration: 0 }; } componentDidMount(){ MyAudioPlayer.preparePlayer(this.state.mp3Url); MyAudioPlayer.setOnPreparedCallback((duration) => { this.setState({ prepared: true, duration: duration }); ToastAndroid.show('Audio prepared', ToastAndroid.LONG); }); } playSound(){ if (this.state.prepared === true) { this.setState({ playing: true }); MyAudioPlayer.play(); return true; } return false; } pauseSound(){ if (this.state.prepared === true && this.state.playing === true) { MyAudioPlayer.pause(); this.setState({ playing: false }) return true; } return false; } render() { return ( <View style={{ flex:1, alignItems: 'stretch', backgroundColor: '#F5FCFF' }}> <View style={{ padding: 10, backgroundColor: '#939cb0' }}> <Text style={{ color: '#ffffff', textAlign: 'center', fontSize: 24 }}>Audio Player</Text> </View> <View style={{ alignItems: 'flex-start', flexDirection: 'row', marginTop: 8 }}> <View style={statStyle}><Text style={{ textAlign: 'center' }}>Prepared : {(this.state.prepared) ? 'Yes' : 'No'}</Text></View> <View style={statStyle}><Text style={{ textAlign: 'center' }}>Playing : {(this.state.playing) ? 'Yes' : 'No'}</Text></View> <View style={statStyle}><Text style={{ textAlign: 'center' }}>Duration : {this.state.duration}</Text></View> </View> <View style={{ padding: 5 }}> <TouchableHighlight style={buttonStyles} onPress={this.playSound.bind(this)}> <Text style={{ textAlign: 'center' }}>Play</Text> </TouchableHighlight> <TouchableHighlight style={buttonStyles} onPress={this.pauseSound.bind(this)}> <Text style={{ textAlign: 'center' }}>Pause</Text> </TouchableHighlight> </View> </View> ); } } AppRegistry.registerComponent('ReactNativeModuleTutorial', () => ReactNativeModuleTutorial); 

Интерфейс приложения

Сначала импортируйте компонент NativeModule , поскольку он содержит только что созданный модуль и любые другие собственные модули.

Вы получили доступ к модулю, используя следующий код:

 var MyAudioPlayer = NativeModules.MyAudioPlayer; 

Теперь доступны все методы, определенные в модуле. Посмотрите на метод componentDidMount , где вы сначала MyAudioPlayer.preparePlayer проигрыватель, используя метод MyAudioPlayer.preparePlayer а затем устанавливаете метод обратного вызова для OnPreparedListener .

 componentDidMount(){ MyAudioPlayer.preparePlayer(this.state.mp3Url); MyAudioPlayer.setOnPreparedCallback((duration) => { this.setState({ prepared: true, duration: duration }); ToastAndroid.show('Audio prepared', ToastAndroid.LONG); }); } 

Кроссплатформенный родной мост

Создавая собственные модули React Native, вы получаете возможность связать встроенную функциональность Android (и iOS) с кроссплатформенной кодовой базой. Вы должны понимать кодирование для своей исходной кодовой базы по своему выбору, но, тем самым, помогите разработчикам React Native получить доступ к новым функциям и возможностям.

Вы когда-нибудь создавали свой собственный модуль React Native? Что вы сделали и как вы нашли процесс?