美文网首页
修复RN-0.76以上版本使用react-native-code

修复RN-0.76以上版本使用react-native-code

作者: sunny635533 | 来源:发表于2024-12-04 14:29 被阅读0次

Fixed a problem with react-native-code-puh library when using RN-0.76 or later

In order to make the hot update function work properly in the new newArch version 0.76, I added the following code, hoping it can help you.
I tried to add these code in my project and code-push update function can be used normally.
1、in Android,create RestartModule.java file in your app's dir.

import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.ichoi.ichoi.MainActivity;
import com.microsoft.codepush.react.ReactInstanceHolder;

/**
 * author by sunny
 * created at 2024/12/2 10:03
 */
public class RestartModule extends ReactContextBaseJavaModule {
    private static String restartReason = null;

    private LifecycleEventListener mLifecycleEventListener = null;

    public RestartModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    private void loadBundleLegacy() {
        final Activity currentActivity = getCurrentActivity();
        if (currentActivity == null) {
            return;
        }

        currentActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
//                currentActivity.recreate();

                Intent intent = new Intent(currentActivity, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                currentActivity.startActivity(intent);
                currentActivity.finish();
                Runtime.getRuntime().exit(0);
            }
        });
    }

    private void loadBundle() {
        clearLifecycleEventListener();
        try {
            final ReactInstanceManager instanceManager = resolveInstanceManager();
            if (instanceManager == null) {
                return;
            }

            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    try {
                        instanceManager.recreateReactContextInBackground();
                    } catch (Throwable t) {
                        loadBundleLegacy();
                    }
                }
            });

        } catch (Throwable t) {
            loadBundleLegacy();
        }
    }

    private static ReactInstanceHolder mReactInstanceHolder;

    static ReactInstanceManager getReactInstanceManager() {
        if (mReactInstanceHolder == null) {
            return null;
        }
        return mReactInstanceHolder.getReactInstanceManager();
    }

    private ReactInstanceManager resolveInstanceManager() throws NoSuchFieldException, IllegalAccessException {
        ReactInstanceManager instanceManager = getReactInstanceManager();
        if (instanceManager != null) {
            return instanceManager;
        }

        final Activity currentActivity = getCurrentActivity();
        if (currentActivity == null) {
            return null;
        }

        ReactApplication reactApplication = (ReactApplication) currentActivity.getApplication();
        instanceManager = reactApplication.getReactNativeHost().getReactInstanceManager();

        return instanceManager;
    }


    private void clearLifecycleEventListener() {
        if (mLifecycleEventListener != null) {
            getReactApplicationContext().removeLifecycleEventListener(mLifecycleEventListener);
            mLifecycleEventListener = null;
        }
    }

    @ReactMethod
    public void restart(String reason) {
        restartReason = reason;
//        loadBundle();
        loadBundleLegacy();
    }

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

create RestartPackage.java file in your app's dir.

import androidx.annotation.NonNull;
import com.facebook.react.ReactPackage;
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;

/**
 * author by sunny
 * created at 2024/12/2 10:04
 */
public class RestartPackage implements ReactPackage {
    @NonNull
    @Override
    public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @NonNull
    @Override
    public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();

        modules.add(new RestartModule(reactContext));

        return modules;
    }
}

add register the package in MainApplication

 override fun getPackages(): List<ReactPackage> =
            PackageList(this).packages.apply {
              // Packages that cannot be autolinked yet can be added manually here, for example:
              // add(MyReactNativePackage())
              add(RestartPackage())
            }

2、in ios,create Restart.m

//
//  Restart.m
//  iChoi
//
//  Created by sunny on 2024/12/2.
//
#import "Restart.h"

@implementation Restart

RCT_EXPORT_MODULE(RNRestart)
NSString  *restartReason = nil;

- (void)loadBundle
{
    RCTTriggerReloadCommandListeners(@"react-native-restart: Restart");
}

RCT_EXPORT_METHOD(restart: (NSString *)reason) {
    restartReason = reason;
    if ([NSThread isMainThread]) {
        [self loadBundle];
    } else {
        dispatch_sync(dispatch_get_main_queue(), ^{
            [self loadBundle];
        });
    }
    return;
}

@end

create Restart.h

//
//  Restart.h
//  iChoi
//
//  Created by sunny on 2024/12/2.
//
#import <React/RCTBridgeModule.h>
#import <React/RCTRootView.h>
#import <React/RCTReloadCommand.h>

@interface Restart : NSObject <RCTBridgeModule>

@end

3、in Android,we need to change some code in react-native-code-push.
Please find the CodePushNativeModule.java,then find this method "notifyApplicationReady"
change it like that:

@ReactMethod
    public void notifyApplicationReady(Promise promise) {
    try {
        mSettingsManager.removePendingUpdate();
        if(promise!=null){
            promise.resolve("");
        }
    } catch(CodePushUnknownException e) {
        CodePushUtils.log(e);
        if(promise!=null) {
            promise.reject(e);
        }
    }

find the method "loadBundle",change it like that:

//note this line
// instanceManager.recreateReactContextInBackground();
//add the line 
 notifyApplicationReady(null);

4、in JS,test it,

if (Platform.OS == "android") {
          CodePush.restartApp();
        }

        NativeModules.RNRestart.restart("")

Congratulation!!!

相关文章

网友评论

      本文标题:修复RN-0.76以上版本使用react-native-code

      本文链接:https://www.haomeiwen.com/subject/dtjpsjtx.html