2

About Mobile Widget

Posted by admin on September 12, 2011 in Android, WebKit, Widget, 软件架构

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283

Widget与移动设备

Widget是什么

Widget是一个广泛的概念,从其字面意思可以翻译成小物件,小工具,小软件。Widget的实现可以多种多样,但是都有一个共同特性,即可以源码复用。换句话说,Widget软件只要开发一次,便可以在具有该Widget运行引擎平台下完美的运行,具有完全一样的功能,UI风格和用户体验方式。

从Widget的实现方式上来说主要有两种,一种是基于DHTML, JAVASCRIPT和CSS技术的Widget。另一种是基于Adobe Flash技术的Widget。目前大多数Widget实现还是基于前者,尤其是目前日渐流行的移动设备上的Widget技术均指Web Widget。

Widget的特点

  1. 小尺寸:Widget的尺寸通常都不大,并且运行速度比较快,占用的系统资源也较少。
  2. 形式多样:Widget的展现方式可以多种多样,可以是一个悬浮在窗口里的小图标,可以是占用全屏的全屏应用,也可以是插入某个应用子窗口中的小程序。
  3. 功能多样:Widget应用可以提供的功能可以多种多样(依赖Widget引擎提供的功能),如提供新闻资讯阅读,视频观看,系统状态监视,天气预报,股票信息,时钟,联系人管理,短信接收发送等。
  4. 美观:Widget应用设计的一般都比较漂亮,并且具有很好的用户体验和操作方式。
  5. 个性化强:由于Widget的小尺寸和多样的形式和功能,因此用户可以随意的安装、摆放和设置Widget,达到个性化的Widget展示和使用效果。
  6. 开发方便:由于大多数Widget都是基于Web技术或者Flash技术,并且这两种技术都已经发展成熟,提供大量的集成开发环境以及可以复用的代码。因此,开发人员可以很快速的开发出功能强大、界面美观的Widget应用。

Widget应用

  1. 桌面电脑上的Widget
  • Yahoo Widget
  • Mac OS dashbord
  • Windows Vista侧边栏
  • Windows 7桌面小工具
  1. 移动终端上的Widget
  2. 个性化首页中的Widget
  • Netvibes
  • iGoogle
  1. 博客中的Widget

移动平台上的Widget规范(Web Widget)

目前,移动平台上支持的Widget运行环境主要遵循三套规范:W3C Widget规范、BONDI Widget规范和JIL Widget规范。

  1. W3C Widget规范

该规范是由W3C组织制定,包含6个子规范,主要定义了Widget的运行时状态,打包和配置,数字签名,自动升级,以及核心API和事件处理。

  1. BONDI Widget规范

该规范由OMTP组织制定,对W3C Widget规范进行了扩充。严格定义了Widget的安全验证体系,丰富了API接口。目前W3C组织考虑将BONDI规范纳入到标准中。

  1. JIL Widget规范

该规范是由中国移动、沃达丰、软银以及Verizon共同提出和定义的Widget规范。该规范目前主要是被中国移动的BEA平台所支持。

Widget引擎

Widget引擎的作用

Widget引擎为安装、运行、管理、升级,验证Widget应用提供了一整套完整的框架体系。

  1. 安装

Widget的发布方式可以多种多样,可以是基于Web页面的发布方式也可以是基于安装包的发布方式,因此Widget引擎需要对各种发布方式兼容,将用户的Widget应用安装和部署到当前的Widget运行环境中。

  1. 运行

Widget应用有其自身的生命周期(初始化,运行,暂停,恢复,终止),因此Widget引擎有责任管理每个Widget应用的生命周期,在Widget不同的阶段执行Widget内部定义的事件处理代码。

  1. 管理

Widget引擎负责像用户提供已安装Widget应用的管理功能,用户可以通过Widget引擎查看当前运行的Widget运行状态,占用的系统资源,终止应用,运行应用以及删除应用。

  1. 升级

Widget引擎会根据Widget的配置文件定期的检测Widget的版本,并且动态的更新Widget应用。

  1. 验证

出于安全性的考虑,Widget应用都需要进行签名,并且需要显示的声明其需要使用的特殊功能接口。并且在运行时刻,Widget引擎需要对Widget调用受限接口的合法性进行验证。

Widget引擎与浏览器的关系

由于Web Widget应用采用DHTML、JAVASCRIPT和CSS技术实现,因此运行Widget需要浏览器引擎作为支持。但是通常的浏览器引擎不足以支撑Widget的应用。比如:Widget规范中严格的定义了Widget的打包方式,尤其固有的配置和部署方式,通常的浏览器引擎是无法识别并且按照规范要求正确安装和部署的。某些Widget规范中定义了Widget应用对设备能力的访问,这也是通常浏览器引擎所不支持的。因此,如果浏览器需要支持某个特定Widget规范需要对浏览器引擎进行扩展,对Widget规范中定义的打包发布、升级安装、安全验证以及设备相关的API进行扩展和支持。

这里还有一类Widget不需要访问设备功能,并且并不遵循某套特定的Widget规范,而只是以Web页面中的一个小控件或者小程序形式出现,该Widget应用是不需要对浏览器做扩展。但由于没有一套标准统一的规范标准作为支持,因此只能由该站点开发者自己去设计并且开发,不具有广泛性。

Widget引擎框架设计

这里的Widget引擎框架主要是以Android平台上的Widget引擎的设计为基础,所支持的标准不限(可包括W3C,BONDI,JIL规范)。

Widget引擎框架

NewImage

  1. Widgets

如上图所示,Widget表示该Widget引擎所支持的各种Widget应用,该应用采用DHTML, JAVASCRIPT, CSS技术编写和实现。该Widget引擎所支持的Widget种类完全依赖于APIs Implement部分。

  1. Widget Module Loader

模块载入器的主要作用有两个:第一,负责各个已实现的Widget规范API模块的初始化。第二,负责在浏览器DOM树中注册载入的API模块对象,以使得Widget应用中可以使用相应的接口、对象和属性。

  1. Application Management

应用程序管理模块负责Widget应用的生命周期管理、应用程序的下载安装,以及应用程序的删除。应用程序管理模块与Widget DOM对象有紧密联系。比如:Widget应用在初始化阶段为resume事件注册了回调函数,在该函数中会对暂停时的应用数据进行恢复操作。应用程序管理模块在接收到Widget的恢复事件时,有责任调用该应用注册的resume回调函数,并且执行其定义的恢复操作。

  1. Security Management

安全管理模块负责Widget应用的安全验证。比如在Widget应用安装时,安全管理模块需要对Widget应用签名的合法性进行验证,并且对Widget声明的设备接口使用权限进行验证。当Widget运行时,Widget应用访问某个设备接口(比如Camera),安全管理模块需要对该应用是否有权访问该设备接口进行验证。

  1. APIs Implement

API实现包含了各个Widget引擎需要支持的Widget规范的底层实现。该部分的实现可以是纯JAVA实现、可以是JAVASCRIPT和JAVA混合实现、可以是JAVA和C/C++混合实现、亦可以是纯C/C++实现。

