Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

My app stops white blank screen when app back to foreground from background #1232

Closed
gouteru opened this issue Apr 20, 2022 · 15 comments · May be fixed by #1235
Closed

My app stops white blank screen when app back to foreground from background #1232

gouteru opened this issue Apr 20, 2022 · 15 comments · May be fixed by #1235

Comments

@gouteru
Copy link

gouteru commented Apr 20, 2022

Bug Report

Many of my app users has been reporting the issue that my app stops as white screen when it back to foreground from background.

Problem

What is expected to happen?

When back to foreground, app should display its webview contents properly.

What does actually happen?

When back to foreground, app displays white blank screen and no way to control by user(it looks freezing).

Information

I have been researching the issue a couple of months because I haven't reproduced.
Finally I could reproduce the issue by killing 2 webview processes with Acitivity Monitor of MacOS.

Here’s the procedure.

  1. Start app with XCode Simulator(ex: iPhone12 mini).
  2. By using Simulator, get app switch to background.
  3. Kill 2 processes(com.apple.Webkit.networking, com.apple.Webkit.WebContent) of app by using Activity Monitor. Clicking “Forced termination“.
  4. Back the app to foreground.
  5. The app shows white screen and no way to control.

When the app is back to foreground, app shows white screen but the killed 2 processes are reloaded in Activity Monitor view. But those 2 processes seem never communicate with app main process properly.

I guess, cordova-ios detects that webview processes are terminated and do webview.reload() but after that the reloaded processes are not communicating with app main process. Then my Javascript code is not loaded, not working, not rendering anything, so I can do nothing.

Here’s the log of Xcode.

2022-04-19 21:56:05.574242+0900 Miley PTA[1372:4054372] app entered background
2022-04-19 21:56:05.574344+0900 Miley PTA[1372:4054372] Set state background
2022-04-19 21:56:05.574434+0900 Miley PTA[1372:4054372] Disconnected from FCM
2022-04-19 21:56:05.590935+0900 Miley PTA[1372:4054372] [Snapshotting] Snapshotting a view (0x7fd97b078a00, UIKeyboardImpl) that has not been rendered at least once requires afterScreenUpdates:YES.
2022-04-19 21:56:05.893567+0900 Miley PTA[1372:4054372] pause!
2022-04-19 21:58:28.746089+0900 Miley PTA[1372:4054372] [Process] 0x111aca330 - NetworkProcessProxy::didClose (Network Process 0 crash)
2022-04-19 21:58:28.746328+0900 Miley PTA[1372:4054372] [Process] 0x111af1600 - [PID=1511] WebProcessProxy::didClose: (web process 0 crash)
2022-04-19 21:58:28.746420+0900 Miley PTA[1372:4054372] [Process] 0x111af1600 - [PID=1511] WebProcessProxy::processDidTerminateOrFailedToLaunch: reason=4
2022-04-19 21:58:28.747083+0900 Miley PTA[1372:4054372] [ProcessSuspension] 0x111abd420 - ProcessAssertion: Failed to acquire RBS Background assertion 'ConnectionTerminationWatchdog' for process because PID is invalid
2022-04-19 21:58:28.747464+0900 Miley PTA[1372:4063884] [ProcessSuspension] 0x111abd420 - ProcessAssertion: Failed to acquire RBS assertion 'ConnectionTerminationWatchdog' for process with PID=0, error: (null)
2022-04-19 21:58:28.747907+0900 Miley PTA[1372:4054372] [Process] 0x7fd97b033420 - [pageProxyID=11, webPageID=12, PID=1511] WebPageProxy::processDidTerminate: (pid 1511), reason 4
2022-04-19 21:58:28.750921+0900 Miley PTA[1372:4054372] [Loading] 0x7fd97b033420 - [pageProxyID=11, webPageID=12, PID=1511] WebPageProxy::dispatchProcessDidTerminate: reason=4
2022-04-19 21:58:28.763300+0900 Miley PTA[1372:4054372] CDVWebViewEngine shouldReloadWebView::
2022-04-19 21:58:28.763576+0900 Miley PTA[1372:4054372] CDVWebViewEngine shouldReloadWebView title:
2022-04-19 21:58:28.763874+0900 Miley PTA[1372:4054372] CDVWebViewEngine shouldReloadWebView location: app://localhost/index.html#/AppView
2022-04-19 21:58:28.764176+0900 Miley PTA[1372:4054372] CDVWebViewEngine shouldReloadWebView reload: 0
2022-04-19 21:58:29.053010+0900 Miley PTA[1372:4054372] app become active
2022-04-19 21:58:29.053151+0900 Miley PTA[1372:4054372] Set state foreground
2022-04-19 21:58:29.145401+0900 Miley PTA[1372:4054372] IAB.close() called but it was already closed.
2022-04-19 21:58:29.584398+0900 Miley PTA[1372:4054372] Cordova view ready
2022-04-19 21:58:29.589231+0900 Miley PTA[1372:4054372] BuildInfo init: 0.0000 sec(40616 nsec): Cache data return
2022-04-19 21:58:29.590158+0900 Miley PTA[1372:4054372] start Js Event Bridge
2022-04-19 21:58:29.603274+0900 Miley PTA[1372:4054372] FCM: has been created
2022-04-19 21:58:29.603535+0900 Miley PTA[1372:4054372] FCM: Ready!
2022-04-19 21:58:30.373260+0900 Miley PTA[1372:4065189] [boringssl] boringssl_metrics_log_metric_block_invoke(151) Failed to log metrics
2022-04-19 21:58:58.749429+0900 Miley PTA[1372:4054372] Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service
2022-04-19 22:27:59.054707+0900 Miley PTA[1372:4077801] [default] LaunchServices: disconnect event interruption received for service com.apple.lsd.mapdb
2022-04-19 22:28:54.071186+0900 Miley PTA[1372:4080043] [XPC] Handle connection with error: Connection interrupted

