iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android之 WebView的使用
  • 120
分享到

Android之 WebView的使用

androidwebviewjava 2023-09-12 10:09:23 120人浏览 薄情痞子
摘要

一 简介 1 WEBView是用来展示网页的控件,底层是Google的WebKit的引擎。 比起苹果的WebView,webkit一些不足地方: 不能支持Word等文件的预览纯标签加载,并不支持所有标签的加载不支持文件的下载,图片的放大

一 简介

1 WEBView是用来展示网页的控件,底层是Google的WebKit的引擎。

比起苹果的WebView,webkit一些不足地方:

  • 不能支持Word等文件的预览
  • 纯标签加载,并不支持所有标签的加载
  • 不支持文件的下载,图片的放大,都要单独处理

2 其它Web引擎,腾讯的webx5,其功能比WebKit要强大些,支持常见文件格式的预览(word文档,excel表格等),还支持文件的下载。

官方地址: https://x5.tencent.com/tbs/

3 WebView大部分场合还是能满足需求的,用官方Webkit就可以了

二 WebView的使用

1 初始化webview组件

xml里面初始化

获取动态初始化

WebView webView = new WebView(this);llWebview.addView(webView);

2 配置WebSettings

//声明WebSettings子类WebSettings webSettings = webView.getSettings();//如果访问的页面中要与javascript交互,则webview必须设置支持JavascriptwebSettings.setJavaScriptEnabled(true);  //支持插件webSettings.setPluginsEnabled(true); //设置自适应屏幕,两者合用webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小 webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小//缩放操作webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件//其他细节操作webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存 webSettings.setAllowFileAccess(true); //设置可以访问文件 webSettings.setJavaScriptCanOpenwindowsAutomatically(true); //支持通过js打开新窗口 webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

3 加载网页链接或加载标签

加载网页链接

//加载Http链接:http://www.google.com///加载assets链接:file:///Android_asset/test.html//加载本地存储链接:http://www.google.com/webView.loadUrl("http://www.google.com/");

加载标签

String goods_content="

我的第一个段落。

";webView.loadDataWitHBaseURL(null, WebUtil.getHtmlData(goods_content), "text/html", "utf-8", null);public static String getHtmlData(String bodyHTML) {String head = "" +" " +"" +"";return "" + head + "" + bodyHTML + "";}

4 设置WebViewClient,来处理通知和请求事件

常规用法,复写shouldOverrideUrlLoading()方法,使得打开网页时不调用系统浏览器, 而是在本WebView中显示

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

完整用法

