Android app freezes instead of getting crash in Jetpack Compose project - crash

I implemented crashlytics in my android project. Now wanted to test crash and while I try to crash application by throwing Runtime exception in my compose project instead of crashing UI gets frozen forever.
No ANR nothing just UI freeze.
Anybody having clue why its happening and how it can be fixed.
Update:
Here is code that I'm using to crash app:
Button(
onclick = {
throw RuntimeException("issue test")
}
)
{
Text("Crash")
}

Related

Expo API for app updates resulting in blank white screen

I’m using Expo in the managed workflow. The app is coming along and I’ve added the ability for the app to auto-update itself. I’m using the expo-updates library: https://docs.expo.dev/versions/latest/sdk/updates and the implementation is pretty straightforward.
When our app is opened, our app’s App.tsx runs Updates.checkForUpdateAsync() and then Updates.reloadAsync(). We throw up a brief spinner and 9 out of 10 times the update works just fine. But about 1 out of 10 times the app screen goes white. The iOS header bar with time and Wi-Fi is still visible, but everything else is white. The user has to kill the app and re-open it to resume and now they’re running the latest version.
Unfortunately, this is a difficult issue to reproduce. We can’t do updates in development so we are trying to debug this in our staging environment (a mirror of production). Our repro steps are to push a trivial update to Expo, when the build completes, relaunch the app. We have to do it about ~10 times before we’ll get a freeze case.
The key code is: App.tsx runs:
newUpdate = await checkForAppUpdate()
If (newUpdate) await forceUpdate()
And then our library for these two methods is simple:
import * as Updates from 'expo-updates'
import {Platform} from "react-native"
export const checkForAppUpdate = async (): Promise<boolean> => {
if (Platform.OS == "web" || __DEV__) return false
try {
const update = await Updates.checkForUpdateAsync()
return update.isAvailable
} catch (e) {
console.error(e)
return false
}
}
export const forceUpdate = async () => {
try {
const result = await Updates.fetchUpdateAsync()
if (result.isNew) {
await Updates.reloadAsync()
}
} catch (e) {
console.error(e)
}
}
I’m at a loss for how to debug this. Any clues as to what might be going on? I’m assuming a race condition given the sporadic behavior but I’m stuck.
I ended up figuring this out, but it was tricky. I added all sorts of additional logging to try and catch any exception being thrown and there was not one. The issue is that I had a new dependency in my Expo build/bundle which was not yet supported by the binary version of my app I was running. I rebuilt my binary with the latest libraries and this started working again.
So anyone else who might be faced with this issue: do an audit of all library dependencies with your app and roll back to a previous version when updating was working to isolate what changed.

Segment trackEvent doesn't work right after CodePush update installs

Our React Native project has both Segment and CodePush integrated.
Segment works fine, normally.
But there's a scenario where Segment stops working right after a CodePush update has been installed. Nothing gets flushed out and none of the events are shown in the Live Debugger list - except for events that are tracked in the native layer (eg: "Application Opened" and "Application Backgrounded" - only these show up).
So I assumed that any Segment call in the RN - Javascript layer only stops working after the app restarts the bundle (by CodePush).
The user should close and kill the app and reopen the app for it to work normally again.
Happens to both iOS and Android (when installed from the store).
And weirdly enough, I cannot recreate the issue on Android when I run a debug or release build directly to my Android phone from my machine (it just works 🤷‍♂️). Same goes for iOS simulators.
Any ideas or workarounds on this?
This is how the setup looks like:
import React, { Component } from "react";
import CodePush from "react-native-code-push";
import segment from "#segment/analytics-react-native";
...
class App extends Component {
constructor(props) {
super(props);
this.setupSegment();
}
private setupSegment(): void {
segment.setup("<Segment Write Key>", {
debug: true,
trackAppLifecycleEvents: true,
ios: {
trackAdvertising: true
}
});
}
...
}
export default CodePush({
installMode: CodePush.InstallMode.IMMEDIATE,
checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
updateDialog: null
})(App);
react-native: 0.61.5
react-native-code-push: 6.1.0
#segment/analytics-react-native: 1.1.1-beta.2 (also tried 1.1.1-beta.5)

Why Android App showing blank screen when coming out of an App with back button React Native Navigation?

