Android入门之路 - WebView加载数据的几种方式

之前客户端加载H5时遇到了一些问题,我为了方便解决问题,所以将对应场景复刻到了Demo中,从之前的网络加载模拟为了本地加载Html的方式,但是没想到无意被一个基础知识点卡了一些时间,翻看往昔笔记发现未曾记录这种基础场景,故补不足,记录于此

关于 WebView 加载数据的几种方式,可以算是基础内容,相信大家都耳熟于心了,直接开讲

基础配置

关于 WebView 基础配置 主要是对 WebSettings 相关属性的设置

简化版

kotlin 复制代码
 WebView webView = (WebView) findViewById(R.id.webView);
 WebSettings mWebSettings = webView.getSettings();
 mWebSettings.setJavaScriptEnabled(true);

因为后续我们需要加载网络资源,所以有必要 添加一下网络权限

Tip :如果仅加载本地资源,可不添加该权限... 但一个项目中不可能没有 INTERNET权限

kotlin 复制代码
 <uses-permission android:name="android.permission.INTERNET" />

通用 xml 布局

html 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

加载方式

关于以下所有方式有的是经常使用的,也有的很少使用,当然还有一些我基本都没用过,没想到AI直接一起归总了,故我整合解释了一下,希望对你我有所帮助

WebView 加载数据的方式很多,但是我从业以来 用的最多的还是本地加载和网络加载,所以这也是我们主讲的内容,关于其他加载方式先做记录,以后如果我遇到了类似场景再来补充实战感受

经常使用

插一句:在项目中有些富文本的样式也可以通过 Html实现,如果主要是看WebView,请忽略此句

本地加载 (加载本地 html文件)- 项目中会遇到一些组件需要固定的数据,有的成品数据就是html文件,所以有时候会用到这种方式

使用 loadUrl(String path) 方法加载本地文件,如 file:///android_asset/test.html(自行定义html 文件名)

java 复制代码
 webView.loadUrl("file:///android_asset/test.html");

网络加载 (加载H5的URL)- 主流方式,项目中基本90%都用这种方式

使用 loadUrl(String url) 方法加载网络或本地文件的URL

java 复制代码
 webView.loadUrl("https://www.example.com");

WebView 实际使用中,我们经常会通过 WebViewClient 监听一些加载情况,以下是比较常用的两个重载监听方法

通过设置 WebViewClient 并重写 shouldOverrideUrlLoading 方法来控制URL加载行为

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

使用 WebResourceRequest:在Android N(API 24)及以上版本,可以在 WebViewClient 中重写 shouldOverrideUrlLoading 方法的重载版本,接收 WebResourceRequest 参数

java 复制代码
webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        view.loadUrl(request.getUrl().toString());
        return true;
    }
});

较少遇到

加载HTML字符串感觉这种方式相当于把html文件提到了代码内部,如果html比较多的话,可能不太适用

使用 loadData(String data, String mimeType, String encoding) 方法加载HTML字符串

java 复制代码
 String htmlData = "<html><head><title>Page Title</title></head><body>Hi, WebView!</body></html>";
 webView.loadData(htmlData, "text/html; charset=UTF-8", "UTF-8");

加载JavaScript代码 (双端交互时调用H5的Js方法,前提的和H5确定过交互需求,否则无效,且有可能报错)

使用 loadUrl(String js) 方法执行 JavaScript 代码。

java 复制代码
 String jsCode = "javascript:alert('Hello, world!');";
 webView.loadUrl(jsCode);

加载数据并设置基础URL可能类似URL组装效果,未使用过)

使用 loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) 加载HTML字符串,并可以设置基础URL

java 复制代码
 String baseUrl = "https://www.example.com";
 String htmlData = "<html>...</html>";
 webView.loadDataWithBaseURL(baseUrl, htmlData, "text/html", "UTF-8", null);

加载POST请求数据可能类似URL组装效果,未使用过)

使用 postUrl(String url, byte[] postData) 方法通过POST请求加载数据。

java 复制代码
 String url = "https://www.example.com/post";
 byte[] postData = ...; // 你的POST数据
 webView.postUrl(url, postData);

