Android -- WebView之loadData加载html字符串显示网页

目录
  • 前言
  • 1. loadUrl 加载网页地址
  • 2. loadData 加载Html字符来显示网页
  • 3. loadDataWithBaseURL
  • 4. 总结

前言

最近在给一个老项目做64位so文件的适配,当应用发布到应用市场上后,用户反馈64位手机上的网页加载不出内容,但32位的手机上是正常的。

我的第一反应是:网页加载不出内容,那不是网页没做好适配嘛!(把锅甩出去)

后经多方细细排查,是WebView的锅。。。(锅又回来了。。)

WebView 加载网页的方法有三种:loadUrl、loadData、loadDataWithBaseURL,下面只记录本人在这三个方法上遇到的问题,具体WebView的基础使用请参考:

Android – WebView 与 JS 交互方式总结
Android – WebView 支持文件下载的几种方式

1. loadUrl 加载网页地址

先写个网页用于加载测试,test2.html(路径:assets/webpage/test2.html):

<html><body><h1>Hello, WebView</h1><p style="color: #f00">This is a simple HTML page loaded into a WebView.</p>
</body></html>

loadUrl(String url) 加载网页地址:

....
//这里省略WebView的其他基础设置
mWebView.loadUrl("file:///android_asset/webpage/test2.html");
....

显示的内容:
在这里插入图片描述
使用 loadUrl(String url) 加载网页,在32位和64位的手机上显示都没有问题。

我的线上应用不是通过url这种方式加载网页的,是通过加载Html字符来加载网页的。

2. loadData 加载Html字符来显示网页

loadData(String data, String mimeType, String encoding)

官方定义:

Load the given data into the WebView. This will load the data into WebView using the data: scheme. Content loaded through this mechanism does not have the ability to load content from the network.
将给定的数据加载到WebView中。这将使用 data: scheme 将数据加载到WebView中。通过此机制加载的内容无法从网络加载内容。

字面意思就是此方法是通过读取Html字符来显示网页的。

