Android: prevención de la recarga de WebView en Rotate

91

Cuando giro mi pantalla, WebView recarga toda la página. No puedo tener esto porque parte de mi contenido contiene material dinámico / aleatorio. Actualmente, cuando se gira la pantalla, se vuelve a cargar la URL original del método loadUrl ().

¿Alguna idea de lo que está mal con mi código?

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>
marca
fuente
1
La solución simplificada que utilicé yo mismo y podría recomendar está aquí: twigstechtips.blogspot.com/2013/08/…
Andrius Baruckis

Respuestas:

103

Creo que el principal problema es que llamas a web.loadUrl (webURL); también cuando se guardaInstanceState! = null

EDITAR

Tratar:

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

EDIT2 : también necesita la anulación onSaveInstanceState y onRestoreInstanceState.

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

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

Nota: también agregue su AndroidManifest.xml en su Actividad android: configChanges = "Orientación | ScreenSize" Gracias

Giuseppe
fuente
1
¡Si! Esto funciona para mí (después de la edición, ¡Tim lo vio!). ¡Gracias! ¿Podría explicar por qué y cómo funciona esto y por qué esos métodos necesitan ser reemplazados?
marca el
Una última cosa, ¿realmente necesito la siguiente declaración if: if (SavedInstanceState! = Null) ((WebView) findViewById (R.id.web)). RestoreState (SavedInstanceState);
marca el
21
esto mantiene la misma página pero aún se recarga en la pantalla rotar
Grasper
2
Esto funciona si agrego la propiedad android: configChanges a <activity> en AndroidManifest, por lo que las dos cosas de su respuesta más esa. Aquí hay una mejor respuesta que incluye las tres cosas: stackoverflow.com/a/46849736/454780
trusktr
63

No se necesita codificación Java. use esto en su archivo de manifiesto.

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

me gusta:

<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
fuente
2
de que cambios estas hablando?
Pratik Poddar
siguiendo el comentario de @Mgamerz ... cuando el asunto está rotando ... esta es la peor sugerencia que puede dar
Guilherme Oliveira
54
Noooooooooooo. Ni siquiera pienses en hacer esto. Los cambios de configuración no se limitan a la rotación. Además, el estado de la instancia se puede restaurar después de regresar de poca memoria. El problema aquí es que la configuración no se actualizará correctamente cuando haga esto. Por favor, nadie haga esto.
Eric Cochran
6
@EricCochran ¿Podría escribir la respuesta correcta, si conoce una? La respuesta aceptada todavía vuelve a cargar la página para mí, también pierde la información de la sesión. Lo que en mi caso es como wow, enciendes el teléfono, tienes que iniciar sesión de nuevo.
Atomosk
Esto puede ser solo parte de una respuesta completa. Vea este mejor: stackoverflow.com/a/46849736/454780
trusktr
20

en etiqueta (manifiesto)

android:configChanges="orientation|screenSize"
01wifi01
fuente
9
En realidad, no hay ninguna razón para anular el onConfigurationChangedmétodo, ya que no se agrega ninguna funcionalidad personalizada. Simplemente hacer el cambio en el archivo de manifiesto funcionó para mí.
i2097i
manifiesto fue suficiente, y voto positivo por agregar soloorientation|screenSize
Varun Garg
14

Agregar un android:configChanges="orientation|screenSize"manifiesto funciona para mí

<activity
            android:name="com.example.HelloWorld.WebActivity"
            android:label="@string/title_activity_web"
            android:configChanges="orientation|screenSize" >
</activity>
Rasel
fuente
¿Puede publicar lo que hace su MainActivity con respecto a WebView?
trusktr
8

No creo que esto funcione más. En mi caso, restaurar el estado usando WebView.restore(Bundle savedInstanceState)aún activa una recarga de la URL.

En cuanto a los documentos para restoreState()que usted verá que dice:

Si se llama después de que este WebView haya tenido la oportunidad de crear un estado (cargar páginas, crear una lista de retroceso / avance, etc.), puede haber efectos secundarios no deseados.

y

Tenga en cuenta que este método ya no restaura los datos de visualización para este WebView.

Apoyos a @ e4c5 por señalarme en la dirección correcta en su respuesta

Y, por supuesto, el curso de acción extremo sería evitar que los cambios de orientación desencadenen la destrucción / creación de actividades. La documentación sobre cómo hacer esto está aquí

Ranjeev Mahtani
fuente
6

Agrega este código en Manifest

<activity 
     ...
     android:configChanges="orientation|screenSize">
Confundir
fuente
4

Anular el onConfigChange método para evitar volver a cargar datos al cambiar de orientación

sobre su actividad en el AndroidMainfestarchivo.

android:configChanges="orientation|keyboardHidden" 

y tenerlos también en la configuración de WebView

webview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
webview.loadUrl("Your URL To Load");
Sampath Kumar
fuente
4

Pruebe esto en su archivo de manifiesto:

android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
Ajeet Yadav
fuente
4

Coloque esto en la actividad del archivo Manifest.xml:

android:configChanges="orientation|screenSize"

Aquí hay un ejemplo:

<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>
Carlos Alberto González
fuente
4

Como se cita aquí ,

Precaución: a partir de Android 3.2 (nivel de API 13), el "tamaño de la pantalla" también cambia cuando el dispositivo cambia entre la orientación vertical y horizontal. Por lo tanto, si desea evitar que el tiempo de ejecución se reinicie debido a un cambio de orientación al desarrollar para el nivel de API 13 o superior (como lo declaran los atributos minSdkVersion y targetSdkVersion), debe incluir el valor "screenSize" además del valor de "orientación". Es decir, debe descartar android: configChanges = "orientación | screenSize". Sin embargo, si su aplicación tiene como objetivo el nivel de API 12 o inferior, entonces su actividad siempre maneja este cambio de configuración por sí misma (este cambio de configuración no reinicia su actividad, incluso cuando se ejecuta en un dispositivo Android 3.2 o superior).

ajuste android:configChanges="orientation|screenSize" de su actividad resolverá este problema.

Además, tome nota de lo siguiente

Recuerde: cuando declara su actividad para manejar un cambio de configuración, usted es responsable de restablecer cualquier elemento para el que proporcione alternativas. Si declara su actividad para manejar el cambio de orientación y tiene imágenes que deberían cambiar entre horizontal y vertical, debe reasignar cada recurso a cada elemento durante onConfigurationChanged ().

davejoem
fuente
3

Esta solución me funciona bien:

(1) En AndroidManifest.xml agregue esta línea android: configChanges = "keyboard | keyboardHidden | Orientación | screenLayout | uiMode | screenSize | smallestScreenSize"

Así (y como las respuestas anteriores)

<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) Luego en MainActivity.java verifique 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) y luego:

@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.
fuente
0

Agregue esto en Androidmanifest.xml:

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

Ahora, cuando una de estas configuraciones cambia, MyActivityno se reinicia. En cambio, MyActivityrecibe una llamada a onConfigurationChanged().

Agrega esto:

@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();
    }
}
Sunny Singh
fuente