Project connection: HelloRN ReactNative User manual

Install the React Native component into your Android app.

First of all, I have an MMP sentence. I don’t know whether I should mention it or not, but this is a huge pit I have encountered since I started to play RN. When you read this article, it has been two and a half days since I started to complete this project. Saw a lot of related issues including # Facebook/React-native issues and finally came out

1. First, of course, be aware of the React Native component you're implementing. 2. Use NPM to install 'react-native' in the Android project root, which also creates a directory for 'node_modules/'. 3. Create the JS file and write the JS code for the React Native component. 4. Add 'com.facebook.react:react-native:+' to the 'build.gradle' file, and a 'Maven' path to the 'react-native' precompiled library in the 'node_nodules/' directory. 5. Create a React Native specific 'Activity' and create a 'ReactRootView' in it. 6. Start the React Native Packager service and run the application. 7. Add more React Native components as required. 8. On a real machine [running] (https://reactnative.cn/docs/0.40/running-on-device-android.html), [debugging] (https://reactnative.cn/docs/0.40/debuggin We've HTML). [package] 9. (https://reactnative.cn/docs/0.40/signed-apk-android.html). 10. Launch your app, get a raise, get to the top of your life!Copy the code

Although the official website provides the methods and steps, but the documentation is too simple, and there are many holes, so this article is still valuable, of course, in the above steps we do not need to pay attention to some, but the main steps are still there, next follow this step to complete RN into the Android native project

Integrate the React Native component into the Android app

Step 1: Introductionreact-native

Type NPM init in the Terminal window of AndroidStudio and you will be prompted to type something (you can enter default values for everything except the project name) as shown below

When we finished typing, we switched the project to project mode, and we could see that the project had a package.json file

{
"name": "hellorn"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
  "test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Lai Tianbing"."license": "ISC"
}

Copy the code

This file has a familiar and unfamiliar feel to it, but it does the same thing as build.gradle, which configures the properties of the project

Step 2: Add the React and React_native modules

NPM install –save react react-native: NPM install –save react react-native: NPM install –save react react-native Because “–” may be different on different systems, you can see that the project has an additional node_modules module

Step 3: Run it from the command linecurl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig(This is really bad for Windows.)

Running ‘curl’ directly will remind you that ‘curl’ is not an internal or external command, nor is it a runnable program

The first thing I need to do is to run curl on Windows

Curl is an open source file transfer tool that works on the command line using URL syntax. It is widely used in Unix, various Linux distributions, and has ports for DOS and Win32 and Win64. So the first thing to solve the problem of support the curl command under Windows under Windows installation using the curl command prompt likely you won’t find | curl – 7.33.0 – win64 – SSL – sspi. Zip

One more hint
Run the curl command to install the software in Windows

Curl -v -x OPTIONS https://www.baidu.com/ : curl -v -x OPTIONS https://www.baidu.com/ Curl: curl curl: curl curl: curl curl: curl curl: curl curl: curl curl: curl curl: curl curl: curl curl

Curl. Exe to the root directory of your project. You can run curl in the root directory of your project

But: if YOU want to swear, it still won’t produce a. Flowconfig file,

So the most straightforward solution is to create your own project in the root directory.flowconfigText file, and then open it. Flowconfig connectCopy the text into the file you just created

Step 3: In package.json filescriptsConfigure the startup script"start": "node node_modules/react-native/local-cli/cli.js start",

{
  "name": "hellorn"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"."start": "node node_modules/react-native/local-cli/cli.js start"."bundle-android": "react-native bundle --platform android --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --dev false"
  },
  "author": "Lai Tianbing"."license": "ISC"."dependencies": {
    "react": "^ 16.2.0"."react-native": "^ 0.53.3"}}Copy the code

The third step is over in the official documentation, but after all I’ve been through a lot and I’ve read a lot of blogs and I’m telling you that this step is not over yet. As usual, you should also configure the package to generate index.andriod.bundle from index.android.js (you can also try not to do this, There will definitely be some classic bugs, but I won’t mention them here, I’ll write a special article about them.)

Configure the configuration of the bundle files required for publishing and packaging

Many blogs solve this problem by adding “bundle-Android” as in the complete package.json code above: “react-native bundle –platform android –entry-file index.android.js –bundle-output App/SRC/main/assets/index. The android. Bundle — — dev false “did not say this sentence in the official document, but the best plus (although I add after, at least I no eggs used here, The new version of RN does not support the automatic generation of bundles required for packaging.) “React-native bundle — platform android — dev false — entry-file index.android.js — bundle-output Android/app/SRC/main/assets/index. The android. The bundle – sourcemap – the output of the android/app/SRC/main/assets/index. The android. The map – assets – dest android/app/SRC/main/res/” but this is wrong, packaging we all want to do some adjustment according to the results of the project directory, but in the above package. I have done adjust in json, but still can’t automatically packaged bundle

Solution: Let’s first create the results folder under Main, Then go to the project root directory, open CMD, and enter react-native bundle –platform android –entry-file index.android.js –bundle-output App/SRC/main/assets/index. The android. Bundle — — dev false (note – behind the output parameters according to your own project directory structure to write)

You’ve probably seen a lot of RNS nested in the original Android project and followed through on them, but it just didn’t work out, and this is one of the big reasons why

If this is done, then congratulations, you should basically see the results, there may be bugs, but these are fixed things that are easy to fix

Step 4: Create in the project root directoryindex.android.jsfile

import React from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

class HelloWorldApp extends React.Component {
  render() {
return( <View style={styles.container}> <Text style={styles.hello}>Hello world! I am from ReactNattive!! </Text> </View> ) } } var styles = StyleSheet.create({ container: { flex: 1, justifyContent:'center',
  },
  hello: {
fontSize: 20,
textAlign: 'center', margin: 10, }, }); / / here first and familiar name to name and we created this project AppRegistry. RegisterComponent ('HelloRN', () => HelloWorldApp);
Copy the code

