Loading...

Make Access Platform APIs with React Native Modules

View: 22342    Dowload: 0   Comment: 0   Post by: hanhga   Category: Android   Fields: Other

SitePoint has a full guide for installing React Native available here. Once it’s installed, create a new project with the following command:

react-native init ReactNativeModuleTutorial

This will create a new folder named ReactNativeModuleTutorial in your current working directory. Navigate to the folder and run the new project on your device or emulator using the following command.

react-native run-android

Creating a React Native Android Native Module

Now that you have set the project up, it’s time to create a React Native module. Create a new folder named myaudiomodule in the following directory:

ReactNativeModuleTutorial/android/app/src/main/java/com/reactnativemoduletutorial

 

To create a simple native module you need to at least two files.

  1. React Package class
  2. A java class that extends ReactContextBaseJavaModule

The React Package file takes care of packaging different modules together in one file to used later in JavaScript code. Create a file named MyAudioPlayerPackage.java inside the myaudioplayer folder. You don’t have to pay much attention to this file as the important part is to add the module (that you will create shortly) to the package inside the createNativeModules method. If you decide to create multiple module files then you will need to add those here as well.

Add the following to 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();
    }
}

It’s time to move on to the exciting part of writing the module that you will use later in the JavaScript code. Create another file in the same folder named MyAudioPlayerModule.java. In this file you will implement all the logic of the module and to access the Android API’s that are not yet available in 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";
   }

}

The package is com.reactnativemoduletutorial.myaudioplayer since you are inside themyaudioplayer folder. You can also create these files anywhere inside the reactnativemoduletutorial folder if you change the package accordingly.

The code first imports all the classes needed to create the functionality the module needs. Every module class extends ReactContextBaseJavaModule and ReactContextBaseJavaModule requires thegetName method. The method allows you to set a name for the module used inside the JavaScript code to access the module.

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

The methods annotated with @ReactMethod will be accessible in the JavaScript code and these bridge methods are always of return type void. You must declare every method you want to use in the JavaScript code this way.

I have created a couple of methods for playing the audio file in the module but the implementation of the audio player is up to you, feel free to write your own code for the player.

@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){}
}

The code is reasonably self-explanatory with methods for setting up the audio player, playing and pausing using the MediaPlayer class available in Android.

The vital part of writing a native module is creating methods that accept callback methods invoked after certain tasks. This is how you can pass values from Java to JavaScript.

Create a new method called setOnPreparedCallback which will take a callback method as an argument and will fire this callback when the audio file is ready to play.

@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){}
}

The last step is to tell React Native about the package. Edit MainApplication.java inReactNativeModuleTutorial/android/app/src/main/java/com/reactnativemoduletutorial/ to importMyAudioPlayerPackage.java from the myaudioplayer folder.

import com.reactnativemoduletutorial.myaudioplayer.MyAudioPlayerPackage;

Update the getPackages method to the following:

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

Now you can use the module in the React Native application. Open index.android.js in the root of the project and paste the following code in, replacing anything that is already there. I have designed a simple application that has play and pause buttons with 3 indicators of the current state of the application.

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);

First import the NativeModules component, as it contains the module that just created and any other native modules.

var MyAudioPlayer  = NativeModules.MyAudioPlayer;

Now all the methods defined in the module are available. Look at the componentDidMount method, where you prepare the player first using MyAudioPlayer.preparePlayer method and then set the callback method for OnPreparedListener.

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

A Cross-Platform Native Bridge

By creating your own React Native modules you have the possibility to bridge native Android (and iOS) functionality to a cross-platform codebase. You need to understand coding for your native codebase of choice, but by doing so help React Native developers access new functionality and possibilities.

Make Access Platform APIs with React Native Modules

SitePoint has a full guide for installing React Native available here. Once it’s installed, create a new project with the following command

Posted on 16-07-2016 

Comment:

To comment you must be logged in members.

Files with category

 
File suggestion for you
Loading...
File top downloads
Loading...
Loading...
Codetitle - library source code to share, download the file to the community
Copyright © 2018. All rights reserved. codetitle Develope by Vinagon .Ltd