Remembering State Before App Goes in Foreground

Remembering state before app goes in foreground

you can show/hide Splash in modal instead of screen when app status change

import {  Modal } from "react-native";

const [modalVisible, setModalVisible] = useState(false);

const _handleAppStateChange = nextAppState => {
if (
appState.current.match(/inactive|background/) &&
nextAppState === 'active'
) {
setModalVisible(false);
} else {
setModalVisible(true);
}
};

return (
<>
<AuthContext.Provider
value={{ user, setUser, authenticated, setAuthenticated }}
>
<NavigationContainer theme={navigationTheme} ref={navigationRef}>
{user && authenticated ? (
<AppNavigator />
) : user ? (
<PasscodeNavigator />
) : (
<AuthNavigator />
)}
</NavigationContainer>
</AuthContext.Provider>
<Modal animationType="slide" transparent={true} visible={modalVisible}>
<SplashScreen />
</Modal>
</>
);

How to detect when an Android app goes to the background and come back to the foreground

The onPause() and onResume() methods are called when the application is brought to the background and into the foreground again. However, they are also called when the application is started for the first time and before it is killed. You can read more in Activity.

There isn't any direct approach to get the application status while in the background or foreground, but even I have faced this issue and found the solution with onWindowFocusChanged and onStop.

For more details check here Android: Solution to detect when an Android app goes to the background and come back to the foreground without getRunningTasks or getRunningAppProcesses.

Jetpack compose - how do I refresh a screen when app returns to foreground

Edit 2: There is a new issue to have this feature included in the Compoose API. Not yet available thought (as of aug 2022)

Edit: If you want a "pure" compose answer, check @JoJoIV 's answer

Answer:

Compose is not aware of state changes like onPause or onResume, you have to handle it using the parent activity's methods.

An example would be a LiveData instance in your activity that updates each time onResume is executed and observe it as a state in your main parent composable.

Let's take a look at the following example:

class MainActivity : AppCompatActivity() {
// Use whatever type your prefer/require, this is just an example
private val exampleLiveData = MutableLiveData("")

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// Your main composable
MyApplicationTheme {
// Save the state into a variable otherwise it won't work
val state = exampleLiveData.observeAsState()
Log.d("EXAMPLE", "Recomposing screen - ${state.value}")

Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
}

override fun onResume() {
super.onResume()

// Save whatever you want in your live data, this is just an example
exampleLiveData.value = DateTimeFormatter.ISO_INSTANT.format(Instant.now())
}
}

@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
MyApplicationTheme {
Greeting("Android")
}
}

As you can see in this example, I have a LiveData property in my activity that containts a String. Whenever onResume is executed the property is updated with the new timestamp and the observing composable is recomposed.

On Application Resume From Background To Foreground, App Restarts From First Navigation Screen

I solved it by using State Persistence of react-navigation

Here is the documentation https://reactnavigation.org/docs/4.x/state-persistence/

Here is what my App.js look like now

import AsyncStorage from '@react-native-community/async-storage';

const App: () => React$Node = () => {

const persistenceKey = "navigationStatePersistenceKey"
const persistNavigationState = async (navState) => {
try {
await AsyncStorage.setItem(persistenceKey, JSON.stringify(navState));
} catch(err) {
// handle error
}
}
const loadNavigationState = async () => {
const jsonString = await AsyncStorage.getItem(persistenceKey);
return JSON.parse(jsonString);
}
return(
<View style={{flex: 1, backgroundColor: '#000000'}}>
<AppContainer
persistNavigationState={persistNavigationState}
loadNavigationState={loadNavigationState}
/>
</View>
);
};

It now takes user to the same screen where it was left off, no more restart from first screen.

Reload application data when the app comes into foreground?

- (void)applicationDidBecomeActive:(UIApplication *)application {
}

Reload the data in the above function of the app delegate to refresh the data when ever the app comes to foreground.

Issue when app coming back to foreground

A dirty workaround to your problem is to check if the global variables are filled in the onResume method of your activities. If the variables are not filled start the splashscreen activity with an Intent with the CLEAR_TOP flag set. This should cause all your activities to be removed from the activity stack and your splash screen will load and is able to reload all the data needed for your app to work.

This is a dirty workaround to help a badly designed application to work.
If you want your app to be nicer to you and the user go with the solution inazaruk provided. He is correct about the basic setup of an application.

Android App, Activity State (Running, Not Running, Foreground/ Background)

To differentiate between case #2 and case #3, you can do the following:

Launch ActivityB if it is not case #1. In ActivityB.onCreate() do this:

super.onCreate(...);
if (isTaskRoot()) {
// ActivityB has been started when the app is not running,
// start the app from the beginning
Intent restartIntent = new Intent(this, MyRootActivity.class);
startActivity(restartIntent);
finish();
return;
}
... rest of onCreate() code here...

Will application Relaunch after app goes background

Quick "prologue":

Welcome to the wonderful world of stack overflow (SO), I myself am rather new here, but found it much friendlier to use welcome you anyway!

Just in case you haven't: Before you ask a question please look around a bit on SO in case someone else has asked the same thing, but if you can't get your question answered from that, then you should of course ask your own question.

Answer:

This question has no definite answer, because it depends. When you tap the home button your app enters, as you've said, the background and is still running to a certain degree. However after done so, the apps life cycle is up to iOS (the devices operating system) to determine. iOS controls and checks memory and CPU usage (etc..) of the device, and if you start another activity while your app is in the background that makes the available memory and CPU etc of the device not sufficient, iOS will terminate any apps in the background to not waste those resources (or battery etc). If so your app will relaunch next time you tap on it.

Although if you don't do anything performance heavy it is more likely that iOS keeps your device running in the background.

I'm not sure about the exact conditions and such the iOS works on, but i would say its very likely your app will have gotten terminated and is relaunched after 1 or 2 hours "in the background". Additional conditions apply if the device is locked during that period.

For proper documentation of this i would recommend reading Apples documentation for handling App State Transitions and/or the api for UIApplicationDelegate on apples developer website. Where you can see what the different methods in the AppDelegate does and how they interact.

Edit (answer to comment):

  1. A way to relaunch the app everytime it goes into background?

    • Hm, yes, but also no. I'm not 100% sure about this (never encountered that "wish" before), but you can do this in your AppDelegate: (It will basically crash your app, but beware that apple does not encourage you to crash your own app anywhere). Doing this might stop the app from passing through apple store review process (i.e. your app might not be accepted to the App Store).

      func applicationDidEnterBackground(_ application: UIApplication) {
      exit(0)
      }
    • Check out the answer to these post for a bit more information: call exit(0) in iphone app , objc - Proper way to exit iPhone application?.

    • Personally I would recommend you to work around it and don't do this. Also remember that when your app will enter the background applicationWillResignActive will be called and when the user opens it again, applicationDidBecomeActive gets called so you can do a reload or something from there if you want to refresh any data.



Related Topics



Leave a reply



Submit