Problemas y soluciones comunes para usar Android WebView (avanzado)

Resumir algunos métodos de uso de WebView

Recordatorio: cuando usamos WebView, es mejor no escribir WebView en xml. Es mejor usar el siguiente método para cargar WebView de forma dinámica directamente

WebView webView = new WebView();
frameLayout.addView(webView);//动态加载

 1. Se llama al navegador del sistema cuando se abre la página web, pero no se muestra en este WebView. Podemos llamar al setWebViewClient de mWebView para que se muestre en este WebView.

mWebView.setWebViewClient(new WebViewClient(){
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
          view.loadUrl(url);
          return true;
      }
  });

2. Llame a javascript a través del código java

WebSettings webSettings =   mWebView .getSettings();       
webSettings.setJavaScriptEnabled(true); 
mWebView.addJavascriptInterface(new Object() {       
            public void clickOnAndroid() {       
                mHandler.post(new Runnable() {       
                    public void run() {       
                        webview.loadUrl("javascript:wave()");       
                    }       
                });       
            }       
        }, "demo");

3. Cuando presione la tecla de retorno, no saldrá del programa sino que regresará a la página de exploración anterior.

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

4. La página admite el zoom.

WebSettings webSettings =   mWebView .getSettings();       
webSettings.setJavaScriptEnabled(true);  
webSettings.setBuiltInZoomControls(true);
webSettings.setSupportZoom(true);

5. Cuando se abre la página, se adapta a la pantalla.
Android4.4 (API versión 19) proporciona una nueva versión de WebView basada en la versión de Chromium , ya no en webkit. Entonces, en la configuración de la configuración web, debemos agregar las siguientes configuraciones:

WebSettings webSettings =   mWebView .getSettings();       
webSettings.setUseWideViewPort(true);//设置此属性,可任意比例缩放
webSettings.setLoadWithOverviewMode(true);

6. Si webView requiere que el usuario ingrese manualmente el nombre de usuario, contraseña u otro, entonces la vista web debe configurarse para admitir el enfoque por gestos.

webview.requestFocusFromTouch();

 //添加后WebView获取焦点,可输入文本
 selectWebView.requestFocus();
 selectWebView.setFocusable(true);
 selectWebView.setFocusableInTouchMode(true);

7. La interfaz de carga de WebView llama principalmente a tres métodos: LoadUrl, LoadData, LoadDataWithBaseURL ..

LoadUrl            直接加载网页、图片并显示.(本地或是网络上的网页、图片、gif)  
LoadData           显示文字与图片内容 (模拟器1.5、1.6)  
LoadDataWithBase  显示文字与图片内容(支持多个模拟器版本) 

8. Introducción a los métodos comunes de WebSettings

setJavaScriptEnabled(true);  //支持js

setPluginsEnabled(true);  //支持插件 

setUseWideViewPort(false);  //将图片调整到适合webview的大小 

setSupportZoom(true);  //支持缩放 

setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局 

supportMultipleWindows();  //多窗口 

setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  //关闭webview中缓存 

setAllowFileAccess(true);  //设置可以访问文件 

setNeedInitialFocus(true); //当webview调用requestFocus时为webview设置节点

webview webSettings.setBuiltInZoomControls(true); //设置支持缩放 

setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 

setLoadWithOverviewMode(true); // 缩放至屏幕的大小

setLoadsImagesAutomatically(true);  //支持自动加载图片

setRenderPriority(RenderPriority.HIGHT);  //设置提高渲染的优先级

setMediaPlaybackRequiresUserGesture(boolean require); //设置WebView是否通过手势触发播放媒体,默认是true,需要手势触发。

##特别说明:如果是跳转百度网页,因baidu.com对这个属性进行了拦截,这里在有的情况,不能设置为true,使用默认就好
setSupportMultipleWindows(true);//设置WebView是否支持多屏窗口,参考WebChromeClient#onCreateWindow,默认false,不支持。

下面再新增进行编号处理:

101:setStandardFontFamily(String font)

设置WebView标准字体库字体,默认字体“sans-serif”。

getSettings.setStandardFontFamily("sans-serif");

102:setFixedFontFamily(String font)

设置WebView固定的字体库字体,默认“monospace”。

getSettings.setFixedFontFamily("monospace");

103:setSansSerifFontFamily(String font)

设置WebView Sans SeriFontFamily字体库字体,默认“sans-serif”。

getSettings.setSansSerifFontFamily("sans-serif");

104、setSerifFontFamily(String font)

设置WebView seri FontFamily字体库字体,默认“sans-serif”。

getSettings.setSansSerifFontFamily("sans-serif");

105、setCursiveFontFamily(String font)

设置WebView字体库字体,默认“cursive”

getSettings.setCursiveFontFamily("cursive");


106、setFantasyFontFamily(String font)

