A few months ago, I published an app called SimpleMarkdown, which, as you can probably guess from the title, is a markdown editor. I had a strange bug that I couldn’t quite figure out no matter how much I searched it and eventually I had to put it on the back burner as I got overwhelmed with work. Gotta pay the bills somehow. Anyways, what was happening was the app would randomly crash due to a memory leak that was happening in the WebView, which is what I use to render the preview of the markdown. I couldn’t quite pin what was causing it, but you can see the full stack trace in the GitHub issue. The exception message was as follows:

Activity com.wbrawner.simplemarkdown.view.activity.MainActivity has leaked IntentReceiver org.chromium.content.browser.accessibility.LollipopBrowserAccessibilityManager$1@9a08817 that was originally registered here. Are you missing a call to unregisterReceiver()?

Naturally, this confused me, as I wasn’t registering any IntentReceivers in the Fragment nor in the Activity. This was also a pretty big show stopper, as I myself had lost at least one or two blog posts due to not saving the file before I ran into the crash. I can only imagine how frustrated other users were. I finally had the time to look into this again and I decided that I’d give it another go before just pulling out the preview functionality altogether. I’d rather have a small feature set in a stable app than a feature-packed app that doesn’t do the job it sets out to do properly.

After a little searching, I came across this GitHub issue, where user vickychijwani was experiencing the same issue in a similar app of his called Quill. He discovered that by removing the WebView from its parent View prior to calling WebView#destroy(), he no longer experienced the crash. I tested this myself, and sure enough, I’m no longer experiencing the crash myself! In fact, I was able to get through writing this blog post from my tablet using SimpleMarkdown and haven’t run into any issues whatsoever. Kudos to you, vickychijwani!

Before:

@Override
public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
}

You can see here that I was simply expecting for the view to be properly disposed of by simply destroying it. I am using a fragment here though, so this may not be an issue when using a WebView within an Activity. The fix is as follows:

After:

@Override
public void onDestroyView() {
    if (markdownPreivew != null){
        ((ViewGroup) markdownPreview).getParent().removeChild(markdownPreview);
        markdownPreview.destroy()
    }
    unbinder.unbind();
    super.onDestroyView();
}

The key takeaways from this are that you have to explicitly destroy a WebView (at least in a fragment), as Android doesn’t handle this for you, and prior to doing that, you have to remove it from its parent view.

Just to play it safe, I’ve added Crashlytics to the next release, so that I can see any and all crashes, and make sure I squash the bug completely. I’ll be adding a privacy policy for SimpleMarkdown accordingly. Crashlytics only reports the device, version of Android, and stack trace If this makes you uncomfortable with using SimpleMardown, please feel free to build the app from source (it’s not very difficult and you can reach out to me if you need any assistance.)

Anyways, if you haven’t already, check out SimpleMarkdown and let me know what you think!