Widget引擎实现方式

基于WebKit引擎的扩展实现

该实现方式直接修改和扩展WebKit引擎,在引擎内部创建widget的DOM对象,并且提供抽象的调用方法。除此之外,需要在WebKit引擎中实现对各个规范模块的调用机制。

  1. 基于JAVA语言的模块调用

该实现方式需要对WebKit引擎实现JAVASCRIPT语言和JAVA语言之间的平滑调用机制。即Widget应用访问widget对象的某个API接口时,WebKit引擎需要将该SCRIPING对象动态的转换成相应的JAVA对象,并且调用其相应的方法。并且,将该JAVA方法执行后的结果动态的转换成JAVASCRIPT对象,并且返回给Widget应用。

采用该机制实现的API模块均用可采用JAVA语言来实现。因此,该实现方式具有实现速度快的特点,但是也正因为与JAVA语言的紧密关系移植性不好。

  1. 基于C/C++语言的模块调用

所有的API模块的扩展均采用C/C++语言来实现,这类似gears的实现方式。引擎内幕会将Widget应用使用的JAVASCRIPT方法动态转换成定义的C/C++对象,并且执行相应的方法。而后将返回结果转换成JAVASCRIPT方法返回给Widget对象。

采用该机制实现的API模块均采用C/C++语言来实现,因此开发周期相对较长,但是具有良好的移植性。

采用WebKit引擎扩展实现方式,可以让浏览器引擎原生的对Widget应用进行支持,但是在每次WebKit升级时,需要对修改的代码进行合并和再发布。

基于WebKit插件的扩展实现

该实现方式基于NPAPI插件扩展技术的基础之上。将Widget的DOM对象实现包含在NPAPI插件中,当浏览器检测到该对象的访问时,动态的载入该NPAPI插件,并且将所有对Widget DOM对象的访问操作均转发给NPAPI插件来完成。

NPAI插件的实现方式如WebKit引擎扩展实现一样,也有JAVA和C/C++两种实现方式,这里不再重复。

采用该实现方式的扩展无需对WebKit引擎修改,但是需要按照NPAPI规范,实现完整的SCRIPTING插件。

基于C/S架构的扩展实现

该实现方式采用借用了C/S设计模式的思想。在Widget引擎初始化阶段会启动一个内部的服务,该服务会监听系统中某个端口。Widget引擎运行时,如果访问Widget对象的某个方法时,封装的Widget JS对象会向服务端口发送方法请求。服务端接受请求后,首先会对请求进行合法性验证和分析,然后调用相应的接口来完成实际的操作。并且将结果以异步的方式返回给封装的Widget JS对象,而由该对象通知Widget应用操作结果。

C/S架构的扩展实现也可以采用JAVA和C/C++实现方式,这里不再重复。

采用该方式实现的扩展有良好的灵活性,不同的Widget规范定义的Widget应用只需要包含相应的Widget封装JS包即可正确运行。但是由于采用C/S模式的调用方式,因此在执行效率上略低于直接调用的方式。

Browser&Widget

这部分对Browser的设计提出一个概念层面上的设计。如下图所示:


NewImage
  1. Table Manager

负责管理浏览器中各个Table页面,每个Table页面是一个独立的Web页面或者Widget应用。

  1. Bookmark Manager

负责管理书签,该书签包括用户收藏的网站URL以及喜爱的RSS频道和文章信息。

  1. RSS Manager

负责RSS频道的订阅、RSS新闻列表、RSS频道退订

  1. Plugin Manager

负责管理已经安装的浏览器插件

  1. Notification Manager

负责事件通知管理,比如RSS新闻数据的更新通知,浏览器插件的升级通知,Widget升级通知等。

  1. History Manager

负责记录当前Table的运行数据,包括访问的URL历史,当前窗口大小位置信息,可用于当浏览器crash后的状态恢复操作。

  1. Download Manager

负责浏览器的下载管理,包括android软件的下载、安装,Widget软件的下载、安装

  1. Gesture Manager

负责手势操作的自定义操作管理。

  1. Thread Manager

为了加快浏览器的载入效率,每个Table在一个单独的线程中运行,因此对线程的运行状态需要一个统一管理机制。

  1. Skin Manager

负责Browser外观的管理,用户可以通过该模块动态的给系统更换皮肤和显示方式。

  1. Widget Manager

负责Widget引用的下载、安装、删除、以及运行时环境的支持。



Post Footer automatically generated by wp-posturl plugin for wordpress.

Tags: , , , ,

 
1

[Toy] 获取土豆FLV下载地址的小工具

Posted by admin on December 8, 2010 in Toy

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283

一个获取土豆FLV下载地址的小工具,使用方法也比较简单:
前提条件,你必须安装了JAVA JRE 1.5以上的运行环境