设置WebView字体库字体,默认“fantasy”。

getSettings.setFantasyFontFamily("fantasy");

107、setMinimumFontSize(int size)

设置WebView字体最小值,默认值8,取值1到72

getSettings.setMinimumFontSize(8);

108、setMinimumLogicalFontSize(int size)

设置WebView逻辑上最小字体值,默认值8,取值1到72

getSettings.setMinimumLogicalFontSize(8);

109、setDefaultFontSize(int size)

设置WebView默认值字体值,默认值16,取值1到72

getSettings.setDefaultFontSize(16);

110、setDefaultFixedFontSize(int size)

设置WebView默认固定的字体值,默认值16,取值1到72

getSettings.setDefaultFixedFontSize(16);

111、setGeolocationEnabled(boolean flag)

设置是否开启定位功能,默认true,开启定位

getSettings.setGeolocationEnabled(false);

112、setJavaScriptCanOpenWindowsAutomatically(boolean flag)

设置脚本是否允许自动打开弹窗,默认false,不允许

113、setAllowContentAccess (boolean allow)
是否允许在WebView中访问内容URL(Content Url),默认允许。内容Url访问允许WebView从安装在系统中的内容提供者载入内容。

 9. Solución completa del método WebViewClient

doUpdateVisitedHistory(WebView view, String url, boolean isReload)  //(更新历史记录) 

onFormResubmission(WebView view, Message dontResend, Message resend) //(应用程序重新请求网页数据) 

onLoadResource(WebView view, String url) // 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。 

onPageStarted(WebView view, String url, Bitmap favicon) //这个事件就是开始载入页面调用的,通常我们可以在这设定一个loading的页面,告诉用户程序在等待网络响应。
 
onPageFinished(WebView view, String url) //在页面加载结束时调用。同样道理,我们知道一个页面载入完成,于是我们可以关闭loading 条,切换程序动作。 

onReceivedError(WebView view, int errorCode, String description, String failingUrl)// (报告错误信息) 

onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,String realm)//(获取返回信息授权请求) 

onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) //重写此方法可以让webview处理https请求。

onScaleChanged(WebView view, float oldScale, float newScale) // (WebView发生改变时调用) 

onUnhandledKeyEvent(WebView view, KeyEvent event) //(Key事件未被加载时调用)
 
shouldOverrideKeyEvent(WebView view, KeyEvent event)//重写此方法才能够处理在浏览器中的按键事件。 

shouldOverrideUrlLoading(WebView view, String url) 
//在点击请求的是链接是才会调用,重写此方法返回true表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边。这个函数我们可以做很多操作,比如我们读取到某些特殊的URL,于是就可以不打开地址,取消这个操作,进行预先定义的其他操作,这对一个程序是非常必要的。

El método shouldOverrideUrlLoading () es el método utilizado por Android WebView para interactuar con js (avanzado). Esta parte explicará principalmente la interacción entre Java y Js.

10. Introducción al método complementario de WebSettings (para asegurar que la longitud no sea deslumbrante, se usa comúnmente en el punto 8)

设置自适应屏幕,两者合用
setUseWideViewPort(true);  //将图片调整到适合webview的大小 
setLoadWithOverviewMode(true); // 缩放至屏幕的大小

setSupportZoom(true);  //支持缩放,默认为true。是下面那个的前提。
setBuiltInZoomControls(true); //设置内置的缩放控件。
//若上面是false,则该WebView不可缩放,这个不管设置什么都不能缩放。

setDisplayZoomControls(false); //隐藏原生的缩放控件

setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局  
supportMultipleWindows();  //多窗口 
setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  //关闭webview中缓存 
setAllowFileAccess(true);  //设置可以访问文件 
setNeedInitialFocus(true); //当webview调用requestFocus时为webview设置节点
setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 
setLoadsImagesAutomatically(true);  //支持自动加载图片
setDefaultTextEncodingName("utf-8");//设置编码格式

Acerca del almacenamiento en caché

Modo caché

LOAD_CACHE_ONLY: No utilice la red, solo lea los datos de la caché local
LOAD_DEFAULT: (predeterminado) Decida si desea obtener datos de la red de acuerdo con el control de la caché.
LOAD_NO_CACHE: No use la caché, solo obtenga datos de la red.
LOAD_CACHE_ELSE_NETWORK, siempre que esté disponible localmente, independientemente de si está caducada o sin caché, se usan los datos en la caché.

Uso combinado (carga sin conexión):

if (NetStatusUtil.isConnected(getApplicationContext())) {
    webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//根据cache-control决定是否从网络上取数据。
} else {
    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//没网,则从本地获取,即离线加载
}

webSettings.setDomStorageEnabled(true); // 开启 DOM storage API 功能
webSettings.setDatabaseEnabled(true);   //开启 database storage API 功能
webSettings.setAppCacheEnabled(true);//开启 Application Caches 功能

