Every few days I get a crash report for my application with the following stack trace, or small variants thereof (with different line numbers based on different android versions)
java.lang.NullPointerException at
WebView.java:8241:in `android.webkit.WebView$PrivateHandler.handleMessage'
Handler.java:99:in `android.os.Handler.dispatchMessage'
Looper.java:150:in `android.os.Looper.loop'
ActivityThread.java:4293:in `android.app.ActivityThread.main'
Method.java:-2:in `java.lang.reflect.Method.invokeNative'
Method.java:507:in `java.lang.reflect.Method.invoke'
ZygoteInit.java:849:in `com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run'
ZygoteInit.java:607:in `com.android.internal.os.ZygoteInit.main'
NativeStart.java:-2:in `dalvik.system.NativeStart.main'
This specific stack was on Android 2.3.4 on a HTC EVO 3D PG86100 device. My app does host several webviews for some oAuth-related login scenarios.
How should I go about trying to figure out how to fix this? I've tried looking on grepcode to find the source, but I'm unable to find a matching line number that makes sense. Is my Grepcode-fu weak?
I ran into this issue recently and in my case I managed to figure out that a secondary bug fix was causing this issue.
So, if you didn't create a custom class which extends webview, that overrides onCheckIsTextEditor to always return true because of a suggestion in this android bug report... I would stop reading here.
If you have done that, then it appears that this fix has already been implemented by HTC and for some reason causes it to crash when it receives focus. This issue manifested itself in two places for me, when placing touch events on the view and by setting the views visibility. In my project I set a WebViewClient and waited until the page had finished loading before setting the webview's visibility to visible. This caused the following stack trace:
java.lang.NullPointerException at android.webkit.WebView.navHandledKey(WebView.java:9353)
at android.webkit.WebView.requestFocus(WebView.java:7910)
at android.view.View.requestFocus(View.java:3718)
at android.view.View.requestFocus(View.java:3696)
at android.view.ViewRoot.focusableViewAvailable(ViewRoot.java:1803)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:474)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:474)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:474)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:474)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:474)
at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:474)
at android.view.View.setFlags(View.java:4680)
at android.view.View.setVisibility(View.java:3163)
By wrapping the setVisibility call in a try/catch I was able to determine if I should override the touch events or not. If I caught the event, that would mean I should disable the override. This is an example of what I did:
try {
webView.setVisibility(View.VISIBLE);
} catch (NullPointerException e) {
Log.i(TAG, "Error setting webview visibility due to overriding focus. It will be disabled.");
webView.setOverrideOnCheckIsTextEditor(false);
// Confirm window is visible
webView.setVisibility(View.VISIBLE);
}
My custom webview now looks like this, special attention paid to the final two methods:
/**
* When using a webview in a dialog, there are issues relating to the keyboard not appearing when focusing on a text box.
* This overrides a function to ensure the keyboard is shown when focusing on a text box in a webview.
* See link for bug report and solution.
*
* @see http://code.google.com/p/android/issues/detail?id=7189
* @see http://stackoverflow.com/questions/12325720
* @author James O'Brien
* @since 10/16/2012
*/
public class FocusableWebView extends WebView {
private boolean mOverrideCheckIsTextEditor = true;
/**
* Default Constructor
*
* @param context
*/
public FocusableWebView(Context context) {
super(context);
}
/**
* Default Constructor
*
* @param context
* @param attrs
*/
public FocusableWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Default Constructor
*
* @param context
* @param attrs
* @param defStyle
*/
public FocusableWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onCheckIsTextEditor() {
if (mOverrideCheckIsTextEditor) {
return true;
} else {
return super.onCheckIsTextEditor();
}
}
/**
* Enable/Disable overriding of onCheckIsTextEditor to always return true.
*/
public void setOverrideOnCheckIsTextEditor(boolean foo) {
mOverrideCheckIsTextEditor = foo;
}
}
Sorry I can't go into more detail about why this fixes the issue. All I can assume is that its related to focus and dynamically disabling it works a treat :)
** Update (12/11/12) **
Managed to solve both issues presented above. It seemed to be an issue with the focus of the webview. My code now looks like this
webView.setVisibility(View.VISIBLE);
webView.setFocusable(true);
webView.requestFocus();
I would suggest making sure that you explicitly set the focusable attribute to 'true' or calling setFocusable(true).