React Native embedded in existing Native apps (Android)

React Native is a great choice if you’re building a new app from scratch. But if you just want to add a view or two or a business process to an existing Native app, React Native also works. In a few simple steps, you can add new React Native features, graphics, and views to existing apps.

1. Core concepts

Here are the main steps to incorporating the React Native component into an Android application:

  1. The first thing to understand is the React Native component you’re implementing.
  2. Install using NPM in the Android project root directoryreact-native, which creates one at the same timenode_modules/The directory.
  3. Create javascript files and write javascript code for the React Native component.
  4. inbuild.gradleAdd to filecom.facebook.react:react-native:+And a point tonode_nodules/In the directoryreact-nativePrecompiled librarymavenThe path.
  5. Create a React Native exclusiveActivity(can be mixed), in which to createReactRootView.
  6. Generate the correspondingbundleStart the React Native Packager service and run the React Native application.
  7. Feel free to add more React Native components next.
  8. Run on the real machine, debug (here need to update firstbundleFile).
  9. Packaging.

2. Prepare the development environment

Here’s another article I wrote about React Native setting up environments.

3. Add JS code management

  • Run the following command at the root of your project:
$ npm init
$ npm install --save react react-native
$ curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig
Copy the code

In this case, you can see the following files/folders in the root directory of the Android project: node_modules/ and package.json

  • Open thepackage.jsonFile,scriptsAdd the following fields under property:

"start": "node node_modules/react-native/local-cli/cli.js start"

  • Create a js folder in the root directory (store React Native components), index.android.js(RN startup file). The main startup code is as follows:
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */
import {AppRegistry} from 'react-native';
import AwesomeProject from './js/AwesomeProject'/ / register (as long as it again) AppRegistry. RegisterComponent ('AwesomeProject', () => AwesomeProject);

Copy the code

4. Add App development preparation operations

  • In your appbuild.gradleIn-file addReact NativeRelated dependencies:

compile 'com.facebook.react:react-native:+' // From node_modules.

  • In your projectbuild.gradleAdd local to fileReact NativeMaven repository:
allprojects {
    repositories {
        jcenter()
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/node_modules/react-native/android"}}}Copy the code

Note: The url path must be correct, otherwise the following error will occur: “Failed to resolve: com.facebook.react:react-native:0.x.x” errors after running Gradle sync in Android Studio.

  • AndroidManifest.xmlManifest file configuration
  • If you need to access React Native’s DevSettingsActivity, you need to register<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

5. All set: Add native code next

  • React Native
package com.itingchunyu.reactnative.view;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.appcompat.BuildConfig;
import android.view.KeyEvent;

import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;

/**
 * Created by liyanxi on 2016/12/13.
 * Copyright (c) [email protected]. All rights reserved.
 */

public class MyReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle"SetJSMainModuleName ()"index.android")// the index.android.js file in the root directory.addPackage(new MainReactPackage()trueDeveloper options such as JS reload and debugging are enabled. SetUseDeveloperSupport (true)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();
                //'AwesomeProject'= = > index. Android. Js page registered name, can be adjusted freely according to oneself mReactRootView. StartReactApplication (mReactInstanceManager,"AwesomeProject", null);
        setContentView(mReactRootView);
    }

    @Override
    protected void onPause() {
        super.onPause();

        if(mReactInstanceManager ! = null) { mReactInstanceManager.onHostPause(this); } } @Override protected voidonResume() {
        super.onResume();

        if(mReactInstanceManager ! = null) { mReactInstanceManager.onHostResume(this, this); } } @Override protected voidonDestroy() {
        super.onDestroy();

        if(mReactInstanceManager ! = null) { mReactInstanceManager.onHostDestroy(this); } } @Override public boolean onKeyUp(int keyCode, KeyEvent event) {if(keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager ! = null) { mReactInstanceManager.showDevOptionsDialog();return true;
        }
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public void invokeDefaultOnBackPressed() { super.onBackPressed(); }}Copy the code
  • Native and RN hybrid page main code (full code address at bottom) :
package com.itingchunyu.reactnative.view;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.appcompat.BuildConfig;
import android.widget.LinearLayout;

import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.shell.MainReactPackage;
import com.itingchunyu.reactnative.R;

/**
 * Created by liyanxi on 2016/12/13.
 * Copyright (c) [email protected]. All rights reserved.
 */

public class HybridActivity extends AppCompatActivity {

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    private LinearLayout layoutReactContainer;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_second);

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android").addPackage(new MainReactPackage()trueDeveloper options such as JS reload and debugging are enabled. SetUseDeveloperSupport (true)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();
        mReactRootView.startReactApplication(mReactInstanceManager, "AwesomeProject", null); layoutReactContainer= (LinearLayout) findViewById(R.id.layout_react); layoutReactContainer.addView(mReactRootView); }}Copy the code

6. Configure permissions to ensure that red screen errors are correctly displayed during development

If your application specifies an Android API level of 23 or higher, make sure you have enabled overlapping permissions for development releases. You can use Settings to check. CanDrawOverlays (this); This is required in the development release because the reflection of a local development error must be displayed above all other Windows. Due to the introduction of a new permissions system in API level 23, users need to approve it. You can do this by adding the following code to the Activity file in the onCreate () method. OVERLAY_PERMISSION_REQ_CODE is a field of the class that is responsible for passing the result back to the Activity.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if(! Settings.canDrawOverlays(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+ getPackageName())); startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE); }}Copy the code

Finally, the onActivityResult() method (as shown in the code below) must be overwritten to handle permission acceptance or denial on consistent UX.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if(! Settings.canDrawOverlays(this)) { // SYSTEM_ALERT_WINDOW permission not granted... }}}}Copy the code

7. Apps fly

  • Start the serverReact packager

$NPM start(with package.json file start)

or

$react-native start

  • Start the App (see the effect)

  • Potholes that have been stepped on during debugging

The page for launching ReactNative related activities crashes

Solution look at the code screenshot:

8. Package APK in Android Studio

You can also use Android Studio to pack! You can use Android Studio to create your release builds too! It’s as easy as creating release builds of your previously existing native Android app. There’s just one Additional step, Which you’ll have to do before every release build. You need to execute the following to create a React Native bundle, Which’ll be included with your native Android app:

react-native bundle --platform android --dev false --entry-file ./index.android.js --bundle-output ./app/src/main/assets/index.android.bundle --assets-dest ./app/src/main/res/
Copy the code

The following operations are unavoidable before packaging:

1. Run the following command in the root directory to generate the React Native Activity page bundle file: /app/ SRC /main/assets/

2. Remote bundle files (used for dynamic updates, not detailed here)

9. At this point, believe that your application should be running. If you have any questions, please leave a message or send me an email ([email protected]), thank you for browsing;

10. Full code address

ReactNativeDemo