String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
webSettings.setAppCachePath(cacheDirPath); //设置  Application Caches 缓存目录

Nota: Cada aplicación solo llama a WebSettings.setAppCachePath (), WebSettings.setAppCacheMaxSize () una vez

WebViewClient

WebViewClient es para ayudar a WebView a manejar varias notificaciones y solicitar eventos.
Al abrir una página web, no se llama al navegador del sistema, sino que se muestra en este WebView:

mWebView.setWebViewClient(new WebViewClient(){
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
          view.loadUrl(url);
      return true;
      }
  });

Método WebViewClient

WebViewClient mWebViewClient = new WebViewClient()
{
    shouldOverrideUrlLoading(WebView view, String url)  最常用的,比如上面的。
    //在网页上的所有加载都经过这个方法,这个函数我们可以做很多操作。
    //比如获取url,查看url.contains(“add”),进行添加操作

    shouldOverrideKeyEvent(WebView view, KeyEvent event)
    //重写此方法才能够处理在浏览器中的按键事件。 

    onPageStarted(WebView view, String url, Bitmap favicon) 
    //这个事件就是开始载入页面调用的,我们可以设定一个loading的页面,告诉用户程序在等待网络响应。 

    onPageFinished(WebView view, String url)
    //在页面加载结束时调用。同样道理,我们可以关闭loading 条,切换程序动作。 

    onLoadResource(WebView view, String url) 
    // 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。 

    onReceivedError(WebView view, int errorCode, String description, String failingUrl)
    // (报告错误信息) 

    doUpdateVisitedHistory(WebView view, String url, boolean isReload)  
    //(更新历史记录) 

    onFormResubmission(WebView view, Message dontResend, Message resend) 
    //(应用程序重新请求网页数据) 

    onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,String realm)
    //(获取返回信息授权请求) 

    onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) 
    //重写此方法可以让webview处理https请求。

    onScaleChanged(WebView view, float oldScale, float newScale) 
    // (WebView发生改变时调用) 

    onUnhandledKeyEvent(WebView view, KeyEvent event) 
    //(Key事件未被加载时调用) 
}

Configure el WebViewClient definido anteriormente en WebView:

 webView.setWebViewClient(mWebViewClient);

WebChromeClient

WebChromeClient es un cuadro de diálogo que ayuda a WebView a procesar Javascript, el icono del sitio web, el título del sitio web, el progreso de la carga, etc.
El código del método lo maneja el lado de Android.

WebChromeClient mWebChromeClient = new WebChromeClient() {


    //获得网页的加载进度,显示在右上角的TextView控件中
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        if (newProgress < 100) {
            String progress = newProgress + "%";
        } else {
        }
    }

    //获取Web页中的title用来设置自己界面中的title
    //当加载出错的时候,比如无网络,这时onReceiveTitle中获取的标题为 找不到该网页,
    //因此建议当触发onReceiveError时,不要使用获取到的title
    @Override
    public void onReceivedTitle(WebView view, String title) {
        MainActivity.this.setTitle(title);
    }

    @Override
    public void onReceivedIcon(WebView view, Bitmap icon) {
        //
    }

    @Override
    public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
        //
        return true;
    }

    @Override
    public void onCloseWindow(WebView window) {
    }

    //处理alert弹出框,html 弹框的一种方式
    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        //
        return true;
    }

    //处理confirm弹出框
    // Js的Prompt实际上就是一个确定弹出框,Android上一般用不上这个功能
    // 我们直接把弹出框这个功能拿来用做交互,当需要交互的时候,就把交互参数作为弹出框内容,然后在Android中拦截了就行了
    // 如果你对HTML不熟悉,就告诉你们的前段:就是js的prompt方法,然后把上面的html给他看看他肯定就知道怎么写了
    // 这种方式我个人不太喜欢,毕竟把JsPromot给占用了
    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult 
            result) {
        //
        return true;
    }

    //处理prompt弹出框
    @Override
    public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
        //
        return true;
    }
};

De manera similar, configure el WebChromeClient definido anteriormente en WebView:

Llamar al código JS

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

  mWebView.addJavascriptInterface(new InsertObj(), "jsObj");

¡Esta es la premisa anterior! ! !
Luego implemente la clase anterior, esta clase proporciona cuatro métodos, las anotaciones son muy claras.

class InsertObj extends Object {
    //给html提供的方法,js中可以通过:var str = window.jsObj.HtmlcallJava(); 获取到
    @JavascriptInterface
    public String HtmlcallJava() {
        return "Html call Java";
    }

    //给html提供的有参函数 : window.jsObj.HtmlcallJava2("IT-homer blog");
    @JavascriptInterface
    public String HtmlcallJava2(final String param) {
        return "Html call Java : " + param;
    }

