raginggoat
raginggoat

Reputation: 3600

App Crashing When Replacing Fragment Before WebView Loads

My app uses a navigation drawer and replaces the fragment on my main activity when a selection is made in the drawer. I have a couple of fragments that show a web view. The problem occurs if I open the drawer and select a different item , thus replacing the fragment with the web view, before the page in the webview has finished loading. When this happens, I get this error:

12-02 08:07:48.605  11745-11745/kyfb.android.kyfb.com.kyfb A/chromium﹕ [FATAL:jni_android.cc(271)] Check failed: false.
12-02 08:07:48.605  11745-11745/kyfb.android.kyfb.com.kyfb A/libc﹕ Fatal signal 6 (SIGABRT), code -6 in tid 11745 (d.kyfb.com.kyfb)

Here is one of the fragments with a webview.

public class AnnualMeetingFragment extends Fragment {

    private WebView web;
    private ProgressBar progressBar;

    private String url;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View rootView = inflater.inflate(R.layout.fragment_ag_facts, null);

        url = "http://www.kyfbnewsroom.com/2013-kentucky-farm-bureau-annual-meeting-program/";

        web = (WebView)rootView.findViewById(R.id.web);
        progressBar = (ProgressBar)rootView.findViewById(R.id.prgPageLoading);

        web.getSettings().setDomStorageEnabled(true);
        web.getSettings().setJavaScriptEnabled(true);
        web.getSettings().setSupportZoom(true);
        web.getSettings().setBuiltInZoomControls(true);
        web.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
        web.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
        web.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);

        web.loadUrl(url);

        web.setWebChromeClient(new WebChromeClient() {
            public void onProgressChanged(WebView webView, int progress) {
                getActivity().setProgress(progress * 100);
                progressBar.setProgress(progress);
            }
        });

        web.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(web, url, favicon);
                progressBar.setVisibility(View.VISIBLE);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(web, url);
                progressBar.setProgress(0);
                progressBar.setVisibility(View.GONE);
            }

            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                Toast.makeText(getActivity(), description, Toast.LENGTH_SHORT).show();
            }

            public boolean shouldOverrideUrlLoading(WebView view, String url)
            {


                if(url.endsWith(".mp4") || url.endsWith(".3gp") || url.endsWith(".avi") || url.endsWith(".flv")){
                    Intent i = new Intent(Intent.ACTION_VIEW);
                    i.setData(Uri.parse(url));
                    startActivity(i); //warning no error handling will cause force close if no media player on phone.
                    return true;
                }

                view.loadUrl(url);
                return true;
            }
        });

        return rootView;
    }
}

Upvotes: 3

Views: 2415

Answers (3)

Jacques Massa
Jacques Massa

Reputation: 33

You should destroy the webview when the fragment is detached.

Call the webview.destroy() from the fragment's on detached method.

Upvotes: 2

Dandalf
Dandalf

Reputation: 2425

The FragmentManager may be holding on to old fragments that you can retrieve by a tag key. Go into your activity that has the FragmentManager that is doing the replace. When doing the replace, use a tag to identify the fragment. Before you do the replace, check if the fragment manager already has a fragment with that tag and use that one instead of creating a new fragment instance. Your fragment transaction should look something like this:

String fragTag = "FRAGMENT_1"; //Should be a class constant 
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = fm.findFragmentByTag(fragTag);
if(fragment == null) {
    fragment = new AnnualMeetingFragment();
}
ft.replace(R.id.container, fragment, fragTag);
ft.commit();

Also, "onReceivedError" in your WebViewClient implementation may happen when the Fragment is not actually attached to an activity. So getActivity() may not be returning a valid value there.

Upvotes: 0

Anatol
Anatol

Reputation: 961

I am not sure why are you getting this error, i think it should be something like NullPointerException. Try next: Evert time you calling getActivity() on Fragment instance you should be sure, that fragment is actually have this Activity. Because when your webview is loading you are calling this function:

web.setWebChromeClient(new WebChromeClient() {
        public void onProgressChanged(WebView webView, int progress) {
            getActivity().setProgress(progress * 100);
            progressBar.setProgress(progress);
        }
    });

I thing you should replace all your code where you are calling getActivity() on something like this:

Activity activity = getActivity();
if (activity != null) {
    // do something
}

Try this and tell me if this work.

Upvotes: 1

Related Questions