Environment, Platform, Device

Various of iPhone hardware and iOS versions has been reported from my app users.

Version information

  • Installed platforms:  android 10.1.1,  ios 6.2.0
  • cordova-plugin-android-dark-mode-support 1.0.0 "AndroidDarkModeSupport"
  • cordova-plugin-androidx-adapter 1.1.3 "cordova-plugin-androidx-adapter"
  • cordova-plugin-badge 0.8.8 "Badge"
  • cordova-plugin-buildinfo 4.0.0 "BuildInfo"
  • cordova-plugin-calendar 5.1.6 "Calendar"
  • cordova-plugin-customurlscheme 5.0.0 "Custom URL scheme"
  • cordova-plugin-fcm-with-dependecy-updated 7.8.0 "Cordova FCM Push Plugin"
  • cordova-plugin-file 6.0.2 "File"
  • cordova-plugin-inappbrowser 5.0.0 "InAppBrowser"
  • cordova-plugin-splashscreen 6.0.0 "Splashscreen"
  • cordova-plugin-statusbar 3.0.0 "StatusBar"
  • cordova-plugin-webviewcolor 2.2.0 "WebView background color plugin"
  • cordova-plugin-wkwebview-file-xhr 3.0.0 "Cordova WKWebView File XHR Plugin"
  • Vue 2.6.14
  • Firebase 9.6.1
  • MacOS 12.3.1
  • Xcode 13.3

Checklist

[x] I searched for existing GitHub issues
[x] I updated all Cordova tooling to most recent version
[x] I included all the necessary information above

@gouteru
Copy link
Author

gouteru commented Apr 22, 2022

Here's info I found about WKwebview process.
https://nevermeant.dev/handling-blank-wkwebviews/

Please help!

@MarcelSchuermann
Copy link

MarcelSchuermann commented Apr 22, 2022

I have a similar issue.
Now with cordova 11 I get stuck at the splash screen window on iOS after I kill (close) the app and reopen it.
Any hints?

Maybe remove all plugins and add one by one again or clean build in Xcode (Product > Clean Build Folder). But for me it did not work.

edit:
For me there seems to be a problem with the plugin cordova-plugin-screen-orientation.
Maybe check for any plugins, which could stop your app from loading (OnDeviceReady event).

edit 2:
If I set AutoHideSplashScreen to "true" I get whitescreen too.
If I set it to "false" I still get stuck later when I kill and reload the app.

@gouteru
Copy link
Author

gouteru commented Apr 23, 2022

I have a similar issue. Now with cordova 11 I get stuck at the splash screen window on iOS after I kill (close) the app and reopen it. Any hints?

Maybe remove all plugins and add one by one again or clean build in Xcode (Product > Clean Build Folder). But for me it did not work.

edit: For me there seems to be a problem with the plugin cordova-plugin-screen-orientation. Maybe check for any plugins, which could stop your app from loading (OnDeviceReady event).

edit 2: If I set AutoHideSplashScreen to "true" I get whitescreen too. If I set it to "false" I still get stuck later when I kill and reload the app.

I think your issue is probably different from mine.

@MarcelSchuermann
Copy link

I could solve mine.
It was an error in OnDeviceReady (i was acessing a device function before it was initialized). The error does not happen in desktop browser therefore I needed to debug with safari on physical device.
GL to you!

