28
2015
01

webview中使用swf的各种坑

有一个安卓平板上的项目,打算用webview加载flash来实现,由于之前没有做过,就开始各种搜索和尝试。webview里边单纯播放swf还是很好实现的,在深入一点就各种坑了。

其实webview就是一个简单的浏览器,实际上就是在安卓里自己做了一个浏览器,用浏览器加载页面来显示flash 。

首先是实现交互,as与js的交互,以及as与java的交互(java和js的交互比较简单了)。

1、第一个坑,as与js的交互——安全沙箱问题。

用webview直接加载swf,相当于在本地打开浏览器,来播放swf文件,是存在安全沙箱问题的。pc上我们可以设置本地信任来解决(看到有人说这种方法也有可能会有问题,只是我还从来没遇到过),平板上就不知道怎么设置了,而且也不可能去设置用户的平板。

对于这种安全沙箱问题,无非是两种方案:1本地信任、2放到服务器上。

本地信任不知道是否可行,通过java程序来设置,没有尝试过;用的第二种方法解决的。当然解决过程没有这么一帆风顺,经过了长时间的摸索才成功的,问题能够解决,主要受益于天地会论坛的一篇帖子。好在java实现一个http服务器还是很简单的,一个类就解决了。

这样,as和js就可以交互了,js和java是可以交互的,所以as和java也就可以交互了。as和java交互经过了js中转,效率是必要下降,具体还有根据实际要求来,进行模拟测试才能决定是否可行。还有一种方法实现as和java的交互,就是使用socket,不过这样就需要再在安卓机程序里实现一个socket服务器,实现起来也比较简单,实际通信可能要麻烦一点,双方都要处理socket消息,还要约定消息传递方式,而且socket是异步的,不过一次做好了是一劳永逸的事。用socket通信还有一个坑,就是策略文件的问题,swf首次访问socket服务器的时候会请求843端口,寻找策略文件,找不到的话,会从请求的端口继续获取策略文件,如果还球球不到,就会报错,所以服务器需要给swf返回一个策略文件,有些设备843端口是禁用的,所以最好两个端口都能返回策略文件,具体可以自己从网上搜,例子还是很多的(需要java来实现,作者不懂java)。

两种方式各有利弊,自己酌情选择。我更倾向于第一种方式,虽然牺牲点效率(效率究竟如何,需要自己测试),但是做起来很简单。最主要的是能满足要求,自己完全能把握住。

2、第二个坑,单击变双击。

swf里边用的click事件,在pc上正常,放到安卓设备上,单击就变成了双击,每点一下,就会有两个click事件。自己做的推箱子,可以在安卓设备上试一下

这么明显的bug都能一直存在,flash在移动设备上支持不好也不能只怪adobe了。

发现了问题就要想办法解决,试了试用js来屏蔽掉所有的事件,只留一个mouseDown,可行,只是不知道各种浏览器是否都能用(最烦浏览器的兼容性问题)。

具体代码是这样

  1. //swf.onmousedown=a;

  2. swf.onclick=a;

  3. swf.onmousemove=a;

  4. swf.onmouseup=a;

  5. function a(event){ 

  6. event.preventDefault();

  7. return false;

  8. }

mousemove和mouseup应该不会有影响,可以自己试试。

3、第三个坑,平板上点击响应慢

手指在按钮上点下去,抬起来,又过了“好长时间”按钮才响应,安卓平板上是这样,手机上没问题。

一开始以为是swf效率低,卡了,后来看了看帧频,能有50多帧,根本不是卡造成的;又用html做了几个按钮试了试,发现一样响应慢。

搜索之后才知道,这是触屏设备本身机制造成的,在触屏设备上,touch才是原生的,mouse事件都是转发的。

网上说,有一个300毫秒的延时,是为了等待双击全屏,禁用缩放就好了,可能真的有用,但是实际上禁用了,效果还是不行,尤其是swf里边根本感觉不到有任何改善。

测试发现,不同的浏览器响应的速度和频率都不一样,而且同为安卓设备,手机就可以,平板就不行。个人认为应该能通过修改webview的源码,或是调用webkit的api来解决。但是作者不懂安卓开发,就无从下手了。

后来发现,mouse事件是有延时的,但是touch事件是实时的。如果是页面的话,可以把用mouse事件的地方全部改成响应的touch就好了,这个从网上可以搜到。但是只适用于html+js,swf还是不适用。flash发布成apk的时候可以用touch事件,但是发布成swf的时候touch事件不起作用(官方api里没有注明touch只是用于air,所以不知道是不是能够实现,只是作者不会用)。

估计很少有人用webview加载swf,还要实时互动,所以网上很难找到相应的资料。


好在作者比较熟悉as,既然js的touch是实时的,那么就用js侦听touch事件,获取点击的坐标,通过函数传递给flash,然后flash内部通过传入的坐标,自己实现各种鼠标事件。

为了方便,flash内部侦听依然使用原生的鼠标事件,自己只需要根据传入的坐标,捕获到发送事件的对象,然后让该对象发送事件。相当于屏蔽flash事件的捕获和目标阶段(作者是直接在页面中flash上边盖了一个div),然后自己来实现。

经测试,自己捕获target对象,以作者电脑为准,大约耗时是0.01-0.06毫秒,元件嵌套或重叠越多耗时越长,其中0.06毫秒对应12个元件重叠的结果。而且作者没有进行优化,速度还是不错的。

这个问题是最麻烦的,而且没有找到一个好的解决方法。

上述方法虽然可行,但是会有隐患。比如:页面的缩放旋转,以及不同浏览器的不同显示效果,导致js获取到的坐标不准确。所以最好是固定大小,并锁定横屏或竖屏。


暂时就这么多。其他一些小坑就不提了。自己遇到了也容易解决。

自己实现鼠标事件的捕获,还可以用在其他地方,比如屏蔽页面上的鼠标事件,然后用代码控制鼠标的动作。做在线教学或者只是娱乐,也挺有意思的。

air+ane的方式应该可以,但是ane实在不好用。

安卓上不能像pc上一样直接加载播放swf的控件,还要经过浏览器,确实不方便。也有用flash发布成apk然后和安卓开发的程序进行交互的。有时间研究研究这种方法。


没有源码,有问题一起交流。

« 上一篇下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。