2011年11月4日星期五

bigbluebutton客户端flex分析- 初始化流程(1)

  作为flex的初学者,大致浏览的一下flex官方的视频教程,接下来就打算了解bigbluebutton的客户端了。进程远没有我当初想象中的那么顺 利,经常的都会碰到一些问题。相信在解决一个个问题的过程中,会慢慢的熟悉flex和这个产品。通读文档肯定是来不及,时间紧迫,很多不清楚的地方就查阅 一下资料,然后自己推测或猜测的,可能会有些不对的地方,但有需要的时候一定会查阅资料弄清楚问题。


  首先从启动开始,客户端已经通过flex build编译通过,但是启动的时候并没有显示加载的进度条,而是卡在了初始画面,为了找到原因,只有探索源码。第一步,要知道flex程序的入口在哪里,一个flex程序可以有很多mxml和as文件,但是包含Application只有一个,这个Application在mxml中用来标识,把鼠标移到到其上,可以看到其对应的as类mx.core.Application。

  flex程序感觉写起来要敲很多的字符,并不简洁,也不明了。可以看到BigBlueButton实际上就只做的下面几个事情:

  1. 声明pageTitle为"BigBlueButton"。
  2. 声明应用程序的布局采用绝对布局的方式。
  3. 构造了一个ResourceUtil对象,处理i18n。
  4. 声明了IDragManager,可能是支持窗口拖动?不太清楚,先跳过。
  5. 声明了HistoryManager,绑定浏览器的前进后退操作?不太清楚,先跳过
  6. 声明了一个私有的handleChatEvent,没有看到有引用的地方,函数体里面也是打了一条trace,不太清楚,先跳过
  7. 然后声明了一个ApplicationEventMap,这个是mate框架相关的,定义了一些事件处理的映射关系。不太清楚,先跳过
  8. 声明了一个MainApplicationShell,估计也是和mate框架相关,定义了app的视图。不太清楚,先跳过
  9. 在application中,可以看到有一个preloader的属性,其中指向了"org.bigbluebutton.main.model.BigBlueButtonPreloader",这里有点类似js, BigBlueButtonPreloader是一个as文件。

  由此可以看到,入口的地方应该是顺着preloader往下走,接下来看看BigBlueButtonPreloader都干了些什么。

  可以看到有一个“import flash.display.Sprite;”查阅了一下“在不使用 Flash 动画时用这个 Sprite ,Sprite 是轻量级的容器,不包括时间轴的容器,比 MC 小一些,更少占用内存(系统资源)。”

  下面这两个应该就是显示进度条相关的,RSL(Runtime Shared Libraries)。
  import mx.events.RSLEvent;
  import mx.preloaders.DownloadProgressBar;

  然后定义了一个继承自DownloadProgressBar的类并自定义了一些显示的字符串。这里好像没看到有什么特殊的逻辑。

  接下来再看MainApplicationShell,这里主要是定义了UI视图,最外层的是一个VBox,可以看到VBox有一个creationComplete属性,指向一个initialzeShell()函数。

  再下面的一系列的声明了一系列的事件监听器,先跳过。

  再下面是,这个也先跳过,再后面分析了mate框架就明白了。

  里面是as脚本,定义了上面的事件监听器函数,基本上都是根据事件来更新UI显示的。

  再往下就是一些UI的布局了:MainToolbar,然后是MainCanvas,在MainCanvas中定义了LoadingBar和BrandingLogo,其中BrandingLogo(.mxml)中可以添加自己Logo图片。再往下就是ControlBar,下面是copyright和一个log按钮(可以打开调试窗口看日志)和reset layout窗口。

  看到这里,都还没什么头绪,为什么会freeze住,但是从上面发现可以打开调试窗口,显示日志,接下来再来一次,进度条显示为"connecting to the server",难道server没连上?打开调试窗口,可以看到,语言和模块都已经加载成功,并且已经能够联通rtmp服务器,最下面显示:

11/3/2011 15:44:02.980 [DEBUG] JoinService:load(...) http://64.104.177.100/bigbluebutton/api/enter
11/3/2011 15:44:03.396 [DEBUG] Join FAILED =
  FAILED
  Could not find conference null.


加会失败?为什么刚开始登录的时候就会加会?从日志里面看到对应的url地址为:http://64.104.177.100/bigbluebutton/api/enter,想到之前修改过config.xml,其中有一项是,这里我是修改过的,最初的值不太记得了,但是好像官网上说如果要调试运行,要将host修改一下,好像和join-mock有关系,但是当时感觉官网没说太清楚,再查阅一下吧,又看了一下,只是提到了要用这个替换掉,另外有些帖子说join-mock文件没更新,连不上freeswitch。猜测这个join-mock应该是模拟http://64.104.177.100/bigbluebutton/api/enter的返回值,但是为什么用flex编译调试就有问题,直接从浏览器打开就没问题呢?看来还得继续再分析。

首先第一步就要看哪里会读取config.xml配置了。搜索到了,这个在ApplicationEventMap.mxml文件中引用了,下面还有一行,不清楚是做什么的,joinResultMock.xml这个文件不存在。