1. 访问欲下载的土豆视频连接
2. 点击视频下方的转帖到博客或BBS
3. 拷贝FLASH代码的连接(例如:http://www.tudou.com/l/9Uby2NgANWI)
4. 运行下面的命令
java -jar FLVParser.jar -t http://www.tudou.com/l/9Uby2NgANWI
得到如下下载连接:

http://124.232.157.18/f4v/65/65364165.h264_1.f4v?80000&key=a7111b24f706743495ab584cff1934fe94f5d5&playtype=1&tk=476898256&brt=2&id=tudou&itemid=38111542&fi=65364165&sz=243731218

http://180.137.254.12/f4v/65/65364165.h264_1.f4v?80000&key=a7111b24f706743495ab584cff1934fe94f5d5&playtype=1&tk=476898256&brt=2&id=tudou&itemid=38111542&fi=65364165&sz=243731218

5. 使用你喜爱的下载工具下载FLV视频即可

下载地址


Post Footer automatically generated by wp-posturl plugin for wordpress.

 
0

[Toy] 一个将指定URL的页面数据保存成图片的小工具

Posted by admin on December 8, 2010 in Toy

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283

这个小工具功能比较简单,将指定的URL的页面的DOM元素保存成图片文件。
—————————————————————————–
Usage: WebPageCapture –url=http://www.example.org/ –out=localfile.png
—————————————————————————–
–help Print this help page and exit
–url= The URL to capture (http:…|file:…|…)
–out= The target file (.png|bmp|jpeg|emf|…)
–html= Output HTML file
–class= Mark specified class name element
–bg= Background image path
–id= Mark specified id element
—————————————————————————–
http://www.jjos.org – (c) 2010 Jiang Jiang –

下载

下面附上一张抓去取的新浪网首页图片


Post Footer automatically generated by wp-posturl plugin for wordpress.

 
0

构建XCode免证书开发环境

Posted by admin on November 27, 2010 in Apple

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283

写在最前面
如果你和我一样,是一名爱好iOS开发的开发者,并且又舍不得花费99美金去购买一个合法的开发License,这篇博客则非常适合你。如果,您是一位已经获得Apple开发者证书的开发者,则可以完全无视该篇Blog。

开篇
在没有证书的情况下,开发iOS应用程序只能在功能有限的模拟器环境中运行你的应用程序(x86环境)。对于那些与硬件平台关系不大的iOS应用程序开发来说,模拟器环境可以模拟大多数功能,但是一旦你的应用需要涉及实际的硬件设备(比如:摄像头,感应器等),则模拟器就无法满足您的开发需求。拜股沟大神所赐,网路上已经早已有开发者用自签名证书的方式,绕开XCode的证书检查,可以将XCode编译的应用程序部署到实际的iOS设备上进行测试和调试。

生成自签名开发证书
1. 启动证书链管理工具(应用程序->实用工具->钥匙串访问)创建证书
wpid387-PastedGraphic-2010-11-27-16-45.gif

  1. 设置证书名称设置为iPhone Developer(该名称需要和XCode编译签名时使用的证书名称一致,下文会提到),身份类型选择自签名根证书,证书类型选择S/MIME (电子邮件),并且在覆盖这些默认值选项上打勾。

wpid388-PastedGraphic1-2010-11-27-16-45.gif
选择继续制作自签名证书
wpid389-PastedGraphic2-2010-11-27-16-45.gif

  1. 设置证书有效期365天(时长不要超过365天)

wpid390-PastedGraphic3-2010-11-27-16-45.gif

  1. 输入用户信息

wpid391-PastedGraphic4-2010-11-27-16-45.gif

  1. 选择密钥大小和算法(2048位和采用RSA算法)

wpid-PastedGraphic5-2010-11-27-16-45.gif

  1. 设置密钥扩展功能(选择签名功能和代码签名功能)

wpid-PastedGraphic6-2010-11-27-16-45.gif
wpid-PastedGraphic7-2010-11-27-16-45.gif

  1. 禁止基本约束扩展

wpid-PastedGraphic8-2010-11-27-16-45.gif

  1. 设置主题设备用名称扩展,RFC822输入邮箱即可

wpid-PastedGraphic10-2010-11-27-16-45.gif

  1. 设置钥匙串类型为登陆类型

wpid-PastedGraphic11-2010-11-27-16-45.gif
至此,自签名证书创建完毕

Hacking XCode
1. 绕开XCode证书检测(以下代码在终端执行)
#!/bin/bash
cd /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS\ Build\ System\ Support.xcplugin/Contents/MacOS/
dd if=iPhoneOS\ Build\ System\ Support of=working bs=500 count=255
printf “\x8f\x2a\x00\x00″ >> working
dd if=iPhoneOS\ Build\ System\ Support of=working bs=1 skip=127504 seek=127504
/bin/mv -n iPhoneOS\ Build\ System\ Support iPhoneOS\ Build\ System\ Support.original
/bin/mv working iPhoneOS\ Build\ System\ Support
chmod a+x iPhoneOS\ Build\ System\ Support

mkdir /Developer/iphoneentitlements30
cd /Developer/iphoneentitlements30
curl -O http://www.alexwhittemore.com/iphone/gen_entitlements.txt
mv gen_entitlements.txt gen_entitlements.py
chmod 777 gen_entitlements.py

  1. 设置PROVISIONING为禁止证书

在/Developer/Platforms/iPhoneOS.platform/Info.plist中增加如下两个项目
PROVISIONING_PROFILE_ALLOWED 设置成 NO
PROVISIONING_PROFILE_REQUIRED 设置成 NO
并且,将该文件中的XCiPhoneOSCodeSignContext字符串替换成XCCodeSignContext

  1. 使用XCode打开你的项目文件,在Project->Edit Project Setting中选择Build页面,找到Code Signing Identifty选项,将签名设置成iPhone Developer
  2. 修改项目的xxx-Info.plist文件,添加SignerIdentity,将其设置为Apple iPhone OS Application Signing
  3. 在Project->New Build Phase->New Run Script Build Phase的script部分,输入下面的代码

export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate
if [ "${PLATFORM_NAME}" == "iphoneos" ]; then
/Developer/iphoneentitlements30/gen_entitlements.py “my.company.${PROJECT_NAME}” “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/${PROJECT_NAME}.xcent”;
codesign -f -s “iPhone Developer” –resource-rules “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/ResourceRules.plist” \
–entitlements “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/${PROJECT_NAME}.xcent” “${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}/”
fi

  1. 选择项目部署的目标为Device
  2. 打开Window->Organizer,选择实际需要测试的设备平台(我这里是iPad)
  3. 点击XCode的Build and Debug按钮,在设备上部署和运行应用程序

Post Footer automatically generated by wp-posturl plugin for wordpress.

Tags: , ,

 
0

青春如同奔流的江河,而生活像一把无情刻刀

Posted by admin on November 17, 2010 in Uncategorized

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283

不想多说什么,一切都在短片中。。。

那是我日夜思念深深爱着的人呐
到底我该如何表达
她会接受我吗
也许永远都不会跟他说出那句话
注定我要浪迹天涯
怎么能有牵挂

梦想总是遥不可及
是不是应该放弃
花开花落又是雨季
春天啊你在哪里

青春如同奔流的江河
一去不回来不及道别
只剩下麻木的我没有了当年的热血

看那漫天飘零的花朵
在最美丽的时刻凋谢
有谁会记得
这世界她来过

转眼过去多年时间多少离合悲欢
曾经志在四方少年羡慕南飞的燕
各自奔前程的身影匆匆渐行渐远
未来在哪里平凡啊谁给我答案

那时陪伴我的人啊
你们如今在何方
我曾经爱过的人啊
现在是什么模样

当初的愿望实现了吗
事到如今只好祭奠吗
任岁月风干理想
再也找不回真的我

抬头仰望着满天星河
那时候陪伴我的那颗
这里的故事
你是否还记得

生活像一把无情刻刀
改变了我们模样
未曾绽放就要枯萎吗
我有过梦想

春如同奔流的江河
一去不回来不及道别
只剩下麻木的我没有了当年的热血

看那漫天飘零的花朵
在最美丽的时刻凋谢
有谁会记得这世界她曾经来过

当初的愿望实现了吗
事到如今只好祭奠吗
任岁月风干理想 再也找不回真的我

抬头仰望着满天星河
那时候陪伴我的那颗
这里的故事你是否还记得
如果有明天 祝福你亲爱的


Post Footer automatically generated by wp-posturl plugin for wordpress.

 
0

Tomorrow is just another day

Posted by admin on November 16, 2010 in Apple

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283

刚刷新苹果的官方主页,发现下面一张页面,难道明日苹果ios 4.2即将发布么?期待中…


Post Footer automatically generated by wp-posturl plugin for wordpress.

Tags:

 
0

iPad把玩-初体验

Posted by admin on November 2, 2010 in iPad

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283

从老乔手握iPad出现在Apple新品发布大会的那一刻起,iPad华丽的外观、强大的功能以及App store上数以千计的高质量应用就深深的吸引了我。在我毫无意识的情况下,又一次被拉入到老乔的“陷阱“中。经过半年时间的关注,最终还是决定入手一只iPad。

从iPad发布之初公布的尺寸大小(242.8×189.7×13.4mm)以及相关的视频上看,iPad的尺寸是相当薄的。但是一直只是一个概念性的认识,直到第一次拿到iPad真机后,才惊叹Apple竟然可以在不影响功能、效率的基础上将iPad作的如此只薄,真的不得不佩服Apple的工艺水平。下面从拿到iPad后把玩的过程,来介绍一下这个新增神器。

iPad配备了9.7英寸大小的电阻式多点触摸显示屏,由于其运行的系统和iPhone/iTouch一样,并且其外观类似,因此之前很多网上评论文章都将其比为打好iPhone/iTouch。但是,在实际的把玩过程中发现,iPad的大屏幕的用户体验感受是iPhone/iTouch的小屏幕无法比拟的。比如,在iPhone/iTouch上打开一张页面,要想导航到目标区域可能需要做多次的放大,移动等滑动操作。而在iPad上的体验确大为不同,由于其9.7寸屏的优势,可以让整个网页内容尽收眼底,并且不需要做很很多(甚至压根不需要)滑动操作即可浏览到想要的信息。处理器方面,iPad采用了自家设计研发的A4 SoC处理器,主频是1GHz。电池采用25Whr的俚电,按照老乔的介绍,该电池可让iPad续航10个小时,但是按照我实际的使用时间来计算,一共使用了16.5小时后,系统剩余电量还有25%。在这个过程中主要是进行iTunes同步,网页浏览,QQ,邮件,RSS,越狱等操作,这让我对iPad的续航能力非常满意。Flash容量有16G,32G和64G三种规格。内存大小是256MB。由于我没有做实际的称量,按照前人的评测说,整体重量0.73公斤。虽然感觉很轻便,但是在实际的使用过程中发现,长时间的手握iPad会感觉   1. 安装iTunes和注册iTunes美国免费帐号

拿到iPad后的第一件事情是安装iTunes,然后注册一个美国的iTunes帐号。关于如何注册美国免信用卡帐号的方法网络上有很多介绍,这里不做详细说明,可以参考weiphone网的这篇注册介绍文章:

http://bbs.weiphone.com/read-htm-tid-205881.html

2. 同步和备份iPad

当iTunes安装完毕后,使用刚才注册的美国帐号登录App Store,后将数据线插入iPad,这时iTunes会自动弹出检测到iPad的对话框,并且提示用户输入该iPad的名称。点击确认后,就可以在iTunes中看到iPad的当前名称,序列号以及系统的版本号。这时,右键点击iTunes左边栏的iPad图标,选择备份,即可将iPad中的数据备份到PC端。

3. 获取和保存SHSH

获取SHSH的工具,当然是传说中的umbrella,备份的过程全图形化操作,很简单。可以参看下面这篇文章:

http://ifan.178.com/thread-690979-1-1.html

4. 越狱

并不是说不越狱iPad不能使用,App Store上为iPhone/iPad/iTouch提供了很多免费的应用供下载。但是一些主流、优秀、功能强劲的Apple应用往往是需要出血的。而且,在没有越狱的情况下,一些辅助性的神器(backgrounder,activator等)都是无法使用的。因而,对于我个人来说越狱是必须的,可以让我更好的体验iPad上强大的应用程序以及功能。

我的iPad运行的是iOS 3.2.2版本,通过疯狂的Google后发现,网络上提供两个越狱软件-绿蛙、绿雨,以及大量的越狱教程(在这里,不得不感谢哪些无私奉献的DXJM们)。通读完大量的越狱文章,了解了越狱的大致步骤、可能出现的问题后。先是下载了绿蛙的最新版本,然后开始了我的第一次越狱。按照网站上的教程说明,启动绿蛙后软件再等待2秒以后,会提示用户按住POWER键,关闭iPad(大概持续3秒),然后提示用户按住POWER键的同时,按下HOME键,进入到恢复模式(整个过程大概持续10秒)。最后,软件会提示用户按住HOME键不放,松开POWER键(过程大概持续15秒)。当软件的越狱按钮变为可用时,松开HOME键,然后用鼠标点击软件上的越狱按钮进行越狱。此时,iPad会显示让用户插入iTunes连接线的图标。等待大概10-15秒以后,iPad会出现白色屏幕,然后出现Console界面。最后,iPad会关机,手工按住POWER开机后,按照教程上所说,应该在第2屏中出现Cydia的图标。在我疯狂的用手翻动iPad面板后,我失望了。iPad屏幕中只有默认屏和search屏,压根没有传说中的第2屏,更别说见到神奇的Cyndia图标了。继续关机重启数回以后,现象依旧,难道是越狱失败?

没招,这次转换工具用传说中的绿毒进行第二次越狱。不得不说,绿毒的用户操作要比绿蛙简便。不说别的,由于不熟悉越狱的按键过程,在使用绿蛙的时,几次都由于没有及时按照提示按键被要求重新尝试,而这点绿毒要作的好很多。打开绿毒界面后,按照提示一路走下去,最后会弹出一个对话框说明,表示越狱成功。此时,iPad屏幕上显示一个硕大的绿色水滴图标,并且风火轮开始神转。紧接着,iPad重启了并且一直停留在要求用户插入iTunes连接线的界面。按照界面提示,插入数据线后,iTunes提示,系统进入恢复模式,要求下载3.2.2版本进行恢复。神马?难道给刷挂了?不管了,点击了下载按钮后。将iPad关机了,然后再次使用绿蛙进行越狱。整个操作和上面过程一样,但是这次不同的是,越狱之后竟然iTunes找到iPad设备了(不再提示要求下载固件并且恢复了)。虽然,是可以进入系统了,但是依旧是没有看到Cydia图标。

就这样来回用绿蛙和绿毒越狱多次后,一次关机重启后发现神奇的第2屏出现了,而且屏幕上出现了绿毒和绿蛙两个图标,并且神奇的Cydia图标也出现了。后来,我在想,之前也许也越狱成功了,但是由于自己越狱心切,越狱在进行中时,由于没有提示,误认为是关机或者其他操作了,然后强制重启,导致越狱失败。

越狱教程可以参看:

http://ifan.178.com/thread-690450-1-1.html

5. 设置Cydia源,安装补丁

同样参看上面的越狱教程,里面有很详细的说明

最后,越狱完毕后就是疯狂的下载软件。至此,神器可以真正开始释放威力了。

~~~ END ~~~


Post Footer automatically generated by wp-posturl plugin for wordpress.

Tags: , ,

 
0

CSS 兼容一览表

Posted by admin on July 12, 2010 in CSS

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283


Post Footer automatically generated by wp-posturl plugin for wordpress.

Tags: ,

 
3

Introduce to WebKit2

Posted by admin on May 12, 2010 in WebKit, 浏览器, 软件架构

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283

WebKit2是为WebKit引擎而设计的支持单独进程模型的API层。将Web的内容(Javascript,HTML,布局等)处理与应用程序UI分离,分别运行在两个不同的进程之中。这种分离的进程模型和Google的Chrome浏览器有几分类似,不同的是WebKit2将从引擎内部原生的支持这种多进程机制。通过将内容和展现相分离的方式,可以更加有效的提高浏览器的运行效率。

WebKit2提供了一套基于C语言的非阻塞API接口,为了实现WebKit2引擎中对这些API接口的非阻塞调用,WebKit2在设计的时候采用了以下几个方面的技术:

  • 以通知的方式回调客户端函数(比如,didFinishLoadForFrame),通过这种机制可以告知client发生了什么事情(目前WebKit版本中也大量的使用了该技术,用来通知client事件的发生)
  • 以策略方式回调客户端函数(比如,decidePolicyForNavigationAction),当引擎执行某一项操作时,通过该机制由实现具体功能的client来决定是否该操作被执行。
  • 策略设置(例如WKContextSEtCacheModel, WKContextSetPopupPolicy),该机制允许client重新定义策略,而不需要再通过回调的方式访问UIProcess。
  • 代码注入(例如,WebBundle),当所有其他的方法都无法完成时,可以通过代码注入的方式将代码载入到WebProcess中。不过按照WebKit官方文档所说,这个功能目前只是在计划中,还没有真正的在代码级实现。

WebKit的多进程架构

下图是之前webkit的进程架构图

从上图可以看到,之前的WebKit的ui进程和webkit内核进程都是运行在相同的进程空间。其中API Boundary表示和系统相关的api层,应用层使用webkit api使用webkit引擎,并且引擎使用该api访问系统资源。

接着,再看看新版的webkit2引擎的架构

从上图可以看到,webkit2将webkit引擎分成了2个部分,一个部分是和ui相关的操作,运行在一个进程中。而另外的webkit部分运行在独立的进程中。通过多进程机制的支持,增加了ui响应和引擎布的效率,同时也增强了系统的健壮性和安全性。

之前也提到,webkit2的多进程模型有点类似chrome的多进程模型,但是有一些不同之处,下图是chrome的进程模型:

从上图可以看到api bondary是在render进程的下方,也就是说ui绘制进程是在webkit框架之上扩展支持的。该部分的扩展是非webkit原生支持的,属于chromium代码的一部分,这导致无法在其他平台或者框架中支持多进程功能。

为了支持多进程的机制,在webkit中增加了两个新的子系统:

  • CoreIPC:为消息传递和事件处理提供支持。
  • DrawingArea:为交叉绘制区域提供了抽象。通过共享内存位图信息的方式,为多个进程绘制提供了支持。

目前,我只在Mac OS 10.6.3平台上编译并且体验了Webkit2,可以使用下面的方法加入多进程支持:

WebKitTools/Scripts/build-webkit –webkit2

~~~ END ~~~


Post Footer automatically generated by wp-posturl plugin for wordpress.

Tags:

 
1

Titanium 架构分析

Posted by admin on May 12, 2010 in 软件架构

如需转载,请注明出处!
WebSite: http://www.jjos.org/
作者: 姜江 linuxemacs@gmail.com
QQ: 457283


一、分析的目标

  1. 了解Titanium产品的基本框架结构和特点
  2. 了解Titanium产品如何扩展本地API以及访问方式
  3. 了解Titanium产品中的动态语言之间如何相互调用

二、Titanium概述

2. 1 Titanium介绍

Titanium是一个Web应用程序运行环境,它支持不同的系统平台(WindowsLinuxMac),并且支持Web应用程序对本地APIs的访问。在基于Titanium平台上,用户可以快速开发和方便的部署应用程序,并且这些应用程序可以使用本地APIs实现许多普通Web应用程序无法完成的功能和特性。

2.2 Titanium特点

Titanium框架具有如下几个方面的特点:

  1. 支持多平台(LinuxMacWindows、移动设备)
  2. 使用Web技术加快软件开发速度
  3. 支持Web中内嵌多种编程语言
  4. 支持对本地APIs的访问
  5. 通过Appcelerator网络云服务,基于Titanium的应用可以更容易的打包、测试和部署
  6. 本地功能的模块化,可动态加载指定的功能模块
  7. 强大灵活的语言扩展,用户在Titanium框架中可以很方便的扩展多种动态语言

2.3 Titanium 框架结构

上图来自于Appcelerator官网,该图以iPhoneAndroid两个移动平台为例,描述了Titanium的总体框架结构。在Titanium框架中,Web应用程序可以很方便的访问设备UI组件。比如,可以在页面中使用Titanium提供的API控制导航条、工具栏、菜单,以及可以动态的向用户弹出对话框、警告框等。除此,之外Titanium API还支持本地功能模块的访问,即用户可以使用Titanium提供的APIs接口访问数据库、定位功能、文件系统功能、网络功能、媒体功能等。

不过该框架图,并没有将Titanium中对多种脚本语言的相互访问机制很好的表现出来。但是,这一机制却又是Titanium框架的一个比较重要的功能特性。

三、Titanium构建

Titanium的构建过程使用scons管理(http://www.scons.org/)。scons是一个开源的软件构建工具,使用Python语言来描述软件构建规则。通过Titanium的源码级构建和Titanium的构建规则两个方面,可以了解Titanium运行环境由那些部分组成、这些模块和模块之间的关系是什么。

[注]以下所有的测试和分析内容均是以Linux平台上Desktop版本的Titanium代码为基础。

  1. 构建Titanium所依赖的库和环境
  • Ruby 1.8.x 开发包
  • Python 2.5.x开发包
  • scons构建工具
  • git 版本管理工具
  1. Ubuntu 9.04上构建Titanium所需的支持包
    sudo apt-get install build-essential ruby rubygems libzip-ruby \
    scons libxml2-dev libgtk2.0-dev python-dev ruby-dev \
    libdbus-glib-1-dev libnotify-dev libgstreamer0.10-dev \
    libxss-dev libcurl4-openssl-dev 
    
    sudo apt-get install git-core
  2. 获取Titanium源码
    git clone git://github.com/marshall/titanium
    cd titanium
  3. 获取Kroll源码
    git submodule init
    git submodule update
    cd kroll
    git checkout master
  4. 构建Titanium测试程序
    cd ..
    scons debug=1
  5. 运行
  6. scons testapp debug=1 run=1

有关Titanium构建相关的信息,可以访问以下页面获得:

http://wiki.github.com/marshall/titanium/build-instructions

3.2 Titanium构建规则分析

3.2.1 版本需求

构建过程所需的库/程序版本
Python 2.5
Ruby 1.8
Scons 1.2
kroll 源码版本 12/30/99
titanium_desktop 源码版本 12/30/99
WebKit版本 libwebkittitanium-1.0.so.2.7.0

3.2.2 默认配置项

默认配置项
配置 备注
PRODUCT_VERSION 0.7.0
INSTALL_PREFIX /usr/local
PRODUCT_NAME Titanium
CONFIG_FILENAME tiapp.xml
BUILD_DIR build
THIRD_PARTY_DIR kroll/thirdparty
DISTRIBUTION_URL api.appcelerator.net
CRASH_REPORT_URL api.appcelerator.net/p/v1/app-crash-report
GLOBAL_NS_VARNAME Titanium 定义了全局Titanium对象名称

3.2.3 scons编译参数

Scons编译参数
debug 0表示release版本,1表示debug版本
clean 清除构建的工程
qclean 清除构建的工程
run 运行TestApp
run_with 带参数运行TestApp,好像Linux平台上没用

3.2.4 构建规则文件

构建规则文件
kroll/SConscript.thirdparty Titanium所需的第三方支持文件规则
installation/SConscript Titanium安装器构建规则
kroll/SConscript 构建kroll库规则
modules/SConscript 构建语言支持模块规则
apps/SConscript 构建TestApp规则
SConscript.dist 构建SDK规则
SConscript.docs 构建APIs文档规则
SConscript.test 构建测试程序规则

3.2.5 核心库和程序构建规则

/程序 规则
build/linux/runtime/template/kboot kroll/boot/breakpad/common/*.c

kroll/boot/breakpad/common/*.cc

kroll/boot/breakpad/client/*.cc

kroll/boot/breakpad/processor/*.cc

kroll/boot/breakpad/client/linux/handler/*.cc

kroll/boot/breakpad/common/linux/*.cc

build/linux/runtime/libkroll.so kroll/api/*.cpp

kroll/api/config/*.cpp

kroll/api/binding/*.cpp

kroll/api/utils/*.cpp

kroll/api/utils/poco/*.cpp

kroll/api/utils/linux/*.cpp

kroll/api/net/proxy_config.cpp

kroll/api/net/*_linux.cpp

build/linux/runtime/libkhost.so kroll/host/linux/host.cpp

kroll/host/linux/linux_job.cpp

/linux/modules/api/libapimodule.so poco third library(http://pocoproject.org/)

kroll/modules/api/*.cpp

build/linux/modules/javascript/libjavascriptmodule.so poco third library(http://pocoproject.org/)

webkittitanium-1.0 third library

kroll/modules/javascript/*.cpp

build/linux/modules/ruby/librubymodule.so poco third library(http://pocoproject.org/)

libruby third library

kroll/modules/ruby/*.cpp

build/linux/modules/php/libphpmodule.so poco third library(http://pocoproject.org/)

kroll/modules/php/*.cpp

四、Titanium静态分析

该部分主要是说明整个Titanium的阅读工作量、弄清楚Titanium中定义的核心对象的功能作用,以及各个模块之间的关系是什么。

4.1 代码统计

这里,将Titanium项目代码分成kroll和功能模块扩展两部分代码来统计,数据如下两表所示:

Kroll模块代码量统计
Language Files Blank Comment Code Scale Equiv
C/C++ Header 1168 35490
63506
111461
1.00
111461
HTML 386 1252 16112 51375 1.9 97612.5
C++ 162 6401 7046 33133 1.51 50030.83
Javascript 47 3273 1598 13214 1.48 19556.72
CSS 3 554 41 2720 1 2720
Object C 6 359 312 1400 2.96 4144
Python 10 260 185 1206 4.2 5065.2
Shell 11 56 157 234 3.81 891.54
Make 3 30 29 93 2.5 232.5
Assembly 1 15 39 57 0.25 14.25
Ruby 1 10 0 54 4.2 226.8
Yaml 1 0 0 12 0.9 10.8
SUM 1802 47938 89263 217012 1.35 293546.95
titanium_desktop模块(排除Kroll模块)
Language Files Blank Comment Code Scale Equiv
Javascript 118 5801 3276 28678 1.48 42443.44
C++ 125 4690 5169 27320 1.51 41253.2
C/C++ Header 159 1647 3443 7682 1 7682
HTML 49 347 39 3715 1.8 7058.5
Ruby 29 673 643 3227 4.2 13553.4
CSS 5 542 41 2655 1 2655
Python 45 601 664 2632 4.2 11054.4
C 1 167 237 1925 0.77 1482.25
Shell 13 60 158 251 3.81 956.31
PHP 5 37 1 179 3.5 626.5
XML 5 0 8 151 1.9 286.9
Object C 2 31 15 119 2.96 352.24
SUM 556 14596 13694 78534 1.65 129404.14

4.2 核心对象的介绍

对象 基类 说明
AccessorBoundObject StaticBoundObject settergetter的封装,当用户访问想访问XXX属性时,该对象会调用setXXX方法或者getXXX方法。目前Titanium中主要是JSTitanium对象使用AccessortBoundObject封装
AccessorBoundMethod StaticBoundMethod 用于通过属性的方式访问方法,由该对象封装的方法,会自动的导出settergetter方法
AccessorBoundList StaticBoundList 用于以属性的方式访问list对象,由该对象封装的list,会自动导出settergetter
ArgList 对参数列表对象的封装
Blob 对数据封装,可以描述任何数据
Tuplex 对元组对象的封装
DelegateStaticBoundObject KObject 用于对全局访问对象的封装,目前Titanium中只有UITitanium JS对象使用该对象封装
KList KObject 封装List对象
KMethod KObject 对方法的封装,所有扩展语言的函数,都需要用该对象封装
KEventObject AccessorBoundObject 描述事件对象,JS中可以通过该对象,向主线程发送事件。比如重新载入页面、弹出对话框。
KEventMethod KEventObject 对事件方法的封装,目前只有ti.Process模块使用该对象
KObject ReferenceCounted 所有的其他类型语言对象和方法都是继承该类,这样可以按照相同的方法处理不同语言对象和方法
StaticBoundList KList 静态列表,使用内部map绑定属性
StaticBoundMethod KMethod 静态方法
StaticBoundObject KObject 静态对象,继承该对象可以很方便的设置对象的属性、方法。

每个StaticBoundObject内部,都保存着一个StringShareValuemap成员属性。

Value ReferenceCounted 描述对象类型

4.3 模块之间的关系

从整体框架结构上来看,可以将Titanium分成三个部分,最上层是WebKit以及针对WebKit的扩展(修改很少),中间层是kroll可以将其看成是一个中间件,最下层是个个模块的扩展。模块之间的关系如图所示:

以下从WebKitKroll和模块扩展三个部分来说明

WebKit: WebKit引擎解析页面数据发现<script>标签,或者当用户触发了页面中某个与脚本函数相关的控件时,WebCore会将相应的脚本代码片段传递给JavascriptCore解析执行。如果对比Tinanium修改的WebKit代码和原始的WebKit代码(http://www.webkit.org)会发现,tinaniumWebKit的修改是及小的。主要是作了两个方面的工作:首先,tinanium扩展了KURL的处理,增加了ti://, app://等私有协议的支持。再者,在WebKit/gtk/webkit/目录中,添加了几个接口函数(主要是用来处理扩展的协议和注册解析器),其中最重要的是webkit_titanium_add_script_evaluator,该接口在Kroll模块的script类中会被调用,用来向WebKit引擎注册一个Evaluator Proxy

KrollBase Module:这部分主要的职责是负责Javascript的方法、对象和PythonRubyPHP等语言之间相互转换、事件处理,以及模块动态加载。Kroll模块中,定义了一个host对象,这个对象是整个TestApp的主线程,UI初始化、WebKit初始化和事件处理都是在host中完成的。host对象中保存了一个全局对象表,该表会在WebKit引擎、Python引擎、Ruby引擎之间以KObject中间对象形式相互传递,最终达到不同语言之间的相互调用。

API Extension:这里扩展了大量的与系统平台功能相关的APIWeb应用使用。其中最重要的一个对象是ti.UI,该模块负责UI相关的资源、事件处理、GTK主界面的创建、Tininum JS对象的创建。

五、Titanium动态分析

下面从6个方面以TestApp为例,来分析Titanium的主要特性和功能。

5.1 TestApp初始化

TestApp的启动过程有个自启动过程。首先,TestApp启动后会创建一个Application对象,该对象会从Mainifest文件中获取App相关的资源,并且保存在一个全局变量中。然后,TestApp会设置几个系统环境变量:

KR_BOOTSTRAPPED: 描述是否已经初始化环境变量以及构建Application对象

KR_HOME:描述运行程序的HOME路径

KR_RUNTIME:描述运行时资源路径

KR_MODULES:描述需加载模块信息

LD_LIBRARY_PATH:描述模块所在的文件夹路径

最后,TestApp会使用exec系统调用将自己自启,然后通过之前设置 KR_BOOTSTRAPPED环境变量判断是否进入下一阶段的初始化过程。如果 KR_BOOTSTRAPPED设置为YES,则会首先将其unset,然后启动LinuxHost

titanium框架中,使用动态库的方式将模块之间的关系解耦合。在TestApp启动的第二阶段中,StartHost(kroll/boot/boot_linux.cpp)会根据之前设置的 KR_RUNTIME路径信息,找到libkhost.so动态库,然后从libkhost.so中获取Execute函数指针,并且调用(这里有个问题,如果多个实列同时运行,有可能KR_RUNTIME尚未unset就启动第二个应用,则会出现TestApp异常)。

libkhost.so动态库中的Execute方法,首先创建一个Host实例,在这里是LinuxHost对象,然后调用该对象的Run方法进入一个循环。这个循环是整个TestApp的主循环,主要负责模块的动态发现和加载,事件处理。在LinuxHost的实现中,会维护一个job队列,通过定时器的方式,每隔250ms的时间会去检测该job队列中是否有job存在(LinuxJob描述)。如果,事件存在则会一次性将所有的事件取出,并且清空事件队列,然后一个个的执行job对象的Execute方法。

TestApp的两次初始化过程如下图所示:

5.2 模块初始化

TestApp程序创建LinuxHost对象,并且执行Run方法之后,会首先扫描KR_MODULES环境变量中指定的模块,并且从 LD_LIBRARY_PATH定义的路径信息中寻找到这些动态库模块,并且加载(调用相应模块的Initialize方法)。LinuxHost首先加载的是基本模块(APIPythonModuleRubyModulePHPModuleJavascriptModule)。

pythonModule为例,描述一个完整的加载过程:

  1. Host::LoadModules从环境变量中获取到python动态库的路径信息
  2. 调用Host::FindBasicModules方法,将libpythonmodule.so文件加载进来,然后调用PythonModuleInitialize方法
  3. PythonModule::Initialize首先会向全局属性表中创建一个PythonPythonEaluator对象的关联。前面也说到,Host对象会保存一个全局属性表,这个表中使用KObject中间对象形式,将JAVASCRIPTPYTHONRUBYPHP等语言定义的对象封装,并且保存在该表中。运行时,可以使用Host对象的GetGlobalObject方法获取。
  4. 调用Script::AddScriptEvaluator静态方法将PythonEvaluator对象放入Script对象中维护的一个Ealuator列表中。当JavascriptCore引擎发现<script>标签会遍历这个evaluator链表,通过MIME类型找到相应的解析器实例,然后将代码片段传递给相应的解析器处理(这样就可以支持HTML代码中内嵌多种语言)。

这里还有一个模块比较特殊需要仔细说明,即ti.UI模块。该模块负责WebKit引擎初始化,GTK窗口创建以及UI事件的处理。加载过程类似PythonModule,首先Host对象找到libtiuimodule.so动态库,然后调用Initialize方法初始化,ti.UI模块中的Initialize方法只做了两件事情,创建了一个APIBinding对象,然后将“API”属性和APIBinding关联起来,保存在全局属性表中。接下来,当Host::LoadModules方法加载完毕所有的动态库后,会调用Host::StartModules来启动模块(在整个TestApp运行中,只有ti.UI模块的Start方法被重载了,而其他模块在StartModules方法被执行时,什么事情都没有做)。UIModule::Start方法做了三个非常重要的操作:1、创建GtkUIBinding对象,并且将“UI”和该对象绑定,存放在全局属性表中。2、调用ScriptEvaluator::Initialzie()使用WebKit扩展中导出的webkit_titanium_add_script_evaluator函数,将自己注册到JavascriptCore中。3、创建初始化WebView

至此,WebKit引擎已经初始化完毕、UI界面已经初始化完毕、相应语言的解析器以及JAVACRIPT API扩展对象已经添加到全局属性表中。但是至此,页面中是无法正常访问Titanium对象的。

整个过程如下图所示:

5.3 Titanium对象的注册

Javascript中的Titanium并没有通过硬编码的方式定义该名称,而是在构建的过程中通过变量的方式指定的。在构建规则中有GLOBAL_NS_VARNAME变量,该变量名称会作为编译参数传递,代码通过改变量的定义,来确定Javascript可见的Titanium主对象的名称是什么。

webView构建完毕后,Titanium Js主对象并不存在,只有当第一次WebKit遇到脚本代码时,这个对象才被创建。当WebKit引擎碰到脚本对象时,会调用JavascriptCoreinitScipt方法,初始化Javascript引擎。在此JavascriptCore会将我们之前调用webkit_titanium_add_script_evaluator增加的Evaluator代理和JavascriptCore解析关联起来。当引擎和资源都初始化完毕,会向FrameClient发送object avaliable通知,会调用FrameLoader::dispatchWindowObjectAvaliable()方法。这个方法会导致UserWindow::RegisterJSContext()方法的调用。然后UserWindow对象会创建一个DelegateStaticBoundObject对象来描述Titanium对象,并且将之前初始化完毕的Titanium API对象(KObject)与Titanium对象关联起来,然后将其放入到全局属性表中。这样,之后Web应用程序就可以从全局属性表中访问到Titanium对象了。但是Titanium对象中有哪些子属性是不知道的,这是运行时才去确定。

这个初始化过程如下图所示:

5.4 事件系统

Titanium的事件系统分成两个部分来说明,一部分是如何获取事件,另一部分是如何向事件系统中增加新事件。

linuxHost::RunLoop循环被调用后,立即会注册一个定时器,每隔250ms调用一次main_thread_job_handler函数。该函数首先通过GetJobs方法获取当前系统中未处理的事件,并且依次的调用事件对象(LinuxJob)的Execute方法执行。如果系统没有未决的事件存在,则立即返回。

事件的添加和触发均通过LinuxHost::InvokeMethodOnMainThread()方法完成。该函数会创建一个LinuxJob对象,并且插入到事件队列尾中。事件的触发有多种可能性,可以是由Javascript代码触发,也可以是内部事件触发,同样也有可能是UI事件触发。

由于Titanium扩展的JS APIC层上都会与相应的C方法对应,当Web应用程序调用相应的JS方法,对应的C方法会被调用,该方法则会使用LinuxHost::InvokeMethodOnMainThread()方法,向主线程发送事件处理请求。

对于UI来说,在Linux平台上所有的UI相关的事件首先是被GTK的应用框架截获,当有UI事件到来时,ti.UI模块会创建对应事件的KEvent对象(在event.h中定义),然后调用KEvent对象的Fire方法,触发事件。该方法会间接的使用LinuxHost::InvokeMethodOnMainThread方法向LinuxHost事件队列注册事件。

这个过程如下图所示:

5.5 访问Titanium对象属性和方法

比如,有一段Javascript脚本中调用Titanium.API获取Titanium对象的API属性,当JavascriptCore解析到这部分代码时,并不知道这个对象是什么类型的,完全当作一个抽象的JSValue对象来对待,因为对于Javascript引擎来说,并不需要时刻知道对象是什么,有那些属性和方法,只有到运行时才会去用查询该对象中是否存在指定的属性或者方法(JavascriptCore内部维护了一张属性表,通过查询方式获取相应属性或者函数的处理函数指针。这点V8做的就比较高明,用类的方式描述,动态将对应JS的方法和属性转换成C++的成员函数和成员变量,大量的减少了访问时间)。由于API这个对象是由Kroll创建的,是一个KObject对象,在挂载到Javascript 全局属性表之前,Titanium会调用KObjectToJSValue方法,将KObject对象转换成一个JSObject对象,并且设置了几个比较重要的回调函数:

  1. HasPropertyCallback: 当查询属性时候被调用
  2. GetPropertyCallback: 当获取指定属性时被调用
  3. SetPropertyCallback: 当设置指定属性时被调用

javascript访问用Titanium对象的API属性时,通过JSValue.Get方法会调用到GetPropertyCallback函数,该函数会查询KObject对象中(这里是说的Titanium)是否有API这个属性,如果有则转换成JSValue对象,并且返回给Javascript引擎。

如果这里访问的是一个属性的方法,过程和访问对象是一样的,只不过最后创建的是一个Function Js对象,而非Object对象。当Javascript访问这个返回的Function对象时,Javascript引擎会调用callAsFunction方法,而该方法会引发CallAsFunctionCallback回调函数被调用(该函数是静态函数在KMethodToJSValue函数中注册)。这样通过CallAsFunctionCallback这个回调接口,调用实际的KObjectCall方法,执行实际的处理函数。

属性访问过程如下图所示:

5.6 JavascriptPythonRuby动态语言间的相互调用

Titanium框架中引入了一个比较有意思的特性,即支持多种语言之间的相互调用。从实现技术角度来说,Titanium的多语言支持的设计思想,是在学习了WebKitBinding机制而发展过来的。主要用到了JavascriptCore引擎可以动态注册Evaluator的机制。HTML语言中定义了<script>标签,用于内嵌脚本语言,该标签有个子属性type,通过该属性可以让浏览器引擎区分是什么类型的脚本。加入我们有如下的脚本代码:

<script type=”text/python” src=”xxx.py”></script>

首先,WebCore引擎会解析HTML页面数据,当发现有<script>标签出现,则会创建HTMLScriptElement,对于script有两种处理情况,一种是如上代码通过src包含一个脚本路径,还有一种情况是定义一段代码,通过控件或者超连接的方式以事件方式触发。如果是第一种情况,则会在创建HTMLScriptElement的时引发ScriptElementData::requestScript方法的调用。如果是第二种情况,则会在触发相应事件时候调用FrameLoader::executeScript方法执行脚本。最终都会调用JavascriptCore中的EvaluatorAdapter::evaluate()。由于在初始化ti.UI模块时,我们已经注册了自己的evaluatorScriptEvaluator),因此会将获取的脚本信息传递给ScriptEvaluator,在该对象中,会通过Script::Evaluate()方法,根据传递下来脚本的MIME类型(也就是scripttext字段定义的类型)派发给注册的不同解析器去执行。

这里以Javascript调用Python代码,并且Python代码中又调用了ruby代码为例子说明其调用过程。

Python代码:

def abc():

ruby_fun()

Ruby代码:

def ruby_func()

end

pythonEvaluator::Evaluate()被调用后,首先将保存的全局JS对象表转换成Python可识别的对象字典(KMethodToPyObject完成,转换成PyKMethodTypePython对象)。这样在之后编译的Python代码中就可以访问到这些对象。然后将Python代码使用Python编译器编译,并且将编译后的函数对象转换成KObject对象,插入到全局的JS对象表中(abc)。这样,Javscript,和其他语言都可以识别该对象。同样,对Ruby函数的处理,也会首先将全局JS对象表中的KObject对象转换成Ruby的对象,然后对Ruby函数进行编译,将新生成的Ruby函数对象(ruby_fun)转换成KObject对象,然后从新更新JS全局对象转换表。至此,全局JS对象表中就新增了两个KObject对象:ruby_fun, abc

javascript访问该abc函数对象时,按照通常方式首先调用CaAsFunctionCallback,该函数会调用KObjectCall方法,由于该KObject实际上就是一个KPythonMethod对象,因此KPythonMethod对象的Call方法会被调用。之前我们注册的Python方法是一个PyKMethodType,该类型中定义了一个方法回调函数,当Python方法被调用时,该回调函数(PyKMethod_call)会被调用。这个例子中,在Python代码里调用了ruby_fun,因此当PyKMethod_call被调用时,首先将调用的KObject对象(实际上是一个对Ruby函数对象的封装)转换成KMethod对象,然后调用Call方法。这样就通过间接调用,调用到KRubyMethodCall方法,使得Ruby函数得到执行。

整个过程如下图所示:

六、参考资源

http://www.appcelerator.com/


Post Footer automatically generated by wp-posturl plugin for wordpress.

Tags:

Copyright © 2010-2011 Jelly's Blog All rights reserved.
Desk Mess Mirrored version 1.9 theme from BuyNowShop.com.

Jelly's Blocnzz&51la for wordpress,cnzz for wordpress,51la for wordpress