安卓APP承载网页(WebView)- 用例程解析到位

    

安卓APP承载网页(WebView)- 用例程解析到位

安卓APP自身如何打开网页,如何制作一个简单的浏览器,WebView在其中将是一个重要的角色。WebView是一个基于WebKit引擎、展现Web页面的控件。

Webview 是一个基于webkit引擎,可以解析DOM 元素,展示html页面的控件,它和浏览器展示页面的原理是相同的,所以可以把它当做浏览器看待。(chrome浏览器也是基于webkit引擎开发的,Mozilla浏览器是基于Gecko引擎开发的)

简而言之,WebView可以实现安卓APP中承载网页

手机浏览器:

国内手机的自带浏览器不是chrome,主要是版权的原因,自带的浏览器都是手机厂商基于国内主流的几大浏览器自己定制,然后发布在自己手机系统版本中.不过国内几大浏览器厂商如QQ浏览器,UC浏览器、都是基于webkit引擎的,iphone的自带浏览器是Safari,Safari浏览器的内核是webkit

使用WebView的好处:

使用内核都是webkit,所以APP中网页展示的效果与主流浏览器差别无几
这是一个BS架构即浏览器和服务器的,所以在某些要经常改变的界面嵌入WebView,可以方便随时在后台修改其内容
加载一个网页的方法
加载服务器的网页

//获取到webview控件
WebView webv=findViewById(R.id.mywebview);
//加载网页
webv.loadUrl("https://www.cnblogs.com/dongxiaodong/");

加载资源文件(assets目录)的网页

assets目录是Android的一种特殊目录,用于放置APP所需的固定文件,且该文件被打包到APK中时,不会被编码到二进制文件。

//获取到webview控件
WebView webv=findViewById(R.id.mywebview);
//加载网页
webv.loadUrl("file:///android_asset/androidt.html");

网页加载时附加网页代码

baseUrl表示基础的网页

data表示要加载的内容

mimeType表示加载网页的类型

encoding表示编码格式

historyUrl表示可用历史记录,可以为null值

webv.loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl))

网页浏览器的基础属性
canGoBack() 是否可以后退

canGoForward() 是否可以前进

canGoBackOrForward(int step) 是否可以前进或者后退多少步,正数为前进,负数为后退

goBack() 后退

goBack() 前进

goBackOrForward(int step)前进或者后退多少步,正数为前进,负数为后退

reload() 重新加载或刷新界面

stopLoading() 停止加载

实现:

//后退函数实现
public void But_back(View v){
    //查询是否可以返回上一级
    boolean canx=webv.canGoBack();
    //返回上一级
    if(canx) webv.goBack();
    //不可返回
    else  Toast.makeText(MainActivity.this,"已经到达底端",Toast.LENGTH_SHORT).show();
}
//前进函数实现
public void But_forward(View v){
    boolean canx=webv.canGoForward();
    //返回上一级
    //查询是否可以返回上一级
    if(canx) webv.goForward();
        //不可返回
    else  Toast.makeText(MainActivity.this,"已经到达顶端",Toast.LENGTH_SHORT).show();
}
//刷新页面
public void But_reload(View v){
    webv.reload();
}
//停止界面加载
public void But_stop(View v){
    webv.stopLoading();
}

WebView配置类(WebSettings)

WebSettings webSettings = webView.getSettings();
    //如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
    webSettings.setJavaScriptEnabled(true);

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

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

    //缩放操作
    webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
    webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
    webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
    webSettings.setTextZoom(2);//设置文本的缩放倍数,默认为 100

    webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);  //提高渲染的优先级

    webSettings.setStandardFontFamily("");//设置 WebView 的字体,默认字体为 "sans-serif"
    webSettings.setDefaultFontSize(20);//设置 WebView 字体的大小,默认大小为 16
    webSettings.setMinimumFontSize(12);//设置 WebView 支持的最小字体大小,默认为 8

    // 5.1以上默认禁止了https和http混用,以下方式是开启
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
    }

    //其他操作
    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
    webSettings.setAllowFileAccess(true); //设置可以访问文件
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
    webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
    webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
    webSettings.setGeolocationEnabled(true);//允许网页执行定位操作
    webSettings.setUserAgentString("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0");//设置User-Agent


    //不允许访问本地文件(不影响assets和resources资源的加载)
    webSettings.setAllowFileAccess(false);
    webSettings.setAllowFileAccessFromFileURLs(false);
    webSettings.setAllowUniversalAccessFromFileURLs(false);

事件监听
各种通知和请求事件(WebViewClient)

onPageStarted() 页面加载时

onPageFinished():页面加载完毕时调用。

shouldOverrideKeyEvent():重写此方法才能处理浏览器中的按键事件。

shouldInterceptRequest():页面每一次请求资源之前都会调用这个方法(非UI线程调用)。

