preface

This paper summarizes the practical project of React Native. Based on the differences between React Native and H5 in development efficiency, functional performance, user experience and other aspects, the functional module is carefully designed, mainly based on the business of our current actual project and combined with the unique features of mobile terminal.

This paper focuses on the environment configuration and operation of React Native project, introduction of React Native, main functions of the project, and drawbacks of React Native development. If you don’t have React Native development experience, this article will give you a good overview of React Native, including official documentation, ecology, compatibility, etc. Hopefully you’ll find the answers you need in this article.

Hard to sort out for a long time, but also hope to manually praise encouragement ~

Blog github address: github.com/fengshi123/… , a summary of all the author’s blogs, also welcome to follow and star ~

The github address of this project is: github.com/fengshi123/…

The github address of the supporting server Express project is github.com/fengshi123/…

First, start the project

1.1. Environment Configuration

In the React Native App development, the configuration of my development environment is as follows:

names The version number
node.js 11.12.0
npm 6.7.0
yarn 1.17.3
Android Studio 3.4.1 track
JDK 1.8
react 16.8.6
react-native 0.60.5

1.2. Run the project

(1) Install yarn and React-native command-line tools

$ npm install -g yarn react-native-cli
Copy the code

(2) Set the YARN mirroring source

$ yarn config set registry https://registry.npm.taobao.org --global
$ yarn config set disturl https://npm.taobao.org/dist --global
Copy the code

(3) Install third-party plug-ins

Go to the react_native_project directory and install the third-party plug-in:

$ yarn
Copy the code

(4) Android Studio configuration

The react-Native version of Android Studio is not available here.

(5) Compile and run the project

$ react-native run-android
Copy the code

(6) Start the project

If Metro is not started after step 5, you can close the Node window opened in step 5 and restart Metro:

npm start
Copy the code

(7) Supporting projects of the server

Remember to clone the server Express project that comes with this project and start it.

React Native

“Learn once, write anywhere”, React Native is defined as: Learn React and master both web and APP development skills. React Native uses the React design model, which allows developers to write JS code and convert it into Native controls and operations through the React Native middle layer, providing a user experience close to Native development. Here are four features from the official website:

(1) Write native mobile apps using JavaScript and React

React Native lets you write Native mobile apps using only JavaScript. It is designed in the same way as React, using declarative component mechanisms to build a rich user interface.

(2) React Native is a true mobile app

React Native doesn’t produce “web apps,” or “HTML5 apps,” or “hybrid apps.” The end product is a true mobile application that is almost indistinguishable from an application written in Objective-C or Java. React Native uses the same basic UI components as Native apps. All you have to do is combine these basic components using JavaScript and React.

(3) Don’t wait to compile

React Native lets you develop your app iteratively and quickly. Instead of the lengthy compilation process of traditional native apps, you can now refresh your app in an instant. With Hot Reloading enabled, you can even hot-replace new code while keeping your application running!

(4) Call native foreign aid at any time

React Native is perfectly compatible with components written in Objective-C, Java, or Swift. If you need to optimize for a particular part of your application, it’s easy to switch to native code halfway through. It’s also perfectly fine to use React Native for part of your application.

Iii. Project functions

3.1. Functional design

Considering the difference between React Native and H5 in development efficiency, function performance, user experience and other aspects, we designed the function module carefully, mainly based on the business of our current actual project and combined with the unique features of mobile terminal. The functional design of relevant modules is shown in the figure below.

3.2 display of functional interfaces

Some features are captured below:

3.3 Project structure Directory

Our project directory structure is as follows:

> ├─.vscode Editor Settings > ├─ Android Native > ├─ ios Native > ├─ Node_modules > ├─ SRC Code home directory > │ ├─assets To store style files ├─ styles > │ │ ├─ style ├─ ├─ ├.js > │ │ ├─ ├.js │ ├─ ├─ Pages > │ │ ├─ Pages > │ │ ├─ Components > │ ├─ Navigation > │ │ ├─ index. ├─ exercises - ├─ constant. Js │ ├─ constant. Server IP port, etc > │ │ ├ ─ globalVar. Js some global variables > │ │ └ ─ request. Js ajax request > ├ ─. Eslintrc. Js eslint configuration > ├ ─. Gitignore. Js git Ignore Configuration > ├─index.js project entry > ├─package.json Project depends on package configurationCopy the code