/*** 读取 Html字符* @param fileName 文件名*/
private String readAsset(String fileName) {AssetManager assetManager = getAssets();StringBuilder stringBuilder = new StringBuilder();try (InputStream inputStream = assetManager.open(fileName);BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {String line;while ((line = reader.readLine()) != null) {stringBuilder.append(line);}} catch (IOException e) {e.printStackTrace();return null;}return stringBuilder.toString();
}private void loadUrl() {.......StringBuilder stringBuilder = new StringBuilder();//读取Html字符内容stringBuilder.append(readAsset("webpage/test2.html"));mWebView.loadData(String.valueOf(stringBuilder), "text/html; charset=UTF-8", null);.......
}

在32位的手机上显示正常,64位的个别手机显示如下:
(线上反馈,Android 10 以上的手机出问题的较多)
在这里插入图片描述

由图可知,Html中带颜色的标签p的内容未显示出来。

回到官网看下loadData的入参说明:

data

A String of data in the given encoding. The date must be URI-escaped – ‘#’, ‘%’, ‘’, ‘’ should be replaced by %23, %25, %27, %3f respectively.

mimeType

The MIMEType of the data. i.e. text/html, image/jpeg

encoding

The encoding of the data. i.e. utf-8, base64

data:此入参中不能出现特殊字符 ‘#’, ‘%’, ‘’, ‘’ ,需要将其替换成 %23, %25, %27, %3f。

这就为内嵌的css制造了麻烦,因为css中经常使用这4种符号,就如 test2.html 中使用’#'设置了颜色:color: #f00 。

根据官网文档,将 ‘#’ 替换成 ‘%23’:

....StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(readAsset("webpage/test2.html"));
mWebView.loadData(String.valueOf(stringBuilder).replace("#", "%23"), "text/html; charset=UTF-8", null);....

这样在64位安卓10以上的手机上就能正常显示了,同时也不影响32位的手机。

在正式的应用里,后台返回的Html字符数据结构都是很复杂的,里面包含css,script等内容,里面用到特殊字符的频率都很大,如果每次加载之前都要对Html做特殊字符替换处理的话,难免会出现乱码等其他问题。

所以这里就需要使用 loadDataWithBaseURL

3. loadDataWithBaseURL

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

官网资料:

Load the given data into the WebView, use the provided URL as the base URL for the content. The base URL is the URL that represents the page that is loaded through this interface. As such, it is used to resolve any relative URLs. The historyUrl is used for the history entry.
将给定的数据加载到WebView中,使用提供的URL作为内容的基本URL。基本URL是表示通过此接口加载的页面的URL。因此,它用于解析任何相对URL。historyUrl用于历史条目。

Note for post 1.0. Due to the change in the WebKit, the access to asset files through “file:///android_asset/” for the sub resources is more restricted. If you provide null or empty string as baseUrl, you won’t be able to access asset files. If the baseUrl is anything other than http(s)/ftp(s)/about/javascript as scheme, you can access asset files for sub resources.
1.0 后的注释。由于 WebKit 的更改,通过"file:///android_asset/"这种方式子资源受到更多的限制。如果你提供null 或空字符串作为baseUrl,你将无法访问资产文件;如果baseUrl不是http(s)/ftp(s)/about/javascript 作为 scheme,你可以访问子资源的文件。

入参说明:

baseUrl

Url to resolve relative paths with, if null defaults to “about:blank”

data

A String of data in the given encoding.

mimeType

The MIMEType of the data. i.e. text/html. If null, defaults to “text/html”

encoding

The encoding of the data. i.e. utf-8, us-ascii

historyUrl

URL to use as the history entry. Can be null.

从入参上看,loadDataWithBaseURL中并没有对 data 做特殊字符的限制。

....StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(readAsset("webpage/test2.html"));
mWebView.loadDataWithBaseURL("", String.valueOf(stringBuilder), "text/html", "UTF-8", "");....

所以,最终使用 loadDataWithBaseURL 完美解决了64位安卓10以上部分手机网页加载不出来的问题。

4. 总结

一开始线上反馈这个问题的时候,我也没有想到是loadData的问题。正式的应用上返回的Html是相当的复杂,里面有Html、css、好几个script,将这些字符内容打印出来在文档上显示时,看着就头疼。(非网页专业的,看着肯定头疼)

想到的最笨的方法,就是将Html、css、script这几个标签拆分开,化复杂为简洁。先将css和script的代码删除,只留下Html,看看 WebView 是否能正常加载出来。结果这一步就不能正常加载,然后我将 Html 中的样式全部去除,只留下文字部分,这样是可以正常显示的,说明问题出在样式上。然后将样式一点点加回到Html中,最终找到是颜色中 ‘#’ 影响了页面的显示。

虽然方法有点儿笨,但好在能排查到问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/63792.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebSocket解读

WebSocket是一种网络通信协议&#xff0c;它允许在单个TCP连接上进行全双工通信&#xff0c;即服务器和客户端可以同时发送和接收数据。这种协议非常适合需要实时数据交换的应用场景&#xff0c;如在线聊天、实时数据更新、协同办公等。 WebSocket的工作原理 握手阶段&#x…

Docker在Ubuntu和CentOS系统下的安装

目录 1. 各版本平台支持情况2. 在Ubuntu系统下安装docker3. 常见报错4. Docker的镜像源修改5. Docker目录修改6. 在CentOS系统下安装docker 1. 各版本平台支持情况 &#xff08;1&#xff09;平台支持情况如下&#xff1a; Server 版本 桌面版本 2. 在Ubuntu系统下安装docker…

Ansible-Playbook基础学习

一.Ansible Playbook基本介绍 1.Playbook 介绍 Ansible Playbook 是 Ansible 的核心组件之一&#xff0c;它是一个用于配置管理、应用部署和任务自动化的文本文件&#xff0c;使用 YML格式编写。YML 的语法简洁明了&#xff0c;易于阅读和编写&#xff0c;使得用户可以方便地…

基于PHP课堂签到系统的设计与实现

摘 要 随着教育业的迅速发展和学生人数的不断增加&#xff0c;导致在班级登记制度中传统的“点到”方式不能适应学校的实际需要。从而需要设计一个好的课堂签到系统将会对课堂签到管理工作带来事半功倍的效果。文章着重介绍了基于实践应用的班级签到系统的开发流程&#xff0c…

MTK android12 user版本默认开启root权限,添加su

1、需求 &#xff1a; 客户要求在user版中默认开启root权限&#xff0c;添加su。2、实现&#xff1a; From cc066de135c93975d4a50b71c63447c50065195b Mon Sep 17 00:00:00 2001 From: ***** Date: Wed, 11 Dec 2024 16:33:36 0800 Subject: [PATCH] ?UTF-8?q?[root]user…

openjdk17 jvm加载class文件,解析字段和方法,C++源码展示

##构造方法ClassFileParser&#xff0c;parse_stream解析文件流 ClassFileParser::ClassFileParser(ClassFileStream* stream,Symbol* name,ClassLoaderData* loader_data,const ClassLoadInfo* cl_info,Publicity pub_level,TRAPS) :_stream(stream),_class_name(NULL),_load…

蓝桥杯我来了

最近蓝桥杯报名快要截止了&#xff0c;我们学校开始收费了&#xff0c;我们学校没有校赛&#xff0c;一旦报名缴费就是省赛&#xff0c;虽然一早就在官网上报名了&#xff0c;但是一直在纠结&#xff0c;和家人沟通&#xff0c;和朋友交流&#xff0c;其实只是想寻求外界的支持…

Nginx 缓存那些事儿:原理、配置和最佳实践

Nginx 缓存那些事儿&#xff1a;原理、配置和最佳实践 在当今的互联网世界&#xff0c;网站的访问量和数据处理量不断攀升&#xff0c;如何确保用户能够快速、稳定地访问我们的网站&#xff0c;已经成为每个运维工程师面临的挑战。幸运的是&#xff0c;Nginx 作为一款高性能的…

【智体OS】官方上新发布智体电视:基于rtpc和rttouchpad实现智体电视的手机遥控-可安装任意PC应用用于智体电视

【智体OS】官方上新发布智体电视&#xff1a;基于rtpc和rttouchpad实现智体电视的手机遥控-可安装任意PC应用用于智体电视 dtns.network是一款主要由JavaScript编写的智体世界引擎&#xff08;内嵌了three.js编辑器的定制版-支持以第一视角浏览3D场馆&#xff09;&#xff0c;…

ES(elasticsearch)整合Spring boot使用实例

1.1通过docker安装es详细教程参考 docker部署elasticsearch(内涵集群部署的compose文件)-CSDN博客 2.1创建MySQL数据库&#xff0c;通过sql命令进行表的创建与数据的写入&#xff08;sql命令如下&#xff09; /*Navicat Premium Data TransferSource Server : localSo…

GitHub使用

太久不用GitHub发现自己又有些不会了&#xff0c;突发奇想为何不把每次看到的有指导意义的博客收录一下以便下次查阅呢 如何上传文件夹到GitHub上&#xff08;配图详解&#xff09;&#xff1f;_github上傳資料夾-CSDN博客 github上如何删除自己的仓库_github删除仓库-CSDN博…

单独测试 pyautogui 的鼠标点击功能,确保它能够在当前环境中正常工作,鼠标自动点击的录制回放功能

感谢您提供的详细日志信息。根据您的反馈&#xff0c;问题可能出在 pyautogui 没有正确获取鼠标焦点或无法在预期的位置执行点击操作。我们将采取以下步骤来进一步诊断和解决这个问题&#xff1a; 1. **确保 pyautogui 正确执行点击操作**&#xff1a; - 我们将添加更多的调…

保姆级教学 uniapp绘制二维码海报并保存至相册,真机正常展示图片二维码

一、获取二维码 uni.request({url: https://api.weixin.qq.com/wxa/getwxacode?access_token${getStorage("token")},responseType: "arraybuffer",method: "POST",data: {path: "/pages/index/index"},success(res) {// 转换为 Uint…

coco数据集转换SAM2格式

coco是一个大json汇总了所有train的标签 SAM2训练一张图对应一个json标签 import json import os from pycocotools import mask as mask_utils import numpy as np import cv2def poly2mask(points, width, height):points_array np.array(points, dtypenp.int32).reshape(-…

Vue.createApp的对象参数

目录 template 属性 data 属性 methods 属性 疑问 function 函数的两种写法 methods 属性中 this 的指向 总结 Vue 实例是通过 Vue.createApp() 创建的&#xff0c;该函数需要接收一个对象作为参数&#xff0c;该对象可添加 template、data、methods 等属性。 template …

LLM大语言模型私有化部署-OpenEuler22.03SP3上容器化部署Ollama与OpenWebUI

背景 你是不是也有私有化部署大模型的需求&#xff1f;如今有了 Ollama &#xff0c; HuggingFace &#xff0c; ModelScope 等开源平台&#xff0c;我们可以非常方便地搭建一个属于自己的大模型&#xff0c;如果网速给力&#xff0c;真是分分钟~~。简单起见&#xff0c;这篇文…

使用字典进行动态编程

在你的程序中&#xff0c;你想要执行各种计算&#xff0c;例如计算卫星的总数。 此外&#xff0c;当你进行更高级的编程时&#xff0c;你可能会发现你需要从文件或数据库中加载此类信息&#xff0c;而不是直接编码到 Python 中。 为了帮助支持这些场景&#xff0c;Python 使你…

Linux——rootfs根文件系统构建

根文件系统也叫做rootfs FATFS这类的文件系统属于Linux内核的一部分&#xff0c;属于软件代码&#xff0c;所以ROOTFS不等于FATFS。 Linux的根文件系统实际上是一个文件夹或者叫目录&#xff0c;这个目录下会有许多子目录&#xff0c;这些目录中存放许多Linux运行所必须的文件…

go语言的成神之路-标准库篇-os标准库

一、权限 在操作系统&#xff08;OS&#xff09;中&#xff0c;标准库的权限管理是非常重要的&#xff0c;它确保了不同用户和进程能够安全地访问系统资源。以下是一些常见的权限概念和说明&#xff1a; 1.用户权限 用户ID&#xff08;UID&#xff09;&#xff1a;每个用户在…

linux 生成 nginx 的https ssl 证书详解

证书生成 1. 生成证书 会提示输入密码&#xff0c;输入两次相同密码即可。 openssl genrsa -des3 -out server.key 20482. 去除密码校验 如果想去除此输密码的步骤&#xff0c;可以执行如下命令&#xff0c;根据使用需求选择。 openssl rsa -in server.key -out server.ke…