onLoadResource():页面加载资源时调用,每加载一个资源(比如图片)就调用一次。

onReceivedError():加载页面的服务器出现错误(比如404)时回调。

onReceivedSslError():重写此方法可以让webview处理https请求。

doUpdateVisitedHistory():更新历史记录。

onFormResubmission():应用程序重新请求网页数据。

onReceivedHttpAuthRequest():获取返回信息授权请求。

onScaleChanged():WebView发生缩放改变时调用。

onUnhandledKeyEvent():Key事件未被加载时调用。

辅助 WebView 处理补充问题(WebChromeClient)

onProgressChanged():获得网页的加载进度并显示。

onReceivedTitle():获得网页的标题时回调。

onReceivedIcon():获得网页的图标时回调。

onCreateWindow():打开新窗口时回调。

onCloseWindow():关闭窗口时回调。

onJsAlert():网页弹出提示框时触发此方法。

上例程
统一统一步骤:

第一步:

在AndroidManifest.xml下添加网络访问权限,如果需要外网访问的情况下

<!--网络权限-->
<uses-permission android:name="android.permission.INTERNET" />
<!--文件读写权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

第二步:

在xml下添加WebView控件

<WebView
    android:layout_width="match_parent"
    android:id="@+id/mywebview"
    android:layout_height="match_parent" />

第三步:

编写逻辑程序

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
    private WebView webv=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取到webview控件
        webv=findViewById(R.id.mywebview);
        //设置访问的URL,此条将会触发系统调用浏览器打开,博客园东小东
        webv.loadUrl("https://www.cnblogs.com/dongxiaodong/");
        //通过下面的代码阻止APP直接通过浏览器打开网页
        webv.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //使用WebView加载URL内容
                view.loadUrl(url);
                return  true;
            }
        });
    }
    //监听程序的返回事件
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //如果按下返回键且网页有历史记录,可以返回上一级
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webv.canGoBack()) {
            //返回上一级
            webv.goBack();
            return true;
        }
        //否则返回真实的按键信息给系统,系统将将退出程序
        return super.onKeyDown(keyCode, event);
    }
}

加载资源文件(assets目录)的网页
assets目录是Android的一种特殊目录,用于放置APP所需的固定文件,且该文件被打包到APK中时,不会被编码到二进制文件。

第三步:

编写HTML代码,保存到文件androidt.html

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>这里是网页头</title>
</head>
<body style="margin: 0 auto;text-align: center">
    <h1>我是网页标题1</h1>
    <h3>(资源文件方法)</h3>
    <button onClick="showA()" style="width: 100%;height: 100px;">点我弹框</button>
</body>
    <script>
        function showA(){
            alert("弹框内容,完成");
        }
    </script>
</html>

第四步

创建assets目录

右键【app】-【New】-【Folder】-【Assets Folder】-【finish】

第五步

将HTML文件拷贝到assets目录下

第六步

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取到webview控件
        WebView webv=findViewById(R.id.mywebview);

        WebSettings webSettings = webv.getSettings();
        webSettings.setJavaScriptEnabled(true);//设置支持Javascript
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//允许js弹出窗口

        //访问本地资源文件网页
        webv.loadUrl("file:///android_asset/androidt.html");

        //通过下面的代码阻止APP直接通过浏览器打开网页
        webv.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //使用WebView加载URL内容
                view.loadUrl(url);
                return  true;
            }
        });
        //如果要实习alert弹框,必须实现此监听事件
        webv.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                // TODO Auto-generated method stub
                return super.onJsAlert(view, url, message, result);
            }
        });
    }
}

加载部分源代码
直接写一部分的HTML代码,可以直接显示在WebView上

第三步:

编写逻辑程序

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
    private WebView webv=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取到webview控件
        webv=findViewById(R.id.mywebview);
        WebSettings webSettings = webv.getSettings();

        //将网页界面缩放至手机屏幕大小
        webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
        webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

        //设置支持缩放操作
        webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
        webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
        webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件

        //编辑网页代码
        String myhtml="<h1 >东小东标题</h1>" +
                      "<hr/>" +
                      "<a href='https://www.cnblogs.com/dongxiaodong/'>去东小东博客园看看<a/>" +
                      "<h3 >网页显示小标题</h3>" +
                      "<img style=\"width: 100%;\" src=\"https://img2018.cnblogs.com/blog/1485202/201811/1485202-20181116215233782-319594948.png\"/>";
        //设置显示
        webv.loadDataWithBaseURL("",myhtml,"text/html", "utf-8",null);

        //通过下面的代码阻止APP直接通过浏览器打开网页
        webv.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //使用WebView加载URL内容
                view.loadUrl(url);
                return  true;
            }
        });
    }
    //监听程序的返回事件
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //如果按下返回键且网页有历史记录,可以返回上一级
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webv.canGoBack()) {
            //返回上一级
            webv.goBack();
            return true;
        }
        //否则返回真实的按键信息给系统,系统将将退出程序
        return super.onKeyDown(keyCode, event);
    }
}