I am working on React Native Application and integrated react-native-navigation package for navigation inside app, link of package
Android App got stuck and show blank screen. This happens if I am closing app using back button in case of Android app. At the end I have a listing screen, after reopen the application it shows blank screen because it's not calling Navigation.registerComponent again, it might be destroying app when closed using back button.
This is a code inside my index.js::
import { Navigation } from "react-native-navigation";
import App from './src/app';
Navigation.registerComponent("appName", () => App);
Killing the app and restarting would fix the stuck on splash screen issue. But shouldn't be stuck in the first place. Just an issue when closing through back button.
Does anyone have a fix for this? Please suggest how can I handle and call my Navigation.registerComponent once again after closing app using back button.
Environment
React Native Navigation version: 2.12.0
React Native version: 0.58
Platform(s) : Android only
To resolve this you need to make modification inside react-native-navigation package. Open NavigationActivity.java file and replace below code with new one:
Replace this code:
#Override
public void invokeDefaultOnBackPressed() {
if (!navigator.handleBack(new CommandListenerAdapter())) {
super.onBackPressed();
}
}
With this one:
#Override
public void invokeDefaultOnBackPressed() {
if (!navigator.handleBack(new CommandListenerAdapter())) {
this.moveTaskToBack(true);
//super.onBackPressed();
}
}
After saving your changes check on android device.

Component recreated without call to componentWillUnmount

I'm developing a react-native app. I'm currently testing in android and it appears that when the app loses focus and then the launch icon is pressed again that the components are recreated without a call to componentWillUnmount.
I can recreate this with a trivial react-native app:
react-native init MultipleComponents
And adding the following to the App class:
componentDidMount() {
clearInterval(this._interval);
this._interval = setInterval(() => {
console.log("Timeout");
}, 5000);
}
componentWillUnmount() {
console.log("Timeout");
clearInterval(this._interval);
}
Once this is done run it with:
react-native run-android
Then on the emulator you can end up with multiple timers running by pressing the home button and relaunching the app. Having multiple timers running is obviously not ideal.
Note that componentWillUnmount is not called.
Am I missing something? How is this meant to be handled?
The JavaScript thread is gone when the app is not in the foreground, so no React code is executed after your app loses focus and this includes componentWillUnmount and other lifecycle methods.
But if you end up having multiple timers when pressing the icon, you should probably check your AndroidManifest.xml file for launchMode. If the value for launchMode is either standard or singleTop, then multiple instances of your app can exist. If you change the setting to singleInstance or singleTask there will always be just one instance.
android/app/src/AndroidManifest.xml:
<manifest>
<application>
<activity
android:launchMode="singleTask">
</application>
</manifest>

How to initilaze react-native on the view of window manager from android

I'm searching the way to implement running react-native application on both of activity and service in single package.
Running RN app on activity is usual, but can't find the right way to execute another react-native application on the service. The latter app should be run on the foreground service and view on the window manager.
My code roughly looks like:
// ReactNativeWindowService.kt
fun startNewReactWindow(
reactContext: ReactContext,
jsMainModuleName: String?,
bundleAssetName: String?,
module: String
) {
Toast.makeText(reactContext, "START()", Toast.LENGTH_SHORT).show()
val headLayout = createHeadLayout(reactContext)
headsManager.addLayout(headLayout)
launch(UI) {
reactInstanceManager = createReactInstanceManager(reactContext, jsMainModuleName, bundleAssetName)
reactRootView = ReactRootView(reactContext)
reactRootView?.startReactApplication(reactInstanceManager, module, null)
headsManager.addHeadView(bubbleLayout.apply { addView(reactRootView) })
}
}
But, this code produce:
07-10 01:05:07.662 26269-26380/Sample E/ReactNativeJS: Error while starting app: TypeError: undefined is not an object (evaluating 'NativeReactModule.startApp')
07-10 01:05:07.674 26269-26380/Sample I/ReactNativeJS: Running application "index" with appParams: {"rootTag":21}. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
07-10 01:05:07.674 26269-26380/Sample E/ReactNativeJS: Application index has not been registered.
Hint: This error often happens when you're running the packager (local dev server) from a wrong folder. For example you have multiple apps and the packager is still running for the app you were working on before.
If this is the case, simply kill the old packager instance (e.g. close the packager terminal window) and start the packager in the correct app folder (e.g. cd into app folder and run 'npm start').
This error can also happen due to a require() error during initialization or failure to call AppRegistry.registerComponent.
I'm sure that code passed right parameters such as jsMainModuleName to create ReactInstanceManager. (I got same parameters as activity's params)
What do I miss in my code? or any other reference/docs/advice that would be helpful to me. Thanks in advance. :)
You have to make sure that your file MainAcitivity.java has a function
protected String getMainComponentName() {
return "your file name for example abc";
}
But in your index.android.js file you register other component
AppRegistry.registerComponent('123', () => 143);
Where it must be like this e.g.
AppRegistry.registerComponent('abc', () => abc);
Try to fix it.