Android WebView 加载 file:// 离线页面调试教程

本文记录一种调试场景:当前已经通过 Chrome DevTools 连接到 Android App 内的 WebView,希望让这个 WebView 直接加载手机本地的 file:// 离线页面。

示例目标地址:

text 复制代码
file:///storage/emulated/0/Android/data/com.example.app/index.html?file=<path_id>/<resource_id>

1. 为什么 Console 里直接跳转会失败

在 Chrome DevTools Console 里执行:

js 复制代码
window.location.href = 'file:///storage/emulated/0/Android/data/com.example.app/index.html?file=<path_id>/<resource_id>'

或:

js 复制代码
location.replace('file:///storage/emulated/0/Android/data/com.example.app/index.html?file=<path_id>/<resource_id>')

可能会报:

text 复制代码
Not allowed to load local resource: file://...

原因是:当前页面脚本从 http://https:// 页面主动跳转到 file:// 本地资源时,会被 Chromium/WebView 的安全策略拦截。

这不是 URL 拼写问题,而是页面上下文发起 file:// 导航被禁止。

2. 不要把 file:// 粘到地址栏

如果把下面这种地址直接粘到 Chrome 或 DevTools 的地址栏:

text 复制代码
file:///storage/emulated/0/Android/data/...

Chrome 有时会把它当成普通搜索或网页地址处理,出现自动拼接 http:// 的情况。

调试 WebView 时,不建议通过地址栏输入这种手机端本地路径。

3. 用 Protocol Monitor 发送 Page.navigate

更合适的方式是通过 Chrome DevTools Protocol 让调试器发起导航,而不是让页面 JS 发起导航。

打开 Protocol Monitor

  1. 打开连接 WebView 的 DevTools 页面。
  2. Cmd + Shift + P,Windows/Linux 使用 Ctrl + Shift + P
  3. 搜索:
text 复制代码
Protocol Monitor
  1. 选择:
text 复制代码
Show Protocol Monitor

如果搜不到:

  1. 打开 DevTools 右上角齿轮 Settings
  2. 进入 Experiments
  3. 勾选 Protocol Monitor
  4. 关闭并重新打开 DevTools。
  5. 再通过命令面板打开 Show Protocol Monitor

正确发送方式

在 Protocol Monitor 里,方法名填:

text 复制代码
Page.navigate

参数填:

json 复制代码
{
  "url": "file:///storage/emulated/0/Android/data/com.example.app/index.html?file=<path_id>/<resource_id>"
}

注意:不要把下面这种函数调用整体填进去:

js 复制代码
Page.navigate({"url":"file:///..."})

否则会报:

json 复制代码
{
  "code": -32601,
  "message": "'Page.navigate({...})' wasn't found"
}

这个报错表示 DevTools 把整段 Page.navigate({...}) 当成了 method 名,而不是调用了 Page.navigate 方法。

如果 Protocol Monitor 只有单行 JSON-RPC 输入,可以尝试:

json 复制代码
{"id":1,"method":"Page.navigate","params":{"url":"file:///storage/emulated/0/Android/data/com.example.app/index.html?file=<path_id>/<resource_id>"}}

4. URL 参数里的 https 要编码

如果原始参数里有:

text 复制代码
cdn=https://cdn.example.com

建议编码成:

text 复制代码
cdn=https%3A%2F%2Fcdn.example.com

否则嵌套 URL 容易在解析 query 参数时出问题。

5. 如果 Page.navigate 也失败

如果通过 Protocol Monitor 发送 Page.navigate 后仍然失败,例如出现:

text 复制代码
Not allowed to load local resource

或:

text 复制代码
net::ERR_ACCESS_DENIED

或页面空白,那通常说明 WebView 本身没有允许访问本地文件。

这时需要从 App 代码侧加载,而不是从 DevTools 侧强行跳转。

Kotlin 示例:

kotlin 复制代码
webView.settings.allowFileAccess = true
webView.settings.allowFileAccessFromFileURLs = true
webView.settings.allowUniversalAccessFromFileURLs = true

webView.loadUrl(
    "file:///storage/emulated/0/Android/data/com.example.app/index.html?file=<path_id>/<resource_id>"
)

Java 示例:

java 复制代码
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setAllowFileAccessFromFileURLs(true);
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);

webView.loadUrl(
    "file:///storage/emulated/0/Android/data/com.example.app/index.html?file=<path_id>/<resource_id>"
);

6. 判断问题属于哪一类

现象 可能原因 处理方式
地址栏自动拼 http:// 地址栏把输入当普通网页地址处理 不用地址栏,改用 DevTools Protocol
Console 报 Not allowed to load local resource 页面 JS 不能从 http/https 跳到 file 不用 window.location.href,改用 Page.navigate 或 App 侧 loadUrl
Protocol Monitor 报 -32601 method 填错,把函数调用当方法名 method 填 Page.navigate,params 单独填 JSON
Page.navigate 后仍报 ERR_ACCESS_DENIED WebView 文件访问权限不允许 App 侧开启 file access 并调用 webView.loadUrl
页面打开但资源加载失败 file 页面内跨域访问 http/https 或其他 file 资源受限 检查 allowFileAccessFromFileURLsallowUniversalAccessFromFileURLs

7. 推荐调试顺序

  1. 先确认文件真实存在于手机路径:
bash 复制代码
adb shell ls -l /storage/emulated/0/Android/data/com.example.app/index.html
  1. 用 Chrome DevTools 连接目标 WebView。

  2. 打开 Protocol Monitor

  3. 发送 Page.navigate,不要在 Console 里执行 window.location.href

  4. 如果仍然被拦截,改为 App 代码侧 webView.loadUrl(fileUrl)

  5. 如果页面能打开但内容异常,再检查 WebView 的 file access 相关设置和页面内资源路径。

相关推荐
plainGeekDev1 小时前
Activity 间传值 → Navigation 参数
android·java·kotlin
Asmewill1 小时前
curl命令学习笔记一
前端
我是一只快乐的小螃蟹1 小时前
1.2 ArrayList 源码解析
前端
星栈1 小时前
我用 Rust + Dioxus 做了个全栈跨平台笔记应用:再把新建、编辑和交付补上
前端·rust·前端框架
plainGeekDev1 小时前
onActivityResult → ActivityResult API
android·java·kotlin
我是一只快乐的小螃蟹1 小时前
1.1 HashMap (JDK1.8) 源码解析
前端
爱勇宝4 小时前
小红花成长新版:模板来了,鼓励也更容易开始
前端·后端·程序员
竹林8184 小时前
Solana前端开发:我在一个NFT铸造页面上被@solana/web3.js的Connection和Transaction签名坑了两天
前端
冬奇Lab5 小时前
每日一个开源项目(第144篇):ai-website-cloner-template - 一条命令、多 Agent 并行,把任意网站逆向成 Next.js 代码
前端·人工智能·开源