Flutter 静态挂载腾讯X5WebView(Tbs)浏览器内核_flutter tbs-程序员宅基地

技术标签: dart  webview  flutter  webrtc  plugin  Flutter  


背景

项目中(Flutter项目)有一个需求是通过webview加载界面,来显示实时视频(webrtc),那么问题是,不同Android手机浏览器对于webrtc视频解码的支持性有差异导致部分手机无法正确显示视频,部分手机只有声音没有视频。那么我决定通过端侧来解决这个问题(我猜测修改web端代码进行适配也能解决),由此引申出了这篇文章,留作参考记录。涉及到的主要知识点如下:

  1. Android 平台下替换浏览器内核方案。
  2. Android Native 静态集成腾讯X5(tbs)浏览器内核。(需要原生静态集成tbs浏览器内核的同学同样适用)
  3. Flutter plugin 插件开发。
  4. Flutter 打包机制。

一、寻找Android WebView 内核替换方案(在native层面验证)

1.CrossWalk

经过测试,最新版本的CrossWalk并不能解决问题,仍然存在视频无法解码的问题。集成方式不再多说,相关教程很多。要注意的是crosswalk webview 想要略过ssl验证,需要修改源码中的SslUtil文件,修改为如下,直接忽略掉ssl异常。

 public static boolean shouldDenyRequest(int error) {
    
        if (error >= -214 && error <= -200) {
    
            switch(error) {
    
            case -213:
            case -212:
            case -211:
            case -208:
            case -207:
            case -206:
            case -203:
            case -202:
            case -201:
            case -150:
            case -129:
                return false;
            default:
                return false;
            }
        } else {
    
            throw new AssertionError();
        }
    }

然后将这个java文件编译成".class"文件后,替换到crosswalk的aar包中。我在验证过程中也做了一些工作,把用到的资源分享一下,以便有同学用得到,下面的下载链接是编译成.class的SslUtil文件(其实这个是比较难搞的),将内核的aar sdk解压替换即可,可以到crosswalk官网自行下载32or64位的sdk。
下载链接
提取码:8cy5

2.腾讯X5浏览器

另外一个方案是腾讯的X5浏览器内核(https://x5.tencent.com/),经测试,可以解决我的问题,兼容性良好,有两种集成方式说明一下

1)动态集成

动态集成具体方式官网上&其他帖子有很多说明,自行查找。经过测试,动态集成在Native项目中,内核挂载还算相对稳定(也有反复挂载不成功的情况),但是已Flutter 插件(Flutter 插件为静态集成)的方式,集成到Flutter项目后,体验非常之差,内核挂载成功率很低。所以动态集成方案pass,无法使用。(说句题外话,虽然这里只写了一段,但是验证过程确实还是用了一些时间的)

2)静态集成

那么目前就明确了两点,要解决两个问题,首先是采用x5Webview替换内核方案,其次是需要静态集成。

参考文章 原生项目需要静态集成的同学对照这篇文章集成即可。

我这里补充一下我提取到到的64位内核资源(实际提取不难但我觉得麻烦,其实用32位的so文件足够),下载链接如下:
下载链接
提取码:fmy5

到此,这两个问题圆满解决。

二、Flutter 静态集成的X5WebView 的插件开发

明确了方案,并且tbs静态集成也ok,那么下一步就是要创建一个静态集成的X5WebView的Flutter插件给Flutter项目使用,搜索了一下目前只有x5webview动态集成的flutter插件,那么这里就需要自己去搞一个插件来用,这里我借鉴了pub上已有的动态继承tbs的库。
插件提供了两种使用方式,一种是直接从Flutter界面跳转到Native方式使用了Tbs浏览器的Activity,一种是直接使用实现了TbsWebView的Flutter Widget

1.StaticTBS Flutter Plugin(插件) 开发

1)创建Flutter Plugin

as中,点击File->New->New Flutter Project ,弹出选择项目类型界面,选择Flutter Plugin,点击Next,之后填写相应信息,最后finish,完成创建。创建的项目中内含一个example目录(是一个flutter 项目),这个是用来调试plugin功能的,可作为临时宿主使用。

