We have an Ionic v4/Angular app.
A number of users have reported that during a particular operation (selecting and then uploading a video), the app screen will suddenly “go white” and reloading the app is the only way to do anything again.
- The app is not crashing. If left open, the background operation continues and appears to finish.
- Absolutely nothing is visible on the screen. It is just plain white.
- Have not been able to reproduce this issue in a dev build of the app.
- Our error reporting system (Rollbar, JS within the app) doesn’t report anything.
- Historically, when we had issues with WebKit, the app would crash. Therefore, I question that WebKit has a major issue.
Any ideas on how to continue forward to debug the issue? Our next idea is to add additional debugging within the app and see where things are going, but how do we figure out what’s going on if Rollbar already isn’t giving us anything.
All "crash"es are not created equal.
Specifically, an uncaught exception in JavaScript code that is triggered during ordinary event loop processing (which, in practice, is just about everything in your app code) can short-circuit the rendering of the UI. This is IMHO far and away the most common cause of “white screen of death”.
This is different from a “crash” as seen by the underlying OS. The OS doesn’t know or care that your JavaScript house of cards has come tumbling down. This would be consistent with what you are seeing in terms of background uploading continuing to happen.
I would suggest carefully auditing all asynchronous code in your app, to make certain that you are not inadvertently relying on order of execution, as that often changes in the field.
This would be consistent with what you are seeing in terms of background uploading continuing to happen.
Just to be clear, these “background” uploads are happening in JS, too. I’m not sure exactly how to differentiate between the main thread or other threads in this case, but the background upload is actually an XHR. Does that make a difference in this case?
Sort of.
Yeah, whether directly or indirectly, any HTTP requests out of an Ionic app are XHRs, and unless you’re using a plugin like that cordova HTTP, they’re XHRs managed eventually by the webview. So…
I don’t think so, in the sense that “uncaught exception murdering rendering” would still be consistent with an XHR that has been fired finishing its job, because as far as the webview is concerned, your app is still fine. The V8 engine hasn’t crashed, it’s just twiddling its thumbs.
OK! Solved!
It was an out of memory issue.
Somewhere in my research, I found this page: iOS 12, Web View reloads, possibly when using high amount of resources. · Issue #337 · ionic-team/cordova-plugin-ionic-webview · GitHub. The thing that stuck out to me was that several comments pointed out a white screen:
Ever since iOS 12 (up to 12.2) my Apps users have been reporting random crashes, either white screens or the App attempting to reload. Particularly on iPad.
And this one:
I am getting white screen issue after loading 159kb of JSON response. It works fine when the response is empty.
Given that we are sending files in the 10s or 100+MB range, this made sense.
The code was rewritten to use the GitHub - apache/cordova-plugin-file-transfer: Apache Cordova File Transfer Plugin plugin. It’s now much faster and doesn’t cause the white screen issue.
1 Like
Glad you solved it, but extremely unhappy to see the solution be such a step backwards in terms of having to use a deliberately obsoleted plugin across a bridge (Cordova) that itself is on life support.
It’s a bit of a head-scratcher for me, too. It’s a weird edge-case. If it were possible to create a File
reference rather than having to deal with Blob
data, this wouldn’t be necessary. However, I’m not aware of a way to create a real File
object.
It almost appears that File has something that would do this. The FileEntry
object has a .file()
method which returns an IFile
, but when passing that into the FormData
, it doesn’t treat it like an actual File
.
Oh well. At some point we hope to move to Capacitor and maybe this can be done more elegantly there.
There are huge security implications for that, in that you don’t want arbitrary web code Hoovering up random stuff from your filesystem and sending it to identity thieves.
Unfortunately, the one glaring thing that I despise about Capacitor (and let me make clear that I realize it’s unfair of me to throw shade without fully understanding everything that went into this design choice) is that it can’t pass binary data across its bridge - everything has to be Base64ed. So I don’t think it’s going to be a silver bullet here.
One area that we may want to investigate further is using fetch
: specifically its capability to deliver ReadableStream
s. That still leaves the problem of how to transmit these streams upward, but at a glance I think it might solve the problem you’re seeing of WebView OOM due to having to process entire files at once.