It all started with a simple WebView within an Android app.
This view loads info from a public URL. Nothing unusual there.
However ... if there should be a network interruption, you can easily end up with an error displayed prominently in the WebView.
Well, that's no good, right? So I searched the docs and elsewhere for a way to suppress this, or trap it ... and found no leads. With that, I inquired on #android-dev
on IRC: I know about WebView.onReceivedError, but can the visual portion be suppressed? (Instead, I wanted to display a Dialog warning of said network problem, with an option to retry.)
Answer: You can't. :(
Very well. Time for plan B. Perhaps an ImageView might fill the bill?
Should there be any kind of WebView error, the ImageView can be used as a makeshift curtain. It overlays the WebView at the start (before the URL is loaded), then it fades to reveal the WebView behind it. If the WebView works, wonderful! But if onReceivedError kicks in, we put the curtain back up immediately and show the aforementioned dialog. Once WebView gets an onPageFinished, the curtain fades once more.
... and THIS ... works WONDERFULLY!
Until I was asked to support screen orientation changes. (Foreshadowing: "Things went downhill from here.")
Up until now the app was using android:screenOrientation="portrait"
in the Manifest's main activity. So I removed that part, and of course we ran into the infamous "activity is being restarted" issue, which blows away and then brings back the WebView.
Of course it's not an issue per se. This is Android OS working as designed.
Also, we want the ImageView to display properly depending on orientation. Thankfully, we have alternate resources we can leverage! Meanwhile, we still have this WebView we don't want to reload. We want it to be left alone and let the view do its own thing, be it in portrait or landscape at the time.
I found a few well-explained ways to handle screen orientation, plus I have already read through author Mark Murphy's eBooks (highly recommended reading). Yet I was still stuck! With the ImageView now in the mix, none of the techniques seem to fill the bill:
Forcing portrait mode is, of course, out of the question (or is it?).
android:configChanges="keyboardHidden|orientation"
andonConfigurationChanged
seem to take care of the WebView, which blissfully handles the screen resizing gracefully on its own. Of course, the ImageView doesn't get the memo either, and it keeps using its original (portrait/landscape) resource!An ill-conceived call to
activity.setRequestedOrientation(newConfig.orientation)
within the config change handler didn't help matters.Since the WebView doesn't need to be persisted between app executions,
onRetainNonConfigurationInstance
looked like another possibility. Alas, that didn't seem to work either. Resettingwebview
with the last nonconfig instance (since that's all I really passed in) resulted in a blank WebView. Not quite what I was after.On the other hand, the ImageView seemed to responding nicely to orientation changes. Go figure.
How about
onSaveInstanceState
? Same gotchas. WebView has asaveState
method, but it doesn't seem to be saving it at a level deep enough to keep the transition seamless. If so, then it's probably not supposed to either, so this might be the wrong way to go too.
As to the wisdom of using configChanges
, the documentation recommends this very technique, in fact:
Standard behavior for an Activity is to be destroyed and recreated when the devices orientation is changed. This will cause the WebView to reload the current page. If you don't want that, you can set your Activity to handle the
orientation
andkeyboardHidden
changes, and then just leave the WebView alone. It'll automatically re-orient itself as appropriate.
Of course I could also be committing some sort of pilot error here, but I have yet to figure out what that might be.
I have read and re-read the documentation and tried every which way to hack through this on my own. Perhaps I'm missing something (obvious?) in the docs, or the solution is non-obvious (but someone can shed light) ... or this simply isn't possible. Hoping it's not the latter.
Clues welcome/appreciated!