2)编写Android Native代码

这点比较关键的,我想通过android studio 开发原生部分的代码,关键点是,先要构建一下生成的eample项目,cd 到 example目录,执行“flutter build apk ”即可,构建完成(是否成功不重要),之后就可以通过android studio 打开项目进行native开发,要注意的是,要打开example里面的android项目。

plugin project结构
将提取到的armeabi架构的tbs so库文件以及,静态加载用到的jar包导入项目。

3)编写Flutter插件代码

这里涉及到的代码以及知识点较多,主要是插件开发相关,后面我也许会单独写文章记录,就不在这单独讲解了,可以搜索Flutter Plugin插件开发相关文章,目前项目已上传到git,请自行查看
插件项目地址

三、集成插件项目的编译

使用静态tbs插件后,直接打包还是会发现内核挂载失败,核心问题就是我目前还没有提取到不同架构下的tbs so库,只提取到了armeabi架构的,受限于tbs挂载规则或者是flutter so加载机制,tbs的armeabi so库并不能向上兼容,放在armeabi-v7下不不好用。只能放到armeabi文件加下才可以保证加载成功,所以还需要关注一下下面的说明

1. 针对“Shrink”做的修改

当项目集成了静态内核,会发现还是无法挂载,是因为flutter的打包apk机制 ,进行了“shrink”操作,将“com.tencent.cmtt” 包下的“utils”文件夹给“优化”掉了,误伤友军,所以为了能正常挂载静态内核,那么需要对flutter gradle文件进行修改。

Flutter 本身gradle的文件路径 :
D:\你的flutter本地源码文件夹\flutter_windows_v1.9.1+hotfix.6-stable\flutter\packages\flutter_tools\gradle

打开这个路径下的“flutter.gradle” 文件进行修改,修改这个部分代码,将注释部分屏蔽掉,这样flutter工程在打包anroid项目的时候,就不会去shrink,对apk进行瘦身了,这里要注意,如果修改了flutter源码下的代码,后面想要通过“flutter upgrade”升级版本的时候会出错,需要先revert掉,才可以正常升级。

     private static Boolean shouldShrinkResources(Project project) {
    
     	//将这个函数屏蔽掉
        if (project.hasProperty("shrink")) {
    
           return project.property("shrink").toBoolean()
        }
         return false
     }

2.so库打包机制

接下来要讲一下到Flutter so 库打包机制了,这里会延伸出一个flutter常见问题“couldn’t find “libflutter.so””,特别是你通过命令行进行打包的时候更容易出现这个问题,原因稍后讲解。
当解压正常的Flutter apk包,我们可以看到lib下的armeabi,arm64-v8a,x86等文件夹下会有“libflutter.so”以及“libapp.so”这两个文件,可以这样理解,libapp.so他就是我们用flutter写的业务逻辑所打包的产物,libflutter.so实际上可以理解为libapp.so执行所必备的环境之一,正常运行的时候根据手机架构加载对应的so库,达到native层面优化的效果。
那么回到上面的问题上来,“couldn’t find "libflutter.so”导致崩溃,极大概率就是你使用了一些plugin,或者是引用了一些第三方库文件,打包时导致slibflutter.so库没有被打到指定的文件夹下,导致应用崩溃,如果是libapp.so没有被打进去,应用只是会白屏,因为找不到UI以及逻辑代码。
解决这个问题需要你理一下你项目中用到了哪些第三方so库,特别关注plugin,然后可以通过修改android目录下的ndk打包模式来进行调整。
修改的位置如下图:
Android gradle 配置修改
有两种情况
如果你只打算适配arm架构,那么就修改为只打包armeabi-v7即可,你需要保证所有的so库,都有这个架构的so文件。
这里有一个坑,flutter现在打包默认不支持将libflutter.so以及libapp.so打到armeabi下,如果你想向上兼容,只对armeabi做适配那是行不通,这里有个骚操作,那就是先生成armeabi-v7 的apk,解压后拿到这两个so库,手动复制到armeabi目录下,在进行只有armeabi架构的打包,就可以了,是有些麻烦,注意,目前如果使用这个插件,需要按照这个步骤操作。
其实也可以修改flutter gradle文件,让它可以将这两个so文件打包到armeabi目录下,不是很好搞。

