Flutter WebView 集成 WebAR (A-Frame + MindAR) 在 Android 上偶发 net::ERR_NAME_NOT_RESOLVED,如何彻底本地化子资源?
我在做一个 Flutter WebAR 项目(技术栈:Flutter WebView + A-Frame + MindAR)。
运行环境:
Flutter 3.x
插件:
webview_flutter(v4)Android 13 / 小米手机
入口页面通过
appassets加载:https://appassets.androidplatform.net/assets/flutter_assets/assets/webar/index.html
问题现象
- 主文档能成功加载(
index.html在 appassets 下)。 - HUD 注入策略已改为 pending → arReady 再贴,确认不是被 A-Frame 画布遮挡。
- 日志中仍然会报子资源失败:
I/flutter: [网络][错误] 资源加载失败 | ctx={"错误码":-2,"描述":"DNS 解析失败(ERR_NAME_NOT_RESOLVED)","是否主框架":false}
这说明仍有某些子资源在尝试访问外域,但我已经把核心库(A-Frame/MindAR)、.mind 文件、GLB 模型等都放到本地 assets/ 路径下。
关键代码片段
1. Flutter WebView 网络错误回调(webar_page.dart)
NavigationDelegate _buildNavigationDelegate() {
return NavigationDelegate(
onWebResourceError: (err) async {
// ✅ 打印 failingUrl,确认是哪条资源出网
debugPrint('[WebAR][NET][error] failingUrl=${err.failingUrl}, '
'isMainFrame=${err.isForMainFrame}, '
'code=${err.errorCode}, '
'desc=${err.description}');
},
);
}
2. utils.js —— 路径统一 & HUD 占位
// English code; 中文备注:统一把 assets/* 转 appassets,同源访问
function resolveAssetPath(rel) {
if (!rel) return '';
if (/^https?:\/\//i.test(rel) || /^file:\/\//i.test(rel)) return rel;
rel = String(rel).replace(/^\/+/, '');
return 'https://appassets.androidplatform.net/assets/flutter_assets/' + rel;
}
// English code; 中文备注:预置 setOverlay 占位,避免 Dart 早注入失败
if (typeof window.setOverlay !== 'function') {
window.setOverlay = function(cfg){
window.__overlayPending = cfg || null; // 中文:先存起来,业务脚本就绪后再贴
};
}
3. index.html —— 本地加载 A-Frame/MindAR 启动器
<script>
(function(){
function load(url){
return new Promise(function(res, rej){
var s = document.createElement('script');
s.src = url;
s.onload = res;
s.onerror = function(){ console.error('[boot] load failed:', url); rej(); };
document.head.appendChild(s);
});
}
function r(p){ return (typeof resolveAssetPath==='function') ? resolveAssetPath(p) : p; }
async function loadLocalLibs(){
await load(r('assets/webar/libs/aframe.min.js'));
await load(r('assets/webar/libs/mindar-image-aframe.prod.js'));
console.log('[boot] local A-Frame/MindAR ready');
}
loadLocalLibs();
})();
</script>
4. mindar.js —— .mind 初始化与候选回退
// 初始 imageTargetSrc
var mindUrl = (typeof resolveAssetPath === 'function')
? resolveAssetPath('assets/mindar/1.mind')
: 'assets/mindar/1.mind';
if (scene) scene.setAttribute('mindar-image', 'imageTargetSrc: ' + mindUrl);
// arReady 时探测候选文件
(async function(){
const candidates = [
resolveAssetPath('assets/mindar/2.mind'),
resolveAssetPath('assets/mindar/1.mind')
];
for (const url of candidates) {
try {
const r = await fetch(url, { method: 'HEAD' });
if (r.ok) {
scene.setAttribute('mindar-image', 'imageTargetSrc: ' + url);
return;
}
} catch(e){ console.error('[Assets] .mind fetch error:', e); }
}
console.error('[Assets] no valid .mind found.');
})();
我的疑问
既然核心库和资源都已本地化,为什么 WebView 仍然会有子资源访问外域?
- 可能是 GLB 模型内部的贴图 URI?
- 还是 CSS 字体/背景?
- 或者 MindAR 内部还尝试访问 CDN?
有没有办法在 WebView 或页面层面拦截所有请求 URL,快速确认是哪条资源还在出网?
问题
有没有朋友遇到过类似情况?如何保证 完全离线运行,避免任何 net::ERR_NAME_NOT_RESOLVED 的子资源错误?
👉 以上就是我最小化后的代码和日志,如果有经验的同学能帮忙看看还有哪些“隐性资源”需要本地化,非常感谢!