@gouteru
Copy link
Author

gouteru commented Apr 24, 2022

Any update on this?
I think iOS will terminate com.apple.Webkit.WebContent process anyway, but that can't be prevented.
I think the real problem is that after reloading the webview with webViewWebContentProcessDidTerminate, app can't communicate properly with the reloaded webview process.

Can't detect an error like "Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service"? And if it can be detected, is there any way to reload webview again or restore communication with the WebContent process?

@gouteru
Copy link
Author

gouteru commented Apr 28, 2022

I think I found the root cause.
The root cause was wkwebview.URL when webViewWebContentProcessDidTerminate was called.
When I terminated "com.apple.WebKit.WebContent" process, webViewWebContentProcessDidTerminate was called but the reload url was incorrect as "app://localhost/index.html#/AppView". The url indicates one of my Vue JS component (the url is the one when app get into background) but not the initial url.
Due to my app is based on Cordova and Vue framework and initial entry file should be "app://localhost/index.html".
Then I modified ios/CordovaLib/Classes/Private/Plugins/CDVWebviewEngine/CDVWebviewEngine.m file as follows.
The change worked fine. I could reproduced 100% of white screen issue with the above mentioned procedures however with the code change below I cannot reproduce the white screen issue.
Since I am not familiar with ObjectiveC and CordovaLib fashion, please someone review the code below and let me know if it's okay or there is better code.

- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
{
    NSLog(@"webViewWebContentProcessDidTerminate  wevView reload:");
    NSString *sURL = @"app://localhost/index.html";
    NSURL *url = [NSURL URLWithString:sURL];
    NSLog(@"webViewWebContentProcessDidTerminate  url: %@", [url absoluteString]);
    NSLog(@"webViewWebContentProcessDidTerminate  wevView.url: %@", [webView.URL absoluteString]);
    [webView loadRequest:[NSURLRequest requestWithURL:url]];
    // [webView reload];
}

@gouteru
Copy link
Author

gouteru commented Apr 29, 2022

Here's additional changes below.

- (BOOL)shouldReloadWebView:(NSURL*)location title:(NSString*)title
{
    BOOL title_is_nil = (title == nil);
    BOOL title_is_empty = ([title length] == 0); // added!
    BOOL title_is_bad = (title_is_nil || title_is_empty);  // added!
    BOOL location_is_blank = [[location absoluteString] isEqualToString:@"about:blank"];

    // BOOL reload = (title_is_nil || location_is_blank);
    BOOL reload = (title_is_bad || location_is_blank);  // added!

#ifdef DEBUG
    NSLog(@"%@", @"CDVWebViewEngine shouldReloadWebView::");
    NSLog(@"CDVWebViewEngine shouldReloadWebView title: %@", title);
    NSLog(@"CDVWebViewEngine shouldReloadWebView title length: %u", [title length]); //  // added!
    NSLog(@"CDVWebViewEngine shouldReloadWebView title is nil: %u", title_is_nil);
    NSLog(@"CDVWebViewEngine shouldReloadWebView location: %@", [location absoluteString]);
    NSLog(@"CDVWebViewEngine shouldReloadWebView location is blank: %u", location_is_blank);
    NSLog(@"CDVWebViewEngine shouldReloadWebView reload: %u", reload);
#endif

    return reload;
}
- (void) onAppWillEnterForeground:(NSNotification*)notification {
    if ([self shouldReloadWebView]) {
        NSLog(@"%@", @"CDVWebViewEngine reloading!");
        NSString *sURL = @"app://localhost/index.html";
        NSURL *url = [NSURL URLWithString:sURL];
        NSLog(@"onAppWillEnterForeground  url: %@", [url absoluteString]);
        [(WKWebView*)_engineWebView loadRequest:[NSURLRequest requestWithURL:url]];
        // [(WKWebView*)_engineWebView reload];
    }
}

I think shouldReloadWebView's title check is insufficient. In my app's case when WebContent process is terminated, title is not nil but empty string. So, empty string check should be added.
With the changes above, my app works fine when WebContent process is terminated while app is in background. When app back in foreground, shouldReloadWebView detects properly and then load index.html.

With this change, when WebContent process is terminated while my app is in background, and then back in foreground, 2 functions "onAppWillEnterForeground" and "webViewWebContentProcessDidTerminate" do loadRequest. As long as my test, 2 times of loadRequest is not making any issue.

@gouteru
Copy link
Author

gouteru commented Apr 29, 2022