如果你打算适配不同架构,核心就是要不把不同架构so库找全了,全部统一到对应so目录下,在进行打包。

如果还是有问题,有个排查技巧,拿到启动会崩溃的apk,丢到as里面,查看lib文件,可以看到哪些so文件出了问题,这样比较直观
不同架构so库分析
上图所示,armeabi有41MB,是因为我把tbs浏览器内核放到了armeabi文件夹下,打包的是全平台,所以其他三个下面没有这些so文件,所以如果运行在arm64,x86设备上,内核是会挂载失败的。

总结

总结一下心得:
首先这边博客还只是算是给出了解决思路,实际看起来有些杂乱,杂乱的原因是目前我这个方案肯定不是最优解,需要后续完善,这里做一下记录,如果能吸引到牛人来一起探讨那更好了,我下一步的思路就是继续尝试修改flutter gradle,让flutter支持打包armeabi架构的apk,因为时间不是很多,之前只是简单试过没有成功。如果哪位有思路欢迎交流。

近期的一些思考
对于技术,每一个点,往细了深究都会牵扯到好多东西,需要静下心来去研究,试错,尽可能的使点连成片。以这篇文章来讲,我还有好多地方做的不过好,需要后续改进。
对于项目,不同业务情况不同的分析方式,面对不同Bug也要有不同的解决思路,具体问题具体分析,不要局限于一小块,已万变应对不变。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yyfd2013/article/details/108225667

智能推荐

浅析HTML_解析html-程序员宅基地

文章浏览阅读430次。HTML面试题整理以及一些自我理解_解析html

idea 启动报错: Failed to create JVM.JVM.Path XXXXXXX\jbr\ 我的解决办法-程序员宅基地

文章浏览阅读2.6k次,点赞2次,收藏6次。idea 启动报错: Failed to create JVM.JVM.Path XXXXXXX\jbr\ 我的解决办法在C:\Users\Administrator\AppData\Roaming\JetBrains\PhpStorm2021.1的文件夹里,找到 phpstorm64.exe.vmoptions 这个文件,并改回原来的配置即可。因为这个路径下的vmoptions文件是我当时修改过的(Help->Edit custom VM Options) phpstorm64.exe.vmop_failed to create jvm

dB、dBFS、dBV、dBu...都是啥啊..-程序员宅基地

文章浏览阅读6.5k次,点赞8次,收藏27次。“7号球员夏普分球,传给了9号,9号也叫夏普,他们可能是兄弟,好球,传给10号传得非常好。咦?10号也叫夏普。可能外国印在球衣上的只是姓,就像韩国很多球员姓朴。漂亮,夏普连过两名队员破门得分!11号上前祝贺,11号也叫夏普...(停顿很久)对不起,夏普/Sharp 是赞助商的名字。” —— 韩乔生经过20年音频市场的普及和发展,音乐爱好者们玩得更深了,开始讨论信噪比、总谐波失真、声压级、最大电平... 就像玩车,上一代人只考虑“开宝马、坐奔驰”,而年轻人开始讨论最大功率、百里加速、扭矩、悬架类型、轮.._db、dbfs、dbv、dbu

(vue)element-ui 表格实现勾选单选_element ui单选框 打勾-程序员宅基地

文章浏览阅读2.3k次,点赞2次,收藏2次。【代码】(vue)element-ui 表格实现勾选单选。_element ui单选框 打勾

Android实现部分文字可点击及变色_spannablestring clickspan 变色-程序员宅基地

