React-native app whitescreen when in background for a longer time - ios

Short description of our situation:
We have a react-native application which renders a website with react-native-webview (https://github.com/react-native-webview/react-native-webview)
Whenever our application is in the background for a longer time (mostly occures over night), the application results in a whitescreen when opening up the next day. This only really occures on iPhones - not on android devices / nor on iPads.
When the application goes to the background, we stop all polling tasks and the app isn't really doing anything till it comes to the foreground again.
Does anyone have an idea what could cause this problem? Is this a general problem on iPhones with webviews?
We have a possible fix by really disabling the webview, when the app goes to the background (by not rendering the Webview once the appState goes to background). Still would be interesting to know where this comes from.
I'm thankful for any help!
Have a nice day.

I found this information with a possible solution: https://blog.embrace.io/bug-of-the-month-blank-webviews/
They occur when web views fail or are killed by the OS. Normally, a process being killed would crash the application, but on iOS, WKWebViews have two additional processes: a content process and a networking process. These can be killed without affecting the main application process. You can provide a better user experience by deciding which web views should be reloaded upon failure and adding this functionality through the webViewWebContentProcessDidTerminate callback on WKNavigationDelegate.
Haven't tried it out yet - but will.

Related

Differences between normal app startup and a wakeup from WatchKit's sendMessage?

According to the docs, sending sendMessage from the WatchKit app will wake the iPhone app if it is inactive.
I would like to know the differences between such a wakeup app startup and a normal one. Surely a background process has a lot of differences to a normal foreground app. However, I could not find a thorough documentation on the subject.
Here's what I found so far:
Since such a "wakeup" is not a normal app startup, I expect didFinishLaunchingWithOptions to receive a special launchOptions key. After all, the user did not start the app on the home screen, so there should be an indication in launchOptions. But when I tried it out, launchOptions was nil. Doesn't that contradict the docs?
I also thought there should be differences because there is no UI present in a background process. So perhaps [UIScreen mainScreen] might be nil. But there seems to be no difference in mainScreen in the background process. In my AppDelegate.m, the code that creates the main window seems to run exactly the same way as in the foreground process.
I also expect that there are limits to the background process. Since the user did not actively start the process, I'm pretty sure that it cannot run for an infinite amount of time. Maybe there are also stricter memory limits.
Is there a way I can debug such a background process in XCode? Can I tell XCode "wait until the app runs on the iPhone", such that the debugger gets attached as soon as the app runs?
I also tried this in a React Native app. The Objective-C code in AppDelegate.m seemed to run exactly the same way, regardless of background or foreground process. However, the whole Javascript part of the app did not run (which is kind of expected, because in a background process, we do not need any React UI). But there must be a difference in the process that causes the Javascript part to not run.
Please don't consider this question to be about "more than one question". The question of this post is quite clear: I want to know all the differences between a didReceiveMessage background process and a normal one. In the enumeration above, I just listed all the differences I would expect or that I have encountered so far, and the lack of documentation on those topics.
I think the background mode is just a UIKit concept. The app is started (thanks to the UIApplicationMain function) as a regular one but your app UI is not rendered.
It is just a warning: this is a transition state, your app can be suspended at any moment, be concise. The documentation is clear.
Regular UIKit APIs are available (if it was not the case, imagine all the potential crashs). But you won't receive any external events like touches.
Some external tasks like asking permissions, launching audio sessions etc would probably not be available too.
You can wait for the app to be launched by using the wait for the executable to be launched option in the scheme panel.
But when I tried it out, launchOptions was nil. Doesn't that contradict the docs?
Unfortunately LaunchOptions doesn't cover all ways an app gets launched. So if you see it nil then your case is one them too.
But there seems to be no difference in mainScreen in the background process.
That's true and expected. Things all get launched using the main thread. See here
Is there a way I can debug such a background process in XCode?
GaetanZ Has already answered this. Additionally you can use os.log and console together. That gives you a more realistic approach. Xcode interruptions are not fun to deal with. The wait for the executable to be launched scheme change often makes debugging super slow or often Xcode just disconnects or even throws you weird errors and the app gets killed without even giving you the option to attach to the debugger again.
I often use reboot the phone entirely. And then use oslog to see what happens to my app without ever having Xcode connected. For more on that see here.
A reboot is different to user-termination because often things don't get launched after-user termination. That being said I don't think the OS restricts app launch if user engages with their watch — even after a user-termination. Because user-engagement trumps everything.
However, the whole Javascript part of the app did not run (which is kind of expected, because in a background process, we do not need any React UI).
You then also said "which is kind of expected, because in a background process, we do not need any React UI"
I know very little of React, but also I'm confused what your question is about if you say it's expected.
But the part that the AppDelegate goes through all it's life-cycle is expected as previously mentioned.
You need to add a gazzilion amount of logs to see where you have a different code-path.
Most developers don't know that launching the app into the background will go all the way till the root viewController of your app and all its child viewcontrollers and stuff. But you learned it the hard way. Just as I did. Congratulations!
But once you know of that then the next thing is making sure your app doesn't segue into a different code-path i.e. on a normal launch you get WillBecomeActive and willEnterForeground, for a launch into the background you get something else. I'm not sure what it is right now. I think it's WillBecomeActive & didEnterBackground. Not sure.
Or like you may not be setting the delegate of your webview before things fire off and you miss its callbacks.
Remember app being in a background state doesn't mean things get executed on background queue. everything gets executed on the same queue/thread as it would in a foregrounded app. The only thing different is that the OS will often restrict network calls when an app isn't provisioned for them.
Likely that's what's happening. Like the OS doesn't want a webview to make network calls when it hasn't informed the app to be using and background Tasks as mentioned here or here

iPhone restarts after API call

I am facing a very weird issue: my iPhone is restarting.
This issue occurs in a particular scenario only.
Step 1: I have a sync process in which I'm loading data for the whole app. So I'm basically doing a heavy API call by uploading 4-5 camera captured images and syncing the app data;
Step 2: After syncing, I'm pressing the iPhone home button to make the app go in background;
Step 3: I'm locking the iPhone screen(by using side button);
After a few seconds I'm seeing the apple logo and the phone seems to restart. This is not replicating when the app is connected in debug mode. I checked the debug navigator app is using only 125 MB of memory, disk and network values is 0%. Energy Impact is showing high, I'm not sure this is due to high energy impact. I'm facing this issue only on iOS 12.4.
The fact that the phone (or possibly just springboard) restarts, and not just your application means this is Apple's bug. You're not supposed to be able to crash iOS even if you try.
Finding a likely cause will be hard since the system is not behaving the way it's supposed to. The device's logs may have more information from things other than your app. This may be a system API breaking due to any number of actions from your application.
Often with this kind of thing the next OS version will fix it, but if that's not the case or it's important to track down I would try removing ways you're interaction with the system (background APIs, notifications, etc.) and see if anything fixes the issue.
If you find the problem, you may even be doing things the "correct" way according to the documentation and have to find a workaround. If you have the time you can submit a bug to Apple so the underlying issue has a better chance of being fixed.
It seems when your app is in the background and phone locked, Automatic Reference Counting (ARC) closes some connection or deallocates a resource that makes the iPhone restart. Are you closing all connections and removing all references once the upload is complete?
Phones do not spontaneously restart just because of an app’s actions. You’re having an issue with your phone, not with a program. You need to repair or replace the phone.

How to debug a crash which happened when come back from background

There is a crash happen when coming back from background through app icon.
However I cannot see any detail info in console log. There is a signal to terminate, but we cannot find signal number.
<FBApplicationProcess: 0x117bcb930; Maixxxx; pid: 1762> exited abnormally via signal.
Process exited: <FBApplicationProcess: 0x117bcb930; Maixxx; pid: -1> -> <FBApplicationProcessExitContext: 0x17103f820; exitReason: signal; terminationReason: (none)>
The procedures to reproduce my crash is as follow:
Start app through click on app icon.
Use the app as normal user.
Press home to put it in background.
Wait for some minutes.
Click the app icon on springboard screen in order to use it again.
The app crash&exit.
Since the crash only happen when coming back from background, and required to enter background for some minutes, I cannot run in debug mode with lldb attached.
I didn't use any of background features.
Also, I didn't see any crash report in Fabric's Crashlytics. So I think signal handler could not be called neither?
How to investigate this kind of problem?
These things can be tough, I know that from similar experiences. Without knowing more about your app I can only offer hints and no definitive answer, but perhaps this helps you.
The fallback and tedious approach to use direct logging with print and so on notwithstanding there are a two ways to try to "catch" a process.
However, first let me stress that "background" is not always the same and people unfortunately use the term often loosely. Depending on what state transition causes your crash you might run out of luck and have to simply experiment using manual logging. Apps can be in background, i.e. not in the foreground, but still running. This is usually the case when the debugger is attached, otherwise it couldn't do its job. Alternatively they can be suspended (or even terminated) by the OS. The debugger prevents this, which you probably already figured out.
The two things that might help you are:
If you're using background fetch, i.e. "coming back from background mode" as you describe it happens automatically you can activate the "Launch due to a background fetch event" option in your build scheme's "Run" configuration section.
Run your app from the Home screen, put it into background with the Home button and wait a bit (you've probably done so in the past already to get a feeling for when the crash would happen). Your app should eventually go into the suspended state (but you have no way to actually see that anywhere AFAIK). Instead of getting it to the foreground again via the multitasking UI, simply attach the debugger again via the "Debug - Attach to process" menu. This should get your app from the suspended state back into the background state, where the crash probably really happens (if it were to happen when coming from background to foreground you probably would have been able to debug it as usual). Hopefully the debugger has finished attaching to it in time, otherwise I'm out of ideas. :(
I haven't run into this specific problem myself personally, but I know background stuff can be tricky. Maybe this discussion also helps you (I took part of my info from there as well).
Run the app in debug mode on a real device. Press the Home button to send the app to background and continue the debugging. Then you can bring the app to foreground and keep debugging, or put a breakpoint at applicationWillEnterForeground.
You can't debug this on the real device. When the debugger is attached, your apps will never go to background mode in the real device.
You can try to debug this on a simulator.
Anyway please check your class attributes and set attributes to strong to make sure this is not happened by missing attributes.
I have read several StackOverflow questions that have FBApplicationProcess. Usually, this one happened by missing array or something when the app started.
Best regards.
I have gone through all the above answers and all have given proper answers. Though, I would like to share my point of view.
If the app is running on any iOS real device with debug mode and wire plug-in or even on Simulator, App will never go in the background.
If the app is running without wire plug-in or run without Xcode(directly launch the app in iPhone) and then put the app in the background, the app will be running in the background of next 3 mins. After 3 mins, the App will automatically be suspended and removed from the main thread. Now, when we open the app again, It will be considered a fresh launch.
If your app having any Background Capabilities ON, then your app will be alive even in the background, but you can't do any UI changes during that time.
To keep app alive in the background, Background Capabilities must be handled properly. ie. If Location is used in your app with 'While-App is in Foreground' condition, app will not run more than 3 mins in background. So, If you want to run your app continuously in background, you must have to represent proper reason in Info.plist file with Battery drain word, or else, Apple will reject it.
Ping me for more detail on your question.
Thanks.
Crash logs still available on your test device.
To get the crash log try the following steps:
Connect your test device to the Mac through USB.
Launch Xcode. Go to Windows > Devices and Simulators.
Choose your device from the devices section on the left side of the screen.
Select View Device Logs button.
Identify and select the Crash Log to see the contents.

If the app is suspended while NSTimer is running, will it crash upon reopening?

Theres something that is making my app crash between when it gets suspended and when it's reopened. It's a location based app that uses the didUpdateLocations callback/delegate function. I have one or two timers running in the background, and i'm not really sure what happens to them when the app is minimized.
I've been doing some thinking. Really, if the timers aren't running in the background that's fine; they dont need to be. But are they getting suspended, and when the app pulls back up they try to catch up to where they were or something? Why does my app crash when i reopen it?
It's not as simple as crashing when it reopens either. It works if it's a normal amount of time. The app is made to run in the background indefinitely, within reason, so if i wait a day or two before opening it again, it crashes on me. Doesn't crash, necessarily, but freezes. It doesnt send a crash report, just sits there and does nothing. I cant interact with the UI or anything. What could be causing it to do this?
Like i said, the only things that run "indefinitely" are the didUpdateLocations method and one or two timers that check things. That's program flow. It all stems from that. I can offer some code or more information if anybody needs it.
Any ideas?
As mentioned by lehn0058, the timers fire once for each missed increment when the app opens. This is potentially disastrous, and sounds like if the timer isn't set up to count down to something, it should probably be invalidated and restarted each time the app is opened and closed. Another option that i discovered recently is software called Flurry. It's analytical software that i recently integrated into my app. Potentially extremely useful; others should look into it if they havent heard of it.

Can throwing the iPhone high in the air launch my app or trigger desired function in iOS 7 or later

My app is an emergency app. It will be used by people in emergency and disasters.
It's possible that they got stuck in situations where they just don't have the time to enter or draw their password on the lock screen, launch the app and push a button. Is it possible that my app can ask the OS to launch the app if user throw their iPhone up in the air or shake it vigorously or something else.
What I wish to achieve by this ?
I want that OS launches my app in background if the user say shake his/her iPhone vigorously. Once launched my app will make a network request and keep running in background for short time.
PS:I think it's possible with the accelerometer.
Accelerometer will not work because Apple doesn't allow background processes opening apps. In your case, user must be opening the app by himself/herself manually. (PS. As far as I know, it's possible in Android)
iOS background tasking problems aside:
Apple don't allow apps that encourage the user to do things that might damage their iOS device. So your 'throw in the air' idea is out.
As for shaking the device -- this just isn't practical. What if the device gets shaken by accident? You've then got false alarms to deal with.
The crux of the issue is that something that triggers an emergency response should be a deliberate action which is hard to do trigger by accident.
This cannot work - and here's why.
Your app would need to run in background to handle motion events. Apps running in background can get killed at any time, i.e. if memory gets low. There might be some restrictions about running and and resource usage as well.
An app in the background cannot bring itself to the front.
Launching from a locked screen would bring great security risks.
Throwing into the air seems like a gesture that can easily be triggered by accident.
I must admit that I'm pretty happy that those apps are not allowed on the AppStore - as it would open many doors that I'd like to see kept close.

Resources