精华内容
下载资源
问答
  • private WebView wv;@Overridepublic void onCreate(Bundle icicle) {super.onCreate(icicle);setContentView(R.layout.main);wv = (WebView) findViewById(R.id.wv1);wv.loadUrl("");wv.setWebViewClient(new WebVi...

    private WebView wv;

    @Override

    public void onCreate(Bundle icicle) {

    super.onCreate(icicle);

    setContentView(R.layout.main);

    wv = (WebView) findViewById(R.id.wv1);

    wv.loadUrl("");

    wv.setWebViewClient(new WebViewClientDemo());

    }

    private class WebViewClientDemo extends WebViewClient {

    @Override

    // 在WebView中而不是默认浏览器中显示页面

    public boolean shouldOverrideUrlLoading(WebView view, String url) {

    view.loadUrl(url);

    return true;

    }

    }

    

    阅读(1772) | 评论(0) | 转发(0) |

    展开全文
  • 封装WebView加载中和错误页面
  • Android 手机中内置了一款高性能 webkit 内核浏览器, SDK 中封装为一个叫做 WebView 组件。 WebView 类是 WebKit 模块 Java 层的视图类,( 所有需要使用 Web 浏览功能的Android应用程序都要创建该视图对象显示...
  • Android开发加载H5页面的WebView控件就是一个深坑的存在: 默认不允许执行JavaScript脚本 H5页面宽度不适配手机 H5的视频播放不能全屏 H5中上传文件标签无响应导致不会拉起系统拍照与选择相册功能 H5的...

    Android WebView总结:封装WebView基类页面,继承基类即可玩转WebView、JS交互的功能演示、项目中内含自定义Dialog,功能强大。

    本文为本人原创首发
    转载请标明出处:https://blog.csdn.net/zang_chen/article/details/84308316
    本文出自陈小二来巡山的博客

    WebView控件的坑

    Android开发加载H5页面的WebView控件就是一个深坑的存在:
    默认不允许执行JavaScript脚本
    H5页面宽度不适配手机
    H5的视频播放不能全屏
    H5中上传文件标签无响应导致不会拉起系统拍照与选择相册功能
    H5的localStorage本地存储无效果
    …等等一堆问题。

    解决方法

    博主封装WebView基类页面,继承基类即可实现:
    允许执行JavaScript脚本功能、
    H5页面自适应屏幕功能、
    H5视频播放与全屏功能、
    上传文件标签的响应拉起系统拍照与选择相册功能(兼容Android7.0以上系统)、
    开启H5的localStorage本地存储功能、自定义UserAgent功能、WebView支持文件下载功能、
    自动播放音频autoplay功能、
    开启自动化测试功能等等
    以及JS交互功能演示。

    此外项目中还封装了自定义Dialog,自己可根据需求增加构造形参实现【弹窗标题是否展示、取消与确定按钮的展示内容、取消与确定按钮是否展示、取消与确定按钮颜色是否高亮】等动态配置功能。

    项目地址

    链接: WebViewDemo
    新增JsBridge示例项目

    项目用到的依赖

    权限管理
    链接: AndPermission
    文件选择器
    链接: RxGalleryFinal

    其他

    第三方浏览器内核
    链接: 腾讯X5
    链接: Crosswalk

    展开全文
  • Android开发WebView详细总结

    千次阅读 2016-10-11 22:32:41
    WebViewandroid开发中专门用来加载网页的一种控件,它采用WebKit渲染引擎来显示网页包括控制网页的前进、后退、放大、缩小、执行文本、搜索等功能。WebKit是一种让网页浏览器绘制网页的排版引擎,被用于Apple ...

    转载请注明出处:http://blog.csdn.net/li0978/article/details/52792162

    前言

    WebView是android开发中专门用来加载网页的一种控件,它采用WebKit渲染引擎来显示网页包括控制网页的前进、后退、放大、缩小、执行文本、搜索等功能。WebKit是一种让网页浏览器绘制网页的排版引擎,被用于Apple Safari,其分支也用于基于Chromuim的网页浏览器,详细了解可移步于https://zh.wikipedia.org/zh/WebKit。WebView在开发项目中使用的频率非常高,尤其是H5的发展,开发模式也由原生开发逐步被混合开发所替代。

    注册

    WebView使用时一般情况下要远程加载,必须在AndroidManifest文件中注册网络权限:

    <uses-permission android:name="android.permission.INTERNET" />

    如果还要涉及到定位,还要注册定位权限:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

    加载方式

    //加载一个网页
    webView.loadUrl(“http://www.google.com/“);
    //加载项目中的一个html页面
    webView.loadUrl(“file:///android_asset/test.html”);
    //加载手机本地的一个html页面的方法
    webView.loadUrl(“content://com.android.htmlfileprovider/sdcard/test.html”);
    //加载一段Html代码
    loadData(String data, String mimeType, String encoding);
    loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl);
    例:webView.loadDataWithBaseURL(null, htmlContent, “text/html”, “UTF-8”,null);
    区别:loadDataWithBaseURL()比loadData()多两个参数,可以指定HTML代码片段中相关资源的相对根路径,也可以指定历史Url。两个方法的其余三个参数相同。但是loadData()中的html data中不能包含’#’, ‘%’, ‘\’, ‘?’四中特殊字符,使用时我们需要用UrlEncoder编码为%23, %25, %27, %3f 。

    WebSettings

    WebSettings类主要针对webview做一些相关的设置,包括自适应屏幕、缩放设置、js脚本控制、网页数据缓存等。

    WebSettings webSettings = webView.getSettings();
    // 设置自适应屏幕
    webSettings.setUseWideViewPort(true);           //设置成webview推荐使用的窗口,可任意比例缩放
    webSettings.setLoadWithOverviewMode(true);      //设置成webview加载的页面大小的模式,
    // 设置缩放网页
    webSettings.setSupportZoom(true);               //是否支持屏幕双击缩放,但是下边的是前提
    webSettings.setBuiltInZoomControls(true);       //是否支持内置按钮缩放和手势“捏”缩放,如果设为false则webview不支持缩放功能
    webSettings.setDisplayZoomControls(false);      //是否隐藏原生的缩放控件
    // 设置可以执行Javascript脚本
    webSettings.setJavaScriptEnabled(true);
    // 设置缓存网页数据
    webSettings.setDomStorageEnabled(true);         //开启 DOM storage API 功能
    webSettings.setDatabaseEnabled(true);           //开启 database storage API 功能
    webSettings.setAppCacheEnabled(true);           //开启 Application Caches 功能
    // 设置支持多窗口,要复写 WebChromeClient的onCreateWindow方法
    webSettings.setSupportMultipleWindows(true);    //支持多窗口
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);  //支持js打开新窗口
    // 支持自动加载图片
    webSettings.setLoadsImagesAutomatically(true);
    // 设置编码格式
    webSettings.setDefaultTextEncodingName("utf-8");

    缓存设置

    webview中的缓存模式有四种:

    • LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
    • LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
    • LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
    • LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

    根据网络合理加载网络数据:

    if (NetStatusUtil.isConnected(getApplicationContext())) {
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//有网,根据cache-control决定是否从网络上取数据。
    } else {
        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //没网,则从本地获取,即离线加载
    }
    String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath();
    webSettings.setAppCachePath(appCachePath);      //设置缓存数据目录

    字体大小控制

    Android版本4.0之前WebView支持字体大小分为5中:

    • SMALLEST(50%),
    • SMALLER(75%),
    • NORMAL(100%),
    • LARGER(150%),
    • LARGEST(200%);

    设定字体大小:

    webSettings.setTextSize(TextSize.SMALLER);

    Android4.0之后WebView使用起来更加灵活,可采用setTextZoom(int)设置字体大小,参数默认是100。上边的方法已经舍弃。

    WebViewClient

    主要展示webview网页加载的一个过程,用于帮助webview处理一些请求事件和通知。

    WebViewClient webViewClient = new WebViewClient(){
    
        //超链接加载,打开网页时不调用系统浏览器,而是在本WebView中显示。也可捕获超链接url,做相关操作
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;    //返回true表示在当前浏览器中加载
        }
    
        //网页开始加载
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        }
    
        //网页加载结束
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
        }
    
        //网页加载失败
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            super.onReceivedError(view, request, error);
        }
    
        //对Https的支持
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            handler.proceed();
        }
    
        //针对页面中每一个资源都会调用一次,用于捕获页面资源
        @Override
        public void onLoadResource(WebView view, String url) {
            super.onLoadResource(view, url);
        }
    };

    WebView调用:

    webView.setWebViewClient(webViewClient);

    WebChromeClient

    WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等。

    WebChromeClient webChromeClient = new WebChromeClient(){
    
        //获取网页加载进度
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            if (newProgress < 100) {
                String progress = newProgress + "%";
            } else {
            }
            super.onProgressChanged(view, newProgress);
        }
    
        //=========捕获网页标题信息==========================================================
        //获取标题
        @Override
        public void onReceivedTitle(WebView view, String title) {
            super.onReceivedTitle(view, title);
        }
        //获取标题ICON
        @Override
        public void onReceivedIcon(WebView view, Bitmap icon) {
            super.onReceivedIcon(view, icon);
        }
    
        //=========捕获弹框信息==========================================================
        //警告框
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            if(message!=null){
                //TODO
                //捕获网页中弹框信息
                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
            }
            result.cancel();   //
            return true;       //表示确认进行捕获
        }
    
        //确认框,会返回布尔值类型,通过这个值可判断点击时是确定还是取消,确定为true,取消为false
        @Override
        public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
            return super.onJsConfirm(view, url, message, result);
        }
    
        //输入框,会返回输入框中的值,点击取消返回null
        @Override
        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
            return super.onJsPrompt(view, url, message, defaultValue, result);
        }
    
        //=========HTML5定位==========================================================
        //需要先加入权限
        //<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
        //<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
        @Override
        public void onGeolocationPermissionsHidePrompt() {
            super.onGeolocationPermissionsHidePrompt();
        }
    
        @Override
        public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) {
            callback.invoke(origin, true, false);  //注意个函数,第二个参数就是是否同意定位权限,第三个是是否希望内核记住
            super.onGeolocationPermissionsShowPrompt(origin, callback);
        }
    
        //=========HTML5多窗口=========================================================
        //WebSettings要支持多窗口
        @Override
        public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
            WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
            transport.setWebView(webView);
            resultMsg.sendToTarget();
            return true;
        }
        @Override
        public void onCloseWindow(WebView window) {
            super.onCloseWindow(window);
        }
    };

    WebView调用:

    webView.setWebChromeClient(webChromeClient);

    支持文件下载

    DownloadListener downloadListener = new DownloadListener() {
        @Override
        public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
            Uri uri = Uri.parse(url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        }
    };

    WebView调用:

    webView.setDownloadListener(downloadListener);

    JS交互

    js交互说白了就两种形式,一种是由webview中的java方法去调用html中的js方法。另一种是html调用webview中java方法。注意在android4.2之前webview有一个漏洞,外部可通过反射来获取手机的联系方式等隐私,4.2以上官方已经修复,可在每个交互方法上添加一个注解“@JavascriptInterface”便可解决,漏洞详情可参阅:http://blog.csdn.net/leehong2005/article/details/11808557

    webview设置对js的支持:

    webSettings.setJavaScriptEnabled(true);

    webview添加js交互接口:

    webView.addJavascriptInterface(new JSInterface(),"jsinterface");

    封装js交互类:

    class JSInterface {
    
            //js中可以通过:window.jsinterface.JS2Java();调用java无参方法。
            @JavascriptInterface
            public void JS2Java(){
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(WebViewActivity.this,"js调用java无参方法。",Toast.LENGTH_SHORT).show();
                    }
                });
            }
    
            //js中可以通过:window.jsinterface.JS2Java('hello java');调用java有参方法,并传参'hello java'。
            @JavascriptInterface
            public void JS2Java(final String str){
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(WebViewActivity.this,"js调用java有参方法,js传递的参数是:"+str,Toast.LENGTH_SHORT).show();
                    }
                });
            }
    
            //Java调用JS中的无参方法
            @JavascriptInterface
            public void Java2JS(){
                webView.loadUrl("javascript: fromJS1()");
                Log.e("TAG","java调用js中的无参方法");
            }
    
            //Java调用JS中的有参方法,并传参数给js
            @JavascriptInterface
            public void Java2JS(final String str){
                webView.loadUrl("javascript: fromJS2('"+str+"')");
                Log.e("TAG","java调用js中的有参方法");
            }
        }

    webview调用js中的方法:

    //调用js有参方法
            js_has_args_bt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new JSInterface().Java2JS("hello js");
                }
            });

    WebView相关方法

    • 前进,后退
      goBack() //后退
      goForward() //前进
      goBackOrForward(intsteps) //以当前的index为起始点前进或者后退到历史记录中指定的steps,如果steps为负数则为后退,正数则为前进
      canGoForward() //是否可以前进
      canGoBack() //是否可以后退
    • 清除缓存
      clearCache(true) //清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
      clearHistory() //清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
      clearFormData() //清除自动完成填充的表单数据,不会清除WebView存储到本地的数据。
    • WebView状态
      onResume() //激活WebView为活跃状态,能正常执行网页的响应
      onPause() //WebView处于暂停状态,onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
      pauseTimers() //暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
      resumeTimers() //恢复pauseTimers时的动作。
      destroy() //销毁,关闭了Activity时,音乐或视频,还在播放。就必须销毁。
    • 重新加载网页
      reload()
      重新加载网页将会重新调用WebClient类中的方法。
    • 判断WebView滚动到顶端还是低端
    // 已经处于底端
    if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
    }
    // 处于顶端
    if(webView.getScrollY() == 0){
    }
    • 退到后台关闭暂停音乐视频播放
    public void onPause() {
           super.onPause();
           webView.onPause();
       }
    
    public void onResume() {
           super.onResume();
           webView.onResume();
       }
    • 设置手机返回按键监听
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
            webView.goBack();
            return true;
        }
        finish();
        return super.onKeyDown(keyCode, event);
    }
    • Activity退出销毁WebView
      这一步主要防止内存溢出,webview调用destory时,自定义webview仍绑定在Activity上.这是由于自定义webview构建时传入了该Activity的context对象,因此需要先从父容器中移除webview,然后再销毁webview。
    @Override
    protected void onDestroy() {
        if (webView != null) {
            webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            webView.clearHistory();
    
            ((ViewGroup) webView.getParent()).removeView(webView);
            webView.destroy();
            webView = null;
        }
        super.onDestroy();
    }

    以上是个人总结WebView掌握的知识点,其他细节请移步官方文档查阅清楚,另外在系统级别4.4以上有一个开源引擎crosswalk对H5支持很好,可参阅crosswalk官方文档https://crosswalk-project.org/进行学习。

    展开全文
  • Android Tencent X5 WebView 集成封装

    千次阅读 2019-01-29 11:00:25
    Android Tencent X5 WebView 集成封装   Cookie管理、进度监听、适配8.1系统等策略    这篇文章的目标就是怎么样快速封装X5WebView,如何有效的同步以及管理Cookie,如何使用IntentService优化预加载,如何...

    Android Tencent X5 WebView 集成封装

     

    Cookie管理、进度监听、适配8.1系统等策略

     

               这篇文章的目标就是怎么样快速封装X5WebView,如何有效的同步以及管理Cookie,如何使用IntentService优化预加载,如何监听进度条以及8.1系统的踩坑适配,等一些在项目中的常用功能。

    本文最近更新内容:

    X5Webview适配Android 8.1系统

    Https与Http混合加载

    功能需求:

    需求一:客户端账号密码登录成功以后,调用H5(也就是使用X5webView,以下简称X5)。H5界面也需要去记录你的状态。比如你客户端本地登录成功以后,H5界面也需要显示登录成功的状态。那么,客户端和H5如何去同步状态?

    需求二:因为X5加载的时候,会有一段时间会显示空白或者卡顿,如何去监听并利用这个进度并优化?

    需求三:如何简单封装X5WebView基本功能,方便日后快速使用?

    需求分析:

    需求一:

    (针对需求一,真的是参考了很多哥们的技术博客,然后由于笔者上周也就是3月9号接到的开发需求,其中遇到了很多坑,所以我希望这篇博客可以把这个需求写的详细,尽可能的造福以后遇到同样需求的朋友让他们节约时间少走弯路)

    对于Cookie,我们并不陌生,如果不是很了解的建议首先参考Cookie、Session、Token那点事儿  先大致掌握一下。这里多提一嘴,Cookie 简单理解,它主要是用来进程保活的,其具有时效性(持久化和非持久化),它是通过服务器的请求,在响应头里面拿到,然后在第二次http请求上以请求头的方式将参数带过去,优点是减少后台查库压力等等,更加具体的细节和说明可以参考上面的链接文章,那么,在Android中,也就是WebView中,我们如何去管理Cookie?

    首先:CookieSyncManager与CookieManager

    Android中关于Cookie的说明:

    早期的cookie是由CookieSyncManager进行管理的,之后CookieSyncManager被抛弃了,换成了CookieManager来进行管理。两个版本的分割线就是Android SDK -- 21。

    Android中Cookie的存储位置:

    目前Android系统WebView是将cookie存储data/data/package_name/app_webview这个目录下的一个叫Cookies的数据中。

    CookieSyncManager在内存和存储器之间同步浏览器的cookie。另外,CookieSyncManager的同步策略是在一个独立的线程里定时进行同步。

    注意:每次同步的时间间隔是5分钟。

    CookieSyncManager类下的常用API介绍

    cookie同步策略:

    CookieSyncManager.createInstance(context); 

    CookieSyncManager.getInstance().startSync();

    cookie停止同步:

    CookieSyncManager.getInstance().stopSync()

    cookie立即同步:调用了该方法会立即进行cookie的同步,代码如下:

    CookieSyncManager.getInstance().sync()

    删除cookie操作:

    CookieSyncManager.createInstance(this);

    CookieManager.getInstance().removeAllCookie();

    CookieManager.getInstance().removeSessionCookie();

    CookieSyncManager.getInstance().sync();

    CookieSyncManager.getInstance().startSync();

    CookieManager管理cookie:从sdk21之后,webview已经内置了cookie的同步操作了。虽然不再需要关注cookie的同步,但是依然需要掌握删除cookie的操作。

    删除cookie操作:底层实现是异步清除数据库的记录

    CookieManager.getInstance().removeAllCookies(null);

    CookieManager.getInstance().flush();

    立即同步:注意到这个flush()方法就是立即同步cookie的操作,本质上与CookieSyncManager中的sync()方法是一样的。于是乎,关于同步cookie我们可以有如下简单的写法:

    cookie同步

    然后,笔者就遇到了第一个坑,按照如下写法以后,cookie居然神奇的不同步(下面是伪代码,下面是伪代码)

    cookie不同步

    之前笔者通过字符串拼接,也就是append字符串 ,拼接字符串以后,我想直接通过cookieManager.setCookie(url, cookie); 在x5WebView.loadUrl(url);调用之前去设置cookie,

    然后,cookie就是同步不了。没得办法,打印日志之后发现,手动设置的cookie值,神奇的只有一个分号 !

    谷歌百度后,有哥们说是因为cookie Value的值在读取时,只会读取到第一个分号时,当发现第一个分号即认为读取结束。所以分号后面的cookie的值将不会读取,实际测试确实是这样。那么,我们该如何解决拼接cookie读取失败的问题?

    解决办法如下图,我们可以一个个手动设置cookie,即可拼接完整的Cookie。(这种办法虽然笨拙,但的确可以有效解决分号切割问题)

    setCookie解决办法

    当然,我在公司项目里用的是Okhttp,(为什么这里用Okhttp,因为!这样就可以用Okhttp、Retrofit、OkGo等网络框架,直接集成 我在项目中给大家提供的拦截器、自定义CookieJar使用了)。通过自定义拦截器,实现CookieJar去完成同步客户端和H5的cookie状态。这里先上下最终效果图:(笔者的代码可能不是唯一实现功能需求的,但凑合还能用。实现方式有很多种,写的不好也请大家见谅)

    Okhttp简单设置

    关于AddCookiesInterceptor以及SaveCookiesInterceptor这两个拦截器,主要就是存Cookie和使用Cookie,具体说明可以参考 两个拦截器的说明 ,然后我们点进自定义cookieJar中的 SaCookieManger

    SaCookieManger

    这个类定义了一个context构造参数,在保存cookie的saveFromResponse方法中,调用了SaasCookieManager.loadCookie(cookies,url.host());方法,我们点进SaasCookieManager

     

    SaasCookieManager

    通过遍历添加到集合里面,然后一个个的setCookie( url ,cookie )、接着判断SDK版本号进行同步刷新即可,具体可以参考项目源代码。

    当然大家也可以在这里面根据开发需求去增加自己的实际功能。

    通过上面的步骤,我们就可以简单的实现 客户端与H5端同步cookie。

    笔者的项目里面,是客户端登录成功以后,进入H5页面,H5页面上直接显示已登录状态。

    拓展:有部分手机使用后可能还是无法同步,那么我们可以尝试,设置跨域读取cookie,开启webview对第三方cookie的支持。

     

    跨域查询

    当页面加载完毕的时候,我们可以通过下面的截图代码,去获取H5上面的cookie,我们也可以打印日志、进行同步

    页面加载完毕

    需求二:

    监听进度,是这样,WebView里面的WebChromeClient这个类,里面有个onProgressChanged方法,重写这个方法就可以获取加载进度。获取到X5Webview的进度之后,还需要通过WebView的setWebChromeClient方法,将我们自定义的WebChromeClient对象传进去,即可完成进度监听。

     

    监听进度

    拓展:WebViewClient 内置的shouldOverrideUrlLoading(WebView view, String url)这个函数的主要意思是指:检查URL主机是否与特定域匹配。 如果它匹配,则该方法返回false以便不覆盖URL加载(它允许WebView像往常一样加载URL); 如果URL主机不匹配,则Intent创建一个以启动默认活动以处理URL(解析为用户的默认Web浏览器)。

    需求三:封装X5Webview基本功能

    常用设置:

    比如设置对JS的支持等等一些比较常用的,我们可以直接这样设置

     

    常用设置

     

    滚动条(内侧、外侧的设置),隐藏或显示的基本使用:

    滚动条属性设置

    处理预加载:

    有的小伙伴说,X5预加载不是很友好。在加载X5内核的时候,X5内核需要进行一些初始化,这些初始化如果不明确指出运行的线程,它就会在你启动页面的时候,默认在主线程中执行,因此就会出现卡顿(这个现象时有时无,但是我们在代码层面尽可能的去规避使用风险),所以,我们可以写个 IntentService 去帮我们管理预加载问题:

     

    IntentService

    多提一嘴:IntentService是Service的子类,比普通的Service增加了额外的功能。

    IntentService会创建独立的worker线程来处理所有的Intent请求;

    会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程的问题;

    所有请求处理完成后,IntentService会自动停止,开发者无需手动调用stopSelf()方法停止Service;

    写完之后我们在去自定义Application里面注册服务:(别忘了去清单文件配置Services)

     

    Application使用service

    返回键的处理:

    这个就根据大家开发需求具体使用了,有的要求返回键按下两次才允许退出等等

    生命周期的处理、释放资源的处理:这个就不说了,大家查阅资料集成功能即可

    拦截广告的处理:

    有些哥们说,使用这个经常会出现广告,解决这个办法有两个办法

    1:使用Https

    2:设计拦截url规则,对允许的url进行放行加载,不允许的url,WebView禁止加载

    Android8.0系统适配:

    2017年8月份,谷歌正式发布了Android8.0系统,时隔3个多月谷歌正式发布了Android 8.1的正式版。但是目前,Android用户持有的系统版本百分之85的系统是介于Android4.4-Android7.0这个系统版本之间,好了,这样真机调试就会有一定的局限性。现在出现了这样一种情况,使用X5去加载Url,8.1系统以下的都正常,8.1系统以上的的就会有问题。这不,腾讯的X5社区也有别的开发者反馈了这个问题,但是没人回答:

    8.1系统的问题

    8.1系统的问题

    具体他是什么问题我不清楚(最后分析可能是遇到了同样的问题),这里先细说我遇到的问题。还是文章内部的代码,到了8.1系统以后,我这边通过X5WebView加载H5游戏就有问题。我们知道 初始化的时候,首先需要调用 QbSdk.PreInitCallback 这个回调函数,也就是onViewInitFinished ( boolean ininTag )这个回调函数,这个函数主要是完成x5內核初始化,其中,这里的ininTag为true则表示x5内核加载成功,false即表示x5内核加载失败,如果为false,X5内核会自动切换到系统内核。

     现在的一个情况是,加载到X5内核以后,这个initTag有一定几率会失败。你可能会说既然初始化失败那就使用系统的WebView呀,嗯,没错,但是现在切换原生的WebView以后,就加载不出来了(蜜汁尴尬)这个原因后面也会说,基于此这里引用一段谷歌针对8.0系统的官方文档:


    多个 Android 应用和服务可以同时运行。 例如,用户可以在一个窗口中玩游戏,同时在另一个窗口中浏览网页,并使用第三个应用播放音乐。同时运行的应用越多,对系统造成的负担越大。 如果还有应用或服务在后台运行,这会对系统造成更大负担,进而可能导致用户体验下降;例如,音乐应用可能会突然关闭。应用在两个方面受到限制:

    后台服务限制:处于空闲状态时,应用可以使用的后台服务存在限制。 这些限制不适用于前台服务,因为前台服务更容易引起用户注意。

    广播限制:除了有限的例外情况,应用无法使用清单注册隐式广播。 它们仍然可以在运行时注册这些广播,并且可以使用清单注册专门针对它们的显式广播。

    注:默认情况下,这些限制仅适用于针对 O 的应用。

    在后台中运行的服务会消耗设备资源,这可能降低用户体验。 为了缓解这一问题,系统对这些服务施加了一些限制。

    系统可以区分 前台 和 后台 应用。 (用于服务限制目的的后台定义与内存管理使用的定义不同;一个应用按照内存管理的定义可能处于后台,但按照能够启动服务的定义又处于前台。)如果满足以下任意条件,应用将被视为处于前台:

    具有可见 Activity(不管该 Activity 已启动还是已暂停)。

    具有前台服务。

    另一个前台应用已关联到该应用(不管是通过绑定到其中一个服务,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的服务,那么该应用处于前台:

    A:IME

    B:壁纸服务

    C:通知侦听器

    D:语音或文本服务

    E:如果以上条件均不满足,应用将被视为处于后台。

    F:绑定服务不受影响,这些规则不会对绑定服务产生任何影响。 如果您的应用定义了绑定服务,则不管应用是否处于前台,其他组件都可以绑定到该服务。

    为了降低发生这些问题的几率,Android 8.0 对应用在用户不与其直接交互时可以执行的操作施加了限制。

    在 Android 8.0 之前,创建前台服务的方式通常是先创建一个后台服务,然后将该服务推到前台。

    Android 8.0 有一项复杂功能;系统不允许后台应用创建后台服务。 因此,Android 8.0 引入了一种全新的方法,即Context.startForegroundService(),以在前台启动新服务。


    以上文档截取自8.0系统谷歌官方文档,那么这一段话主要的意思就是新系统限制了服务,因此,我们写的IntentService就不要这样写了(谷歌有新的推荐方式我这里怎么快就怎么来吧),直接将IntentService里面初始化X5内核的代码拷贝出来,放在自定义Application里面的onCreate()即可。

    还有一点,可能是手机或者种种问题,我这边初始化成功的概率大概是百分之90(测试了十次,有一次内核没有初始化成功),为了规避这种初始化失败又切换到系统内核加载不出来的风险,我找了个笨方法,那就是如果初始化失败就让他继续初始化直到X5初始化成功(这里使用的是EventBus去通知结果),初始化成功以后才使用X5Webview去加载url。

    下面是代码截图:

    自己的8.1解决方案

    当然,这只是笔者自己的解决方案(笨办法),如果腾讯技术团队有最新的说明或者开发者有更好的解决方案,请直接在评论区指出,欢迎斧正,谢谢。

    最新增加:Https与Http混合加载

    我想,这个问题的出现,是之前X5内核在8.1系统上初始化失败,笔者做的一个实验尝试。因为X5内核在8.1系统上初始化失败(解决办法可以参考上面的),所以笔者又将WebView换成了原生的。好的,老铁没毛病,用了原生的WebView以后,问题又出现了,H5游戏加载不出来,这就尴尬到新的地步了?

    带着黑人小哥三个问号的我,没办法呐,花时间跟踪调试,最后发现:这个H5内置的脚本资源,居然是Https和Http两种JS脚本混合的!!!

    但是!!!X5内部默认实现了混合加载!!!所以现在切换到原生WebView以后,加载不出来了。因此针对这种特殊情况,需要加上新的API。

    我们知道Https简单讲就是HTTP的安全版,为什么它是安全的版本?因为Https提供了身份验证与加密通讯方法(确切的说是SSL)但是,Https需要证书,但是Android这边针对WebView加载Https的一般做法是忽略SSL证书错误,继续加载页面。所以需要重写WebViewClient的onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)方法,实现代码如下:

        public WebViewClient client = new WebViewClient() {

            @Override

            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {

                //  忽略SSL证书错误,继续加载页面

                handler.proceed();

            }

    }

    证书的问题我们忽略以后,接下来还需要重写WebSettings内置的API,一行代码搞定:

    WebSettings  webSetting = getSettings();

    //允许混合加载

    webSetting.setAllowUniversalAccessFromFileURLs(true);

    这样就可以实现原生WebView混合加载的问题。

    附录:项目地址

    展开全文
  • 一般在Android应用的开发...在Android开发过程中有一个专门用嵌入网页的控件WebView布局,WebView控件是基于Google Chrome浏览器的内核,只需在逻辑代码里传入网址的url就可以在应用里打开一个网页,但是只是单纯的...
  • import android.webkit.WebView;   public class Example_webview extends Activity {   WebView webView;   final String  mimeType  =  "text/html" ;   final String  encoding  =  "utf-...
  • Android开发,使用Kotlin实现WebView

    千次阅读 2020-08-05 15:49:00
    1、布局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" ... android:id="@+id/webview
  • 本篇为初级总结WebView 加载网页的封装,交互与我在项目中遇到的一些现象的经验总结。   Android 与H5在项目中交互一直在使用中,经常也需要满足各种各样的需求类型。 WebView加载url的调用方法为loadUrl...
  • Android项目中WebView是必不可少的,越来越开的迭代节奏导致越来越多的App采用混合开发,接着我们就介绍一下AndroidWebView的使用。 一、混合开发的优缺点: 优点: 1.开发成本较低:Android和iOS使用一个...
  • Extra WebView Library具有精美主题的灵活易用的WebView库。 与API级别17 RTL兼容的快速概述支持全屏模式的多主题支持sh Extra WebView Library灵活而易于使用的WebView库,具有精美的主题。 与API级别17 RTL兼容的...
  • Android实现微信webview兼容Android 7.0。自带库文件不使用系统的可以全方位兼容各机型,实现二次封装
  • 最近公司App项目里要做活动,活动界面是调用H5展示,里面有转盘抽奖、GIF图片等,由于原生的WebView在每个机型上不能保证都能使用(测试了几个机型,有的会显示一个空白界面,不过网页已经加载完成了,就是不显示...
  • = null) {//Android 5.0及以上版本 Uri[] dataUris = null; try { if (intent.getDataString() != null) { String s = Uri.decode(intent.getDataString()); dataUris = new Uri[]{Uri.parse(s)}; } ...
  • 创建webview // 这个不用说 this.getSettings().setJavaScriptEnabled(true); // 这个解决跨域的问题 this.getSettings().setAllowFileAccessFromFileURLs(true); this.setWebViewClient(new MyWebViewClient()); ...
  • 文章预览前言1....Android内置webkit内核的高性能浏览器,而WebView则是在这个基础上进行封装后的一个 控件,WebView直译网页视图,我们可以简单的看作一个可以嵌套到界面上的一个浏览器控件! 2.相关
  • 因项目需要,需要手机App,因为本身网站页面布局是采用bootstrap框架,所以可以采用Android Webview控件来将网页封装。 在此提醒一下,使用Android Webview控件的前提是网页必须本身能适应手机的布局。 为了将App...
  • 公司开发的一个项目为Android+H5混合开发,虽然开发量对于原生来说不大,但是针对于H5与android结合的各种坑让初次接手这种开发模式的新手简直不可描述可怜,同样的功能在iOS上面运行的好好的,在Android上面各种...
  • 需求原因 ...常规方法,给定一段标准html文档,使用Html.fromHtml()封装,直接使用TextView显示。 TextView textView = (TextView) findViewById(R.id.detailed_question_tv_answer); String testStri
  • import android.content.Intent; import android.os.Bundle;...import android.webkit.WebView; public class MainActivity extends AppCompatActivity { private WebView webview; @Override protected void onCrea
  • Android开发中不可避免的会出现,使用一个WebView来显示一个h5页面。如果仅仅只是显示h5页面,这不需要特殊的处理,但是很多情况下会出现,js和WebView的交互。比如:将html表单中的数据,传递到Activity中,在...
  • Android webview在默认情况下是不支持网页中的文件上传功能的;如果在网页中有,在android webview中访问时也会出现浏览文件的按钮但是点击按钮之后没有反应...那么如何能够让androidwebview能够响应,这个浏览...
  • 近期,使用WebView加载url用的比较频繁,然后就封装了一下使用方法,这里纪录一下,为后期使用提供便利。我在使用的过程中,发现加载url时,会自动跳转到系统自带的浏览器进行展示。这样使得用户体验非常的糟糕,...
  • Android WebView使用

    2021-06-06 05:59:41
    原标题:AndroidWebView使用 前言Android内置webkit内核的高性能浏览器,而WebView则是在这个基础上进行封装后的一个 控件,WebView直译网页视图,我们可以简单的看作一个可以嵌套到界面上的一个浏览器控件!WebView有...
  • Android通过webview控件实现webapp的demo,使用的是 androidstudio,可以实现跟html页面的js交互等
  • 总结 Android WebView 常用的相关知识点,其中包含以下干货内容分析:Js注入漏洞、WebView 遇到的坑、JsBridge 原理以及框架使用(JsBridge,DSBridge-Android)、缓存机制应用、性能优化、腾讯开源框架 VasSonic (之后...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,874
精华内容 4,749
关键字:

安卓开发封装webview