文章浏览阅读1.4k次。可以使用SpannableString和ClickableSpan: TextView userAgreement = findViewById(R.id.user_agreement); SpannableString agreement = new SpannableString("Agree to the User Agreement and Privac..._spannablestring clickspan 变色

ollvm的ida trace操作笔记_ida trace 脚本-程序员宅基地

文章浏览阅读1.6k次。1.启动顺序操作记录1.把android_server push到手机里2.chmod 777 android_server3.adbforward tcp:11678 tcp:116784.ida->debugger->attach->arm-androddebugger5.再按f9把程序跑起来6.file->script_file->选择script.py加载ida脚本,成功后会有日志7.然后点击Debugger->breaklist里可以看到我们的断_ida trace 脚本

随便推点

ChatGLM2本地部署的实战方案-程序员宅基地

文章浏览阅读10w+次,点赞55次,收藏74次。本文主要介绍了ChatGLM2本地部署应用的实战方案,希望对学习大语言模型的同学们有所帮助。文章目录1. 介绍2. 配置环境 2.1 安装虚拟环境 2.2 安装依赖库3. 下载权重文件4. 运行ChatGLM2 4.1 方式一 4.2 方式二_chatglm2

r语言c1,R语言之主成分分析-程序员宅基地

文章浏览阅读568次。主成分分析R软件实现程序(一):>d=read.table("clipboard",header=T)#从剪贴板读取数据>sd=scale(d)#对数据进行标准化处理>sd#输出标准化后的数据和属性信息,把标准化的数据拷贝到剪贴板备用>d=read.table("clipboard",header=T)#从剪贴板读取标准化数据>pca=princomp(d,co..._r语言dcor什么意思

webGl学习-程序员宅基地

文章浏览阅读127次。开个新坑,不知道能不能做完学习地址:mdn地址浏览器支持范围:支持范围首先是创建一个容器,与canvas的canvas.getContext('2d')相似let canvas = document.getElementById('myCanvas');let gl = canvas.getContext('webgl');_webgl学习

基于大数据的音乐推荐系统的设计与实现-程序员宅基地

文章浏览阅读1.7w次,点赞20次,收藏328次。系统提供的功能有,音乐管理:管理员可以添加删除音乐,音乐查找:用户可以在系统中自行查找想要听的歌曲,音乐推荐:系统在收集了用户的行为数据之后为用户个性化推荐音乐,用户管理:管理员可以对用户进行删除,评论管理:管理员可以对评论进行删除,音乐下载:用户可以自行下载个人喜欢分歌曲。选择数据源要确定数据源数据是否可靠真实,要避免爬取音乐平台发布的虚伪的音乐数据,如不存在的歌唱家、专辑、音乐等。通过分析基于大数据的音乐推荐系统,即音乐推荐需要哪些数据,详细了解推荐机制,搞清楚这些数据需要被处理为什么格式。_基于大数据的音乐推荐系统的设计与实现

Nginx反向代理缓存服务器搭建-程序员宅基地

文章浏览阅读672次。Nginx反向代理代理服务可简单的分为正向代理和反向代理:正向代理: 用于代理内部网络对Internet的连接请求(如×××/NAT),客户端指定代理服务器,并将本来要直接发送给目标Web服务器的HTTP请求先发送到代理服务器上, 然后由代理服务器去访问Web服务器,并将Web服务器的Response回传给客户端:反向代理: 与正向代理相反,如果局域网向Internet提供..._o /usr/local/server/ngx_cache_purge-2.3/config was found error: failed to ru

layui用table.render加载数据 用table.reload重载里面的数据---解决table.render重新加载闪动的问题_layui table.reload 闪退-程序员宅基地

文章浏览阅读2.7w次,点赞4次,收藏30次。今天在用layui 展示数据的时候,首先想到了table.render这个插件进行数据的展示,因为数据要实时刷新,说到实时刷新,你最低要三秒刷新一次表格的数据吧!!!一开始写了个定时把table.render放到定时函数里面,三秒执行一次函数,那么问题来了,虽然效果是实现了,但这是重新加载表格啊,三秒闪一次,别说是用户了,我都看不下去了,闪的眼疼,就想有没有只让数据重新加载,表格不动。终于功夫不负..._layui table.reload 闪退