加载XML或HTML文件 :可以将其作为字符串加载,然后解析(未见过该类需求,未使用过


实战场景

本地加载

kotlin 复制代码
 WebView mWebView = (WebView) findViewById(R.id.wv1);
 WebSettings mWebSettings = mWebView.getSettings();
 mWebSettings.setJavaScriptEnabled(true);
 mWebView.loadUrl("file:///android_asset/test.html");//工程目录assets test.html文件
 
 mWebView.loadUrl("file:///android_asset/icon.png");//工程目录assets图片文件(未尝试过)

示例全码

kotlin 复制代码
package com.example.webviewproject

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private val mWebView: WebView by lazy {
        findViewById<WebView>(R.id.webView)
    }

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initWebView(mWebView)
        //加载本地资源
        mWebView.loadUrl("file:///android_asset/test.html");
//        mWebView.loadUrl("file:///android_asset/web/test.html")
    }

    /**
    * 初始化WebSettings配置
    * */
    private fun initWebView(mWebView: WebView) {
        mWebView.clearCache(true)
        mWebView.clearHistory()
        val webSettings = mWebView.settings
        webSettings.cacheMode = WebSettings.LOAD_DEFAULT
        webSettings.domStorageEnabled = true
        webSettings.javaScriptEnabled = true
        webSettings.useWideViewPort = true
        webSettings.loadWithOverviewMode = true
        webSettings.builtInZoomControls = true
        webSettings.displayZoomControls = false
        webSettings.setSupportZoom(false)
        webSettings.javaScriptCanOpenWindowsAutomatically = true
        webSettings.allowFileAccess = true
        webSettings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS
//        webSettings.setAppCacheEnabled(true);
//        webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
//        webSettings.setAppCachePath(this.getApplicationContext().getCacheDir().getAbsolutePath());
//        webSettings.setUserAgentString(webSettings.getUserAgentString() + " ECTASR/1");
//        mWebView.setWebChromeClient(new CustomerActivity.WebChromeClient());
//        mWebView.webViewClient = WebViewClient()
        mWebView.isFocusable = true
        mWebView.isVerticalScrollBarEnabled = false
        mWebView.isHorizontalScrollBarEnabled = false
        mWebView.setOnLongClickListener { v: View? -> true }
    }
}

远程加载

相比加载本地文件,远程加载 url 除了添加授权和加载数据源不同之外,示例层面没变动,主要还是功能方面有了更多的可能性和交互性

kotlin 复制代码
 mWebView.loadUrl("http://www.baidu.com");

示例全码

kotlin 复制代码
package com.example.webviewproject

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private val mWebView: WebView by lazy {
        findViewById<WebView>(R.id.webView)
    }

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initWebView(mWebView)
        //加载本地资源
		mWebView.loadUrl("http://www.baidu.com")
    }

    /**
    * 初始化WebSettings配置
    * */
    private fun initWebView(mWebView: WebView) {
        mWebView.clearCache(true)
        mWebView.clearHistory()
        val webSettings = mWebView.settings
        webSettings.cacheMode = WebSettings.LOAD_DEFAULT
        webSettings.domStorageEnabled = true
        webSettings.javaScriptEnabled = true
        webSettings.useWideViewPort = true
        webSettings.loadWithOverviewMode = true
        webSettings.builtInZoomControls = true
        webSettings.displayZoomControls = false
        webSettings.setSupportZoom(false)
        webSettings.javaScriptCanOpenWindowsAutomatically = true
        webSettings.allowFileAccess = true
        webSettings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS
//        webSettings.setAppCacheEnabled(true);
//        webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
//        webSettings.setAppCachePath(this.getApplicationContext().getCacheDir().getAbsolutePath());
//        webSettings.setUserAgentString(webSettings.getUserAgentString() + " ECTASR/1");
//        mWebView.setWebChromeClient(new CustomerActivity.WebChromeClient());
//        mWebView.webViewClient = WebViewClient()
        mWebView.isFocusable = true
        mWebView.isVerticalScrollBarEnabled = false
        mWebView.isHorizontalScrollBarEnabled = false
        mWebView.setOnLongClickListener { v: View? -> true }
    }
}

所遇问题

加载本地数据报 Not Found...

提前和你说一下,当你遇到这种问题,基本和我一样都是一个粗心的人儿!

  1. 关于 asserts 目录层级要求

关于通过对 WebView 加载本地Html的方式,这么多年来一直没有变过,但是我尝试多次,一直加载失败...

不清楚你是否也遇到了这样粗心的问题?关于存放html的文件需要放置于asserts目录内,而该目录是与 java、res 同级的目录文件,切勿放错了!

  1. 有心的朋友可能注意到了我在本地加载中注释了一行 mWebView.loadUrl("file:///android_asset/web/test.html") ,注意这里加载层级有没有多一层或者少一层之类的? 如下

加载网络资源报 404、500、Not Found... 等

  1. 首先将加载的链接放在游览器看是否可以正常加载?
  2. 是否添加了网络权限?
  3. 是否为https 的url?Android在9.0开始好像对安全有了提升,所以有此要求
  4. 项目中可以看一下另一端是否可正常加载,排除错误场景
  5. 项目中可以找返给你url的同事看看是否有错误地方,请教请教
相关推荐
千里马学框架10 小时前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台10 小时前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone10 小时前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc11 小时前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo12 小时前
Kotlin 协程中的 Job 结构化并发与取消
android
sun00770013 小时前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼14 小时前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone15 小时前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen15 小时前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone15 小时前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui