Problèmes courants et solutions pour l'utilisation d'Android WebView (avancé)

Résumer quelques méthodes d'utilisation de WebView

Rappel: lorsque nous utilisons WebView, il est préférable de ne pas écrire WebView en XML. Il est préférable d'utiliser la méthode suivante pour charger directement WebView de manière dynamique

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

 1. Le navigateur système est appelé lorsque la page Web est ouverte, mais il n'est pas affiché dans cette WebView. Nous pouvons appeler le setWebViewClient de mWebView pour l'afficher dans cette WebView.

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

2. Appelez javascript via le code 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. Lorsque vous appuyez sur la touche retour, il ne quittera pas le programme mais reviendra à la page de navigation précédente.

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 page prend en charge le zoom.

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

5. Lorsque la page est ouverte, elle s'adapte à l'écran.
Android4.4 (API version 19) fournit une nouvelle version de WebView basée sur la version Chromium , et non plus webkit. Donc, dans les paramètres des paramètres Web, nous devons ajouter les paramètres suivants:

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

6. Si la vue Web demande à l'utilisateur de saisir manuellement le nom d'utilisateur, le mot de passe ou autre, la vue Web doit être définie pour prendre en charge le focus gestuel.

webview.requestFocusFromTouch();

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

7. L'interface de chargement WebView appelle principalement trois méthodes: LoadUrl, LoadData, LoadDataWithBaseURL.

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

8. Introduction aux méthodes courantes 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. Solution complète de la méthode 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,于是就可以不打开地址,取消这个操作,进行预先定义的其他操作,这对一个程序是非常必要的。

La méthode shouldOverrideUrlLoading () est la méthode utilisée par Android WebView pour interagir avec js (avancé). Cette partie expliquera principalement l'interaction entre Java et Js.

10. Introduction à la méthode supplémentaire de WebSettings (pour s'assurer que la longueur n'est pas éblouissante, elle est couramment utilisée au point 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");//设置编码格式

À propos de la mise en cache

Mode cache

LOAD_CACHE_ONLY: n'utilisez pas le réseau, ne lisez que les données du cache local
LOAD_DEFAULT: (par défaut) Décidez s'il faut récupérer les données du réseau en fonction du contrôle du cache.
LOAD_NO_CACHE: n'utilisez pas le cache, récupérez uniquement les données du réseau.
LOAD_CACHE_ELSE_NETWORK, tant qu'il est disponible localement, qu'il soit expiré ou sans cache, les données du cache sont utilisées.

Utilisation combinée (chargement hors ligne):

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 缓存目录

Remarque: chaque application n'appelle WebSettings.setAppCachePath (), WebSettings.setAppCacheMaxSize () qu'une seule fois

WebViewClient

WebViewClient aide WebView à gérer diverses notifications et requêtes d'événements.
Lors de l'ouverture d'une page Web, le navigateur système n'est pas appelé, mais affiché dans cette WebView:

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

WebViewClient, méthode

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事件未被加载时调用) 
}

Définissez WebViewClient défini ci-dessus sur WebView:

 webView.setWebViewClient(mWebViewClient);

WebChromeClient

WebChromeClient est une boîte de dialogue qui aide WebView à traiter Javascript, l'icône du site Web, le titre du site Web, la progression du chargement, etc.:
le code de la méthode est géré par le côté Android lui-même.

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 même, définissez WebChromeClient défini ci-dessus sur WebView:

Appeler le code JS

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

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

C'est la prémisse ci-dessus! ! !
Ensuite, implémentez la classe ci-dessus, cette classe fournit quatre méthodes, les annotations sont très claires.

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 appelle js a une faille:

La vulnérabilité d'injection d'objets Js d'Android WebView doit être comprise par tout le monde, ce qui est la vulnérabilité d'exécution de code à distance notoire avant Android 4.2, mais Google les a corrigées après Android 4.2. Utilisez la méthode annotée @JavaInterface

Méthode WebView

en avant en arrière

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

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

Effacer les données mises en cache:

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

Le statut de WebView:

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

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

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

Remarque: lorsque la vue
Web appelle la destruction, la vue Web est toujours liée à l'activité. En effet, l'objet de contexte de l'activité est transmis lors de la création de la vue Web personnalisée. Vous devez donc d'abord supprimer la vue Web du conteneur parent, puis détruire la vue Web:

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

Déterminez si le WebView a défilé vers le bas ou le haut de la page:
getScrollY () // La méthode renvoie la distance entre le haut de la zone actuellement visible et le haut de la page entière, qui est la distance à laquelle le contenu actuel fait défiler.
GetHeight () ou getBottom () // Les méthodes renvoient toutes la hauteur du conteneur WebView actuel
getContentHeight () renvoie la hauteur du code HTML entier, mais ce n'est pas équivalent à la hauteur de la page entière actuelle, car le WebView a une fonction de zoom, donc la hauteur actuelle de la page entière doit en fait être le code HTML d'origine La hauteur est multipliée par le taux de zoom. Par conséquent, la méthode d'évaluation correcte doit être:

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

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

Quelques moyens d'éviter les fuites de mémoire WebView

1. Vous pouvez démarrer un nouveau processus d'activité Webview, quand il se termine, directement System.exit (0); quitter le processus en cours;
démarrer un nouveau processus, le code principal: le code du fichier de configuration AndroidManifest.xml est le suivant

   <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>

Démarrez l'activité dans un nouveau processus et passez une URL à l'intérieur:

   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);

Ajoutez ensuite System.exit (0); à la fin de onDestory () de Html5Activity pour tuer le processus en cours.

2. La vue Web ne peut pas être définie en XML, mais créée si nécessaire, et Context utilise getApplicationgContext (), le code suivant:

       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. Lorsque l'activité est détruite, vous pouvez laisser la WebView charger d'abord le contenu nul, puis supprimer la WebView, détruire la WebView et enfin la laisser vide.
code montrer comme ci-dessous:

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

clé de retour

Revenir à la dernière page consultée

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

Citant la page d'accueil de l'auteur: zhihu.com/people/qydq

 

 

Je suppose que tu aimes

Origine blog.csdn.net/xifei66/article/details/108711001
conseillé
Classement