106

When I rotate my screen, the WebView reloads the whole page. I can't have this since some of my content contains dynamic/random material. Currently when rotated the screen reloads the original URL from the loadUrl() method.

Any idea what's wrong with my code?

MainActivity.java

package com.mark.myapp;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {

    WebView web;
    String webURL = "http://www.google.co.uk/";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState != null)
            ((WebView)findViewById(R.id.web)).restoreState(savedInstanceState);

        web = (WebView) findViewById(R.id.web);
        web.getSettings().setJavaScriptEnabled(true);
        web.loadUrl(webURL);
        web.setPadding(0, 0, 0, 0);
        web.getSettings().setLoadWithOverviewMode(true);
        web.getSettings().setUseWideViewPort(true);
        web.getSettings().setSupportZoom(true);
        web.getSettings().setBuiltInZoomControls(true);

        web.setWebViewClient(new HelloWebViewClient());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    private class HelloWebViewClient extends WebViewClient {
        public boolean shouldOverrideUrlLoading(WebView web, String url) {
            web.loadUrl(url);
            return true;
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) {
            web.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mark.myapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"

            android:configChanges="orientation|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>
mark
  • 2,841
  • 4
  • 25
  • 23
  • 1
    Simplified solution which I used myself and could recommend is here: http://twigstechtips.blogspot.com/2013/08/android-retain-instance-of-webview.html – Andrius Baruckis Dec 04 '13 at 16:50

12 Answers12

119

I think the main problem is that you call web.loadUrl(webURL); also when savedInstanceState != null

EDIT

Try:

if (savedInstanceState == null)
{
  web.loadUrl(webURL);
}

EDIT2: You also need the onSaveInstanceState and onRestoreInstanceState override.

@Override
protected void onSaveInstanceState(Bundle outState )
{
super.onSaveInstanceState(outState);
web.saveState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
web.restoreState(savedInstanceState);
}

Note: Please also add in your AndroidManifest.xml in your Activity android:configChanges="orientation|screenSize" Thanks

MindRoasterMir
  • 324
  • 1
  • 2
  • 18
Giuseppe
  • 2,093
  • 1
  • 21
  • 26
71

EDIT: Found a more suitable solution.

NEW:

In AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.Example.WebviewSample">
    <application
        <activity android:name=".WebViewActivity"
            <!-- ADD THIS -->
            android:configChanges="orientation|screenSize">
        </activity>
    </application>
</manifest>

In WebViewActivity.java file add this to onCreate() method

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    wView = (WebView) findViewById(R.id.webView);
    if (savedInstanceState == null) {
        wView.loadUrl("https://google.com");
    }
}

also update onSaveInstanceState

@Override
protected void onSaveInstanceState(Bundle outState)
{
    super.onSaveInstanceState(outState);
    wView.saveState(outState);
}

and onRestoreInstanceState

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);
    wView.restoreState(savedInstanceState);
}

OLD:

No java coding needed. use this in your manifest file.

 android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"

like:

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.Example.WebviewSample.webviewsample"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>        
</application>
Vettiyanakan
  • 7,957
  • 6
  • 37
  • 55
  • 2
    what changes are you talking about? – Pratik Poddar May 28 '14 at 12:09
  • following @Mgamerz comment.. when the matter is rotating.. this is the worst suggestion you can give – Guilherme Oliveira Jan 09 '15 at 16:45
  • 57
    Noooooooooooo. Don't even think about doing this. Configuration changes are not limited to rotation. Also, the instance state can be restored after coming back from low memory. The problem here is that the configuration will not be updated correctly when you do this. Please, no one do this. – Eric Cochran Feb 26 '15 at 02:33
  • 7
    @EricCochran Could you write correct answer, if you know one? Accepted answer still reloads page for me, also it loses session info. Which in my case is like wow, you turn phone - you have to login again. – Atomosk Mar 27 '17 at 10:39
  • This may only be part of a complete answer. See this better one: https://stackoverflow.com/a/46849736/454780 – trusktr Jan 09 '18 at 01:32
24

in tag (manifest)

android:configChanges="orientation|screenSize"
Noya
  • 3,879
  • 3
  • 26
  • 32