另外再搜索join-mock.xml,可以看到这个在JoinServiceTest.as文件中引用,这个看起来像是Testcase的程序,怎么会跑到这里来?再搜索一下JoinServiceTest这个类,看看哪里有引用到,查了一下,只有在UserTestSuite.as中引用到了。

后来发现config.xml还有一处地方引用到了,ConfigParameters.as,应该就是这里了。可以看到这里是远程的获取config.xml文件,从这里可以知道,我们可以动态的去配置config.xml,不需要重启服务,只需要刷新页面就可以让配置生效了。另外这里host配置项目读取后放置到public的变量host中去了,接下来就要去看哪里引用了这个类。ConfigParameters引用的地方倒是比较好找,但后面就不容易了,由于flex本质上也是一个事件驱动的,再加上这个项目使用了mate这个事件框架(我的理解是mate本质上是封装了flex底层的事件模型,使得各个模块之间通过信号事件进行交互,来达到模块间解耦的目的,还没仔细看,现在的理解是这样的)。

这样单看代码不是特别容易,只好结合调试一起来看,但事件机制导致在不是特别熟悉代码的情况下调试也不是那么容易,因此要利用一切可以利用的信息,比如,在UI上面显示的一些状态提示字符。在最后一会,屏幕上显示了“Connecting to the server”,搜索了工程,发现这个在"en_US/bbbResources.properties"中 。这个文件是多语言中的en_US版本,看来多语言的支持是做在了客户端,并不需要从服务器去更新。接下来搜索“bbb.mainshell.statusProgress.connecting”,发现在LoadingBar.mxml中:

private function testRTMP(e:PortTestEvent):void{

//- Cannot get locale string this early in loading process
       this.label = 'Connecting to the server';  
      //ResourceUtil.getInstance().getString('bbb.mainshell.statusProgress.connecting');
}

这里应该就是对应的位置,可以看到多语言的资源还没加载完,所以这里用英文显示了,如果要做汉化,这里也是需要修改的地方。

可以看到最终浏览器中的flex应用给出的提示是"Sorry, we cannot connect to the server.",再打开log窗口,看到连的服务器是"64.104.177.100",刚换了一下网络,从公司网络切换到家里的网络了,地址已经变了,这个错误和之前出现的并不一样。


有点奇怪的是,本已经通过bbb-conf --setip修改了配置中的ip地址了,但是为什么还是错误的ip地址,难道不是从远程获取的(远程是修改了/var//www/bigbluebutton/conf下面的,并没有修改设置的dev目录下的,我已经将配置改为使用dev环境)?但是明明是URLRequest获取的啊,难道有cache?但是可以看到,代码中获取时加上了时间参数,以避免有cache,_urlLoader.load(new URLRequest(file + "?a=" + date.time)); 只有再调试一把了,看看Network Monitor窗口里的显示(多多少少觉得之前的flex视频教程的基础部分没白看,多少都能用到一些)。居然没有,还不清楚这个Network Monitor是怎么工作的,不过我猜测也就是hack了flex的SDK里面的网络操作。另外构造URLRequest的时候,并没有加上域名或ip的前缀,难道真的是访问本地文件(好像不应该访问远程的,因为现在调试运行时,远程ip都还没有)?先看看SDK说明。看URLRequest里最后一个例子提到:如果没有域名或ip,那这个文件应该就是当前flash的文件所在目录的相对位置,但是bigbluebutton.swf在bin目录下,下面的conf/config.xml配置的是192.168.1.102,应该是没有使用这个配置,我怀疑调试运行的时候,默认的工作目录就是BigBlueButton.mxml所在的目录。当然这是我的猜测,网上还没找到相应的说明。先修改了试试先。如果改了还不行就可能是cache的原因了。

经过修改后,重新运行发现配置生效了。真是在摸索中前进,都是苦力活。好了,现在回到了之前的bug,


11/3/2011 22:02:17.954 [DEBUG] JoinService:load(...) http://192.168.1.101/bigbluebutton/api/enter
11/3/2011 22:02:18.063 [DEBUG] Join FAILED =
  FAILED
  Could not find conference null.


接下来看日志,看起来JoinService是一个加会的服务,怎么会跑到这里来,一开始就加会了?哦,好像是的,demo打开的那个web页面是html的,不是flash的。


那这个问题看来是清楚了,加会但是参数不对,会议根本就不存在。接下来要看看的就是加会的api和对于的官网文档里面提到的那个join-mock文件怎么使用的了。

至此为止,为什么用'conf/join-mock'来替换掉之前的那个url(http://192.168.1.101/bigbluebutton/api/enter)就很清楚了,join-mock直接返回了一个mock的会议信息。

好了,经过验证已经可以成功加会了。是的,如果我按照官网的说明,根本不会遇到这些乱七八糟的问题,但是,通过解决这个问题,让我对bbb-client端的代码有了一个初步的熟悉,特别是我这种一行flex代码都没写过的人来说,我感觉已经找到那么一点门路了。

接下来还得继续写,因为还没有开始写正题 - 初始化的流程,但上面是一个不错的开端。再继续努力吧。





 




没有评论:

发表评论