Closed marcmo closed 4 years ago
what kind of clarifications can I provide?
Hi @marcmo, thanks for reaching us.
I've added clarification tag by mistake. As for your issue, could you please double check if your app has been configured correctly using this installation guide.
Please also take a look at this https://github.com/Microsoft/react-native-code-push/issues/790#issuecomment-294148452 - at the end of the comment you can find the configured app that should work.
thanks for responding @sergey-akhalkov , I checked and my setup is almost exactly the same, only the name I use for my getJSBundleFile
is different:
public class MainApplication extends NavigationApplication implements ReactInstanceHolder {
@Override
public boolean isDebug() {
return BuildConfig.DEBUG;
}
@Nullable
@Override
public List<ReactPackage> createAdditionalReactPackages() {
return getReactPackages();
}
@NonNull
protected List<ReactPackage> getReactPackages() {
return Arrays.<ReactPackage>asList(
new CodePush(getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey), getApplicationContext(), BuildConfig.DEBUG)
);
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
@Override
public String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
@Override
public ReactInstanceManager getReactInstanceManager() {
return getReactNativeHost().getReactInstanceManager();
}
}
I had a lot of different issues and was able to resolve them but now what baffles me is that my setup works perfectly fine when running during development, but the error shows up in the installed release version. (this error: Module AppRegistry is not a registered callable module (calling runApplication))
@marcmo, could you please share which way you are registering your callable module? As for the sample app above, please pay attention to the following code:
import CodePush from 'react-native-code-push';
// register all screens of the app (including internal ones)
export function registerScreens() {
Navigation.registerComponent('example.FirstTabScreen', () => CodePush(FirstTabScreen));
...
}
are you sure about the call to CodePush? For me it seems CodePush
is a function that takes an optional config as parameter and when called returns a function that takes the screen as parameter.
this is how I use codepush:
// module registration
export const CodePushConfig = {
checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
};
export const registerScreens = (store: Redux.Store<RootState>, provider) => {
Navigation.registerComponent('xyz.IntroScreen', () => IntroScreen, store, provider);
...
Navigation.registerComponent('xyz.DevOpts', () => CodePush(CodePushConfig)(DevOpts), store, provider);
...
};
// in DevOpts:
componentWillMount() {
CodePush.sync({
updateDialog: CodePush.DEFAULT_UPDATE_DIALOG,
installMode: CodePush.InstallMode.IMMEDIATE,
deploymentKey: Platform.select({
android: '***',
ios: '***',
}),
});
}
I have to admit I don't yet understand the RN app lifecycle implications on codepush. e.g. if it is possible/advisable to ask for a codepush sync like this:
AppState.addEventListener('change', handleAppStateChange);
const handleAppStateChange = (nextAppState: AppStateStatus) => {
switch (nextAppState) {
case 'active':
CodePush.sync(AppConfig.codePushConfig);
break;
default:
}
};
are you sure about the call to CodePush?
Yeah, I'm sure, please take a look at codePush(..)
usage here.
this is how I use codepush:
Looks good, it's really weird why CodePush doesn't work for you. Could you please share the minimum working version of you App so I'll be able to take a look at it closer? As of now I don't sure what exact root cause of your issue is, but I'm sure that demo app I've provided here https://github.com/Microsoft/react-native-code-push/issues/790#issuecomment-294148452 worked well for me - could you please also download it and confirm if it works for you?
@sergey-akhalkov I will try to prepare a minimal app version but that will take me some time... I was hoping you already experienced situations where code-push was working when running in development mode, but not in an release-build. That indicates to me that all my setup can actually work, my keys are correct and my configuration is OK. but currently I'm really lost on this error:
Module AppRegistry is not a registered callable module (calling runApplication)
anyway...thanks for looking into this. I will try to setup a sharable example to demonstrate this behavior.
Hi @marcmo, got it, will wait for the demo!
I was hoping you already experienced situations where code-push was working when running in development mode, but not in an release-build.
Please note, that running RN app in the development mode is not actually the same as running in release mode, please see official docs:
NOTE: CodePush updates should be tested in modes other than Debug mode. In Debug mode, React Native app always downloads JS bundle generated by packager, so JS bundle downloaded by CodePush does not apply.
Loading JS bundle via packager is the main reason why you have no issue in debug mode. CodePush uses locally installed JS bundle instead.
ok..I prepared a repository (android only) that can demonstrate this behavior: https://github.com/marcmo/code-push-minimal I would be grateful if you could take a look at this @sergey-akhalkov the README has instructions on how to build and how to trigger codepush. I guess you will have no problems with the codepush keys...keystore with everything that is needed is also in the repository.
@marcmo, great, thank you! I'm going to investigate it and let you know if I have any questions or If I'll found the root cause of the issue.
@ruslan-bikkinin let me know if you need anything else from my side...I'm really stuck on this one
Hi @marcmo, I was able to reproduce your issue using demo project you sent us. After further investigation I am suspecting that the root of the problem is somewhere in react-native. Actually, when you are using any install modes but ON_NEXT_RESTART
, CodePush is using soft restart of app without killing it. This mechanism uses react-native
method instanceManager.recreateReactContextInBackground();
that does the trick.
Everything works pretty good when you are starting the app from scratch but something goes wrong after restarting the app using this method because probably several context parts aren't cleared completely in case of registering components asynchronously.
We have similar issue here. I will prepare a clean demo and ask the react-native
team on github about possible solutions. I will post the results here.
As for now, you can switch install mode to ON_NEXT_RESTART
as a workaround.
thanks so much @ruslan-bikkinin and @sergey-akhalkov ! I just verified that using ON_NEXT_RESTART
did the trick!
feel free to close the issue or leave it open until the IMMEDIATE
option also works.
Is there any progress on this? IMMEDIATE
works fine in debug mode, but crashes the app and rolls back the update for release builds
fwiw I believe I've somewhat nailed down why this is a problem in wix/react-native-navigation#2331 and a hacky "fix", but I'm afraid I don't yet have a solid generalized solution figured out ☹️
The app doesn't crash for me but navigation is broken. These are the logs I get
06-07 10:30:51.359 9800-9862/? E/unknown:ReactNative: Invariant Violation: Minified React error #143; visit http://facebook.github.io/react/docs/error-decoder.html?invariant=143 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
This error is located at:
in r
in t
in RCTView
in t
in Connect(t)
in RCTView
in t
in Connect(t)
in RCTView
in t
in Connect(t)
in r
in n
in s
in RCTView
in RCTView
in t, stack:
only@101:4233
value@659:1338
l@44:54398
beginWork@44:56240
n@44:82237
i@44:82566
o@44:82907
C@44:87082
b@44:86624
m@44:85850
d@44:85131
f@44:84822
t@44:50910
updateContainer@44:101734
render@44:69237
exports@283:730
run@279:615
runApplication@279:2046
value@21:3582
<unknown>@21:1067
value@21:3009
value@21:1039
06-07 10:30:51.359 9800-9861/? E/ReactNativeJS: 'Unhandled promise rejection', { [ReferenceError: Can't find variable: AsyncStorage]
line: 1199,
column: 895,
sourceURL: '/data/user/0/fi.taskuparkki.app/files/CodePush/a23158e284ff200eda3120985783f8bf574ee5ab2743218be6b2f32caeb5c7bc/CodePush/index.android.bundle' }
06-07 10:30:51.361 9800-9861/? E/ReactNativeJS: 'Unhandled promise rejection', { [ReferenceError: Can't find variable: AsyncStorage]
line: 1199,
column: 895,
sourceURL: '/data/user/0/fi.taskuparkki.app/files/CodePush/a23158e284ff200eda3120985783f8bf574ee5ab2743218be6b2f32caeb5c7bc/CodePush/index.android.bundle' }
06-07 10:30:51.362 9800-9862/? E/unknown:ReactNative: console.error: "Unhandled promise rejection", {"line":1199,"column":895,"sourceURL":"/data/user/0/fi.taskuparkki.app/files/CodePush/a23158e284ff200eda3120985783f8bf574ee5ab2743218be6b2f32caeb5c7bc/CodePush/index.android.bundle"}, stack:
<unknown>@1078:1147
exports@1085:66
<unknown>@1078:1018
<unknown>@26:1779
u@26:513
c@26:877
callImmediates@26:3180
value@21:3183
<unknown>@21:1516
value@21:3009
value@21:1486
value@21:1094
06-07 10:30:51.363 9800-9862/? E/unknown:ReactNative: console.error: "Unhandled promise rejection", {"line":1199,"column":895,"sourceURL":"/data/user/0/fi.taskuparkki.app/files/CodePush/a23158e284ff200eda3120985783f8bf574ee5ab2743218be6b2f32caeb5c7bc/CodePush/index.android.bundle"}, stack:
<unknown>@1078:1147
exports@1085:66
<unknown>@1078:1018
<unknown>@26:1779
u@26:513
c@26:877
callImmediates@26:3180
value@21:3183
<unknown>@21:1516
value@21:3009
value@21:1486
value@21:1094
06-07 10:30:51.558 9800-9800/? E/zygote: The String#value field is not present on Android versions >= 6.0
06-07 10:30:51.878 9800-9861/? E/ReactNativeJS: 'Unhandled promise rejection', { [ReferenceError: Can't find variable: AsyncStorage]
line: 1199,
column: 895,
sourceURL: '/data/user/0/fi.taskuparkki.app/files/CodePush/a23158e284ff200eda3120985783f8bf574ee5ab2743218be6b2f32caeb5c7bc/CodePush/index.android.bundle' }
06-07 10:30:51.880 9800-9861/? E/ReactNativeJS: 'Unhandled promise rejection', { [ReferenceError: Can't find variable: AsyncStorage]
line: 1199,
column: 895,
sourceURL: '/data/user/0/fi.taskuparkki.app/files/CodePush/a23158e284ff200eda3120985783f8bf574ee5ab2743218be6b2f32caeb5c7bc/CodePush/index.android.bundle' }
06-07 10:30:51.881 9800-9862/? E/unknown:ReactNative: console.error: "Unhandled promise rejection", {"line":1199,"column":895,"sourceURL":"/data/user/0/fi.taskuparkki.app/files/CodePush/a23158e284ff200eda3120985783f8bf574ee5ab2743218be6b2f32caeb5c7bc/CodePush/index.android.bundle"}, stack:
<unknown>@1078:1147
exports@1085:66
<unknown>@1078:1018
<unknown>@26:1779
u@26:513
c@26:877
callImmediates@26:3180
value@21:3183
<unknown>@21:1516
value@21:3009
value@21:1486
value@21:1094
06-07 10:30:51.882 9800-9862/? E/unknown:ReactNative: console.error: "Unhandled promise rejection", {"line":1199,"column":895,"sourceURL":"/data/user/0/fi.taskuparkki.app/files/CodePush/a23158e284ff200eda3120985783f8bf574ee5ab2743218be6b2f32caeb5c7bc/CodePush/index.android.bundle"}, stack:
<unknown>@1078:1147
exports@1085:66
<unknown>@1078:1018
<unknown>@26:1779
u@26:513
c@26:877
callImmediates@26:3180
value@21:3183
<unknown>@21:1516
value@21:3009
value@21:1486
value@21:1094
fwiw the PR I submitted that's linked above seems to fix this bug for me... I'm a bit worried about potential race condition but so far I have yet to see one arise.
Also I doubt it will be merged since its for V1 and they've said they're not accepting V1 PRs any more, but I wanted to get it out there for others that are having this issue to fork & patch themselves without having to spend the time I did figuring out what was going wrong.
exciting news, despite the announcement that V1 is closed for PRs wix actually merged my fix PR, so @sergey-akhalkov (sorry if you're the wrong person to tag) you might be able to close this issue?
edit: cc @ruslan-bikkinin
Hi @ericketts, I am not responsible for codepush stuff anymore, I believe the right person for it is @alexandergoncharov.
Hi all, Yeah, I'll look at this as soon as possible. It is in queue. Sorry for this delay.
Thanks, Alexander
Is there any progress on this? I hope IMMEDIATE option works soon.
Same error for me... restarting the app with react-native-navigation on Android causes this error.
Any news about this ? How can we get the IMMEDIATE option working ?
In my case the problem seemed to be that the onCatalystInstanceDestroy()
method was not blocking the instanceManager.recreateReactContextInBackground()
call here, so the context would be recreated before onCatalystInstanceDestroy()
had a chance to call navigator.destroyViews()
, and the app would come up and find these views that weren't registered (I'm using a tab layout, and I was getting an Invariant Violation: "MyView" has not been registered.
for each tab). Or something along those lines, an issue with synchronization anyway.
The solution that seems to be working well so far was to add a native restartApp()
method to my app that would first call navigator.destroyViews()
to clear RNN state, and use a promise to have the JS call CodePush.restartApp(false)
once that was done.
In code, it's something like this:
/* MyNativeUtils.kt */
@ReactMethod
fun restartApp(promise: Promise) {
val activity = currentActivity
val lock = ReentrantLock()
// MainActivity is my root activity extending RNN NavigationActivity
if (activity == null || activity !is MainActivity) {
Log.e(TAG, "activity is " + activity)
} else {
// show the splash screen while we're reloading
SplashScreen.show(activity, true)
val viewsDestroyed = lock.newCondition()
val destroyed = AtomicBoolean(false)
runOnUiThread(Runnable {
activity.navigator.destroyViews()
try {
lock.lock()
destroyed.set(true)
viewsDestroyed.signalAll()
} finally {
lock.unlock()
}
})
try {
lock.lock()
if (!destroyed.get()) {
// waiting for views to be destroyed
viewsDestroyed.await(3, TimeUnit.SECONDS)
// wake up, JS!
promise.resolve(true);
}
} catch (e: InterruptedException) {
Log.w(TAG, "stopped waiting for views to be destroyed, see stack trace")
e.printStackTrace()
promise.resolve(false)
} finally {
lock.unlock()
}
}
}
I'm using reentrant locks just because, you can synchronize however you like, of course. On the JS side I have a snackbar with a restart button that calls this
onAppRestart: () =>
MyNativeUtils.restartApp().then((ready) => {
if (ready) {
CodePush.restartApp(false);
} else {
MyNativeUtils.toast("couldn't install update");
}
})
The onCatalystInstanceDestroy()
overrides added in this PR (and this one for RNN v2+) can stay, they simply won't do anything as they're called after everything's already been cleared.
Hope this helps somebody, it was really a pain to debug!
Hi @nighttiger1990, @JB-CHAUVIN! Sorry for the delay! I couldn't reproduce the issue. I created a demo project with the latest versions of RN, RNN, and react-native-code-push (link: https://github.com/Krasavinigor/DemoProjectWithRNN). Could you please provide a demo project with the issue?
Hi @nighttiger1990, @JB-CHAUVIN! Unfortunately, I'm going to close this issue for now as I haven't heard from you in a while. Please feel free to reopen it if you have any questions.
My app is using RNN and uses codepush. When running the app with
react-native run-android
everything works and I can update using codepush. But when I install the app, the app crashes after the codepush update.Expected Behavior
same behavior on installed app and app running with local packager
Actual Behavior
What actually happens?
Environment