综合案例
缺点:工程未实现网页的音频和视频播放

实现功能:

l 标题显示

l 网页加载进度条显示

l 后退、前进、刷新、停止加载四大常用功能适配

l 连接跳转,在APP本地打开网页

视图代码:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

     <TextView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:textSize="15dp"
         android:id="@+id/show_text"
         android:background="@color/colorPrimary"
         android:text="标题显示"/>
    <ProgressBar
        android:max="100"
        android:progress="10"
        android:id="@+id/show_progres"
        style="?android:attr/progressBarStyleHorizontal"
        android:background="@color/colorPrimary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <WebView
        android:layout_width="match_parent"
        android:id="@+id/mywebview"
        android:layout_height="match_parent" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="But_back"
            android:text="后退"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="But_forward"
            android:layout_weight="1"
            android:text="前进"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="But_reload"
            android:layout_weight="1"
            android:text="刷新"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="But_stop"
            android:layout_weight="1"
            android:text="停止"/>


    </LinearLayout>

</FrameLayout>

逻辑源码:

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private WebView webv=null;
    private TextView showtext=null;
    private ProgressBar showpro=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //隐藏状态栏
        getSupportActionBar().hide();
        setContentView(R.layout.activity_main);
        //获取到webview控件
        webv=findViewById(R.id.mywebview);
        showtext=findViewById(R.id.show_text);
        showpro=findViewById(R.id.show_progres);

        WebSettings webSettings = webv.getSettings();

       webSettings .setAllowFileAccess(true);
        //设置支持缩放操作
        webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
        webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
        webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件

        //编辑网页代码
        String myhtml="<h1 >东小东标题</h1>" +
                "<hr/>" +
                "<h2><a href='https://www.cnblogs.com/dongxiaodong/'>去东小东博客园看看<a/></h2>" +
                "<h3 >网页显示小标题</h3>" +
                "<img style=\"width: 300px;\" src=\"https://img2018.cnblogs.com/blog/1485202/201811/1485202-20181116215233782-319594948.png\"/>";
        //设置显示
        webv.loadDataWithBaseURL("",myhtml,"text/html", "utf-8",null);

        //通过下面的代码阻止APP直接通过浏览器打开网页
        webv.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //使用WebView加载URL内容
                view.loadUrl(url);
                return  true;
            }
        });
        webv.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onReceivedTitle(WebView view, String title) {
                //标题显示
                showtext.setText(title);
                //Toast.makeText(MainActivity.this,title,Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                //进度条显示
                showpro.setProgress(newProgress);
                //Toast.makeText(MainActivity.this,newProgress+"",Toast.LENGTH_SHORT).show();
            }
        });

    }
    //监听程序的返回事件
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //如果按下返回键且网页有历史记录,可以返回上一级
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webv.canGoBack()) {
            //返回上一级
            webv.goBack();
            return true;
        }
        //否则返回真实的按键信息给系统,系统将将退出程序
        return super.onKeyDown(keyCode, event);
    }

    //后退函数实现
    public void But_back(View v){
        //查询是否可以返回上一级
        boolean canx=webv.canGoBack();
        //返回上一级
        if(canx) webv.goBack();
        //不可返回
        else  Toast.makeText(MainActivity.this,"已经到达底端",Toast.LENGTH_SHORT).show();
    }
    //前进函数实现
    public void But_forward(View v){
        boolean canx=webv.canGoForward();
        //返回上一级
        //查询是否可以返回上一级
        if(canx) webv.goForward();
            //不可返回
        else  Toast.makeText(MainActivity.this,"已经到达顶端",Toast.LENGTH_SHORT).show();
    }
    //刷新页面
    public void But_reload(View v){
        webv.reload();
    }
    //停止界面加载
    public void But_stop(View v){
        webv.stopLoading();
    }
}

所有原创文章采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。
本站部分内容收集于互联网,如果有侵权内容、不妥之处,请联系我们删除。敬请谅解!

仅有一条评论

添加新评论

  关于博主

QQ:1960727927
E-Mail:ceet@vip.qq.com
个人主页:https://aiylqy.com
个性签名:毁掉一个人最好的方式就是放纵他的缺点。

  近期评论

无论有多困难,都坚强地抬头挺胸,告诉所有人,你并非他们想象的那样不堪一击。

每个人心里都有一段伤痕,时间才是最好的疗剂。

人总是珍惜未得到的,而遗忘了所拥有的。

退一步,并不象征我认输;放手,并不表示我放弃;微笑,并不意味我快乐!

人海中再回首,朋友真诚依旧,生命里重逢,心境平和温柔,往事如风,岁月如歌,漫漫人生路,苍桑几许,幸福几何!