3.4. Main functions

3.4.1 Web disk Function

This module contains functions: folder creation, rename, file upload, download, side slide operation, long press list operation, drop down refresh operation, file preview (including pictures) and so on.

3.4.1.1 Holding down the File List

(1) Use plug-ins

react-native-popup-menu
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-popup-menu
Copy the code
  • Logic implementation

In react_native_project/SRC/pages/netDisk/netDisk js for corresponding logic components, key code and comments are as follows:

// Plug-in import
import {
    Menu,
    MenuProvider,
    MenuOptions,
    MenuOption,
    MenuTrigger,
  } from 'react-native-popup-menu';

// render<MenuProvider> <Menu> <MenuTrigger onAlternativeAction={() => this.getDirFile(rowData.item)} triggerOnLongPress={true} customStyles={triggerStyles}> <Image source={ rowData.item.icon } style={styles.thumbnail} /> <View> <Text>{rowData.item.name}</Text> <Text>{dayjs(rowData.item.time).format('YYYY-MM-DD HH:mm:ss')}</Text> </View> <View> { rowData.item.type === 'dir'? <NBIcon type="AntDesign" name="right"/> : Null} </View> </MenuTrigger> <MenuOptions customStyles={optionsStyles}> <MenuOption value={1} text=' rename 'onSelect={() => {this.setState({ modalVisible: true, fileItem: rowData.item, dialogType: 'Rename', hasInputText: true, inputVal: rowData.item.name, isSideSlip: false }); }}/> <MenuOption value={2} text=' delete 'onSelect={() => {this.setState({modalVisible: true, fileItem: Rowdata. item, dialogType: 'Delete', confirmText: 'Confirm deletion? ', hasInputText: false, isSideSlip: false }); }}/> <MenuOption value={3} text=' download 'onSelect={() => this.downloadFile(rowdata.item)} disabled={rowdata.item.type === 'dir'}/> </MenuOptions> </Menu> </MenuProvider>Copy the code

(3) Matters needing attention

  • TriggerOnLongPress, when set to true, long presses to display the drop-down menu, in which case the onAlternativeAction method can be used to trigger a single entry to a folder or file preview.

(4) Reference documents

  • Github address: github.com/instea/reac…
3.4.1.2 File Sideslip Operations

(1) Use plug-ins

react-native-swipe-list-view
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-swipe-list-view
Copy the code
  • Logic implementation

In react_native_project/SRC/pages/netDisk/netDisk js for corresponding logic components, key code and comments are as follows:

// Plug-in import
import { SwipeListView } from 'react-native-swipe-list-view/lib/index';

// render
<SwipeListView
    style={styles.list}
    data={this.state.filesList}
    renderItem={ (rowData) => (
        <TouchableHighlight
            style={styles.rowFront}
            underlayColor={'#AAA'}
        >
            <View style={{flexDirection:'row',flex: 1.alignItems:'center'}} >
                <Text>{rowData.item.name}</Text>
            </View>
        </TouchableHighlight>
    )}
    renderHiddenItem={ (rowData, rowMap) => {
    return (
        <View style={styles.standaloneRowBack} key={rowData.item.time}>
            <NbButton style={[styles.backRightBtn, styles.backRightBtnLeft]} onPress={()= >{ this.setState({ modalVisible: true, fileItem: rowData.item, fileIndex: rowData.item.key, fileRowMap: rowMap, dialogType: 'Rename', hasInputText: true, inputVal: rowData.item.name, isSideSlip: true }); }} ><Text style={styles.backTextWhite}>rename</Text>
            </NbButton>
            <NbButton style={[styles.backRightBtn, styles.backRightBtnRight]} onPress={()= >{ this.setState({ modalVisible: true, fileItem: rowData.item, fileIndex: rowData.item.key, fileRowMap: RowMap, dialogType: 'Delete', confirmText: 'Confirm Delete? ', hasInputText: false, isSideSlip: true }); }} ><Text style={styles.backTextWhite}>delete</Text>
            </NbButton>
        </View>); } } rightOpenValue={- 150.}
    stopRightSwipe={- 150.}
    disableRightSwipe={true}
    swipeToOpenPercent={20}
    swipeToClosePercent={0} / >Copy the code

