How to save the state of a WebView inside a Fragment of an Action Bar

The idea for this post came to me after reading the comment of Esthon Wood: “do you have any idea on how to save the state of the WebView? I mean, the webview refreshes everytime I tap on the tab.” in the post Tab Layout in Android with ActionBar and Fragment.

As a starting point I suppose that you have properly configured the example explained in Tab Layout in Android with ActionBar and Fragment.

In the following steps I configure a WebView in the second tab:

  1. replace the file res/layout/tab2.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tab2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" 
        android:gravity="center">
    
        <WebView
            android:id="@+id/webView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </LinearLayout>
    
  2. replace the eu/lucazanini/Tab2Fragment.java
    package eu.lucazanini;
    
    import android.app.Fragment;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    import android.widget.LinearLayout;
    
    public class Tab2Fragment extends Fragment {
    
        private WebView webView;
        private Bundle webViewBundle;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
    	    Bundle savedInstanceState) {
    
    	LinearLayout ll = (LinearLayout) inflater.inflate(R.layout.tab2,
    		container, false);
    
    	webView = (WebView) ll.findViewById(R.id.webView1);
    	webView.setWebViewClient(new WebViewClient());
    
    	if (webViewBundle == null) {
    	    webView.loadUrl("http://www.lucazanini.eu");
    	} else {
    	    webView.restoreState(webViewBundle);
    	}
    
    	return ll;
    
        }
    
        @Override
        public void onPause() {
    	super.onPause();
    
    	webViewBundle = new Bundle();
    	webView.saveState(webViewBundle);
        }
    }
    
    • row 24: I set the variable webView to the WebView in the layout res/layout/tab2.xml
    • row 25: with this instruction the WebView is displayed under the second tab, and not in full screen hiding the Action Bar, and every link is opened reusing the same webView without opening the default browser; the issue is that I no longer have the address bar
    • row 38: method onPause, here I save the state of the webView in the Bundle webViewBundle; the method onPause is called when the Fragment is going into the background (for example when I select the other tab), after the reselection of the second tab, in the onCreate method after verifying that there is a webViewBundle not null, I use it to restore the state of the WebView (row 30)
  3. add a permission to access to internet in AndroidManifest.xml
    <uses-permission android:name="android.permission.INTERNET"/>
    
  4. launch the app
    webview

For other configurations of the WebView, such as to enable JavaScript, you can refer to Building Web Apps in WebView.


Comments

14 responses to “How to save the state of a WebView inside a Fragment of an Action Bar”

  1. I tried this but it’s not working in kotlin

  2. So theoretically if we have other values to persist, I would be using both savedInstanceState and webviewBundle right?
    Also, is there any risk of having TransactionTooLarge exception with bigger webviewBundle size?

  3. how to create method onKeyDown in this Fragment?

  4. Hi,

    I’m a bit new to android. I nliked your example and it work really Good – Thank you.

    Could you please advise how do I add a progress bar to it?

  5. Post is excellent, i am looking for it since long time. as Mr.Adam Croth said. I got Same problem. Javascript is not working.

    Any solution for it.

    Thanks

    1. insert the following above line 28:
      web.getSettings().setJavaScriptEnabled(true);

  6. I’m using a fixed tab with swipe. There’s only one fragment they all share, and one webView that is always instantiated in my onCreateView. Pls how can I save the webView state for 6 TABS. it only saves for the first two. thanks

  7. Adam Croth Avatar

    Thank you for your tutorial,

    I have a problem, even I inserted Javascript activation code to one Fragment, Javascript is not working.

    String url = “http://www.site.com/”;

    webView = (WebView) ll.findViewById(R.id.webView3);
    webView.setWebViewClient(new WebViewClient());

    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webView.getSettings().setJavaScriptEnabled(true);

    if (webViewBundle == null) {
    webView.loadUrl(url);
    } else {
    webView.restoreState(webViewBundle);
    }
    return ll;
    }

    How can I solve this problem?

    Thanks

  8. Friend, I am using your article as reference when I return in the webview Tab 2 takes about two seconds to reload, there is a way to solve this case? Thanks!!

    1. You can try to replace the onTabSelected and onTabUnselected methods of the inner class TabListener inside TabActionBarActivity.java

      	public void onTabSelected(Tab tab, FragmentTransaction ft) {
      	    // Check if the fragment is already initialized
      	    if (mFragment == null) {
      		// If not, instantiate and add it to the activity
      		mFragment = Fragment.instantiate(mActivity, mClass.getName());
      		ft.add(android.R.id.content, mFragment, mTag);
      	    } else {
      		// If it exists, simply attach it in order to show it
      		// ft.attach(mFragment);
      		ft.show(mFragment);
      	    }
      	}
      
      	public void onTabUnselected(Tab tab, FragmentTransaction ft) {
      	    if (mFragment != null) {
      		// Detach the fragment, because another one is being attached
      		// ft.detach(mFragment);
      		ft.hide(mFragment);
      	    }
      	}
      

      where I use “show” and “hide” instead of “attach” and “detach” at the lines 10 and 18.

      1. Incredible, very good! Thank you

  9. Rb Saud Avatar

    i used your idea. but when we rotate the phone or orientation changes , the links start opening in a new browser.

    how can we prevent that ??

    1. Luca Zanini Avatar
      Luca Zanini

      I don’t have the issue you said.
      The row 25 in Tab2Fragment.java should prevent that.

      I think you don’t need but you can explicitly handle the page navigation as explained here.
      The shouldOverrideUrlLoading method should be:

       public boolean shouldOverrideUrlLoading(WebView view, String url) {
         view.loadUrl(url);
         return false;
      }
      

      Go here for more info.

      1. Aryan Tomar Avatar
        Aryan Tomar

        Thank You very much sir, I was screwed for this thing.
        Thank you really…
        If there is any donation then I will for sure…
        Thanks once again…!!!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.