webViewClient = new WebViewClient() {     @Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {if (Uri.parse(url).getHost().equals("www.baidu.com")) {Intent intent = new Intent(Intent.ACTioN_VIEW, Uri.parse(url));intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent);return true;}return false;}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {// TODO Auto-generated method stubsuper.onPageStarted(view, url, favicon);Log.i(TAG, "onPageStarted:页面开始加载");}@Overridepublic void onPageFinished(WebView view, String url) {// TODO Auto-generated method stubsuper.onPageFinished(view, url);Log.i(TAG, "onPageStarted:页面加载结束");}@Overridepublic void onLoadResource(WebView view, String url) {// TODO Auto-generated method stubsuper.onLoadResource(view, url);Log.i(TAG, "onLoadResource:加载资源指定的网址");}@Overridepublic WebResourceResponse shouldInterceptRequest(WebView view, String url) {// TODO Auto-generated method stubLog.i(TAG, "shouldInterceptRequest");return super.shouldInterceptRequest(view, url);}@Overridepublic void onReceivedError(WebView view, int errorCode,String description, String failingUrl) {// TODO Auto-generated method stubsuper.onReceivedError(view, errorCode, description, failingUrl);view.loadUrl("file:///android_asset/error.html");Log.i(TAG, "onReceivedError");}@Overridepublic void onFORMResubmission(WebView view, Message dontResend,Message resend) {// TODO Auto-generated method stubsuper.onFormResubmission(view, dontResend, resend);Log.i(TAG, "onFormResubmission");}@Overridepublic void doUpdateVisitedHistory(WebView view, String url,boolean isReload) {// TODO Auto-generated method stubsuper.doUpdateVisitedHistory(view, url, isReload);Log.i(TAG, "doUpdateVisitedHistory");}@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error) {// view.loadUrl("file:///android_asset/error.html");// TODO Auto-generated method stubsuper.onReceivedSslError(view, handler, error);Log.i(TAG, "onReceivedSslError");}@Overridepublic void onReceivedHttpAuthRequest(WebView view,HttpAuthHandler handler, String host, String realm) {// TODO Auto-generated method stubsuper.onReceivedHttpAuthRequest(view, handler, host, realm);Log.i(TAG, "onReceivedHttpAuthRequest");}@Overridepublic boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {Log.i(TAG, "shouldOverrideKeyEvent");// TODO Auto-generated method stubreturn super.shouldOverrideKeyEvent(view, event);}@Overridepublic void onScaleChanged(WebView view, float oldScale, float newScale) {// TODO Auto-generated method stubsuper.onScaleChanged(view, oldScale, newScale);Log.i(TAG, "onScaleChanged");}@Overridepublic void onReceivedLoginRequest(WebView view, String realm,String account, String args) {// TODO Auto-generated method stubsuper.onReceivedLoginRequest(view, realm, account, args);Log.i(TAG, "onReceivedLoginRequest"); }});

5 设置WebChromeClient,辅助WebVlew处理/avascrlpt的对话框,网站图标,网站tltle,加载进度等

常规用法,加载页面缓冲进度

webView.setWebChromeClient(new WebChromeClient() {@Overridepublic void onProgressChanged(WebView view, int newProgress) {if (newProgress >=80) {llView.setVisibility(View.GONE);} else {llView.setVisibility(View.VISIBLE);}super.onProgressChanged(view, newProgress);}});

完整用法

webView.setWebChromeClient(new WebChromeClient() {@Overridepublic void onProgressChanged(WebView view, int newProgress) {// TODO Auto-generated method stubsuper.onProgressChanged(view, newProgress);if (newProgress <= 100) {Log.i(TAG, newProgress + "===onProgressChanged===");}}@Overridepublic void onReceivedTitle(WebView view, String title) {// TODO Auto-generated method stubsuper.onReceivedTitle(view, title);Message message = new Message();message.what = 100;message.obj = title;handler.sendMessage(message); }@Overridepublic void onReceivedIcon(WebView view, Bitmap icon) {// TODO Auto-generated method stubsuper.onReceivedIcon(view, icon);Message message = new Message();message.what = 200;message.obj = icon;handler.sendMessage(message);}@Overridepublic void onReceivedTouchIconUrl(WebView view, String url,boolean precomposed) {// TODO Auto-generated method stubsuper.onReceivedTouchIconUrl(view, url, precomposed);Log.i(TAG, "====onReceivedTouchIconUrl====");} @Overridepublic void onRequestFocus(WebView view) {// TODO Auto-generated method stubsuper.onRequestFocus(view);Log.i(TAG, "====onRequestFocus====");}@Overridepublic boolean onJsAlert(final WebView view, String url, String message,JsResult result) {final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext()); builder.setTitle("对话框").setMessage(message).setPositiveButton("确定", null);builder.setOnKeyListener(new OnKeyListener() {public boolean onKey(DialogInterface dialog, int keyCode,KeyEvent event) {Log.v("onJsAlert", "keyCode==" + keyCode + "event=" + event);return true;}});// 禁止响应按back键的事件builder.setCancelable(false);AlertDialog dialog = builder.create();dialog.show();result.confirm();// 因为没有绑定事件,需要强行confirm,否则页面会变黑显示不了内容。return true;// return super.onJsAlert(view, url, message, result);}@Overridepublic boolean onJsConfirm(final WebView view, String url, String message,final JsResult result) {final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());builder.setTitle("对话框").setMessage(message).setPositiveButton("确定", new OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.confirm();}}).setNeutralButton("取消", new OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.cancel();}});builder.setOnCancelListener(new OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialog) {result.cancel();}}); // 屏蔽keycode等于84之类的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题builder.setOnKeyListener(new OnKeyListener() {@Overridepublic boolean onKey(DialogInterface dialog, int keyCode,KeyEvent event) {Log.v("onJsConfirm", "keyCode==" + keyCode + "event=" + event);return true;}});// 禁止响应按back键的事件// builder.setCancelable(false);AlertDialog dialog = builder.create();dialog.show();return true;}@Overridepublic boolean onJsPrompt(WebView view, String url, String message,String defaultValue, final JsPromptResult result) {final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext()); builder.setTitle("对话框").setMessage(message); final EditText et = new EditText(view.getContext());et.setSingleLine();et.setText(defaultValue);builder.setView(et).setPositiveButton("确定", new OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.confirm(et.getText().toString());} }).setNeutralButton("取消", new OnClickListener() {public void onClick(DialogInterface dialog, int which) {result.cancel();}}); // 屏蔽keycode等于84之类的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题builder.setOnKeyListener(new OnKeyListener() {public boolean onKey(DialogInterface dialog, int keyCode,KeyEvent event) {Log.v("onJsPrompt", "keyCode==" + keyCode + "event=" + event);return true;}}); // 禁止响应按back键的事件// builder.setCancelable(false);AlertDialog dialog = builder.create();dialog.show();return true;// return super.onJsPrompt(view, url, message, defaultValue,// result);}});

6 Android调用JS

添加网络权限

编写html文件,放到assets文件里面

 
function say(value){
  callJS(value);
}

java文件,android调用js

public class MainActivity extends AppCompatActivity {    private WebView webview;    private TextView tvAndroid;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                webview = (WebView) findViewById(R.id.webview);        tvAndroid = (TextView) findViewById(R.id.tv_android);        tvAndroid.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                //Android调用js方法                //Android 4.4以下使用loadUrl,Android 4.4以上evaluateJavascript                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {                    webview.loadUrl("javascript:callJS('aaa')");                } else {                    webview.evaluateJavascript("javascript:callJS('aaa')", new ValueCallback() {                        @Override                        public void onReceiveValue(String value) {//此处为 js 返回的结果Toast.makeText(MainActivity.this,value,Toast.LENGTH_SHORT).show();                        }                    });                }            }        });                initWebView();    }    public void initWebView() {        //启用JS脚本        webview.getSettings().setJavaScriptEnabled(true);        // 设置允许JS弹窗        webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);        //加载网页        webview.loadUrl("file:///android_asset/index.html");        // 由于设置了弹窗检验调用结果,所以需要支持js对话框        // webview只是载体,内容的渲染需要使用webviewChromClient类去实现        // 通过设置WebChromeClient对象处理JavaScript的对话框        //设置响应js 的Alert()函数        webview.setWebChromeClient(new WebChromeClient(){            @Override            public boolean onJsAlert(WebView view, String url, String message, JsResult jsResult) {                new AlertDialog.Builder(view.getContext()).setMessage(message).setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        jsResult.confirm();                    }                }).setCancelable(false).create().show();                return true;            }        });        //覆盖WebView默认使用第三方或系统默认浏览器打开网页的行为,使网页用WebView打开        webview.setWebViewClient(new WebViewClient() {            //override            public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {                handler.proceed("admin", "sunlight");                int d = Log.d("MyWebViewClient", "onReceivedHttpAuthRequest");            }            @Override            public boolean shouldOverrideUrlLoading(WebView view, String uri) {                // TODO Auto-generated method stub                //返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器                view.loadUrl(uri);                return true;            }        });    }}

效果

注意:

  • 启用JS脚本 webview.getSettings().setJavaScriptEnabled(true);
  • 设置允许JS弹窗webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
  • 4.4以下通过​​WebView​​​的​​loadUrl()​,4.4以上通过​​WebView​​​的​​evaluateJavascript()​​
  • JS代码调用一定要在 ​​onPageFinished()​​ 回调之后才能调用,否则不会调用 

7 js调用android方法 

方法一:通过​​WebView​​​的​​addJavascriptInterface()​​进行对象映射

html文件

  

java文件

package com.serial.jsweview;import android.os.Build;import android.os.Bundle;import android.view.View;import android.webkit.JavascriptInterface;import android.webkit.ValueCallback;import android.webkit.WebView;import android.widget.TextView;import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;public class MainActivity2 extends AppCompatActivity {    private WebView webview;    private TextView tvAndroid;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main2);                webview = (WebView) findViewById(R.id.webview);        tvAndroid = (TextView) findViewById(R.id.tv_android);        tvAndroid.setText("//继承自Object类,别名是aa,即在html可以直接用aa.showToast(\"哈哈哈\")来调用android方法\n" +                "public class MyObject extends Object {\n" +                "    @JavascriptInterface\n" +                "    public void showToast(String name){\n" +                "         Toast.makeText(MainActivity2.this, \"您好!\"+name, Toast.LENGTH_SHORT).show();\n" +                "    }\n" +                "}");                initWebView();    }    public void initWebView() {        // 设置与Js交互的权限        webview.getSettings().setJavaScriptEnabled(true);        //将java对象暴露给JavaScript脚本        //参数1:java对象,里面定义了java方法        //参数2:Java对象在js里的对象名,可以看作第一个参数的别名,可以随便取,即在html可以直接用aa.showToast("哈哈哈")来调用android方法        webview.addJavascriptInterface(new MyObject(), "aa");//AndroidtoJS类对象映射到js的test对象        //加载网页        webview.loadUrl("file:///android_asset/index2.html");    }    //继承自Object类,别名是aa,即在html可以直接用aa.showToast("哈哈哈")来调用android方法    public class MyObject extends Object {        // 定义JS需要调用的方法        // 被JS调用的方法必须加入@JavascriptInterface注解        @JavascriptInterface        public void showToast(String name){            Toast.makeText(MainActivity2.this, "您好!"+name, Toast.LENGTH_SHORT).show();        }    }}

 

 方法二:通过 ​​WebViewClient​​​ 的​​shouldOverrideUrlLoading ()​​方法回调拦截 url

原理:

  • Android通过 ​​WebViewClient​​​ 的回调方法​​shouldOverrideUrlLoading ()​​拦截 url
  • 解析该 url 的协议
  • 如果检测到是预先约定好的协议,就调用相应方法

html文件

 java文件

public class MainActivity3 extends AppCompatActivity {    private WebView webview;    private TextView tvAndroid;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main2);                webview = (WebView) findViewById(R.id.webview);        tvAndroid = (TextView) findViewById(R.id.tv_android);                initWebView();    }    public void initWebView() {        // 设置与Js交互的权限        webview.getSettings().setJavaScriptEnabled(true);        // 设置允许JS弹窗        webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);        //步骤1:加载网页        webview.loadUrl("file:///android_asset/index3.html");        // 复写WebViewClient类的shouldOverrideUrlLoading方法        webview.setWebViewClient(new WebViewClient() {  @Override  public boolean shouldOverrideUrlLoading(WebView view, String url) {  // 步骤2:根据协议的参数,判断是否是所需要的url  // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)  //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)  Uri uri = Uri.parse(url);  // 如果url的协议 = 预先约定的 js 协议  // 就解析往下解析参数  if ( uri.getScheme().equals("js")) {  // 如果 authority  = 预先约定协议里的 webview,即代表都符合约定的协议  // 所以拦截url,下面JS开始调用Android需要的方法  if (uri.getAuthority().equals("webview")) {  // 步骤3:  // 执行JS所需要调用的逻辑  Toast.makeText(MainActivity3.this, "您好!js调用了Android的方法", Toast.LENGTH_SHORT).show();  // 可以在协议上带有参数并传递到Android上  HashMap params = new HashMap<>();  Set collection = uri.getQueryParameterNames();  }  return true;  }  return super.shouldOverrideUrlLoading(view, url);  }    }        );    }}

效果

 

方法三:通过 ​​WebChromeClient​​​ 的​​onJsAlert()​​​、​​onJsConfirm()​​​、​​onJsPrompt()​​​方法回调拦截JS对话框​​alert()​​​、​​confirm()​​​、​​prompt()消息

原理:

  • Android通过 ​​WebChromeClient​​​ 的​​onJsAlert()​​​、​​onJsConfirm()​​​、​​onJsPrompt()​​​方法回调分别拦截JS对话框,得到他们的消息内容,然后解析即可。比如拦截 JS的输入框prompt()​​方法
  • 因为只有​​prompt()​​可以返回任意类型的值,操作最全面方便、更加灵活;
  • 而alert()对话框没有返回值;confirm()对话框只能返回两种状态(确定 / 取消)两个值

html文件

当使用​​mWebView.loadUrl("file:///android_asset/javascript.html")​​​加载了上述JS代码后,就会触发回调​​onJsPrompt()​​,具体如下:

如果是拦截警告框,即​​alert()​​​,则触发回调​​onJsAlert();
如果是拦截确认框,即​​confirm(),则触发回调​​onJsConfirm();

java文件

package com.serial.jsweview;import android.net.Uri;import android.os.Bundle;import android.webkit.JsPromptResult;import android.webkit.JsResult;import android.webkit.WebChromeClient;import android.webkit.WebView;import android.webkit.WebViewClient;import android.widget.TextView;import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import java.util.HashMap;import java.util.Set;public class MainActivity4 extends AppCompatActivity {    private WebView webview;    private TextView tvAndroid;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main4);        webview = (WebView) findViewById(R.id.webview);        tvAndroid = (TextView) findViewById(R.id.tv_android);        initWebView();    }    public void initWebView() {        // 设置与Js交互的权限        webview.getSettings().setJavaScriptEnabled(true);        // 设置允许JS弹窗        webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);        webview.loadUrl("file:///android_asset/index4.html");        webview.setWebChromeClient(new WebChromeClient() {                // 拦截输入框(原理同方式2)                // 参数message:代表promt()的内容(不是url)                // 参数result:代表输入框的返回值                @Override                public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {                    // 根据协议的参数,判断是否是所需要的url(原理同方式2)                    // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)                    //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)                    Uri uri = Uri.parse(message);                    // 如果url的协议 = 预先约定的 js 协议                    // 就解析往下解析参数                    if (uri.getScheme().equals("js")) {                        // 如果 authority  = 预先约定协议里的 webview,即代表都符合约定的协议                        // 所以拦截url,下面JS开始调用Android需要的方法                        if (uri.getAuthority().equals("webview")) {//// 执行JS所需要调用的逻辑System.out.println("js调用了Android的方法");// 可以在协议上带有参数并传递到Android上HashMap params = new HashMap<>();Set collection = uri.getQueryParameterNames();//参数result:代表消息框的返回值(输入值)result.confirm("js调用了Android的方法成功啦");                        }                        return true;                    }                    return super.onJsPrompt(view, url, message, defaultValue, result);                }                // 拦截JS的警告框                @Override                public boolean onJsAlert(WebView view, String url, String message, JsResult result) {                    return super.onJsAlert(view, url, message, result);                }                // 拦截JS的确认框                @Override                public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {                    return super.onJsConfirm(view, url, message, result);                }            }        );    }}

效果

总结

JS调用Android代码的方法有3种:

  1. 通过​​WebView​​​的​​addJavascriptInterface()​​进行对象映射,存在安全漏洞
  2. 通过 ​​WebViewClient​​​ 的​​shouldOverrideUrlLoading ()​​方法回调拦截 url,不存在1的漏洞,但JS获取Android方法的返回值复杂
  3. 通过 ​​WebChromeClient​​​ 的​​onJsAlert()​​​、​​onJsConfirm()​​​、​​onJsPrompt()​​​方法回调拦截JS对话框​​alert()​​​、​​confirm()​​​、​​prompt()​​ 消息。不存在漏洞,需要协议的约定

8  页面返回

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

9 缓存的配置

WebSettings webSettings = mWebView.getSettings();//优先使用缓存webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //只在缓存中读取webSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);/不使用缓存WwebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);

10 清除缓存

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

10 webview生命周期

onResume()
WebView为活跃状态时回调,可以正常执行网页的响应。

onPause()
WebView被切换到后台时回调, 页面被失去焦点, 变成不可见状态,onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。

pauseTimers()
当应用程序被切换到后台时回调,该方法针对全应用程序的WebView,它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。

resumeTimers()
恢复pauseTimers时的动作。

destroy()
关闭了Activity时回调, WebView调用destory时, WebView仍绑定在Activity上.这是由于自定义WebView构建时传入了该Activity的context对象, 因此需要先从父
容器中移除WebView, 然后再销毁webview。
mRootLayout.removeView(webView);  
mWebView.destroy();

跟随Activity的生命周期

@Overrideprotected void onResume() {    super.onResume();    //恢复webview的状态(不靠谱)    webView.resumeTimers();    //激活webView的状态,能正常加载网页    webView.onResume();}@Overrideprotected void onPause() {    super.onPause();    //当页面被失去焦点被切换到后台不可见状态,需要执行onPause    //通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。    webView.onPause();    //当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview    //它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。(不靠谱)    webView.pauseTimers();}@Overrideprotected void onDestroy() {super.onDestroy();//在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview//但是注意:webview调用destory时,webview仍绑定在Activity上//这是由于自定义webview构建时传入了该Activity的context对象//因此需要先从父容器中移除webview,然后再销毁webview:ViewGroup parent = findViewById(R.id.container);parent.removeView(webView);webView.destroy();}

三 防止内存泄漏的注意点

1 在需要的时候在 Activity 中创建,并且使用 getApplicationGContext(),而不要在xml注册。

//mWebView=new WebView(this);mWebView=new WebView(getApplicationContext());LinearLayout linearLayout  = findViewById(R.id.xxx);linearLayout.addView(mWebView);

2 并且Activity退出的时候,需要手动释放webview内存

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

3 尽量不要在webview里面开启新进程 

比如下面这种

四 其它web框架的选择

1 webview大部分场合是没问题的,但涉及到文件下载,文档浏览等只能自己写js交互,处理相对麻烦。所以也有其它web框架供我们选择

2 第一个就是开头提过的腾讯webx5,相对来说比较强大,但可能个别手机会出现兼容问题

官方网址:https://x5.tencent.com/tbs/

3 还有GitHub常用的webview库,内置文件的处理功能,和加载缓冲样式,也可以直接代替webview

项目地址:https://github.com/Justson/AgentWeb

4 还有专门处理JS交互的一个库DSBridge,分为webx5内核版本和webkit内核版本

项目地址:https://github.com/wendux/DSBridge-Android

使用中webx5内核版本由于规则定义不符合我们要求,而且不能改,就换用了webkit内核版本,目前没出现什么问题

五  手机加载网页空白问题解决方案

1 网页加载空白原因有很多,遇到的可以尝试下面方案,第一个就是联网权限没配置,配置下权限

2 https的ssl证书问题

WebView().setWebViewClient(new WebViewClient(){@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {handler.proceed();}});

3  尝试加载DOM缓存

webView.getSettings().setDomStorageEnabled(true);

4  Android5.0以上允许加载http和https混合的页面

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {  webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);}

5 如果上面尝试都不行,那就有可能不是Webview配置问题,可能是内核版本较低,对于高版本的Web或者JS语法不支持。

es6经过尝试在Androd6.0系统上会空白,而且切换腾讯Webx5内核也不行。这时候只能让web前端es6转为es5了

即可以尝试h5做低版本适配,ES6转化为ES5的方案

来源地址:https://blog.csdn.net/qq_29848853/article/details/130368448

--结束END--

本文标题: Android之 WebView的使用

本文链接: https://www.lsjlt.com/news/404288.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android之 WebView的使用
    一 简介 1 WebView是用来展示网页的控件,底层是google的WebKit的引擎。 比起苹果的WebView,webkit一些不足地方: 不能支持word等文件的预览纯标签加载,并不支持所有标签的加载不支持文件的下载,图片的放大...
    99+
    2023-09-12
    android webview java
  • Android开发之WebView组件的使用解析
    在 Android 手机中内置了一款高性能 webkit 内核浏览器, SDK 中封装为一个叫做 WebView 组件。 WebView 类是 WebKit 模块 Java 层...
    99+
    2022-06-06
    android开发 webview Android
  • Android WebView 优化之路
    随着app的迭代,嵌入的html5界面越来越多了,Webview这个强大组件引起的问题越发的多起来,例如: 1、WebView导致的oom问题 2、Android版本不...
    99+
    2022-06-06
    优化 webview Android
  • Android程序开发之WebView使用总结
    前言: 今天修改项目中一个有关WebView使用的bug,激起了我总结WebView的动机,今天抽空做个总结。 使用场景: 1.)添加权限 <uses-perm...
    99+
    2022-06-06
    webview Android
  • Android 之 WebView 缓存问题
    本节引言: 现在很多门户类信息网站,比如虎嗅,ifanr,钛媒体等等的APP,简单点说是信息阅读类的APP,很多 都是直接嵌套一个WebView用来显示相关资讯的,这可能就涉及到了WebView的缓存了! 所谓的页面缓存 就是指:保存...
    99+
    2023-09-29
    android 缓存
  • Android WebView开发之自定义WebView工具框
    附GitHub源码:WebViewExplore 先看图: 在WebView页面长按时会弹出一个复制框,但如果里面的item不是我们想要的或者想自定义,那么可以通过覆盖WebVie...
    99+
    2022-11-12
  • Android WebView 的简单使用
    Android WebView 1.首先修改activity.xml中的代码: 2.然后MainActivity中的代码: 3.最后设置权限: <uses-perm...
    99+
    2022-06-06
    webview Android
  • Android Webview使用小结
    本文实例为大家分享了Android Webview使用小结,供大家参考,具体内容如下 #采用重载URL的方式实现Java与Js交互 在Android中,常用的Java与Js交互...
    99+
    2022-06-06
    小结 webview Android
  • Android 之 WebView (网页视图)基本用法
    本节引言 本节给大家带来的是Android中的一个用于显示网页的控件:WebView(网页视图)。 现在Android应用 层开发的方向有两种:客户端开发和HTML5移动端开发! 所谓的HTML5端就是:HTML5 + CSS + ...
    99+
    2023-08-31
    android harmonyos 华为
  • Android开发笔记之探秘WebView
    概述:            一个显示网页的视图。这个类是你可以滚动自己的W...
    99+
    2022-06-06
    android开发 webview Android
  • android控件之WebView控件缩小
    代码如下:package com.weizhu.lan.view; import com.weizhu.lan.util.MyprogressDialog; import a...
    99+
    2022-06-06
    webview Android
  • Android WebView的使用方法总结
     Android WebView的使用方法  Android app打开H5页一般要实现如下需求:打开指定url网页;2、点击链接可以跳转到下一页,并更新标题;3、按back键或左箭头可以返回上一页;4、当webview...
    99+
    2023-05-30
    android webview roi
  • android WebView组件使用总结
    浏览器控件是每个开发环境都具备的,这为马甲神功提供了用武之地,windows的有webbrowser,android和ios都有webview。只是其引擎不同,相对于微软的we...
    99+
    2022-06-06
    webview Android
  • Android中ViewPager如何使用WebView
    小编给大家分享一下Android中ViewPager如何使用WebView,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Android 中ViewPager中使用...
    99+
    2023-05-30
    android viewpager webview
  • webview如何在Android中使用
    这篇文章给大家介绍webview如何在Android中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Androi1. 打开网页时不调用系统浏览器, 而是在本WebView中显示:mWebView.setWebVie...
    99+
    2023-05-30
    android webview
  • Android APP之WebView校验SSL证书的方法
    Android系统的碎片化很严重,并且手机日期不正确、手机根证书异常、com.google.android.webview BUG等各种原因,都会导致WebViewClient无法访问HTTPS站点。SSL错误的处理方式十分关键,如果处理不...
    99+
    2023-05-30
    android app webview
  • 解析Android中webview和js之间的交互
    1.android中利用webview调用网页上的js代码。Android 中可以通过webview来实现和js的交互,在程序中调用js代码,只需要将webview控件的支持j...
    99+
    2022-06-06
    webview js Android
  • Android总结之WebView与Javascript交互(互相调用)
    前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App、Web App、Hybrid App三种方式...
    99+
    2022-06-06
    调用 webview JavaScript Android
  • Android WebView使用的技巧与一些坑
    随着手机性能的提高,以及iOS和Android两个平台的普及,更多的App都会选择两个平台的App都进行开发,在有些时候,为了更加快速的开发,我们会采用hybird方式开发,这...
    99+
    2022-06-06
    技巧 webview Android
  • WebView如何在Android应用中使用
    这期内容当中小编将会给大家带来有关WebView如何在Android应用中使用 ,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。WebView基本使用 WebView是View的一个子类,可以让你在acti...
    99+
    2023-05-31
    android webview roi
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作