Tip: As mentioned in creating HelloWorld in the second article in this RN blog series, registerComponent () must be registered with the same name as the project name

Step 5: Add ReactNative dependencies

First add it in your APP’s build.gradle

```
dependencies {
     ...
     compile "com.facebook.react:react-native:+" // From node_modules.
 }
```
Copy the code

Second, add the path to the local ReactNative repository in build.gradle of the project, but the path of the official source document is

$rootDir/.. /node_modules/react-native/android

If you copy it directly, congratulations, you’re in the hole again

Because we added the react and react_native modules in the second step, they are in the root directory of the project by default, but the path given in the official document is actually more than “.. / “so that’s a pit (here, a lot of online articles are directly through the official route, but the project structure and is the same as mine, I really doubt when they write the article just copy others, oneself didn’t succeed, this is also a lot of people follow others step by step until the last article still another reason of error). The path here should correspond to the path of module in my project and my project directory

So my path should be

 allprojects {
          repositories {
              ...
              maven {
                  // All of React Native (JS, Android binaries) is installed from npm
                  url "$rootDir/node_modules/react-native/android"}}... }Copy the code

After the completion of the addition, remember to synchronize the following oh, but the waiting time is too long (it is best to open VPN, I opened VPN to complete the synchronization), you can continue to read the article in the future

Step 6: Add network request permissions to the manifest file, mandatory

Next, make sure you have the Internet permission in your Androidmanifest.xml: < USES – permission android: name = “android. Permission. INTERNET” / >, and debugging required permissions

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
Copy the code

Step 7: Register in the manifest fileDevSettingsActivity, this step can be omitted, the function is to reload JavaScript

If you need to access DevSettingsActivity to add to your Androidmanifest.xml:

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

This is only really used in development mode when the development server reloads the JavaScript, so it can be stripped off in the release if needed.

Step 8: Change the code in the MainActivity automatically created by the previous project to the following code, but note that it needs to be used when the APP needs to support models below 5.0com.android.support:appcompatIn the packageAppCompatActivityClass instead of using the Activity directly


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

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;


public class MainActivity 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") // Note here, official documentationsetJSMainModuleName not found in the new version, replaced bysetJSMainModulePath
//                .setJSMainModuleName("index.android"Android.setjsmainmodulepath () // The path is relative to the root directory."index.android") .addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); // Note that the 'moduleName' parameter must be the same as the project name, Also is in ` index. Android. In js ` AppRegistry. RegisterComponent () registered name mReactRootView.startReactApplication(mReactInstanceManager,"HelloRN", null);

        setContentView(mReactRootView);
    }

    @Override
    public void invokeDefaultOnBackPressed() { super.onBackPressed(); }}Copy the code

Next (this step can be skipped), we need to pass some activity lifecycle callbacks to the ReactInstanceManager:

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

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

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

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onDestroy();
        }
    }

Copy the code

Note: If you copy the code directly from the official website, you will get an error because the ReactNative version has been updated and the method name changes are more synchronized with Android

(also skipped) We also need to pass the button event to React Native:

   @Override
    public void onBackPressed() {
        if(mReactInstanceManager ! = null) { mReactInstanceManager.onBackPressed(); }else{ super.onBackPressed(); }}Copy the code

What it does: This allows JavaScript to control what happens when the user presses the hardware back button (for example, to implement navigation). When JavaScript does not handle back on time, your invokeDefaultOnBackPressed method will be invoked. By default, this just completes your Activity.

Finally (this step can also be skipped), we need to connect to the development menu. By default, this is activated by (anger) firing the device, but this is not very useful in the emulator. So we display it when pressing the hardware menu button (Ctrl + M if you’re using an Android Studio emulator, please use it) :

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

Step 9 (this step can be skipped) : Configure permissions so that red screen errors in development are displayed correctly

If your application is targeted to Android API Level 23 or higher, make sure you have overlay enabling permissions for the development version. You can check it Settings. CanDrawOverlays (this); . This is required in development releases because the original 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 the field that will be responsible for passing the results back to the active class.

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, onActivityResult() must override the method (shown in the code below) to handle the consistent UX permission Accepted or Denied.

@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

Finally under the clear index. Android. Js and mReactRootView startReactApplication (mReactInstanceManager, “HelloRN”, null) and package. The json and project name, Which ones are consistent in the end (I also integrated more than 5 times, summed up, if there is any wrong message please point out)

Must be the same: project name (HelloRN) and AppRegistry registerComponent (‘ HelloRN ‘() = > HelloWorldApp); And mReactRootView. StartReactApplication (mReactInstanceManager, “HelloRN”, null); All three have to be the same. This is basically what happens when you make the following errors

The “name”: “hellorn” in package.json certainly feels the same to me, but it can be different, and when you enter the name of the project in the first step, if you enter it in uppercase, you will be prompted to lower case. And when we initialize “main”: Js. From the field, the name of the index.android.js we created later should also be called “index.js”. After all, package.json is similar to our configuration file, but we didn’t do this and found no problems.

Run the application

  • Start the test server by running the following command from the command line in the root folder of your project (you can enter it directly in Termin in Androidstudio, but note the current location).
NPM start or react-native startCopy the code
  • Then run the project directly as you would an Android project

The effect

If an error

Solution: Add it in build.gradle of app
|
|
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
    }

Copy the code

Please like, or pay attention to, the follow-up will improve the release of more articles, your encouragement is my motivation (programmer’s biggest motivation than the encouragement of peers)