I think many of Cordova users will use additional JS frameworks such as Vue or React. So the url issue when WebContet process is terminated by iOS, is critical. When WebContent process is terminated, everything of JS code and state is cleared from memory. In that case, WebContent should load with index.html because app should go through its initialization to initialize Cordova plugins or firebase, etc. But currently, the url is as-is when app switched into background.
Please consider to release update of cordova-ios.

@bratelefant
Copy link

bratelefant commented Apr 29, 2022

Thanks @gouteru for your patch; I‘m running into similar issues with Cordova and meteor 2.7.1.

Applied your patch, with no success. Still WSOD. Meteor determines the port number for localhost based on App ID or something, in order to avoid conflicting ports with other apps. Does your patch take care of ports?

PS: Will try your method to reproduce the issue, which was not really possible before …

@gouteru
Copy link
Author

gouteru commented Apr 30, 2022

Applied your patch, with no success. Still WSOD. Meteor determines the port number for localhost based on App ID or something, in order to avoid conflicting ports with other apps. Does your patch take care of ports?

Sorry, I have no idea about ports.

@JH7
Copy link

JH7 commented Apr 30, 2022

@bratelefant see my comment in meteor/meteor#11811 (comment), maybe this fixes it?

@bratelefant
Copy link

bratelefant commented Apr 30, 2022

@JH7 Just read your post, sounds reasonable for me. Will give it a shot and come back later.

What I did until now: Followed @gouteru 's instructions to reload the initial app url; didn't work at first try, due to "allow-navigation" errors, since the url didn't fit the scheme from cordovas config.xml. So i exchanged the url in the patch by http://localhost:<meteors-generated-portnumber>, hardcoded for now. Next try will be your patch.

During testing I can confirm that the following method let's your quite easily reproduce the issue:

  • open your app (production or even via usb on device).
  • send it to background (i.e. go back to the homescreen)
  • open up several other, mem intensive apps (eg. keynote, pages, numbers, photos, ... ) until you notice, that apps get initially loaded to mem if you get back to them (guess iOS is then suspending apps to disk to free main memory)
  • open your meteor app again -> WSOD

Apples "Instuments" app turns out to be quite helpful in monitoring, just learned that it existed... ;)

@saviolenvica
Copy link

hello, i having an similar issue with ios cordova , ios app in simulator works fine, when i try to acess url call its shows nothing just white screen
let me know of the solution as soon as possible
cordova version -11.0.0
ios platforn -5.1.1
cordova plugins used - geolocat

@ronnievdc
Copy link

ronnievdc commented Sep 7, 2022

I currently use a patchfile in my CI chain as follows:

src-cordova/fix-ios-black-screen.patch

diff --git a/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m b/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
index a07bf290..82356def 100644
--- a/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
+++ b/CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVWebViewEngine.m
@@ -270,7 +270,9 @@ static void * KVOContext = &KVOContext;
 - (void) onAppWillEnterForeground:(NSNotification*)notification {
     if ([self shouldReloadWebView]) {
         NSLog(@"%@", @"CDVWebViewEngine reloading!");
-        [(WKWebView*)_engineWebView reload];
+        NSURL* url = [((CDVViewController*) self.viewController) appUrl];
+        NSURLRequest* appReq = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
+        [self loadRequest:appReq];
     }
 }
 
@@ -516,7 +518,11 @@ static void * KVOContext = &KVOContext;
 
 - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
 {
-    [webView reload];
+    CDVViewController *vc = (CDVViewController *)self.viewController;
+    [vc showLaunchScreen:true];
+    NSURL* url = [vc appUrl];
+    NSURLRequest* appReq = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
+    [self loadRequest:appReq];
 }
 
 - (BOOL)defaultResourcePolicyForURL:(NSURL*)url
diff --git a/CordovaLib/Classes/Public/CDVViewController.h b/CordovaLib/Classes/Public/CDVViewController.h
index 81c7128f..52677c67 100644
--- a/CordovaLib/Classes/Public/CDVViewController.h
+++ b/CordovaLib/Classes/Public/CDVViewController.h
@@ -62,6 +62,7 @@
 
 - (NSString*)appURLScheme;
 - (NSURL*)errorURL;
+- (NSURL*)appUrl;
 
 - (UIColor*)colorFromColorString:(NSString*)colorString CDV_DEPRECATED(7.0.0, "Use BackgroundColor in xcassets");
 - (NSArray*)parseInterfaceOrientations:(NSArray*)orientations;

Somewhere in the CI chain (release_ios.sh)

cd src-cordova/platforms/ios
patch -N -p1 < ../../fix-ios-black-screen.patch

@saviolenvica
Copy link

i think i have the same issue as you had, can you help out with the issue

@gouteru gouteru closed this as completed Sep 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants