Android中WebView使用LoadUrl不刷新网页的问题,网址带#只能通过reload刷新

问题描述

最近在和公司其他项目组沟通联调H5的时候,意外发现对方发过来的地址可以加载,但是没有办法正常刷新。

尤其是对方服务器上已经重新部署页面,二次进入的情况下,依旧显示上一次加载过的内容,直到应用重启为止。

问题复现

写个 WebView 的 demo,然后在 WebViewClient 的所有方法加上日志来监控网页的运行情况。

此处假定测试网址为 https://www.mobibrw.com/#/?p=43064 

对网页第一次加载可以正常加载(即调用了 onPageStartedonPagefinished )。

第二次调用 loadUrl() 加载的时候只会刷新图标,不会真的重新加载网页(只调用了 onPageFinished )。

最后发现当我们第二次加载链接的时候,如果调用的是 webview.loadUrl(url) ,就无法刷新。

但是如果调用的是 webview.reload(url) ,就可以正常刷新网页。

调用 reload 时日志如下:

原因分析

知道了调用 reload 可以重刷网页,调用 loadUrl 无法重刷网页,问题就在于这两个方法的差别了。

经过查找,得知了真正原因是因为对方的 URL 带了 #,所以导致 loadUrl 不会刷新网页。

将网址改为 https://www.mobibrw.com/?p=43064,再次调用 loadUrl,第二次加载日志如下:

可以看到有正常执行 onPageStartedonPageFinished

那么为什么 URL 里面带了个 #,我们的 WebView 就无法通过 loadUrl 刷新网页了呢?

简单来说,URL # 以及其后面的部分,是客户端这边的位置定位符,在加载网页的时候并不会真正的发送给服务端。

我们的测试网址由于带有 #,所以无论怎么调用 loadUrl,他都判断我们只是改变了网页内部的相对位置(虽然实际上我们并没有改变),不会重新加载这个网页,只是加载网页图标。

那为什么 webview.reload 又可以重刷网页呢,实际上是因为 loadUrl 默认会有缓存策略,而 reload 是无视缓存策略强制刷新的,所以我们拿这个地址去浏览器运行,是可以正常刷新的。

结论

loadUrl 会有缓存策略,二次加载遇到带 # 的网页不会刷新,reload 无视缓存策略会强制刷新。

参考链接


BlowFish加解密原理与代码实现

一丶简介

​ BlowFish 是一个对称加密的加密算法。由 Bruce Schneier,1993年设计的。是一个免费自由使用的加密算法。

了解的必要知识

  • BlowFish是一个对称区块加密算法。每次加密数据为 64位 (2个int)类型数据大小。八个字节
  • BlowFish 密钥采用32-448位
  • BlowFish是由一个16轮循环的Feistel结构进行加密的。

二丶原理与代码介绍

2.1 BlowFish算法流程

BlowFish 算法流程是由两部分组成 分别是密钥扩展以及数据加密

在数据加密中是一个16轮循环的Feistel网络。每一轮由一个密钥相关置换和一个密钥与数据相关的替换组成的。

先说一下BlowFish需要的子密钥。

BlowFish在加密或者初始化的过程中会使用两个盒来进行加密

分别是PBOX 以及SBOX

PBOX是 由18个32位的字的子密钥组成的。这些密钥可以通过预计算产生的。

其中PBOX记录的就是Π后面的小数位。转换成16进制存储到pBox中

例如:

关于数学中Π大家应该知道。这里不再累赘。关于如何计算Π后面的小数位以及将小数位转为十六进制存储到p[0]---p[18] 这里也不再赘述。 因为这些都是预计算好的。我们直接使用就可以。

关于小数转为16进制可以使用网站进行转换(不确保以后还能否使用):小数转换16进制

例子如下:

Sbox跟PBOX一样也是Π的小数位组成。sBox是4组8*32的数组。 如下

pBox与Sbox就是BlowFish算法进行加密的核心置换表

2.2 子密钥生成

​ 如果想进行数据加密。那么我们就要进行子密钥生成。也就是要将我们的Key 与 pbox进行 异或

那么说一下流程吧

  • 1.按顺序使用Π的小数部分初始化pbox与sbox (预先计算好了可以直接使用)

  • 2.使用key参数得出key_pbox, 具体流程为 将pbox中的数据 与 key进行 ^ 然后设置到key_pbox中,轮询key每次取出四个字节来与pbox[i]进行 异或

    如果Key不足的情况下 key从零开始补齐4个字节 继续与pbox[i]进行异或

    例子:

  • 3.使用当前的key_pbox数组 与s_box数组对一个64位0数据进行加密。 也就是 两个int 类型数据 8个字节 输出的结果 重新修改到key_pbox 与 key_sbox中。

    key_sbox就是当前的 使用s_box对64位数据进行加密,产生的输出修改的key_sbox中。

  • 一直循环直到修改完key_pbox与key_sbox为止

示例代码如下:

2.3 加密原理

​ BlowFish加密很简单。就是 将一个数 拆分为 左右各32位数值 (也就是 8个字节 左边四个字节,右边四个字节) 然后 左边进行 ^ key_pbox 当作下一次循环的右边。 右边 则是 右边 ^ F(左边) 下次当作循环的左边。

循环16轮。

说着挺难。看下图:

简单的加密流程图:

在这里我们只看加密

这里不得不介绍下F函数。 F函数的输入是一个32位数 也就是四个字节类型数据。 然后内部就是将32位数进行拆分成abcd

例如:

拆分后的a b c d然后去Key_sbox中查表 然后取出对应的值。

公式如下:

F函数明白了那么回头继续看一下加密操作。

图如下:

可以看到 首先计算 L ^Kr(Key_pbox[i]) 然后结果直接作为下一轮的右侧

右侧则是 经过论函数F 进行设置的。 最后变为下一轮循环的左侧。

R = R ^F(L)

最后一轮的话需要单独设置

其实加密函数就是循环16次。 然后每一轮都对 左侧32位 右侧32位进行操作。 操作之后直接作为下一轮循环的左右侧

核心代码如下:

至此我们的blowFish加密已经完成

2.4 BlowFish的解密

​ 解密与加密是相反操作。 加密的时候是从0开始遍历16轮 然后依次对xl xr进行操作。

解密的时候做事从16开始然后迭代16轮 对左右两侧做操作

最后16轮循环完毕之后还是进行一次^

代码如下:

至此解密完成

2.5.完成代码

经过测试加解密输出结果是对的。

参考链接


BlowFish加解密原理与代码实现

make: *** No rule to make target `sqlite_cfg.h', needed by `.target_source'

前置条件

  • macOS Sonoma (14.4.1) 
  • MacBook Pro 2023-Apple M2 Pro (4能效核、8性能核、32GB内存、2TB磁盘)
  • Homebrew (4.2.18 或更高版本)
  • Xcode Version 15.3 (15E204a)
  • DevEco Studio NEXT Developer Preview2 4.1.3.700

错误信息

源代码编译 sqlite3

或者使用 pod 安装 sqlite3 报错:

观察源代码目录,也确实没有 sqlite_cfg.h 文件生成。

继续阅读make: *** No rule to make target `sqlite_cfg.h', needed by `.target_source'

修复 SecurityException: getDataNetworkTypeForSubscriber 问题

1.问题

  • 用户切换改变网络的过程中,应用概率会出现崩溃,日志如下

另外一种场景就是集成了华为的二维码扫描  com.huawei.hms:scanplus:1.3.2.300 ,这个  SDK 比较奇葩的地方在于,使用 Wi-Fi 网络情况下是不会出现问题的。

但是在手机流量的情况下,不申请 android.permission.READ_PHONE_STATE 权限,初始化这个 SDK 会导致应用闪退。

崩溃堆栈如下:

2.分析

  • 根据 SecurityException: getDataNetworkTypeForSubscriber 可以看到,这是一个安全性异常,所以猜测应用在 Android11 的权限有关,由于缺少该权限导致无法访问接口而异常。

  • 找到网络状态检测方法,可以看到调用了 TelephonyManager.getNetworkType()接口获取网络类型,该方法是需要 READ_PHONE_STATE 权限的,该方法上面也有 RequiresPermission 注解声明

  • 进一步分析,接口的调用堆栈为:

3.解决方法

参考链接


修复 SecurityException: getDataNetworkTypeForSubscriber 问题

Android: 通过Intent筛选多种类型文件

一般使用setType()方法来实现文件过滤,如:只显示PDF文件:

但如果要指定多种类型呢,同时要指定pdf,excel,word,ppt这些类型的文件,那要怎样设置呢?

指定多种类型文件

在网上查了,有些答案是

错误方式1——setType中进行拼接:

错误方式2——调用多次setType:

这两种方式都是错误的

我们看下源码

我们可以看到,setType每次都是重新赋值,没有添加到list和数组中,因此这两种方式是实现不了指定多种类型文件的。
既然这种方式实现不了,那么Intent会不会提供字段以便我们传递过滤数据,我们通过官方文档及源码,发现Intent提供了EXTRA_MIME_TYPES这个字段来传递,而且是数组类型:

因此结果就简单了,我们要指定ppt,word,excel,pdf类型的文件,代码如下

MimeType文件

Intent指定多种类型的文件,正确的做法,是通过Intent.EXTRA_MIME_TYPES传递Mime类型数组实现

MimeType 文件列表参考

 1. Mozilla MDN Web Docs: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types

扩展名 文档类型 MIME 类型
.aac AAC audio audio/aac
.abw AbiWord document application/x-abiword
.arc Archive document (multiple files embedded) application/x-freearc
.avi AVI: Audio Video Interleave video/x-msvideo
.azw Amazon Kindle eBook format application/vnd.amazon.ebook
.bin Any kind of binary data application/octet-stream
.bmp Windows OS/2 Bitmap Graphics image/bmp
.bz BZip archive application/x-bzip
.bz2 BZip2 archive application/x-bzip2
.csh C-Shell script application/x-csh
.css Cascading Style Sheets (CSS) text/css
.csv Comma-separated values (CSV) text/csv
.doc Microsoft Word application/msword
.docx Microsoft Word (OpenXML) application/vnd.openxmlformats-officedocument.wordprocessingml.document
.eot MS Embedded OpenType fonts application/vnd.ms-fontobject
.epub Electronic publication (EPUB) application/epub+zip
.gif Graphics Interchange Format (GIF) image/gif
.htm
.html
HyperText Markup Language (HTML) text/html
.ico Icon format image/vnd.microsoft.icon
.ics iCalendar format text/calendar
.jar Java Archive (JAR) application/java-archive
.jpeg
.jpg
JPEG images image/jpeg
.js JavaScript text/javascript
.json JSON format application/json
.jsonld JSON-LD format application/ld+json
.mid
.midi
Musical Instrument Digital Interface (MIDI) audio/midi audio/x-midi
.mjs JavaScript module text/javascript
.mp3 MP3 audio audio/mpeg
.mpeg MPEG Video video/mpeg
.mpkg Apple Installer Package application/vnd.apple.installer+xml
.odp OpenDocument presentation document application/vnd.oasis.opendocument.presentation
.ods OpenDocument spreadsheet document application/vnd.oasis.opendocument.spreadsheet
.odt OpenDocument text document application/vnd.oasis.opendocument.text
.oga OGG audio audio/ogg
.ogv OGG video video/ogg
.ogx OGG application/ogg
.otf OpenType font font/otf
.png Portable Network Graphics image/png
.pdf Adobe Portable Document Format (PDF) application/pdf
.ppt Microsoft PowerPoint application/vnd.ms-powerpoint
.pptx Microsoft PowerPoint (OpenXML) application/vnd.openxmlformats-officedocument.presentationml.presentation
.rar RAR archive application/x-rar-compressed
.rtf Rich Text Format (RTF) application/rtf
.sh Bourne shell script application/x-sh
.svg Scalable Vector Graphics (SVG) image/svg+xml
.swf Small web format (SWF) or Adobe Flash document application/x-shockwave-flash
.tar Tape Archive (TAR) application/x-tar
.tif
.tiff
Tagged Image File Format (TIFF) image/tiff
.ttf TrueType Font font/ttf
.txt Text, (generally ASCII or ISO 8859-n) text/plain
.vsd Microsoft Visio application/vnd.visio
.wav Waveform Audio Format audio/wav
.weba WEBM audio audio/webm
.webm WEBM video video/webm
.webp WEBP image image/webp
.woff Web Open Font Format (WOFF) font/woff
.woff2 Web Open Font Format (WOFF) font/woff2
.xhtml XHTML application/xhtml+xml
.xls Microsoft Excel application/vnd.ms-excel
.xlsx Microsoft Excel (OpenXML) application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.xml XML application/xml 代码对普通用户来说不可读 (RFC 3023, section 3)
text/xml 代码对普通用户来说可读 (RFC 3023, section 3)
.xul XUL application/vnd.mozilla.xul+xml
.zip ZIP archive application/zip
.3gp 3GPP audio/video container video/3gpp
audio/3gpp(若不含视频)
.3g2 3GPP2 audio/video container video/3gpp2
audio/3gpp2(若不含视频)
.7z 7-zip archive application/x-7z-compressed

2. AOSP MediaFle:  

根据不同的MIME类型,显示不同的图标:

参考链接


android: 通过Intent筛选多种类型文件

macOS Sonoma(14.2.1)通过Docker编译Android 12.1源码过程总结(MacBook Pro 2023-Apple M2 Pro)

前置条件


根据 Google 官方文档,2021年6月22日之后的Android系统版本不支持在macOS系统上构建,我们在 Applic SiliconmacOS 系统是不能直接成功构建后续版本的,但是之前的版本可以在修改编译配置后成功编译,只是是否能正常运行存疑

另外,我们需要安装 Rosetta 2 支持运行部分 x86_64 应用。注意  Rosetta 2 只支持 64 位应用,不支持 32 位应用。 参考 Does Rosetta 2 support 32-bit Intel apps?

继续阅读macOS Sonoma(14.2.1)通过Docker编译Android 12.1源码过程总结(MacBook Pro 2023-Apple M2 Pro)

Android:Installed Build Tools revision 33.0.2 is corrupted.

使用33.0.2及以上版本的build-tools编译Android应用时。

有些人会按照提示去SDK Manager中重新安装build tools,然后发现这样做是无用的

编译时会收到:

Windows:

Linux/macOS:

解决方案:

更改批处理文件名称

Windows系统:

  1. 找到build tools目录中的d8.bat,将文件名修改为dx.bat。
  2. 找到build tools目录中的lib/d8.jar,将文件名修改为dx.jar。
  3. 回到Android Studio重新打包。

Linux/macOS系统:

  1. 找到build tools目录中的d8,创建软链接 ln -s d8 dx
  2. 找到build tools目录中的lib/d8.jar,创建软链接 ln -s d8.jar dx.jar
  3. 回到Android Studio重新打包。

参考链接


Android:Installed Build Tools revision 33.0.2 is corrupted.

使用UrlQuerySanitizer来处理URL

网上对于 UrlQuerySanitizer 的资料比较少,这个是 Android 提供的一个用来处理 url 的 API。由于项目的需要,需要对 url 的 query 参数进行排序,因此需要解析 url 并处理 query 参数。

最初的方法是使用 Uri:

通过这样的方式就可以解析 url,并获取到各个 query 参数。但后来发现 Uri 不能处理一些特殊字符,比如#,Uri 会截断#以后的内容,这样就不能满足开发需求。经过各种 google,最后发现了一个 UrlQuerySanitizer 的 API:

首先要使用 setAllowUnregisteredParamaters 让其支持特殊字符,然后使用 setUnregisteredParameterValueSanitizer 来设置支持哪些特殊字符,UrlQuerySanitizer 提供了集中默认的 ValueSanitizer:

每种 ValueSanitizer 都对应过滤哪些字符,被过滤掉的特殊字符会被替换成_或者空格。
如果默认的 ValueSanitizer 不能满足开发需求,还可以自己构造 ValueSanitizer:

UrlQuerySanitizer 也可以通过 key 来获取相应的 value,比如给一个 url:http://coolerfall.com?name=vincent:

UrlQuerySanitizer 还可以只解析 query 参数,比如:name=vincent&article=first:

以上就是 UrlQuerySanitizer 大致用法,用来解析处理 url 非常的方便。

参考链接


使用 UrlQuerySanitizer 来处理 url

macOS Sonoma(14.2.1)通过UTM虚拟机编译Android 12.1源码过程总结(MacBook Pro 2023-Apple M2 Pro)

前置条件


根据 Google 官方文档,2021年6月22日之后的Android系统版本不支持在macOS系统上构建,我们在 Applic SiliconmacOS 系统是不能直接成功构建后续版本的,但是之前的版本可以在修改编译配置后成功编译,只是是否能正常运行存疑

尝试过使用 Podman Desktop / Docker 方式进行编译、也尝试过借助 OrbStackLima 这些纯虚拟机通过安装 ubuntu 22.04 系统镜像的方式进行编译,结果都在执行 lunch 命令的时候长时间卡住,观察系统进程发现名为 nsjail 进程的 CPU 占用持续卡住在 100% 上无法继续编译,并且由于 Docker 或者虚拟机文件系统是 Linux 文件系统,而宿主机的文件系统是 AppleFS 文件系统,导致需要进行文件转换,中间的转换性能代价非常高,性能很差。

相反,目前测试来看,直接在 UTM 虚拟机里执行编译的性能反倒更好一些。

目前测试发现存在严重的文件系统缺陷,编译/大量文件复制过程中,经常出现文件系统损坏,导致编译失败。

原因参考:

https://github.com/utmapp/UTM/pull/5869
https://github.com/utmapp/UTM/pull/5919

需要等待 UTM 合并到主分支。

另外,我们需要安装 Rosetta 2 支持运行部分 x86_64 应用。注意  Rosetta 2 只支持 64 位应用,不支持 32 位应用。 参考 Does Rosetta 2 support 32-bit Intel apps?

继续阅读macOS Sonoma(14.2.1)通过UTM虚拟机编译Android 12.1源码过程总结(MacBook Pro 2023-Apple M2 Pro)

macOS Ventura(13.6)/macOS Sonoma(14.0)编译Android 10.0/Android 11.0源码过程总结(MacBook Pro 2023-Apple M2 Pro)

前置条件


  • macOS Ventura(13.6)/macOS Sonoma(14.0) MacBook Pro 2023-Apple M2 Pro (4能效核、8性能核、32GB内存、2TB磁盘)
  • Homebrew (4.0.28 或更高版本)
  • Xcode Version 15.0 (15A240d)
  • Android Studio Giraffe | 2022.3.1 Patch 1

从Intel版本MacBook Pro迁移到MacBook Pro 2023(Apple M2 Pro)的设备,参考 从Intel版本MacBook Pro 2013迁移到MacBook Pro 2023(Apple M2 Pro)后HomeBrew报错"Error: Cannot install in Homebrew on ARM processor in Intel default prefix (/usr/local)" 重新安装 Homebrew

根据 Google 官方文档,2021年6月22日之后的Android系统版本不支持在macOS系统上构建,我们在 Applic SiliconmacOS 系统是不能直接成功构建后续版本的,但是之前的版本可以在修改编译配置后成功编译。

尝试过使用 Podman Desktop / Docker 方式进行编译、也尝试过借助 OrbStackLima 这些纯虚拟机通过安装 ubuntu 22.04 系统镜像的方式进行编译,结果都在执行 lunch 命令的时候长时间卡住,观察系统进程发现名为 nsjail 进程的 CPU 占用持续卡住在 100% 上无法继续编译,并且由于 Docker 或者虚拟机文件系统是 Linux 文件系统,而宿主机的文件系统是 AppleFS 文件系统,导致需要进行文件转换,中间的转换性能代价非常高,性能很差。

通过 UTM 虚拟机,使用 MacOS 提供的虚拟机执行编译的话,性能会更好。但是目前测试发现存在严重的文件系统缺陷,编译/大量文件复制过程中,经常出现文件系统损坏,导致编译失败。

需要在 M2 上使用UTM 虚拟机编译的,可以参考 macOS Sonoma(14.1.1)通过UTM虚拟机编译Android 11.0源码过程总结(MacBook Pro 2023-Apple M2 Pro) 通过 UTM 虚拟机借助 Rosetta 2 的方式进行编译。目前测试来看,性能勉强能用。

另外,我们需要安装 Rosetta 2 支持运行部分 x86_64 应用。注意  Rosetta 2 只支持 64 位应用,不支持 32 位应用。 参考 Does Rosetta 2 support 32-bit Intel apps?

继续阅读macOS Ventura(13.6)/macOS Sonoma(14.0)编译Android 10.0/Android 11.0源码过程总结(MacBook Pro 2023-Apple M2 Pro)