Android : 关于Tencent vConsole 添加入webView 总结

火影  论坛元老 | 2024-12-16 04:51:00 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1879|帖子 1879|积分 5637

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
官方地址:
  1. https://github.com/Tencent/vConsole/blob/dev/doc/tutorial_CN.md
复制代码
上面文档中提供了两种常见的引入H5工程思绪,简单易懂!

本日这篇文章要说明的是,差别于官方文档的接入方式。
先说背景:H5工程方,因框架原因不愿意大概不方便引入,这样就导致题目定位模糊,容易产生相互推诿的情况,那么作为app 客户端的我们又该如何应对呢?
思绪:了解官方文档明白,本质就是引入一段js代码。那么为何不通过webView 直接注入。
不思量兼容性的情况下(4.4以下),通过webVIew.evaluateJavascript的方法就可实现注入js。
实践1:网络cdn 引用 注入。
代码如下:
  1. String injectScript = "(function() {" +
  2.         "function loadVConsole() {" +
  3.         "    if (!window.vConsoleLoaded) {" +
  4.         "        var script = document.createElement('script');" +
  5.         "        script.type = 'text/javascript';" +
  6.         "        script.src = 'https://unpkg.com/vconsole/dist/vconsole.min.js';" +
  7.         "        script.onload = function() {" +
  8.         "            window.vConsoleLoaded = true;" +
  9.         "            if (window.vConsoleLoaded && window.vConsoleInstance == null) {" +
  10.         "                window.vConsoleInstance = new VConsole();" +
  11.         "            }" +
  12.         "        };" +
  13.         "        document.head.appendChild(script);" +
  14.         "    }" +
  15.         "}" +
  16.         "loadVConsole();" + // 调用函数来加载VConsole
  17.         "})();";
  18. binding.dwebVIew.evaluateJavascript(injectScript, null);
复制代码
至此vConsole 就可以使用了。
然后又突发奇想,假如放到本地会不会更快?
所以出现了
实践2:本地assets 文件中的js 引用 注入。
  1. try {
  2.     if(TextUtils.isEmpty(vConsoleScript)) {
  3.         // 读取assets文件夹中的vconsole.min.js文件
  4.         InputStream inputStream = getAssets().open("jsbrg/vconsole.min.js");
  5.         int size = inputStream.available();
  6.         byte[] buffer = new byte[size];
  7.         inputStream.read(buffer);
  8.         inputStream.close();
  9.         vConsoleScript = new String(buffer, "UTF-8");
  10.     }
  11.     // 构造注入到WebView中的JavaScript代码
  12.     if(TextUtils.isEmpty(injectScript)) {
  13.         injectScript = "(function() {" +
  14.                 "function loadVConsole() {" +
  15.                 "    if (!window.vConsoleLoaded) {" +
  16.                 "        var script = document.createElement('script');" +
  17.                 "        script.type = 'text/javascript';" +
  18.                 "        script.textContent = '" + escapeJavaScriptString(vConsoleScript) + "';" +
  19.                 "        document.head.appendChild(script);" +
  20.                 "        window.vConsoleLoaded = true;" +
  21.                 "        if (window.vConsoleLoaded && !window.vConsoleInstance) {" +
  22.                 "            window.vConsoleInstance = new VConsole();" +
  23.                 "        }" +
  24.                 "    }" +
  25.                 "}" +
  26.                 "loadVConsole();" +
  27.                 "})();";
  28.     }
  29.     // 注入JavaScript代码到WebView中
  30.     binding.dwebVIew.evaluateJavascript(injectScript, null);
  31. } catch (IOException e) {
  32.     e.printStackTrace();
  33. }
复制代码
其中遇到两个坑:
1、从assets文件夹中读取,注意路径一定得有,否则会io异常
2、上述方法有个关键方法,字符转义方法,加载的字符串无法直接注入,所以没这个方法无法注入乐成,如下:
  1. public static String escapeJavaScriptString(String input) {
  2.     if (input == null || input.isEmpty()) {
  3.         return "";
  4.     }
  5.     StringBuilder sb = new StringBuilder(input.length());
  6.     for (int i = 0; i < input.length(); i++) {
  7.         char c = input.charAt(i);
  8.         switch (c) {
  9.             case '\\':
  10.                 sb.append("\\\");
  11.                 break;
  12.             case '\'':
  13.                 sb.append("\\'");
  14.                 break;
  15.             case '"':
  16.                 sb.append("\\"");
  17.                 break;
  18.             case '\r':
  19.                 sb.append("\\r");
  20.                 break;
  21.             case '\n':
  22.                 sb.append("\\n");
  23.                 break;
  24.             case '\f':
  25.                 sb.append("\\f");
  26.                 break;
  27.             case '\b':
  28.                 sb.append("\\b");
  29.                 break;
  30.             case '\t':
  31.                 sb.append("\\t");
  32.                 break;
  33.             // 对于其他需要转义的字符,如 <, >, &, 也可以在这里添加
  34.             // 但通常这些字符在 JavaScript 字符串中不需要转义,除非它们被嵌入到 HTML 中
  35.             default:
  36.                 // 对于 ASCII 范围内的字符,通常不需要转义
  37.                 // 但对于非打印字符或特殊 Unicode 字符,你可能需要添加额外的逻辑
  38.                 if ((c >= 0x20 && c <= 0x7E) || Character.isISOControl(c)) {
  39.                     sb.append(c);
  40.                 } else {
  41.                     sb.append(c);
  42.                 }
  43.         }
  44.     }
  45.     return sb.toString();
  46. }
复制代码
以上就是两种差别官方添加vConsole的方法,本质都是通过安卓 webView的动态注入js方法。
实践2:确实更快一些,个人感觉!免除了网络延时,多了本地处理时间,各人可以对比一下
看到末了,恭喜你得到,踩坑经历大礼包:
注入的时机选择:
  1. 1、onPageFinished
复制代码
  1. 2、onPageStarted
复制代码
  1. 3、onProgressChanged
复制代码
经过我的实践:我这边以为最好的注入时机,这个三个地方都加上,onProgressChanged 方法中进度超过35%时开始注入。由于在注入代码中有添加是否注入过的逻辑,所以不用担心重复注入。
onPageStarted 这里添加是为了能尽大概的快注入乐成,大概尽大概多的获取日志。
onPageFinished 这里添加是,前两处注入都失败了,有个保底方案。
看到这里,缺点也非常明显,日志是否能打印全,取决于注入乐成的时间。所以会损失部分初始日志,但我测试也是偶发情况。
到此分享竣事,我也是迫于无奈才出此下策,有更好的办法,接待分享。末了的末了希望各人不会用到这种方法,只管让前端同学自己添加

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表