RN(React Native) Android 64 bit apk interface is stuck

RN Android 64 bit apk interface stuck

Problem description

The program developed by Rn is packaged with Anroid 64apk. After accessing the pangolin advertisement, start the application and operate for a period of time, and the interface will be stuck,
Specifically, the embedded webview can click and slide, and the native interface can slide up and down, but does not respond to all click operations The software will not go down

This problem only occurs in 64 bit apk. 32-bit apk performs normally

Solution

Let's talk about the solution. The problem is caused by the js engine in sleep. The solution is to change the js engine. RN supports two engines: Javascript core and Hermes This problem occurs under the first engine, JavaScript core So just switch to Hermes engine
Enable Hermes engine support
Open Android / APP / build Gradle file, modify as follows

  project.ext.react = [
      entryFile: "index.js",
-     enableHermes: false  // clean and rebuild if changing
+     enableHermes: true  // clean and rebuild if changing
  ]

An official link of RN is posted here to introduce how to start Hermes engine support
Enable Hermes engine

Solution ideas

Pangolin

First, locate the problem and find that the problem will occur as long as the pangolin is initialized Regardless of whether the pangolin initialization is in Application or Activity, the company's colleagues contacted the pangolin, and the pangolin responded that it has not conducted compatibility test on RN and let us solve it by ourselves... The pangolin dependency packages we got are confused, and there is no way to check what operations the pangolin initialization has done... I T…M…

Commissioning of RN

From the perspective of problem performance, there should be no problem with the rendering of the interface. andorid renders the interface through the main thread, so the main thread runs normally. Moreover, after the main thread gets stuck for a few seconds, the system will prompt the application for an unresponsive message to close the application

By querying the data, it is found that RN has three threads in total

  1. The first thread is used to run the js engine and run the js code
  2. The second thread is the native thread, which is used to run the yoga engine and calculate the layout
  3. The third thread is the main thread for interface rendering

To Debug RN, you need to turn off the online loading function of Rn and package the js code directly into the resource file

1. Turn off RN online loading function
Open the Application class and modify the return value of getUseDeveloperSupport() method to false, as follows

    @Override
    public ReactNativeHost getReactNativeHost() {
        if (mReactNativeHost == null) {
            mReactNativeHost = new ReactNativeHost(this) {
                @Override
                public boolean getUseDeveloperSupport() {
                    return false;
                }
                
                ......
                
            };
        }

        return mReactNativeHost;
    }

2. Package JS code into Android resource file (index.android.bundle)
Run the following command line code in the Rn project directory

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

The specific method and introduction of packaging can be found on the Internet. Here I post a link to other people's blog, which you can check by yourself
How to package react native to generate Js Bundle files (take android as an example)

During debugging, we inherited ReactActivity as the test class, and then let the main interface inherit the test class (to prevent false modification of business code), intercept click messages and system exit messages in the test class The interception code is as follows

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.v("test","======================main======================");
        MainApplication.reactManager.getCurrentReactContext().runOnJSQueueThread(() -> {
            Log.v("test","======================js thread ======================");
        });
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        Log.v("test","======================main======================");
        MainApplication.reactManager.getCurrentReactContext().runOnJSQueueThread(() -> {
            Log.v("test","======================js thread ======================");
        });
        return super.onKeyUp(keyCode, event);
    }

MainApplication.reactManager this variable can be maintained from the Application class
Acquisition method

MainApplication.reactManager = getReactNativeHost().getReactInstanceManager()

When the interface works normally, the log is printed normally However, after the interface is stuck, only the log of the main thread can be printed, and the js thread has no response
From here, it is determined that it is the js engine problem again. After analysis, the problem can be located, but we didn't think of replacing other js engines at that time. Then we grabbed the stack information at runtime and did other things

Writing here, I have to lament the care of the God of fate for me On the way home, I suddenly thought, since there is something wrong with the js engine, can't we try another engine? Maybe different engines have different performance results? Then I checked the information and found that it seemed feasible I told my colleagues the news and agreed to try it the next day
It didn't take much time the next day to make sure the plan was effective

Thank you again for the blessing of the God of fate

This blog is just for learning new knowledge and sorting out knowledge. If there are mistakes and omissions, please correct them

Keywords: Java Android React Native

Added by kbascombe on Sat, 05 Mar 2022 05:50:01 +0200