(3) Matters needing attention

  • After sideslip operation, remember to close sideslip
  // Close sideslip
  closeRow(rowMap, rowKey) {
        if(rowMap[rowKey]) { rowMap[rowKey].closeRow(); }}Copy the code

(4) Reference documents

  • Github address: github.com/jemise111/r…
3.4.1.3 Downloading Files

(1) Use plug-ins

rn-fetch-blob
Copy the code

(2) Function realization

  • Plug-in installation
yarn add rn-fetch-blob
Copy the code
  • recompile

After configuring the plug-in, you need to recompile Android because it involves native Android features.

  • Logic implementation

In react_native_project/SRC/pages/netDisk/netDisk js for corresponding logic components, key code and comments are as follows:

// Plug-in import
import RNFetchBlob from 'rn-fetch-blob';

// Download method
 async actualDownload(item) {
    let dirs = RNFetchBlob.fs.dirs;
    const android = RNFetchBlob.android;
    RNFetchBlob.config({
        fileCache : true.path: `${dirs.DownloadDir}/${item.name}`.// android only options, these options be a no-op on IOS
        addAndroidDownloads : {
          // Show notification when response data transmitted
          notification : true.// Title of download notification
          title : 'Download completed'.// File description (not notification description)
          description : 'An file.'.mime : getMimeType(item.name.split('. ').pop()),
          // Make the file scannable by media scanner
          mediaScannable : true,
        }
      })
      .fetch('GET'.`${CONSTANT.SERVER_URL}${item.path}`)
      .then(async(res) => {
            await android.actionViewIntent(res.path(), getMimeType(item.name.split('. ').pop()));
        });
 }

Copy the code

(3) Matters needing attention

  • The downloaded file cannot be opened
/ / the problem
So basically this needs to be added to line 122- 123. of file android/src/main/java/com/RNFetchBlob/RNFetchBlob.java:
// The solution
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
If above is not working do to the below step: overwrite the 121 line in android/src/main/java/com/RNFetchBlob/RNFetchBlob.java:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 121 line
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 122 line

Copy the code

(4) Reference documents

  • Github address: github.com/eventsPorta…
3.4.1.4 Uploading files

(1) Use plug-ins

// Get the local file
react-native-file-selector
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-file-selector
Copy the code
  • recompile

Since the plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

In react_native_project/SRC/pages/netDisk/netDisk js for corresponding logic components, key code and comments are as follows:

// Plug-in import
import RNFileSelector from 'react-native-file-selector';

// Select the file and upload it
RNFileSelector.Show(
    {
        title: 'Please select file'.onDone: (filePath) = > {
            let data = new FormData();
            let file = { uri: 'file://' + filePath, type: 'multipart/form-data'.name: escape(path.basename(filePath))};
            data.append('file', file);
            let options = {
                url: '/files/uploadFile'./ / request url
                data: data,
                tipFlag: true.// The default prompt is unified. If a custom prompt is required, pass true
            };
            request(options).then(async (res) => {
                if (res.status == 200) {
                    await this.fetchData();
                    ToastAndroid.show(
                        'Upload successful', ToastAndroid.SHORT, ToastAndroid.CENTER ); }}); },onCancel: (a)= > {
            ToastAndroid.show(
                'Cancel upload', ToastAndroid.SHORT, ToastAndroid.CENTER ); }});Copy the code

(3) Matters needing attention

  • To avoid inconsistent file names after Chinese character files are uploaded, you can use escape and unescape to encode and decode them.

(4) Reference documents

  • React-native file-selector plugin: github.com/prscX/react
3.4.1.5 Previewing Files (TXT, Office Files, PDF, etc.)

(1) Use plug-ins

react-native-doc-viewer
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-doc-viewer
Copy the code
  • recompile

Since the plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

In react_native_project/SRC/pages/netDisk/netDisk js for corresponding logic components, key code and comments are as follows:

// Plug-in import
import OpenFile from 'react-native-doc-viewer';

