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!!!
网友评论