    //Html给我们提供的函数
    @JavascriptInterface
    public void JavacallHtml() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //这里是调用方法
                mWebView.loadUrl("javascript: showFromHtml()");
                Toast.makeText(Html5Activity.this, "clickBtn", Toast.LENGTH_SHORT).show();
            }
        });
    }

    //Html给我们提供的有参函数
    @JavascriptInterface
    public void JavacallHtml2(final String param) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mWebView.loadUrl("javascript: showFromHtml2('IT-homer blog')");
                Toast.makeText(Html5Activity.this, "clickBtn2", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Android llama a js tiene una laguna:

La vulnerabilidad de inyección de objetos Js de Android WebView debe ser entendida por todos, que es la notoria vulnerabilidad de ejecución remota de código antes de Android 4.2, pero Google la corrigió después de Android 4.2. Utilice el método anotado @JavaInterface

Método WebView

hacia adelante hacia atrás

goBack()//后退
goForward()//前进
goBackOrForward(intsteps) //以当前的index为起始点前进或者后退到历史记录中指定的steps, 
                              如果steps为负数则为后退,正数则为前进

canGoForward()//是否可以前进
canGoBack() //是否可以后退

Borrar datos en caché:

clearCache(true);//清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
clearHistory()//清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
clearFormData()//这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据。

El estado de WebView:

onResume() //激活WebView为活跃状态,能正常执行网页的响应
onPause()//当页面被失去焦点被切换到后台不可见状态,需要执行onPause动过, onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。

pauseTimers()//当应用程序被切换到后台我们使用了webview, 这个方法不仅仅针对当前的webview而是全局的全应用程序的webview,它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
resumeTimers()//恢复pauseTimers时的动作。

destroy()//销毁,关闭了Activity时,音乐或视频,还在播放。就必须销毁。

Pero tenga en cuenta: cuando las
llamadas a la vista web se destruyen, la vista web todavía está vinculada a la Actividad. Esto se debe a que el objeto de contexto de la Actividad se pasa cuando se crea la vista web personalizada, por lo que primero debe eliminar la vista web del contenedor principal y luego destruir la vista web:

 rootLayout.removeView(webView);
  webView.destroy();

Determine si WebView se ha desplazado hasta la parte inferior o superior de la página:
getScrollY () // El método devuelve la distancia desde la parte superior del área actualmente visible hasta la parte superior de la página completa, que es la distancia que
recorre el contenido actual. GetHeight () o getBottom () // Todos los métodos devuelven la altura del contenedor WebView actual
getContentHeight () devuelve la altura de todo el html, pero no es equivalente a la altura de la página completa actual, porque WebView tiene una función de zoom, por lo que la altura actual de toda la página debería ser en realidad el html original La altura se multiplica por la relación de zoom. Por lo tanto, el método de valoración correcto debe ser:

   if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
        //已经处于底端
    }

    if(webView.getScrollY() == 0){
        //处于顶端
    }

Algunas formas de evitar la pérdida de memoria de WebView

1. Puede iniciar un nuevo proceso de Webview Activity, cuando finaliza, directamente System.exit (0); salir del proceso actual;
iniciar un nuevo proceso, el código principal: el código del archivo de configuración AndroidManifest.xml es el siguiente

   <activity
        android:name=".ui.activity.Html5Activity"
        android:process=":lyl.boon.process.web">
        <intent-filter>
            <action android:name="com.lyl.boon.ui.activity.htmlactivity"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>

Inicie la actividad en un nuevo proceso y pase una URL dentro:

   Intent intent = new Intent("com.lyl.boon.ui.activity.htmlactivity");
    Bundle bundle = new Bundle();
    bundle.putString("url", gankDataEntity.getUrl());
    intent.putExtra("bundle",bundle);
    startActivity(intent);

Luego agregue System.exit (0); al final de onDestory () de Html5Activity para matar el proceso actual.

2. Webview no se puede definir en xml, pero se crea cuando es necesario, y Context usa getApplicationgContext (), el siguiente código:

       LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        mWebView = new WebView(getApplicationContext());
        mWebView.setLayoutParams(params);
        mLayout.addView(mWebView);

3. Cuando se destruye la actividad, puede dejar que WebView cargue primero el contenido nulo, luego eliminar WebView, luego destruir WebView y finalmente dejarlo vacío.
el código se muestra a continuación:

   @Override
    protected void onDestroy() {
        if (mWebView != null) {
            mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            mWebView.clearHistory();

            ((ViewGroup) mWebView.getParent()).removeView(mWebView);
            mWebView.destroy();
            mWebView = null;
        }
        super.onDestroy();
    }

tecla de retorno

Regrese a la última página vista

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

Citando la página de inicio del autor: zhihu.com/people/qydq

 

 

Supongo que te gusta

Origin blog.csdn.net/xifei66/article/details/108711001
Recomendado
Clasificación