// File preview
OpenFile.openDoc([{
    url: `${CONSTANT.SERVER_URL}${item.path}`.fileName: item.name.split('. ').shift(),
    cache: false.fileType: item.name.split('. ').pop()
}], (error) => {
    if (error) {
        this.setState({ animating: false });
        console.log(error);
        ToastAndroid.show('Please install relevant application software first', ToastAndroid.SHORT);
    } else {
        this.setState({ animating: false });
        // toastAndroid.show (' this file does not support preview ', toastAndroid.short);}});Copy the code

(3) Matters needing attention

  • innode_modules/react-native-doc-viewer/android/src/main/java/com/reactlibrary/RNReactNativeDocViewerModule.javaDelete from fileimport com.facebook.react.views.webview.ReactWebViewManager;

(4) Reference documents

  • The react-native doc-viewer plugin is available at github.com/philipphech…
3.4.1.6 Image Preview

(1) Use plug-ins

react-native-image-zoom-viewer
Copy the code

(2) Function realization

  • Plug-in installation
react-native-image-zoom-viewer
Copy the code
  • Logic implementation

In react_native_project/SRC/pages/netDisk/netDisk js for corresponding logic components, key code and comments are as follows:

// Plug-in import
import ImageViewer from 'react-native-image-zoom-viewer';

// Image preview method
saveImg(url) {
    let promise = CameraRoll.saveToCameraRoll(url);
    promise.then((result) = > {
        console.log(result);
        ToastAndroid.show('Saved to album', ToastAndroid.SHORT);
        }).catch((error) = > {
        console.log(error);
        ToastAndroid.show('Save failed', ToastAndroid.SHORT);
        });
}
// render
<Modal
    transparent={true}
    visible={imgModalVisible}
    onRequestClose={() => this.props.closeImg()}>
    <ImageViewer
        onCancel={()= >this.props.closeImg()} onClick={(onCancel) => {onCancel(); }} onSave={(url) => this.saveImg(url)} saveToLocalByLongPress={true} imageUrls={images} index={imgIndex} DoubleClickInterval ={1000} menuContext={{'saveToLocal': 'Save to album ', 'cancel': 'cancel'}}/></Modal>
Copy the code

(3) Matters needing attention

  • This plug-in “photo albums to” method is only applicable to the native preview picture, the remote picture can save method react – native bring method CameraRoll. SaveToCameraRoll (url).

(4) Reference documents

  • The react-native image-zoom-viewer plugin is available at github.com/ascoders/re…

3.4.2 Audio-visual learning

This module contains the following functions: audio/video uploading, downloading, deleting, judging the network, playing, full screen playing, turning to full screen playing, commenting, sharing and so on. The functions of uploading, downloading and deleting are explained in the web disk module and the test module.

3.4.2.1 Video Playing Function

(1) Use plug-ins

react-native-video
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-video
Copy the code
  • recompile

Since the plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

In react_native_project/SRC/pages/video/VideoPlayer js component implementation logic, corresponding key code and comments are as follows:

// Plug-in import
import Video from 'react-native-video';

// Video schedule time method
function formatTime(second) {
  let h = 0, i = 0, s = parseInt(second);
  if (s > 60) {
    i = parseInt(s / 60);
    s = parseInt(s % 60);
  }
  / / zero padding
  let zero = function (v) {
    return (v >> 0) < 10 ? '0' + v : v;
  };
  return [zero(h), zero(i), zero(s)].join(':');
}

// render
// See API for parameters and methods
<Video
    ref={(ref) => this.videoPlayer = ref}
    source={{uri: CONSTANT.SERVER_URL + '/' + this.state.videoUrl}}
    rate={this.state.playRate}
    volume={this.state.volume}
    muted={this.state.isMuted}
    paused={!this.state.isPlaying}
    resizeMode={'contain'}
    playWhenInactive={false}
    playInBackground={false}
    ignoreSilentSwitch={'ignore'}
    progressUpdateInterval={250.0}
    onLoadStart={this._onLoadStart}
    onLoad={this._onLoaded}
    onProgress={this._onProgressChanged}
    onEnd={this._onPlayEnd}
    onError={this._onPlayError}
    onBuffer={this._onBuffering}
    style={{ width: this.state.videoWidth, height: this.state.videoHeight}}
/>

Copy the code

(3) Reference documents

  • The react-native video plugin is available at github.com/react-nativ…
3.4.2.2 Video maximization and steering

(1) Use plug-ins

react-native-orientation
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-orientation
Copy the code
  • recompile

Since the plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

In react_native_project/SRC/pages/video/VideoPlayer js component implementation logic, corresponding key code and comments are as follows:

// Plug-in import
import Orientation from 'react-native-orientation';

// Click the full-screen button on the toolbar
  onControlShrinkPress() {
    if (this.state.isFullScreen) {
      Orientation.lockToPortrait();
    } else{ Orientation.lockToLandscapeRight(); }}// As the screen rotates, the width and height will change. This can be handled in the onLayout method, which can obtain the width and height change more timely than monitoring the screen rotation
  _onLayout = (event) = > {
    // Get the width and height of the root View
    let {width, height} = event.nativeEvent.layout;
    // The width of the horizontal screen is larger than the height of the horizontal screen
    let isLandscape = (width > height);
    if (isLandscape && !this.showKeyboard){
      this.setState({
        videoWidth: width,
        videoHeight: height,
        isFullScreen: true}); }else {
      this.setState({
        videoWidth: width,
        videoHeight: width * 9/16.isFullScreen: false}); } Orientation.unlockAllOrientations(); };Copy the code

(3) Reference documents

  • Github address: github.com/yamill/reac…
3.4.2.3 Sharing on wechat and Moments

(1) Use plug-ins

react-native-wechat
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-wechat
Copy the code
  • recompile

Since the plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

In react_native_project/SRC/components/video/VideoShare js component implementation logic, corresponding key code and comments are as follows:

// Plug-in import
import * as WeChat from 'react-native-wechat';

// const wxAppId = ''; // App ID registered on wechat open platform
// const wxAppSecret = ''; // App secret registered on wechat open platform
// WeChat.registerApp(wxAppId);

/ / share
shareItemSelectedAtIndex(index) {
    // this.props.onShareItemSelected && this.props.onShareItemSelected(index);
    WeChat.isWXAppInstalled().then((isInstalled) = > {
        this.setState({
          isWXInstalled: isInstalled
        });
        if (isInstalled && index === 0) {
          WeChat.shareToSession({
                title: this.state.videoTitle,
                type: 'video'.videoUrl: CONSTANT.SERVER_URL + '/' + this.state.videoUrl
            }).catch((error) = > {
                console.log(error.message);
            });
        } else if (isInstalled && index === 1) {
            WeChat.shareToTimeline({
                  title: this.state.videoTitle,
                  type: 'video'.videoUrl: CONSTANT.SERVER_URL + '/' + this.state.videoUrl
              }).catch((error) = > {
                  console.log(error.message);
              });
          } else {
          console.log('wechat is not installed'); }}); }Copy the code

(3) Reference documents

  • Github address: github.com/yamill/reac…
  • WeChat platform registered reference: www.jianshu.com/p/6a792118f…

3.4.3 Test module

3.4.3.1 Take photos & upload pictures to create test questions

(1) Use plug-ins

react-native-image-crop-picker 
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-image-crop-picker 
Copy the code
  • recompile

Since the plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

In react_native_project/SRC/components/exam/ImageAudioTab js component implementation logic, corresponding key code and comments are as follows:

// Plug-in import
import ImagePicker from 'react-native-image-crop-picker';

// Select the image from the album
ImagePicker.openPicker(paramObj).then(image= > {
	this.props.handleImage(qsIndex, image);
}).catch(err= > {
	console.log(err);
});

// Invoke the camera function
openCamera(qsIndex) {
	ImagePicker.openCamera({
		width: 300.height: 400.cropping: true,
	}).then(image= > {
		this.props.handleImage(qsIndex, image);
	}).catch(err= > {
		console.log(err);
	});
}
Copy the code

(3) Matters needing attention

  • When taking photos or selecting only one picture at a time, the cropping operation can be carried out. When selecting multiple pictures at a time, the cropping operation cannot be carried out.

(4) Reference documents

  • React-native image-crop-picker plugin: github.com/ivpusic/rea…
3.4.3.2 Voice entry create test questions function

(1) Use plug-ins

react-native-audio // Voice input
react-native-sound // Voice playback
react-native-spinkit // Animation effect
Copy the code

(2) Function realization

  • Plug-in installation
yarn add react-native-audio react-native-sound react-native-spinkit
Copy the code
  • recompile

Since the voice input plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

In react_native_project/SRC/components/exam/ImageAudioTab js component implementation logic, corresponding key code and comments are as follows:

// Plug-in import
import { AudioRecorder, AudioUtils } from 'react-native-audio';
import Sound from 'react-native-sound';
import Spinkit from 'react-native-spinkit';

// Audio path configuration
prepareRecordingPath = (path) = > {
	const option = {
		SampleRate: 44100.0./ / sampling rate
		Channels: 2./ / channel
		AudioQuality: 'High'./ / sound quality
		AudioEncoding: 'aac'.// Audio encoding
		OutputFormat: 'mpeg_4'.// Output format
		MeteringEnabled: false.// Whether to measure
		MeasurementMode: false.// Measurement mode
		AudioEncodingBitRate: 32000.// Audio encoding bit rate
		IncludeBase64: true.// Whether it is base64 format
		AudioSource: 0./ / audio source
	};
	AudioRecorder.prepareRecordingAtPath(path, option);
}

// Start recording
startSoundRecording(qsIndex, stemAudio) {
	if (stemAudio.length >= 5) {
		ToastAndroid.show('No more than 5 sounds per question.', ToastAndroid.SHORT);
		return;
	}
	console.log('startSoundRecording.... ');
	// Request authorization
	AudioRecorder.requestAuthorization()
		.then(isAuthor= > {
			if (isAuthor) {
				this.prepareRecordingPath(this.audioPath + qsIndex + '_' + stemAudio.length + '.aac');
				// Recording progress
				AudioRecorder.onProgress = (data) = > {
					this.recordTime = Math.floor(data.currentTime);
				};
				// Complete the recording
				AudioRecorder.onFinished = (data) = > {
					// data Returns the recording data to be uploaded to the background.
					this.isRecording = false;
					if (!this.recordTime) {
						ToastAndroid.show('The recording time is too short... ', ToastAndroid.SHORT);
						return;
					}
					this.props.handleAudio(qsIndex, data.audioFileURL, this.recordTime);
					// Reset to 0
					this.recordTime = 0;
				};
				/ / the recording
				AudioRecorder.startRecording();
				this.isRecording = true; }}); }// End the recording
stopSoundRecording() {
	console.log('stopSoundRecording.... ');
	// Has been intercepted by throttling operation, not recording
	if (!this.isRecording) {
		return;
	}
	AudioRecorder.stopRecording();
}

// Play the recording
playSound(qsIndex, index, stemAudio, audioFlag, path) {
	this.props.changeAudioState(qsIndex, index, 2);
	let whoosh = new Sound(path.slice(7), ' ', (err) => {
		if (err) {
			return console.log(err);
		}
		whoosh.play(success= > {
			if (success) {
				console.log('success - Playback succeeded ');
			} else {
				console.log('fail - playback fails');
			}
			this.props.changeAudioState(qsIndex, index, 1);
		});
	});
}
Copy the code

(3) Matters needing attention

  • If there is no throttling operation for voice recording, it will lead to recording errors by repeatedly clicking start recording and end recording within a short period of time. Therefore, we listen to the user’s long press operation, and then turn on the recorder of the mobile phone and start recording.

(4) Reference documents

  • React-native Audio is available at github.com/jsierles/re… ;
  • The react-native-sound plugin is available at github.com/zmxv/react-… ;
  • The react-native spinkit plugin is available at github.com/maxs15/reac… ;
3.4.3.3 Chart achievement statistics

(1) Use plug-ins

victory-native // Icon drawing plugin
react-native-svg // draw SVG images
Copy the code

(2) Function realization

  • Plug-in installation
yarn add victory-native react-native-svg
Copy the code
  • recompile

Since the plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

In react_native_project/SRC/pages/exam/ResultStatistics js component implementation logic, corresponding key code and comments are as follows:

// Plug-in import
import { 
  VictoryPie, 
  VictoryLegend, 
  VictoryTooltip 
} from 'victory-native';

// Use the graphics drawing component
<VictoryLegend
	orientation="vertical"
	data={[
	  {
		name: 'Fail < 60 marks'.symbol: { fill: colorScale[0].type: 'square'}, {},name: 'Pass 60-75'.symbol: { fill: colorScale[1].type: 'square'}, {},name: 'Good 75-85'.symbol: { fill: colorScale[2].type: 'square'}, {},name: 'Excellent > 85 points'.symbol: { fill: colorScale[3].type: 'square' },
	  }
	]}
	width={180}
	height={125} /> <VictoryPie colorScale={colorScale} data={[ { y: this.state.result[3], label: 'fail:' + this. State. The result of [3] + 'people'}, {y: this. State. The result [2], the label: 'failed:' + this. State. The result of [2] + 'people'}, {y: This.state. result[1], label: 'good :' + this.state.result[1] +' person '}, {y: this.state.result[0], label: } innerRadius={60} height={300} width={345} animate={{duration: 2000 }} labelComponent={ <VictoryTooltip active={({ datum }) => datum.y === 0 ? False: true} constrainToVisibleArea={true} flyoutHeight={30} flyoutStyle={{strokeWidth: 0.1} />} />Copy the code

(3) Matters needing attention

  • no

(4) Reference documents

  • Github address for victory-Native plugin: github.com/FormidableL… ;
  • The react-native-SVG plugin is available at github.com/react-nativ… ;
  • Specific documentation for victory-Native: formidable.com/open-source… ;

3.4.4, other

3.4.4.1 Call & SMS function

(1) Use plug-ins

  Linking  // React Native plugin
Copy the code

(2) Function realization

  • Logic implementation

In react_native_project/SRC/components/user/ListItem. Js component implementation logic, corresponding key code and comments are as follows:

// Call or SMS function
call(flag) {
let tel = flag === 1 ? 'tel:10086' : 'smsto:10086';
Linking.canOpenURL(tel).then(supported= > {
  if(! supported) { ToastAndroid.show.show('You have not authorized call and SMS rights');
  } else {
	return Linking.openURL(tel);
  }
}).catch(err= > console.error('An error occurred', err));
}
Copy the code

(3) Matters needing attention

  • no

(4) Reference documents

  • Address: Linking components document reactnative. Cn/docs/linkedin…
3.4.4.2 Mobile phone positioning function

(1) Use plug-ins

  • No, encapsulate the Android native method for implementation;

(2) Function realization

  • Gets the logical implementation of the positioning function

In react_native_project/android/app/SRC/main/Java/com/react_native_project/module directory to create the implementation class LocationModule. Java, It’s important to note that the class needs to implement ReactContextBaseJavaModule this class:

public class LocationModule extends ReactContextBaseJavaModule {
    private final ReactApplicationContext mContext;
    public LocationModule(ReactApplicationContext reactContext) {
        super(reactContext);
        mContext = reactContext;
    }

    /** * @return js to call the module name */
    @Override
    public String getName() {
        return "LocationModule";
    }


    /** * use the ReactMethod annotation to make the method called by js */
    @ReactMethod
    public void getLocation(Callback locationCallback) {
            // Omit some logic implementation...
            locationCallback.invoke(lat,lng,country,locality);
        }else{
            locationCallback.invoke(false); }}}Copy the code
  • Module registration

Register the module that just implemented the location function, In react_native_project/android/app/SRC/main/Java/com/react_native_project/module directory created in the registration package management class LocationReactPackage. Java, The logic is as follows:

public class LocationReactPackage implements ReactPackage {
    /** * @param reactContext context * @return the native control to call */
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    /** * @param reactContext context * @return the native module to call */
    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new LocationModule(reactContext));
        returnmodules; }}Copy the code
  • Add a package management class

In react_native_project/android/app/SRC/main/Java/com/react_native_project MainApplication. Java package management class is added, the related logic is as follows:

protected List<ReactPackage> getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  List<ReactPackage> packages = new PackageList(this).getPackages();
  packages.add(new LocationReactPackage());
  return packages;
}
Copy the code
  • React Native uses encapsulation classes

We in react_native_project/SRC/components/user/ListItem. Js for corresponding logic components, key code and comments are as follows:

import { NativeModules } from 'react-native';

// Get the location
showLocation() {
 NativeModules.LocationModule.getLocation((lat, lng, country, locality) = > {
  let str = 'Failed to get location information, you may not have mobile phone location information enabled! ';
  if (lat && lng) {
	str = country + ', ' + locality + ', latitude: ' + lat + ', ' + 'longitude:' + lng;
  }
  ToastAndroid.show(str, ToastAndroid.SHORT);
 });
}
Copy the code

(3) Matters needing attention

  • Because this function is encapsulated by the Android native code, so the encapsulation of the Android native class, need to compile, and then call in the JS side, to have the effect.

(4) Reference documents

  • Relevant reference documents address: www.cnblogs.com/weschen/p/8…
3.4.4.3 Online Upgrade

(1) Use plug-ins

rn-fetch-blob
Copy the code

(2) Function realization

  • Plug-in installation
yarn add rn-fetch-blob
Copy the code
  • recompile

Since the plug-in involves native Android features, you need to recompile Android after adding the plug-in.

  • Logic implementation

The general logic of our online upgrade function is to upload the APK installation package at the APP management end and click Publish. At this time, the server will notify the APP of the latest release version through Websocket. The APP will receive the latest version number and compare it with the current app version. If the current version is smaller than the latest version, the latest version is displayed, asking the user whether to install the latest version. If the user confirms to install the latest version, the user downloads the latest APK from the server and installs it. In react_native_project/SRC/components/user/ListItem. Js component implementation logic, corresponding key code and comments are as follows:

import RNFetchBlob from 'rn-fetch-blob';

  checkUpdate = (a)= > {
    const android = RNFetchBlob.android;
    // Path of the downloaded file
    const downloadDest = `${ RNFetchBlob.fs.dirs.DownloadDir }/app_release.apk`;

    RNFetchBlob.config({
      // Configure the notification bar for downloading files. After downloading files successfully, click the notification to run apK files
      addAndroidDownloads: {
        useDownloadManager: true.title: 'RN APP'.description: 'An APK that will be installed'.mime: 'application/vnd.android.package-archive'.path: downloadDest,
        mediaScannable: true.notification: true
      }
    }).fetch(
      'GET',
       CONSTANT.SERVER_URL+'/appVersion/download? path='+this.newVersionInfo.path
    ).then(res= > {
      // Automatically open and run the downloaded APK file after successful download
      android.actionViewIntent(
        res.path(),
        'application/vnd.android.package-archive'
      );
    });
  }
Copy the code

(3) Matters needing attention

  • no

(4) Reference documents

  • Rn-fetch -blob plugin documentation address: github.com/eventsPorta…

React Native developers step on the pit

4.1, run the react – native run – android error: Task: app: mergeDebugAssets FAILED OR Task: app: processDebugResources FAILED.

Solution:

cd android && ./gradlew clean
cd .. && react-native run-android
Copy the code

4.2 if the real phone fails to connect to the development server.

Solution:

The command window runs the following command:

adb reverse tcp:8081 tcp:8081
Copy the code

4.3 Kotlin related JAR package cannot be downloaded.

Solution:

Gradle plugin for Android /build.gradle config Ali Cloud Repository (for example encountered this problem is in plugin react-native webView)

// Maven Central Repository Inside the wall
  maven { url "https://maven.aliyun.com/repository/central"  }
// jCenter inside the warehouse
  maven { url "https://maven.aliyun.com/repository/jcenter"  }
  maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'}
Copy the code

4.4 File preview plug-in: React-native doc-viewer failed to compile run-Android after installation.

Solution:

Could be fixed by removing the import innode_modules/react-native-doc-viewer/android/src/main/java/com/reactlibrary/RNReactNativeDocViewerModule.java Remove the  ununsedimport:

import com.facebook.react.views.webview.ReactWebViewManager;

Copy the code

4.5 Third-party plug-in Rn-fetch -blob download file cannot be opened.

Solution:

So basically this needs to be added to line 122- 123. of file android/src/main/java/com/RNFetchBlob/RNFetchBlob.java:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
If above is not working do to the below step: overwrite the 121 line in android/src/main/java/com/RNFetchBlob/RNFetchBlob.java:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 121 line
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 122 line
Copy the code

Five, the summary

This paper mainly summarizes the practice of React Native framework, and shares the concept of React Native, function introduction of React Native project, compilation of React Native project, and some problems existing in React Native. I hope that you will be inspired and helped after reading the book completely. If there is any shortage, you are welcome to criticize, correct and communicate!

The React Native and Weex comparison can be made in the companion article Weex Practice Summary.

Hard to sort out for a long time, but also hope to manually praise encouragement ~

Blog github address: github.com/fengshi123/… , a summary of all the author’s blogs, also welcome to follow and star ~

The github address of this project is: github.com/fengshi123/…

The github address of the supporting server Express project is github.com/fengshi123/…