01wifi01
  • 415
  • 6
  • 15
  • 9
    There is actually no reason to override the ```onConfigurationChanged``` method as there is no custom functionality added. Simply making the change in the manifest file did the trick for me. – i2097i Mar 30 '15 at 02:24
  • manifest was sufficient, and upvote for adding only `orientation|screenSize` – Varun Garg Mar 13 '18 at 06:48
  • What's weird is that the destructive behavior is the default. No one expects that rotating a web view restarts the web app. That's just... strange. – trusktr Aug 17 '21 at 17:40
15

Adding android:configChanges="orientation|screenSize" in manifest works for me

<activity
            android:name="com.example.HelloWorld.WebActivity"
            android:label="@string/title_activity_web"
            android:configChanges="orientation|screenSize" >
</activity>
Rasel
  • 5,488
  • 3
  • 30
  • 39
  • Can you post what your MainActivity does regarding the WebView? – trusktr Jan 09 '18 at 01:25
  • 1
    @trusktr It doesn't have to do anything. `android:configChanges="orientation|screenSize"` does so that the activity doesn't restart when the device is rotated. If the activity never restarts, there's no need to handle it restarting. – Donald Duck Aug 14 '21 at 17:40
9

I don't believe this will work anymore. In my case, restoring state using WebView.restore(Bundle savedInstanceState) still triggers a reload of the url.

Looking at the docs for restoreState() you'll see it says:

If it is called after this WebView has had a chance to build state (load pages, create a back/forward list, etc.) there may be undesirable side-effects.

and

Please note that this method no longer restores the display data for this WebView.

Props to @e4c5 for pointing me in the right direction in his answer

And of course, the extreme course of action would be to prevent orientation changes from triggering activity destruction/creation. Documentation for how to do this is here

Community
  • 1
  • 1
Ranjeev Mahtani
  • 208
  • 3
  • 5
7

Add this code in Manifest

<activity 
     ...
     android:configChanges="orientation|screenSize">
Confuse
  • 5,646
  • 7
  • 36
  • 58
5

Try this in your manifest file:

android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Ajeet Yadav
  • 693
  • 1
  • 11
  • 31
5

Place this in the Manifest.xml file activity:

android:configChanges="orientation|screenSize"

Here is an example:

<activity android:name=".MainActivity"
          android:label="@string/app_name"
          android:theme="@style/AppTheme.NoActionBar"
          android:configChanges="orientation|screenSize">
          <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
          </intent-filter>
</activity>
4

Override the onConfigChange method to avoid reloading data on orientation change

on your activity in AndroidMainfest file.

android:configChanges="orientation|keyboardHidden" 

and have these as well in your WebView settings

webview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
webview.loadUrl("Your URL To Load");
Pramesh Bajracharya
  • 2,153
  • 3
  • 28
  • 54
Sampath Kumar
  • 4,433
  • 2
  • 27
  • 42
4

As quoted here,

Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the "screenSize" value in addition to the "orientation" value. That is, you must decalare android:configChanges="orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).

setting android:configChanges="orientation|screenSize" on your activity will resolve this issue.

Also, take note of the following

Remember: When you declare your activity to handle a configuration change, you are responsible for resetting any elements for which you provide alternatives. If you declare your activity to handle the orientation change and have images that should change between landscape and portrait, you must re-assign each resource to each element during onConfigurationChanged().

davejoem
  • 4,902
  • 4
  • 22
  • 31
4

This solution works well for me:

(1) In AndroidManifest.xml add this line android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"

Like this (and like the answers above)

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

(2) Then in MainActivity.java verify savedInstanceState

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mainContext = getApplicationContext();
    ----
    myWebView = (WebView) findViewById(R.id.webView);
    prepareWebView();
    myWebView.addJavascriptInterface(myJavaScriptInterface, "WEB2Android");

    if (savedInstanceState == null) {
        myWebView.post(new Runnable() {
            @Override
            public void run() {
                myWebView.loadUrl("http://www.appbiz.ro/foto_konta");
            }
        });
    }
    ----
}

(3) and then:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

@Override
protected void onSaveInstanceState(Bundle outState )
{
    super.onSaveInstanceState(outState);
    myWebView.saveState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);
    myWebView.restoreState(savedInstanceState);
}
Adrian S.
  • 129
  • 1
  • 2
  • 12
1

Add this in Androidmanifest.xml:

<activity android:name=".MyActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">

Now, when one of these configurations change, MyActivity does not restart. Instead, MyActivity receives a call to onConfigurationChanged().

Add this:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}
m02ph3u5
  • 3,022
  • 7
  • 38
  • 51