Symbian Security Studio

About symbian software programming ,security analysis and other things about symbian.

Sunday, May 27, 2007

the ultimate blog template list


the ultimate blog template listPlease note this list has not been updated nor added to since 2004. Hopefully there are still items of worth here; if I ever get a free minute-and-a-half I hope to update it, but for now, just be aware the wee beastie is outdated. -->
Updated July 2006, with many thanks to Rosalind Gash for hunting down the dead and deceased in the old list.
the list
2girlsdesign
Anti-Ivy Linkware and Shareware Blog Templates
Bejewelled
Blog-Plates
BlogDesigns
Blog Fashions
Blogger Templates
BlogSkins
Blog Templates @ ehsany.com - includes templates in Farsi
Colorized Pixels
CSS Colouring Book
Elated Page Kits
Eris Weblog Template Generator (multiple software support)
EyeForBeauty - Templates for your Journal
EyeSites
glish.com - Blogger Template
Groovy Lizard
Joyful Heart Designs
Karysima Pre-coded Movable Type Templates
Love Productions Blogplates
noipo
Point of Focus - Blogger templates
shellen.com - Blogger Templates
Spiderman 2 Blog Templates
Starlit Dreams Weblog Designs
Weblogger Themes

Labels:

Friday, May 25, 2007

中文 Symbian论坛和新闻组




中文 Symbian论坛和新闻组
From Forum Nokia Wiki

Symbian OS是当今发展最为迅速的移动设备操作系统。Symbian的流行在近段时间发展尤为火爆。 越来越多的开发者加入到了为Symbian平台开发应用程序的行列。现在,在互联网上我们拥有充足的学习资源,本文就是为你介绍互联网上有关Symbian OS操作系统的论坛和新闻组,希望能够对开发者有所帮助。
Contents[hide]
1 开发者的论坛
1.1 诺基亚论坛-开发者讨论区
1.2 Symbian开发者网站论坛
1.3 NewLC论坛
1.4 All About Symbian开发论坛
1.5 索尼爱立信开发者世界
2 用户组和群组
2.1 Symbian开发者网站新闻组
2.2 Symbian C++的Google讨论组
3 博客
4 Wiki(维基)
5 IRC频道
6 教程和有用的链接


[edit] 开发者的论坛
开发者的论坛是一种十分有效的在开发者之间进行交流谈谈得地方,是一种十分流行的技术交流形式。下面是一些主要的Symbian开发者论坛:

[edit] 诺基亚论坛-开发者讨论区
这是目前最大最流行的讨论区论坛了。在这个论坛里面,基本讨论对象都是和诺基亚有关的技术话题。要想使用论坛的全部功能,你需要成为一个注册用户。讨论区论坛被分为了很多区域,而且还有一个特别的中文讨论区。除此以外,他们还拥有一个互动讨论区,可以将开发者的反馈提交至诺基亚论坛。
[edit] Symbian开发者网站论坛
这个论坛基本上是讨论关于Symbian OS的一般性内容的。其中有一个讨论Symbian Signed的分论坛。此论坛还连接到了一个用户新闻组(详细情况见下文用户组部分)。
[edit] NewLC论坛
这个论坛仍然是讨论Symbian OS系统的一般性问题的论坛。论坛的分区设置有点类似Symbian C++, JAVA, 通信,等等。这个论坛的一个特别之处是,那里有一个法语讨论区子板块,叫做法语角.
[edit] All About Symbian开发论坛
这仍然是一个讨论Symbian的一般性问题的论坛。它的子板块分区有OPL问题,其它等。Symbian C++,Symbian Java,Symbian和MobileVB是他的特色论坛。
[edit] 索尼爱立信开发者世界
这个论坛是特别为UIQ开发者准备的,在那里的Symbian OS子论坛中你可以讨论关于UIQ2,UIQ3以及OpenGL ES的问题。此外,在这个论坛中有一个Java移动版的Bug报告区。
[edit] 用户组和群组
用户组(Usenet -USEr NETwork)是一个全球性的,分布式的Internet讨论系统,它使用了一个通用的UUCP网络来完成其功能。
[edit] Symbian开发者网站新闻组
Symbian开发者网站(SDN-Symbian Developer Network)使用了同步以及合并的用户新闻组和论坛系统。无论你是在论坛还是在新闻组中发表的问题,他都会被复制到另外一个系统中,也就是说另外一个系统的用户也可以看到你的发言。你只需要一个标准的NNTP新闻阅读器来访问新闻组就可以了,新闻组服务器的地址是: developer.symbian.com。 更多详细信息请访问这里
[edit] Symbian C++的Google讨论组
这个是Google讨论组中有关Symbian C++技术的讨论组。你可以使用你的邮件地址来访问该讨论组,而且不需要认证你就可以直接加入该组并发表话题。除了传统论坛讨论组的功能,那里还有一个“页面”功能,这个功能可以为你带来许多别人编写的优质文章,而且你也可以贡献文章到这个子区域中。
[edit] 博客
博客是近年来十分流行的一种日记形式,它以用户在网站上编写的文章为内容,以时间倒叙的形式陈列,通常具有很强的亲和力以及表现力。博客通常是对于特定事件或新闻,以及特定主题的事情进行讨论以及评述。通常,一篇博客是综合了文字、图像、链接到其他博客或网站的链接以及媒体文件的集合。同样重要的还有浏览博客的用户的互动留言评论系统。下面是一些和Symbian有关的流行博客。
诺基亚论坛博客
字符串常见问题
字符串常见窍门
Symbian C++ 编程教程
[edit] Wiki(维基)
维基(wiki)是一个可以让访问者无需注册即可增添、编辑、删除、替换内容的网站。 Wiki的另外一个特点是,一篇文章中可能有多个词条链接到另外一篇文章中。这种简单直接的交互式操作方式使得wiki成为了一种十分快速有效的大规模用户内容创作工具。Wiki这个词目在有时候也会指称运行wiki系统的软件本身(wiki引擎),比如wiki的创始网站WikiWikiWeb,以及维基百科全书Wikipedia。下面是最流行的有关Symbian社区的wiki:
诺基亚论坛Wiki,就是你现在看到的 :)
Symbian开发者网站Wiki
[edit] IRC频道
互联网聊天服务(Internet Relay Chat -- IRC)是一种实时地互联网聊天或者同步会议服务。这种服务的主要设计思路是解决群组之间,多对多的通信形式。类似论坛讨论区的设置,该服务的分区称作频道(channels),除了频道以外用户之间也可以进行单对单的私聊。
下面是有关Symbian的流行的IRC频道:
#symbian (irc.freenode.net)
#symbian.dev (irc.efnet.net)
有关IRC的使用帮助,详情请在这里了解: Internet Relay Chat (IRC)帮助.
[edit] 教程和有用的链接
下面一些链接,对于学习Symbian开发都是十分有帮助的。
Forum.Nokia Documents/Examples
Nokia Developer Newsletter
Symbian Developer Network - Library
NewLC - Tutorials
Symbian OS Tips, Tricks and Code
symbianresources.com - Tutorials - Overview
A crash course on programming mobile phone using C++
Penrillian - Smarter Strings for Symbian OS
Symbian Example Helping Symbian developers
Symbian Programming - Mika Raento
Some things with Symbian (Series 60)
The Workflow of C++ Game-Development on a Series 60 Platform device.
Creating Self-signed Symbian OS Certificates

Labels:

Psion

Psion
----说起Symbian我们必须提到PSION(音同:佩丝恩或佩森)公司和它的EPOC操作系统,Symbian正是由它们发展而来的。

----Psion公司于1980年创立,始人为David Potter.当时的Psion是欧洲领先的技术公司,一直致力于为数字产品开发和研究.同时Psion也是欧洲第一批主要的PDA厂商,其PDA产品在欧洲一直享有盛誉。至于EPOC则是Psion Software推出的操作系统,专门用于移动信息设备,包括掌上电脑."EPOC”这个词起源于世界将会进入“a new epoch of personal convenience”。EPOC是一个开放的操作系统,一开始的时候EPOC就加上了无线通信和一个外加应用程序的体系,因此在无线通信方面与其他操作系统相比具备先天的优势。同时,和微软的Windows CE一样,EPOC也是一套32位的操作系统,具备实时性、多任务的,多线程、低功耗,内存占用少等特点。我们熟悉的爱立信R380SC就是使用的基于EPOC的操作系统。

----1998年六月,为了在将来的智能移动终端领域取得先机和市场地位。Psion公司联合手机业界巨头,诺基亚、爱立信、摩托罗拉和组建了Symbian公司。该公司继承了Psion公司EPOC操作系统软件的授权,并且致力于为移动信息设备提供一个安全可*的操作系统和一个完整的软件及通讯器平台。作为一种开放式平台,任何人都可以为支持Symbian的设备开发软件。这意味着开发伙伴具有更多可供选择的应用,同时拥有更大的市场。为此symbian推出了白金合作计划吸引了包括ARM、Motorola SPSRealNetworks、TI德州仪器等大量的厂商加入。 Symbian公司还大量参与WAP、WirelessJava和Bluetooth的制定工作,确保EPOC将完全支持市场的内容和服务需求模块化、可伸缩性、低能耗以及与StrongARM这类RISC芯片的兼容性。因此微软的Windos Mobile操作系统相比,Symbian在通信方面的优势得天独厚

----现在的Symbian因为松下,西门子和三星的先后加入已经成为由Psion、诺基亚、索尼爱立信、摩托罗拉、松下、西门子、三星联合控股的公司。尽管后来摩托罗拉出售了在Symbian的股权,但在2004年第一季度,LG、Arima和联想成为最新取得Symbian授权协议的手机制造商,从而使得获得授权的厂商总数达到了18家,几乎囊括了全球所有重量级的手机制造商。

Symbian旗下的系列:珍珠、石英和水晶。

----Symbian为其旗下种类的三种产品分别给予了诗意的命名,即Pearl(珍珠),Quartz(石英)和Crystal(水晶)。分别用于智能手机、笔式输入通讯器和键盘输入通讯器。每种系列都采用Symbian核心平台80%的代码。不同系列之间的区别主要在于用户接口(例如:笔式或键盘式输入)和屏幕大小。

在三个系列中,Quartz和Crystal都被称作“通讯器”,惟有Pearl是“智能电话”。

Quartz是EPOC操作系统中Palm size PC版本。支持系统的能力非常强大,使用者接口设计和操作方式比Palm OS操作系统及Pocket PC操作系统更具人性。基本上是把两个操作系统的优点集于一身。它的特色是 采用笔式输入,屏幕像素为320x240,彩色屏幕,以及图形用户接口的手机。摩托罗拉的三频GPRS/GSM通信器Accompli就属于Quartz系列.而Crystal则是EPOC操作系统中Hand Held PC版本,特色是具有软件和硬件输入键盘的无线信息设备。面向支持键盘操作的终端。对象为配备彩色显示器(640×200像素)、键盘操作功能以及图形用户接口的手机。NOKIA9210就Crystal的代表。至于我们熟悉的诺基亚7650、6600和7610以及索爱P800、P900和P910等则是Pearl珍珠系列的"智能手机"了。

----Symbian的版本介绍

----1999 年3月Symbian推出了Symbian5.0操作系统,它的主要内核集合了网络,无线文字,电子邮件,名片薄以及个人信息助理,同时还具有支持标准网络页面的浏览器,配合java语言的支持,使得Symbian可以运行小型的应用程序。不过这个版本采用的机型甚少,基本上与EPOC没有太多的差别。而Symbian 6.0则在5.0的基础上增加了,GPRS、WAP1.2浏览器以及蓝牙技术的支持,用户可以运行第三方基于C++和J2ME开发的程序。而Symbian 6.1则是和Symbian 6.0相比主要增加了对USB的支持。Symbian 6.0的主要特点是: 支持语音通话和数据通信 ,支持Bluetooth和WAP ,配备安全性功能(SSL,HTTPS,WTLS) ,采用16bit Unicode,支持多语言显示 ,采用“PersonalJava 3.0”和“JavaPhone 1.0” 。

----Symbian 7.0则支持多模式和3G手机,可以让制造商们可以面向全世界推出可以运行于所有网络之上的Symbian OS手机,而且可以不对代码进行重大改动的情况下就可以重新使用许多目前已有的软件应用。7.0包含一些新的通讯、消息、联网和应用开发技术,并对一些与安全和认证相关的功能进行了改进。Symbian OS 7.0的其他功能包括:支持灵活的用户界面,例如Nokia的Series 60;支持几种音频/图像格式和许多面向游戏开发人员的API;全力的加密和认证管理,基于安全通讯协议(包括HTTPS、WTLS和SSL)及认证的应用安装;和Over-the-air(OTA)SyncML同步支持。

----2004年2月,Symbian在授权LG等公司的时候,也发布了最新的Symbian8 .0版本。该版本改善了实时系统性能,提高了原有操作系统的兼容能力。此外,Symbian OS 8.0的软件工具改进了远程接入控制系统功能,运用调节装置消除手机用户使用增值服务时会受到的干扰。这个系统包含了绝对现代化的多媒体和Java设备,支持多种标准,其中包括JSR118, CLDC1.1 (JSR139),MobileMedia (JSR135),3D图像数据(JSR184), JTWI 1.0 c(JSR185)。最后,新版OS还支持SDIO。

Labels: ,

Symbian电池处理软件

zg再次为我们带来的一款空前绝后的系统级辅助软件
  (1) 从电池内部的芯片中读取电池的实际参数(型号、类型、容量、阻抗等),从此告别假冒伪劣的仿原装电池?(有待验证…)
  (2) 当前的电压和电流,这意味着手机的功耗可以从此被普通用户实时测量,这可是很多Symbian开发者梦寐以求的功能!
  (3) 量化显示的剩余待机时间推测值,对于普通用户和开发者来说都有特别的意义。
  (4) 更多与电池相关的附加状态信息:手机内置的备用电池状态、充电类型、充电电压、充电进度、电池温度等,它们对手机维修者来说可是难得的一手信息。
  (5) ……

Labels:

Symbian定时器

(1)TTime::HomeTime() / TTime::UniversalTime()
  最常见的时间获取手段,精度不高;因涉及一定的运算过程,效率较低。适用于需要以常规“年月日时分秒”方式使用时间的场合。在EKA2平台下,其精度与低阶系统时钟(Nanokernel Timer)一致,通常为微妙级别。通过 HAL::Get(HAL::ENanoTickPeriod, result) 可以获的具体精度。  注意:它们使用的是系统时间,这是可以被其它进程修改的。
(2)User::TickCount()
  传统的Tick计数器,精度通常仅为1/64秒(可能随硬件有差异),适用于精度要求较低的场合。通过 HAL::Get(HAL::ESystemTickPeriod, result) 可以获得具体精度。  注意:在休眠(Standby)状态下,TickCount将停止计数,所以User::TickCount()在休眠状态下将“损失”计时!
(3)User::NTickCount()
  低阶系统时钟(Nanokernel Timer),通常提供微妙级Tick。通过 HAL::Get(HAL::ENanoTickPeriod, result) 可以获得具体精度。  注意:Symbian OS 6.x 没有此API。与TickCount不同的是,User::NTickCount()在休眠状态下不“损失”计时。
(4)User::FastCounter()
  返回值类似于Tick,提供Symbian OS所能支持的最高精度,通常比TTime::HomeTime()更准确。(如果硬件不支持high resolution timer,则毫秒级时钟替代)而且,因为它采用快速的exec call读取一个硬件寄存器的数值,效率很高。通过 HAL::Get(HALData::EFastCounterFrequency, result) 可以获得其具体精度。  注意:在每次终端从休眠状态激活后,它将同步至正确的数值,也就是说User::FastCounter()在休眠状态下其实也是不“损失”计时的。
  另外,User::After(), CPeriodic也会在休眠状态下“损失”计时,所以在手机这种特殊的应用环境中,需要特别注意不同定时器在“休眠”状态下计时的差异。

Labels:

THeapWalk的Symbian 9实现



在移植FontRouter2到Symbian 9的过程中,碰到了一个大难题:THeapWalk这个类彻底的从Symbian 9中消失了!与新版本中其它很多API变化不同的是,THeapWalk类的功能虽然被新的RHeap::Walk()所取代,但该方法已不再从EUser.dll中导出,也就意味着它的身份从此变成了“内部API”,不再对第三方应用开发者开放。
  THeapWalk是用于测试内存问题的一大利器,其地位难以被取代,如果就此抛弃,实在太可惜了。好在天无绝人之路,经过一天时间的彻底分析,终于让我发现了Symbian为其留下的一个后门。利用以下适配代码,可以在Symbian 9实现对THeapWalk功能的完整模拟,希望对同样遇到移植问题的朋友有所帮助:class THeapWalk
{
protected:
enum TCellType
{
EGoodAllocatedCell, EGoodFreeCell,
EBadAllocatedCellSize, EBadAllocatedCellAddress,
EBadFreeCellAddress, EBadFreeCellSize
};
public:
THeapWalk(RHeap &aHeap) : iHeap(&aHeap), iValue(0) {}
TInt Walk()
{ iHeap->DebugFunction(RHeap::EWalk, &DoInfo, this); return iValue; }
virtual void Info(TCellType aType,TAny* aBase,TInt aLength)=0;
protected:
inline TInt Value() const { return(iValue); }
inline void SetValue(TInt aValue) { iValue = aValue; }
private:
static void DoInfo(TAny* aPtr, TCellType aType, TAny* aBase, TInt aLength)
{ ((THeapWalk *) aPtr)->Info(aType, aBase, aLength); }
RHeap* iHeap;
TInt iValue;
};
注:EBadFreeCellSize是Symbian 9新增的一种Cell状态。

Labels:

2007马德里S60峰会




本文简介:
S60 2007年峰会于前不久在西班牙马德里召开,Matti Vanska为该峰会致开幕词,开幕词中回顾了S60设备的发展历程,并且对S60设备的未来持乐观态度,当然,就现在的情况来看,S60的前途已经算是一片光明了。







2007马德里S60峰会(1)
【口袋数码- 活动报道】  S60 2007年峰会于前不久在西班牙马德里召开,Matti Vanska为该峰会致开幕词,开幕词中回顾了S60设备的发展历程,并且对S60设备的未来持乐观态度,当然,就现在的情况来看,S60的前途已经算是一片光明了。




  相比上次峰会500人的参会者,本次峰会的参会者人数有了10%的增加。参会者不仅仅有产品开发者,手机服务运营商,厂商代表,媒体记者,还有市场分析师等各种职业人群 本次峰会的主题就是向大家展示S60设备的新时期的面貌。所以,此次峰会开辟了一个展览厅用来展示最新的S60设备,比如很火热的三星SGH-I400。


  峰会接下来对S60目前取得的成功进行了回顾分析:出货量大,产品新功能丰富,能为用户带来新的使用体验,以及较短的新产品开发周期,以上这几点被认为是S60的目前的优势,S60接下来的发展方向将致力于加强设备和网络的结合,并为S60设备定制相应的网络服务,使用户获得更丰富的网络体验。
在2007年第一季度,约20万S60设备被投入市场, 这一数字已经超过了整个市场份额的50%。而S60设备的累计出货量也已超过1亿。当宣布这个数字的时候,会议厅内充满了赞叹的声音, 其实这也是意料中的事情,因为S60设备在智能移动终端市场中一直处于领先的位置,而它的最大对手Windows Mobile,仍然需要发展很长的时间才可以对S60的市场造成本质上的威胁。 也许在未来,S60会退出市场,退出历史舞台, 这也是一个自然的过程, 但是在S60存在的这几年里,它屡屡创下的历史销售新高,以及它对于推广智能设备所做下的巨大贡献,都是应该被人们所铭记的。

接下来各个参会厂商代表都进行了发言,S60设备生产和制造大厂诺基亚(Nokia)宣布将推出用于Symbian OS™ 的carbide.c++下一代开发工具的新的高效和经济的增强版。新的Carbide.c++工具系列的增强版使得开发人员能够有效地满足不断增加的项目资源需求以及解决管理困难,而这些问题均与当今热门的移动应用项目 相关的增长规模、复杂性和风险等相伴出现。开发人员还将发现Carbide.c++ V1.2 的开发人员和专业版(Developer and Professional Edition)具有高级的性能检测(Performance Investigator)工具应用程序,此工具能够在开发过程的早期阶段更多地获得重要的电源消耗和内存使用信息。Matti Vänskä在此峰会的新闻发布会上表示:“我们关注三个影响软件平台需求的关键趋势。首先,移动设备正在成为个人体验的核心,无论其侧重点是图像、商 务、音乐、浏览还是视频。其次,人们使用移动设备访问各种Web 2.0服务。第三,简捷和直觉的用户体验变得越来越重要。”其他厂商以及移动信息运营商(T-mobile)也分别阐述了对于S60设备的未来发展的看法,在很多观点上达成了一致,增强S60设备的网络连接能力并且针对S60推出丰富的网络服务成为了S60设备下一步发展的主要趋势。一些公司已经拿出了一些详细的方案,例如移动浏览器,更加娱乐化的手机功能,更丰富的网络连接资源,以及S60设备上的网络游戏等方案,这一切的一切都向我们昭示着S60设备美好的明天。






  当然,我们还在展会上看到了中国企业的身影。

OK,接下来就让我们把目光聚焦在大家就想看的峰会展厅吧,让我们看看都有什么新鲜玩意儿在等待着我们。

  像以往的展会一样,这次S60峰会也开辟了小型展区,比如手机饰品展区,提供了丰富的手机饰品来供参会者试用。相信没有人会不对这些有趣的小饰品感兴趣,所以这些小展台前面总是站满了人。





这个在出入证上附带的闪盘,可以方便的用来传输资料,尤其适合参会的记者。这真是一个不错的创意。
 要说整个展会上最吸引眼球的东西,那就是三星面向中端市场新发布的S60滑盖智能手机,SGH-I400,拥有对EDGE网络的良好支持,200万像素的摄像头,以及机身背后的立体声喇叭,还有S60第三代操作系统,都是这款新手机的绝佳卖点。这款手机将会在5月到六月间在全球各地区陆续上市。


这款手机的硬件配置和三星旗下的另一款手机i520类似,使用了TI OMAP 2430的处理器,不过它并没有板载图形加速模块,这也是制造商所决定的,三星的这款手机定位和诺基亚E65相似,不过它们之间确有巨大的价格差距,明显三星的这款手机要更平易近人一点,三星作为一个智能手机市场的“后来者”,最近也动作频频,充分说明了三星对智能手机市场的雄心。

  纵观整个展会,我们还能看到很多我们平时很难看到的东西,比如各种各样手机的开发板。

这款Nokia5500具有重力感应系统,我们可以通过移动手机来实现相应的操作,比如现在展示的这款控制小球的游戏。



这个屏幕在演示的是S60 Feature Pack 2(第二代功能扩展包)的新特性展示,屏幕显示的是外观部分,图标的风格看着有点像iPhone。

sysopendigia公司的展台 向我们展示了一些更有趣的东西,就是如何利用无线网络来管理手机中的信息,包括电话簿,短消息,来电转接,电子邮件等等,这种服务可以有效的节省S60设备上的存储空间,但是目前来说这项服务的费用还是非常昂贵的,但也向我们展示了一个很好的发展方向。

  OK,限于篇幅,关于本次马德里S60峰会就先说这么多,一些具体的产品和服务的详细介绍请期待我们的后续文章。

Labels: ,

诺基亚出Carbide.c++工具增强版

2007年4月25日(西班牙,马德里)-诺基亚今天宣布将立即推出用于Symbian OS™ 的Carbide.c++下一代开发工具的新的高效和经济的增强版,而Symbian OS™是智能手机市场的领先操作系统。 通过提供具有设备浏览功能和省时的项目构造工具的新的重要应用程序,Carbide.c++工具增强版通过大量减少编程时间以及压缩开发时间,能够加速移动应用的开发和降低大多数软件项目的总体成本。 正如今天在诺基亚应用峰会及S60 2007年峰会(Nokia Applications Summit & S60 Summit 07)所宣布的那样,新的Carbide.c++工具系列的增强版使得开发人员能够有效地满足不断增加的项目资源需求以及解决管理困难,而这些问题均与当今热门的移动应用项目相关的增长规模、复杂性和风险等相伴出现。开发人员还将发现Carbide.c++ V1.2 的开发人员和专业版(Developer and Professional Edition)具有高级的性能检测(Performance Investigator)工具应用程序,此工具能够在开发过程的早期阶段更多地获得重要的电源消耗和内存使用信息。 Carbide系列移动开发工具基于致力于软件工具创新的Eclipse开源架构,并且能够为所有诺基亚开发工具产品提供单一的ID,它包括适用于入门级和学院级开发人员的Carbide.c++ Express;适用于创建高级系统、中间件和应用软件开发人员的Carbide c++ Developer Edition;以及适用于由Symbian OS 和 S60授权获得厂商进行设备创建的Carbide.c++ OEM Edition。 诺基亚开发工具总监Rich Bartlett表示:“诺基亚非常高兴能够提供Carbide.c++工具的这一重要演进版本,它能够更多地提高开发人员的效率,以及减少适用于Symbian智能手机的令人兴奋的新应用推向市场的时间。在满足入门级开发人员、创建高性能软件的开发人员和设备创建专家的需求方面,诺基亚Carbide.c++工具的这些新的改进将使得不断完善的软件项目比以前任何时候以更快的速度和更低的成本进入市场。” Carbide.c++工具支持开发人员开发基于Symbian OS最新版本(包括UIQ、NTT DoCoMo’s MOAP和 S60 3rd Edition)的智能手机软件。Symbian智能手机是世界上最流行的智能手机,目前其占有所售智能手机的70%以上的市场。在2006年,全世界已经向超过250 家主要网络运营商销售5170万部Symbian智能手机,这使得截止2006年12月31日,Symbian智能手机发货的总数已达1亿1000万部*。 Carbide.c++ V1.2工具的使用者将极大地提高效率,这得益于下列方面的改善 · 改善所有Carbide.c++系列工具的支持Eclipse代码浏览功能和代码完成功能,以及增强项目构造应用程序的功能,包括提供新的工具包检测和项目导入对话框(wizard)、提供更简捷和可靠的项目创建和编辑功能等。 · 改善Carbide.c++开发人员和专业版的性能检测工具的功能,其中包括电源优化器(Power Optimizer)和内存分析器(Memory Analyzer),以便为运行于设备上的目标软件提供电源消耗和内存使用的记录和图片显示,这样,在开发高性能的S60应用和UIQ应用时能够获得更佳的内存和电源使用率。 · 为Carbide.c++ OEM Edition提供新的设备创建功能,其中包括为JTAG 设备调试提供的简化配置支持、能够显示调试图中的Crash调试环境的新的Crash 调试器(Debugger)界面、以及支持查看系统进程、线程、Chunk和库的Symbian OS 数据视图(Data View)等。 Carbide.c++ 开发人员版(Developer Edition)和 Carbide.c++ 专业版(Professional Edition)目前的售价分别是299 ? 和1,299 ?,而对于现有的Carbide.c++ 开发人员版和 Carbide.c++ 专业版客户可以免费升级。Carbide.c++ OEM版(OEM Edition)目前的售价是3,999 ?,而Carbide.c++ Express可以由开发人员从www.forum.nokia.com/carbide 免费下载获得,并且对商业使用没有授权限制。 诺基亚Carbide.c++系列工具将在4月24-25日的诺基亚应用峰会及S60 2007年峰会上高调展出,展示地点是马德里的Melia Castilla酒店。如需获得更多关于Carbide系列开发工具的信息,请访问www.forum.nokia.com/carbide。

Labels:

Explore and Hack the Server Heap in Symbian

One of the most important design in Symbian is the well-known server/client framework. As the server and client are in different process spaces, hacking the server is generally difficult to achieve by means of normal application. But another important framework provided by Symbian give us a chance, the Plug-in framework, which is also merged into the ECOM framework in newer Symbian OS.

Take the Open Font System interface for example, any OFS plug-in installed in Symbian is actually loaded by Font and Bitmap Server at system start-up. Thus they are running just in the same process space of Font and Bitmap Server. So if you want to hack the server, you should first find the right key - the corresponding plug-in interface of that server. Not all servers have a plug-in interface, but the plug-in mechanism is so popular and you can find it in most of the common servers.

After breaking the door of server, we could still see nothing in the dark room. What we need now is a lamp, which can help us find the right things. Fortunately there is a lamp that could even light up all the corners of server heap. But how could you imagine such a powerful tool was even forgotten by people and only be treated as a part of the ordinary debug kit? OK, no more superfluous words, let me introduce the amazing lamp - class THeapWalk. It will walk through all the cells in the specified heap, and pass each one to the virtual function. We just need to identify each given cell and find out the cookie. As a restriction in Symbian, RTTI is not supported (in pre Symbian 9, and also not recommended in Symbian 9), but we could still simulate the typeid() for all CBase derived classes by extracting the pointer of virtual function table.

Some more words here, the address of allocated cells in heap are not the address of corresponding objects. Actually there is a small piece of cell header which keeps the information of cell length and pointer to next cell, in the beginning of each heap cell. The real object resides just behind its cell header.

Tip: For compatible reason, never assume that the length of cell header to be sizeof(RHeap::SCell), use a live constructed object and RHeap::GetAddress() to figure out.

Now, let’s do a small wrap and help our Cinderella wear her glass slippers. (:

class THeapSearch : private THeapWalk
{
public :
THeapSearch(RHeap& aHeap);
TInt Search(CBase & aRefObject);
inline CBase * FirstResult() { return iObjectFound; }
// Override this function to deal with each object found.
virtual void DealL(CBase * /*aObject*/) {}
private:
void Info(TCellType aType,TAny *aBase,TInt aLength);
RHeap & iHeap; // The heap to search object in.
CBase * iObjectFound; // Object found (NULL if not found)
CBase * iRefObject; // Reference object
TInt iCellLengthExpected; // Expected length of cell
TInt iCellHeaderLength; // Length of cell header in current build
TInt iTypeId; // Address of virtual function table
};Detailed implementation is omited and can be found here: [Heap Search Code Snippet]

Finally, we have all the essential bases ready for an exciting “Server Heap Tour”, and I will demonstrate the process by hacking our innocent CFontStore object of Font and Bitmap Server to change the default font render effect to enjoyable “Anti-Aliased”. (Only available on Symbian 7 and later, because Symbian 6 has no anti-aliased bitmap type support.)

CFontStore * font_store = NULL, * ref = CFontStore::NewL(& User::Heap());
THeapSearch heap_search(User::Heap());
if (1 == heap_search.Search(* ref))
{
font_store = reinterpret_cast(heap_search.FirstResult());
if (font_store)
font_store->SetDefaultBitmapType(EAntiAliasedGlyphBitmap);
}
delete ref;Note: Symbian 9 has striped away the THeapWalk class in the SDK, visit my blog and get a working simulation version of class THeapWalk in Symbian 9:
http://blog.oasisfeng.com/2007/02/23/theapwalk-for-symbian9/

Labels:

Thursday, May 10, 2007

用C++实现的访问Symbian手机电话薄

在Symbian OS中,电话薄部分是通过一个默认的数据库(contacts.cdb.)来操作和管理的。因此在Symbian系统里可以用联系人模型(Contacts Model)API来访问和管理电话薄,这里主要用的类就是CContactDatabase(数据库类,电话薄所有条目的集合),CContactItem(它代表一个单独的电话薄条目,由唯一的一个TContactItemId标识。例如电话薄中的一个联系人),CContactItemField(域类,每一个电话薄条目有很多类组成,例如姓名域(EPbkFieldIdFirstName,EPbkFieldIdLastName),电话号码域(EPbkFieldIdPhoneNumberGeneral)...).
而Series60开发者则扩展了这一模型,使用“电话薄引擎”;下面是几个关键的类。

Class CPbkContactEngine

电话薄引擎通过CPbkContactEngine来实现。如果已经存在一个缺省数据库,CPbkContactEngine::NewL()就连接到该数据库,否则创建该数据库。

Class CPbkContactItem

CPbkContactItem类代表电话薄数据库中的一个具体条目,例如一个联系人。它提供了对所拥有的TPbkContactItemField数组的访问和查找函数。

Class TPbkContactItemField

TPbkContactItemField是某个电话薄条目的域类,例如某人的电话域,或者某人的电子邮件。

//关于电话薄引擎的具体知识还是参看SDK的help吧。

//呵呵,下面把访问电话薄的一段代码贴出来,希望大家多指正。

void CPhoneEngine::DisplayContactInfoL(MObjectProvider* aMopParent)
{

RPbkViewResourceFile phonebookResource( *(CEikonEnv::Static()) );

if ( !phonebookResource.IsOpen())
{
phonebookResource.OpenL();
}

// Add searching array to parameters
CContactDatabase::TContactViewFilter filter(CContactDatabase::EPhonable);
CPbkMultipleEntryFetchDlg::TParams params;
params.iContactView = &iPbkContactEngine->FilteredContactsViewL( filter );

// Launch fetching dialog
CPbkMultipleEntryFetchDlg* fetchDlg = CPbkMultipleEntryFetchDlg::NewL( params, *iPbkContactEngine );
fetchDlg->SetMopParent( aMopParent );
TInt okPressed = fetchDlg->ExecuteLD();
CleanupStack::PushL( params.iMarkedEntries );

if ( okPressed )
{

// Get the first selected contacts id array
const TContactItemId cid = ( *params.iMarkedEntries )[0];

// Open the selected contact using Phonebook engine,
CPbkContactItem* pbkItem = iPbkContactEngine->ReadContactLC( cid );

//get the first name
TPbkContactItemField* fnameField = pbkItem->FindField(EPbkFieldIdFirstName);
fnameField->GetTextL(iFirstName);

// get the last name
TPbkContactItemField* lnameField = pbkItem->FindField(EPbkFieldIdLastName);
lnameField->GetTextL(iLastName);

// get the General PhoneNumber
TPbkContactItemField* phoneFieldGeneral = pbkItem->FindField(EPbkFieldIdPhoneNumberGeneral);
phoneFieldGeneral->GetTextL(iNumberGeneral);

// get the Mobile PhoneNumber
TPbkContactItemField* phoneFieldMobile = pbkItem->FindField(EPbkFieldIdPhoneNumberMobile);
phoneFieldMobile->GetTextL(iNumberMoblie);

//get the email address
TBuf<30> emailAddress;
TPbkContactItemField *eMailField=pbkItem->FindField(EPbkFieldIdEmailAddress);
eMailField->GetTextL(emailAddress);


// add codes to get other fields you interested in

//......


CleanupStack::PopAndDestroy(pbkItem); // pbkItem, eMailAdd
}

//release the resource
CleanupStack::PopAndDestroy(); // iMarkedEntries
phonebookResource.Close(); // Close the phonebook view

Labels:

Wednesday, May 9, 2007

Symbian OS应用开发-SMS的故事(二)

摘要:上节我们了解了Symbian OS中对SMS的主要操作,比如新建、修改以及删除等等,这篇文章我们主要认识一下有关SMS的发送。

发送SMS也许我们大多数人都操作过,简单说来就是编辑一段文本,然后选择一个或多个目标号码,点击发送一切ok。其实在程序中实现的步骤也是如此,只不过需要我们了解更多的知识。
老方法,我们先来了解一些必须的类:
CSmsSettings
设置sms服务的属性类
CSmsHeader
sms头信息,主要有关消息的各种参数,当然与上面的CSmsSettings密切相关

其他有关sms的类在上一节我们都大致介绍了,这里不重复说明,接下来我们会用一些具体的源码加以分析。
首先,我们需要新建一个sms而且得到接受方的号码,这两步可以参照上一节的内容,里边详细介绍了如何新建一条sms。
然后就是要设定发送前的一些参数信息,并选择做一些相应的操作。
---------------------------------------------------------------------------------------------------
//iMtm是在新建sms阶段设定
TMsvEntry msvEntry = iMtm->Entry().Entry();
// 得到sms内容
CRichText& mtmBody = iMtm->Body();
mtmBody.Reset();
mtmBody.InsertL(0, KGDSMSTag); //插入我们的短信标示
//重新设定TMsvEntry
msvEntry.iDetails.Set(iRecipient->Des()); // set recipient info in details
msvEntry.SetInPreparation(EFalse); // set inPreparation to false
msvEntry.SetSendingState(KMsvSendStateWaiting); // set the sending state (immediately)
msvEntry.iDate.HomeTime(); // set time to Home Time
// 使用CSmsClientMtm类处理sms
CSmsClientMtm* smsMtm = STATIC_CAST(CSmsClientMtm*, iMtm);
smsMtm->RestoreServiceAndSettingsL();
// CSmsHeader封装sms消息的参数,像服务中心号码和发送设定
CSmsHeader& header = smsMtm->SmsHeader();
//CSmsSettings类用来详细设定sms Header
CSmsSettings* sendOptions = CSmsSettings::NewL();
CleanupStack::PushL(sendOptions);
sendOptions->CopyL(smsMtm->ServiceSettings());
sendOptions->SetDelivery(ESmsDeliveryImmediately);//设定立即发送
header.SetSmsSettingsL(*sendOptions);
//检查服务中心号码有效性
if (header.Message().ServiceCenterAddress().Length() == 0)
{
// 如果没有设定,则查找默认中心号码
CSmsSettings* serviceSettings = &(smsMtm->ServiceSettings());
// 中心号码列表为空
if (!serviceSettings->NumSCAddresses())
{
// 错误消息
iEikonEnv->InfoWinL(_L("No service center number"),_L("cannot send this one."));
}
else
{
// 设定为默认服务中心号码
CSmsNumber* sc = 0;
sc = &(serviceSettings->SCAddress(serviceSettings->DefaultSC()));
header.Message().SetServiceCenterAddressL(sc->Address());
}
}
CleanupStack::PopAndDestroy();

... ...

CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
CleanupStack::PushL(selection);
selection->AppendL(movedId); // 添加我们要发送的sms,movedId在省略部分有定义,是TMsvId型变量
// 调用的这个函数是用于发送的,具体的代码后面介绍
SetScheduledSendingStateL(selection);
CleanupStack::PopAndDestroy(); // selection
return ETrue; // 到这里sms已被发送
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
void ...::SetScheduledSendingStateL(CMsvEntrySelection* aSelection)
{
CBaseMtm* smsMtm = iMtm;
// 添加entry到任务列表
TBuf8<1> dummyParams;
CCommandAbsorbingControl::NewLC();
CMsvOperationWait* waiter = CMsvOperationWait::NewLC();
waiter->Start();
// 这个函数是关键
CMsvOperation* op= smsMtm->InvokeAsyncFunctionL(
ESmsMtmCommandScheduleCopy,
*aSelection,
dummyParams,
waiter->iStatus);
CleanupStack::PushL(op);
CActiveScheduler::Start(); //开始时间表中任务
CleanupStack::PopAndDestroy(3); // waiter, op, CCommandAbsorbingControl
}
---------------------------------------------------------------------------------------------------

需要我们注意的是:在发送sms的过程中大部分的操作都是用于设定发送sms时的参数,所以东西比较琐碎;如果您想自己实现这部分工作,给您的建议就是尽量采用一个比较通用的方法,无需设定一些让人捉摸不定的信息。在发送sms中起主要作用的还是CBaseMtm类,这个类以及从它继承的类负责sms的具体发送,所以整个过程的结束点一定是使用这些类的函数来实现发送的动作,犹如上述的InvokeAsyncFunctionL函数。

Labels:

Symbian OS应用开发--SMS的故事(一)

摘要:SMS(短消息服务)是GSM规范的一部分。Symbian OS SMS实现基于SMS规范的ETSI GSM 03.40 v7.4.0 Technical实现。(可从http://www.etsi.org中下载该规范)因为我们的主要工作主要是读取、新建、修改、删除等操作,所以我们本篇文章的重点放在这些操作上,在文章的结束部分,我们也会简单的谈及有关SMS的发送。

首先和以前各篇文章一样,我们先简要介绍几个重要的类:
CMsvSession
该类代表客户端(客户端MTM、用户接口MTM或者客户端消息应用程序)与消息服务器端的通讯通道。每一个客户端线程对应一个该类的实例,CMsvSession提供客户端能及时获取消息服务端消息的有效方式。一个消息客户端应用必须在正常使用任何MTM或CMsvEntry对象前,使用OpenSyncL()或者OpenASyncL()来新建一个session对象。
CClientMtmRegistry
Registry掌握了客户端所有目前可用的MTM有关的细节,消息客户端可以使用该类获得从CBaseMtm继承de对象。
CBaseMtm
这个类主要用来操作sms的内容,比如可以新建、修改sms;具体是使用方法下面将会借助代码说明,更详细的内容你也可以查看具体sdk的help。
CMsvEntry
相当于一个特定消息服务器的入口,当前entry与其的具体内容相关联。CMsvEntry包含两个部分的功能:一是可以允许访问与这个entry关联的,不同类型的数据;而是运行访问它的子entry。该类只在客户端使用,服务器端使用CMsvServerEntry。
TMsvEntry
用于代表消息服务器的一个入口,主要用于sms的新建。

下面还是看几段例程吧:)TMsvSelectionOrdering sort;
sort.SetShowInvisibleEntries(ETrue); //全部内容排序,包括隐藏
//设置入口为outbox,也就是发信箱
CMsvEntry* entry = CMsvEntry::NewL(*iSession,KMsvGlobalOutBoxIndexEntryId,sort);
CleanupStack::PushL(entry);
//选择全部内容
CMsvEntrySelection* entries = entry->ChildrenL();
CleanupStack::PushL(entries);

TTime time;
//得到首信息的时间,At(0)代表首信息,取其他的可以给出相应的index
time = entry->ChildDataL(entries->At(0)).iDate;
//弹出对话框,有首信息接收人的号码信息
CAknInformationNote* informationNote = new (ELeave) CAknInformationNote;
informationNote->ExecuteLD(entry->ChildDataL(entries->At(0)).iDetails);

CleanupStack::PopAndDestroy(2);


------------------------------------------
注意:一些变量没有做介绍,比如iSession,这是因为前面的文章有提到过!
------------------------------------------
上面这段例程的作用就是让大家了解一下如何获取并操作sms。
简单说一下:首先定义一个消息服务器的入口,关联着outbox;然后取出outbox中所有的短信内容,并存储到CMsvEntrySelection型指针指向的list中,操作list便可方便的操作outbox中的sms。
下面讲述了如果取单个sms的具体内容,这些都是公共变量,可以利用它们来获取sms的具体细节:
------------------------------------------
TTime iDate (类型和名称)
Time (描述)短信时间
--------------------------------------------------------------------------------
TPtrC iDescription
Description 短信内容
--------------------------------------------------------------------------------
TPtrC iDetails
Details 发送或接受人号码
--------------------------------------------------------------------------------
TInt32 iError
Error
--------------------------------------------------------------------------------
TUid iMtm
MTM
--------------------------------------------------------------------------------
TInt32 iMtmData1
MTM data 1: this can be used for any purpose by an MTM.
--------------------------------------------------------------------------------
TInt32 iMtmData2
MTM data 2: this can be used for any purpose by an MTM.
--------------------------------------------------------------------------------
TInt32 iMtmData3
MTM data 3: this can be used for any purpose by an MTM.
--------------------------------------------------------------------------------
TMsvId iRelatedId
Related folder ID.
--------------------------------------------------------------------------------
TMsvId iServiceId
Service ID.
--------------------------------------------------------------------------------
TInt32 iSize
Size 短信大小
--------------------------------------------------------------------------------
TUid iType
Entry type
--------------------------------------------------------------------------------
TInt32 iWdpPortNumber
Port number
--------------------------------------------------------------------------------
TInt32 iBioType
BIO message type
------------------------------------------
通过使用上述变量就可以取得sms中的所有信息,我只对经常使用的几个做了介绍,剩下的当大家使用到时可以详细研究一下。上面的一段例程很简单、也很清楚,使用起来也会比较方便,接下来使用上面的方法我们可以同样实现delete操作:

TMsvSelectionOrdering sort;
sort.SetShowInvisibleEntries(ETrue);
CMsvEntry* entry = CMsvEntry::NewL(*iSession,KMsvDraftEntryId,sort);
CleanupStack::PushL(entry);

CMsvEntrySelection* entries = entry->ChildrenL();
CleanupStack::PushL(entries);
TInt i = entries->Count();
for(TInt ncount=0;ncountentry->DeleteL(entries->At(ncount));
// information to the user
iEikonEnv->InfoMsg(_L("DeleteAll Done!"));
CleanupStack::PopAndDestroy(2);

如果你已经理解了上面的读取sms信息的操作,这个全部删除也就不难理解了。所不同的只是调用了一个DeleteL()函数,这个函数是在类CMsvEntry中定义的,它可以删除固定index位置的sms。详情可以查看相关sdk help

有了上面的了解,不难看出sms的操作其实和我们上一讲所说的vCard有类似之处,下面我们来看看如何将sms的内容导出到文件。
这里会用到类CBaseMtm,看下面例程:

iSmsMtm->SwitchCurrentEntryL(aEntryId);
iSmsMtm->LoadMessageL(); // load the message

CRichText& body = iSmsMtm->Body(); //sms的内容存到CRichText控件对象中
TPtrC msg(body.Read(0));
WriteToFileL(msg);

iSmsMtm是CBaseMtm类型的指针变量,它当然需要初始化,如下方式:
1.iSession = CMsvSession::OpenAsyncL(*this);
// 该函数的参数应该是从MMsvSessionObserver继承过来的任何类.....它会和 session library 间建立一个异步连接...
//然后你可以在函数HandleSessionEventL中收到事件EMsvServerReady...
//事件到达表明同服务器间的通话已建立... 接着去得到 Mtm Registry,并返回 SMS mtm...
2.iMtmReg = CClientMtmRegistry::NewL(*iSession);
3.iMtmSms = static_cast (iMtmReg->NewMtmL(KUidMsgTypeSMS));

下面是WriteToFileL()函数的具体实现:

void WriteToFileL(const TPtrC &aMsg)
{ //设置存储路径以及文件
_LIT(KDirName,"\\system\\apps\\MyApp\\Data");
_LIT(KFileName,"\\system\\apps\\MyApp\\Data\\MsgBody.txt");
//连接文件服务器并生成相应文件夹
RFs fileSession;
fileSession.Connect();
fileSession.MkDirAll(KDirName);

RFileWriteStream writer;
writer.PushL();
User::LeaveIfError(writer.Replace(fileSession,
KFileName, EFileWrite));
//写入文件并确认
writer << aMsg;
writer.CommitL();

CleanupStack::PopAndDestroy();
fileSession.Close();
}
//以下头文件会使用到
#include
#include

上面的步骤清晰明了,无需多说,大家要注意一下CBaseMtm这个类的用法,因为在接下来,我们看到的新建sms同样会重点使用到这个类,而且使用的次数会更多。

新建sms的步骤较为复杂,我们列出一些主要步骤:

TMsvEntry newEntry;
newEntry.iMtm
newEntry.iType
newEntry.iServiceId
newEntry.iDate.HomeTime();//一般设置为当前时间
newEntry.SetInPreparation(ETrue);//设置为true

设置好上面的参数之后,接下来就可以使用CBaseMtm类来完成新建操作了

CBaseMtm* iMtmSms;
...
iMtmSms->SwitchCurrentEntryL(KMsvGlobalInBoxIndexEntryId);//设置为收信箱
iMtmSms->Entry().CreateL(newEntry);

long smsId = newEntry.Id();//得到新sms的id
iMtmSms->SwitchCurrentEntryL(smsId);
//设置sms的详细内容
_LIT(KSMSBody,"Hello World!");
CRichText& body = iMtmSms->Body();
body.Reset();
body.InsertL(0,KSMSBody);
newEntry.iDescription.Set(KSMSBody);
//设置sms的收信或发信人手机号码
iMtmSms->AddAddresseeL(_L("13500000000"));
newEntry.iDetails.Set(_L("13500000000"));
iMtmSms->Entry().ChangeL(newEntry);
//别忘了保存
iMtmSms->SaveMessageL();

如此一来,你就可以新建一条sms了,当然有了新建sms的经验,实现修改sms的信息也就不困难,主要步骤可分为三步:
1. 给定一些需要修改sms的信息,比如id、index、所在位置或其他
2. 通过搜索找到满足条件的sms,并暂存这些结果
3. 利用搜索结果进行sms信息修改,最后确认变化即可
这里对sms的修改就不做详细的分析,大家可以自己尝试一下!

下一节内容,我会和大家一起继续讨论有关sms的内容,只不过重点放在发送上,期待您的关注!

Labels:

Symbian OS应用开发--玩转通信录

在上一篇文章中,我们介绍了有关文件和目录的操作方法,本篇文章我们来讨论有关手机中通信录的使用。

首先在文件和目录篇中我们介绍了系统RAM主要用于活动程序和系统内核,另外可作为用户使用的磁盘空间c:盘访问。其实,通信录中的数据就是存在RAM中的,至于操作这些数据的众多功能则是由通信录模型(Contacts Model)提供的。

接下来我们就来简单的讲述一下通信录模型的结构,它是基于一个通信录数据库,数据库中含有一些通信录项。每个通信录都有一些域,诸如姓名、地址,以及电话号码等。某台移动电话可能有好几个通信录数据库,但总会有一个默认的数据库。在我工作的环境中(S60 Sdk 2.1) ..\Symbian\7.0s\Series60_v21_C\Epoc32\wins\c\system\data\Contacts.cdb
就是模拟器默认的数据库。
我们知道在手机应用开发中经常会遇到有关OBEX协议的问题,其实在通信录开发中也遵循这个协议,通信录中的数据是存在一个名叫vCard的载体里。vCard是一类电子名片,得到许多电子设备(如PDA和移动电话等)的支持。vCard的目的是:在这些设备之间用某些协议实现方便的通信录数据传递。可以将vCard编码成MIME规范(RFC 1521)所定义的明码文本。这种编码确保了各种vCard与限制为7位字符集(如在SMS消息中使用的编码)的传递编码的完全兼容。
一张vCard被格式化如下:
BEGIN:VCARD
VERSION:2.1
N:Wilkinson;Steve
FN:Steve Wilkinson
ORG:EMCC Software Ltd.
TEL;WORK;VOICE:01617779700
ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;108 Manchester Rd.=0D=0ACarrington;Manchester;UK;M31 4BD;United Kingdom LABEL;WORK;ENCODING=QUOTED-PRINTABLE:108 Manchester Rd.=0D=0ACarrington=0D=0AManchester, UK M31 4BD=0D=0AUnited K= ingdom
EMAIL;PREF;INTERNET:steve.wilkinson@emccsoft.com
REV:20030909T164330Z
END:VCARD
通信录模型中的许多功能都与vCard的处理有关,以保证Symbian应用开发伙伴们能方便地编制符合电子名片及通讯录交换方面的工业标准的代码。

具体实践之前先来简单介绍几个类:
CContactDatabase类用于创建一个新的数据库或打开一个现有的数据库。还提供了访问各通信录项的功能。既可以读取也可以打开通信录项。如果希望编辑或删除该项,就必须打开它,尽管一个应用在某个时间点只能打开一个特定的通信录项。当完成对通信录项的修改后,即把它们提交给数据库保存。当然这个类还提供了很多其他的功能,例如排序、查找等等。这个类是通信录操作中很重要的一个类。

通信录模型提供了MContactDbObserver类,某个应用可以继承自这个类,用于接收由某个特定的通信录数据库所产生的修订提示。使用该观察者(observer)的那些应用会接收事件提示,这些事件可以是向数据库中添加一个新通信录、修改或删除一个现存的通信录,以及一定范围内的其他有用提示。

所有通信录项都继承自抽象类CContactItem,对其访问是通过前面讲过的CContactDatabase类管理的。可以用CContactItem::Id()函数(该函数返回一个TContactItemId)来获取每个通信录项的唯一ID。CContactItem类也含有对通信录项内部的域进行操作的功能。可以添加及插入新域,也可以删除项目中的现有域。

某个通信录项内部的一些域由CContactItemField类所代表。为方便起见,位于某个特定项内部的所有域都被储存在一个结构内部,该结构被称为一个域集(CContactItemFieldSet)。每个通信录域储存了实际的域数据,以及针对该数据的一个特定储存类型。这可以是一个文本串、一个数据/时间值、一个商店,或者一个代理,它由TStorageType类代表。一个代理域基本上是对另一个通信录的链接,如,Series 60 Platform就是这样实现的:将其他通信录项的ID联系到该通信录域。请注意:这里并不支持数字表示的通信录域。所有数字信息,如电话号码和传真号码,都被作为文本保存。
接下来我们的实践会用到上面的部分类,所以上述的类大家需要认真熟悉一下,更多的细节也可以查找相关sdk的help文件。

打开、关闭数据库
CContactDatabase::OpenL()函数有两个重载函数。如果该函数没有给出一个参数,就打开默认的数据库。另一种情况是,应用设计师也可以传递一个有关数据库的路径和文件名,规定打开另一个数据库。
-------------------------------------------
// Open the default contacts database.
CContactDatabase* contactsDb = CContactDatabase::OpenL(); //打开默认数据库
CleanupStack::PushL(contactsDb);
// Count how many contacts are in the default database and then
// delete the CContactDatabase object.
// Note that all resources owned by the contacts database are freed
// upon deletion.
TInt numberOfContacts = contactsDb->CountL(); //所有数据项数目
CleanupStack::PopAndDestroy(contactsDb);//销毁
-------------------------------------------
要注意的是:某个通信录数据库并不具有Close()函数或类似的函数。

新建数据库
CContactDatabase::CreateL()函数与CContactDatabase::ReplaceL()函数之间的唯一差别就是:如果该数据库已经存在,前者会以KErrAlreadyExists退出。如前所述,如果没有定义参数,这些函数将创建一个默认的数据库。CContactDatabase::FindContactFile()函数给出了一个描述符,如果不存在默认数据库的话,该描述符就会返回该默认数据库的位置。
-------------------------------------------
// If one is found, replace it with a new empty default database.
// If no default database is found, create a new one.
TFileName contactDbFilePath;
CContactDatabase* newDefaultContactDb; if(CContactDatabase::FindContactFile(contactDbFilePath)) //是否存在默认数据库
{ newDefaultContactDb = CContactDatabase::ReplaceL();
}
else
{ newDefaultContactDb = CContactDatabase::CreateL();
}

CleanupStack::PushL(newDefaultContactDb);
// 添加自己功能代码
CleanupStack::PopAndDestroy(newDefaultContactDb);
-------------------------------------------

遍历通信录项
可以用TContactIter类来遍历一个通信录数据库。这个类提供了一整套的函数,用于遍历所有的通信录项。所有的函数都用通信录项ID (TContactItemId) 进行操作,该ID 用于访问某个特定的通信录项。
-------------------------------------------
// Open the default contacts database:
CContactDatabase* contactsDb = CContactDatabase::OpenL(); CleanupStack::PushL(contactsDb);

TContactIter iter(*contactsDb); //类似游标
TContactItemId cardId;

while( ( cardId = iter.NextL() ) != KNullContactId ) //循环遍历
{
CContactItem* card = contactsDb->ReadContactL(cardId); //读取相应项
CleanupStack::PushL(card);

//添加自己功能代码

contactsDb->CloseContactL(card->Id());
CleanupStack::PopAndDestroy(); // card
}
CleanupStack::PopAndDestroy(); // contactsDb
-------------------------------------------

导出所有通信项到文件
主要使用类CContactDatabase中ExportSelectedContactsL函数。s60 2.1help中定义如下:
-------------------------------------------
void ExportSelectedContactsL(const TUid& aFormat,const CContactIdArray& aSelectedContactIds,RWriteStream& aWriteStream,TInt aOption,TBool aExportPrivateFields=ETrue);
void ExportSelectedContactsL(const TUid& aFormat,const CContactIdArray& aSelectedContactIds,RWriteStream& aWriteStream,TInt aOption,const CVersitParser::TVersitCharSet aCharSet, TBool aExportPrivateFields=ETrue);

Supported from 6.0

Description:
Exports an array of contact items to a write stream — overloaded function. The items are converted into vCards before being written to the stream.

Parameters:
const TUid& aFormat:Indicates the format for imported and exported contacts. Must have a value of KVersitEntityUidVCard.

const CContactIdArray& aSelectedContactIds:Array of contact IDs to export.

RWriteStream& aWriteStream:The stream to write to.

TInt aOption:Indicates the options for import and export. See the TOptions enum.

const CVersitParser::TVersitCharSet aCharSet:The character format. If not specified, defaults to CVersitParser::EUTF8CharSet.

TBool aExportPrivateFields=ETrue:ETrue exports fields marked as private. EFalse does not export fields marked as private. See CContactItemField::SetPrivate().

Leave codes:
KErrNotSupported aFormat.iUid is not KVersitEntityUidVCard.
KErrNotFound One or more of the contact items does not exist in the database.
-------------------------------------------
例程如下:
-------------------------------------------
RFs fileSession;
User::LeaveIfError(fileSession.Connect());//连接文件服务器
CleanupClosePushL(fileSession);
CContactDatabase* contactDb = CContactDatabase::OpenL();//打开默认数据库
CleanupStack::PushL(contactDb);
CContactIdArray* exportContact = CContactIdArray::NewL();//记录数据项数组
CleanupStack::PushL(exportContact);

RFile file;
file.Replace(fileSession,aFileName,EFileWrite);//新建文件,aFileName是文件名字
CleanupClosePushL(file);
RFileWriteStream outputStream(file);//声明文件流
CleanupClosePushL(outputStream);

exportContact = iContacts;//iContacts是已初始化了相应导出属性的数组,需用类CCntFilter
//如:
//CCntFilter* filter = CCntFilter::NewLC();
//filter->SetContactFilterTypeALL(EFalse);
//filter->SetContactFilterTypeCard(ETrue);//按vCard格式导出
//contactDb->FilterDatabaseL(*filter); //按照该filter属性取出满足条件的相应项
TUid id;
id.iUid = KVersitEntityUidVCard;
contactDb->ExportSelectedContactsL(id,*exportContact, //导出到文件
aWriteStream,
CContactDatabase::EExcludeUid);

CleanupStack::PopAndDestroy(5);
-------------------------------------------

删除一个指定通信录项
这里可以使用类CPbkContactEngine,这个类可以很方便的完成各种操作,它相当于操作手机通信录的一个快速引擎
使用时:
CPbkContactEngine* iPbkContactEngine = CPbkContactEngine::NewL();
这样它就会建立一个默认通信录的引擎对象。
然后:
-------------------------------------------
IMPORT_C void CPbkContactEngine::DeleteContactL ( TContactItemId aContactId,
TBool aImmediateNotify = EFalse
)
IMPORT_C void CPbkContactEngine::DeleteContactsL ( const CContactIdArray & aContactIds,
TBool aImmediateNotify = EFalse
)
-------------------------------------------
上述两个函数都可以完成删除操作,只是一个是每次删除一个特定Id的通信录项,另一个是删除一个满足条件的通信录项数组。
可以简单的调用实现:
iPbkContactEngine->DeleteContactL(id);
删除后最好调用iPbkContactEngine->CompressL();将数据库进行下压缩,因为压缩比较消耗时间,所以不要每次删除都进行。

当然有了上面的类CPbkContactEngine,我们还可以实现新建和修改通信录项的功能,其实我们在文章开始时讲述的几个类也可以完成同样的功能,但相对于这个类,操作相对复杂一点,究竟选用什么类,只是你自己的爱好。
下面举例说明实现新建和修改操作:
新建
-------------------------------------------
//省略部分声明代码(与上面重复)
...
CPbkContactItem* contact = engine->CreateEmptyContactL();//新建一空通信录项
CleanupStack::PushL(contact);
_LIT(KFName,"King");
_LIT(KLName,"Chai");
_LIT(KNumber,"13777777777");
//修改first name
TPbkContactItemField* field = contact->FindField(EPbkFieldIdFirstName);
field->TextStorage()->SetTextL(KFName);
//修改last name
field = contact->FindField(EPbkFieldIdLastName);
field->TextStorage()->SetTextL(KLName);
//修改手机号码
field = contact->FindField(EPbkFieldIdPhoneNumberMobile);
field->TextStorage()->SetTextL(KNumber);
...//可以添加其他值
//修改后结果添加到数据库中,并返回这个通信录项的id,可以以后使用
TContactItemId Id = engine->AddNewContactL(*contact);

CleanupStack::PopAndDestroy(contact);
-------------------------------------------
实现修改和新建的代码类似,不同是你需要找到你要修改的field,然后修改,最后导入数据库
修改
-------------------------------------------
CPbkContactItem* contact = engine->OpenContactLCX(aContactId);
CleanupStack::PushL(contact);
//找到需要修改的field
TPbkContactItemField* field = contact->FindField(EPbkFieldIdPhoneNumberMobile);
CleanupStack::PushL(field);

_LIT(number,"13500000000");
TBuf<11> phonenumber(number);
//设置并确认修改
field->TextStorage()->SetTextL(phonenumber);
engine->CommitContactL(*contact);

CleanupStack::PopAndDestroy(2);
-------------------------------------------

上述内容主要介绍了手机中phonebook的各种操作,由于篇幅有限,只能列举一些常用的操作实现,大家可以将上面提到的几个类进行更深入的了解,一定会达到预期的效果。希望我的总结对你有所帮助!
最后祝大家新年愉快!
--风小云

Labels:

Symbian OS应用开发--文件和目录

Symbian OS应用开发--文件和目录
在入门指南系列,我们介绍了有关Symbian OS的基础知识,接下来,我们将介绍更多理解如何编写程序的知识。
本篇文章的主要内容是介绍基于Symbian OS的手机,如何去操作有关文件和目录。也就是手机内的一些主要信息,比如:通讯录、记事和任务、sms信息、图片文件、声音文件...在介绍上述内容之前,首先,我们先简要了解一下Symbian OS的硬件系统,这些硬件直接关系到我们对其数据的具体操作。

与典型的台式计算机相比较,Symbian OS机器的相关硬件显然有更多的限制,给我们的软件开发带来了很多的不便,但同时也增加了更多的市场机会。
Symbian OS手机的主要部件:
一个CPU:Symbian Os的CPU是32bit的,运行的速度较低,现有的主要是基于190MHz和206MHz的strongARM CPU,有些则是基于ARM9。
一个ROM:ROM在我们的PC机上同样存在,但PC机上的ROM只包含一个很小的启动载入程序和BIOS,而在Symbian OS中ROM被映射成z:盘。ROM中的所有内容既可以作为z:盘上的文件夹来访问,也可以直接从ROM读取数据。Symbian OS上ROM大约是20MB的空间。
系统RAM:RAM主要用于活动程序和系统内核,另外作为用户使用的磁盘空间,作为c:盘访问,但一般机器的RAM也只不过8MB或16MB左右,所以很可能会耗尽RAM资源。
I/O设备:可能是手写输入的显示屏,紧凑式的键盘,或是内存卡(作为d:盘访问),或是其他连接端口,红外线和蓝牙...
电源:包括主电池以及外部电源。

有了上面Symbian OS部件的大致了解之后,就要谈下我们将要操作的信息数据:通讯录、记事和任务、sms信息、图片文件、声音文件...
这些信息数据主要都是存储在手机的RAM中,因此访问的时候可以通过访问c:盘的方式来进行。

下面我们集中探讨一下有关目录和文件的操作方式:
首先介绍一个类:TParse
用过的朋友都知道,这个类的主要功能就是处理路径,先看一段代码:
----------------------------------
_LIT(KPath,"c:\\new\\meeting.wrd");
...
TParse p;
p.Set(KPath,NULL,NULL);
p.Name();//gives "meeting"
p.NameAndExt();//gives "meeting.wrd"
...
----------------------------------
通过上面的例子,对TPase的功能应该有了一定的了解,对了这个类就是用来处理有关路径的各种信息采集的。当然,它还有合并两个路径的功能,如下:
----------------------------------
_LIT(KSpec,"A:file1");
_LIT(KRelated,"c:\\path1\\related.xxx");
TParse fp;
fp.Set(KSpec,&KRelated,NULL);
----------------------------------
上面操作的结果就是A:\path1\file1.xxx
提示:当我们需要提取指定路径的某些必要信息时,就需要我们使用TParse类来操作这个路径,从而达到目的,在处理路径时,这个类会经常使用!!

操作文件夹:
指定一个绝对路径
比如:指定_LIT(KBitmapFolder, "c:\\nokia\\Images\\Pictures\\");
这个路径就可以代表手机存储图片文件的文件夹。
这种方式简单易用,而且在大多数nokia的手机上,往往路径都是一定的,所以这种方式是完全可行的。但是为了增强程序的可移植性,还是不要用绝对路径的好。因为我们有了第二种方法:
PathInfo类:
我们可以通过这个类获取当前设备的存储器路径。
例如:
根目录:
PathInfo::PhoneMemoryRootPath()
存储图片文件目录:
PathInfo::ImagesPath()
存储安装SIS文件目录:
PathInfo::InstallsPath()
存储声音文件目录:
PathInfo::SoundsPath()
如果想要定位MMC卡这种外加的存储器应该这样:
#include
TFileName path = PathInfo::MemoryCardRootPath();
这种方式的效果更好,但是PathInfo这个类是在S60 2.0平台的,Symbian 6.1也就是S60 1.0平台却用不了!大家可以选择使用。

因为我们这篇文章涉及到的文件主要是图片和声音,因此只需要使用PathInfo::ImagesPath()和PathInfo::SoundsPath()来获得相应文件夹的地址。随后我们也就可以通过这个地址来操作相应的文件了。

操作文件:
Symbian OS下去操作文件主要是通过枚举所有特定文件夹下的文件以及查找指定的文件来完成的。
枚举某个文件夹下的文件:
-----------------------------------
TBuf<50> path,tpath;
TBuf<256> filename;
RFs iSessionRFs;
CDir* dirList;
// Number, name and file size
_LIT(KStringSize,"%S%S");
User::LeaveIfError(iSessionRFs.Connect());
path = PathInfo::PhoneMemoryRootPath();
path.Append(PathInfo::PicturesPath()); //picture的文件夹
User::LeaveIfError(iSessionRFs.GetDir(path, //读出文件夹下文件信息
KEntryAttMaskSupported,
ESortByName,
dirList));
TInt j = dirList->Count(); //文件数目
for (TInt i = 0;i{ //添加你的操作
filename.Format(KStringSize,&path,&(*dirList)[0].iName);
CAknInformationNote* informationNote;
informationNote = new (ELeave) CAknInformationNote;
informationNote->ExecuteLD(filename);
}
delete dirList;
------------------------------------
通过上面的例程可以看出枚举文件夹中的文件主要是通过GetDir()函数来完成的,这个函数的介绍如下:
--------------------------------------------------------------------------------
GetDir()
TInt GetDir(const TDesC& aName,TUint anEntryAttMask,TUint anEntrySortKey, CDir*& anEntryList) const;
Description
Gets a filtered list of a directory's contents. The bitmask determines which file and directory entry types should be listed. The sort key determines the order in which they are listed.

Notes:

If sorting by UID (ESortByUid is OR'ed with the entry sort key), then UID information will be included in the listing whether or not KEntryAttAllowUid is specified in anEntryAttMask.

The function sets anEntryList to NULL, then allocates memory for it before appending entries to the list. Therefore, anEntryList should have no memory allocated to it before this function is called, otherwise this memory will become orphaned.

The caller of this function is responsible for deleting anEntryList after the function has returned.

Parameters
const TDesC& aName Name of the directory for which a listing is required. Wildcards may be used to specify particular files.

TUint anEntryAttMask Bitmask indicating the attributes of interest. Only files and directories whose attributes match those specified here can be included in the listing. For more information see KEntryAttMatchMask and the other directory entry details. Also see KEntryAttNormal and the other file or directory attributes.

TUint anEntrySortKey Flag indicating the order in which the entries are to be sorted. This flag is defined in TEntryKey.

CDir*& anEntryList On return contains a list of directory and file entries.

Return value
TInt KErrNone if successful, otherwise another of the system-wide error codes.
--------------------------------------------------------------------------------
上面介绍摘自Series 60 2.1 help。
主要使用方式就是用户给定一个path,也就是第一个参数const TDesC& aName,通过调用,该文件夹中的内容就会返回到第四个参数CDir*& anEntryList中,接下来这个list中存储的内容就是该文件夹下的文件信息,至于中间两个参数可以设置一些屏蔽信息,使得用户可以取出自己需要的文件信息。

查找相应文件:
-------------------------------------
TFindFile file_finder(aSession); // 1
CDir* file_list; // 2
TInt err = file_finder.FindWildByDir(aWildName,aScanDir, file_list); // 3
while (err==KErrNone)
{
TInt i;
for (i=0; iCount(); i++) // 4
{
TParse fullentry;
fullentry.Set((*file_list)[i].iName,& file_finder.File(),NULL); // 5,6,7
// Do something with the full Symbian OS filename
DoOneFile(aSession, fullentry.FullName()); // 8
}
delete file_list; // 9
err=file_finder.FindWild(file_list); // 10
}
-------------------------------------
具体操作
1. 生成一个TFindFile对象.
2. 在赋值前FindWildByDir()将file_list初始化,所以这时list并没有分配空间.
3. 开始查找指定文件. 注意aWildName和aScanDir的使用,aWildName一般是完整文件名(例如, *.gdr),aScanDir则是相应目录,并不需要一个具体的盘符(例如, \System\Fonts\).
4. list中文件数目.
5. (*file_list)[i].iName表示找到文件的完整名字(e.g. Eon.gdr).
6. file_finder.File()表示文件的具体盘符以及路径(for example Z:\System\Fonts\).
7. TParse::Set()可以完成合并.
8. TParse::FullName()返回该文件的盘符、路径及完整名字.函数DoOneFile()可以是用户自己定义做相应的操作, (因为DoOneFile() 需要访问文件服务器, 所以RFs对象必须作为参数传递).
9. FindWildByDir()和FindWildByPath()都对CDir的对象分配了相应的空间,因此使用完必须删除CDir的对象.
10. 最后,你还可以使用TFindFile::FildWild()继续查询下一个盘符.
--------------------------------------------------------------------------------

有了上面的介绍,你一定对Symbian OS 中的操作有了一定的了解,更多更详细的使用方法还是需要你自己阅读Symbian OS sdk相应的帮助文件。以上给出的例程在vc++ 6.0/s60 sdk 2.1下调试通过。

你也可以阅读本blog中的《文件应该存储在手机的什么地方?》,该文章也有一些例程。
祝你新年愉快!:)

--风小云

Labels:

Using C code in symbian

"Calling the C function in C++ file (Porting)
1.
Create a header file(.h) for your “c” program. The contents of the header file will look like

#ifdef __cplusplus
extern 'C' {
#endif

// functions that you going to call in
C++
void yourFunction( );
void PrintfMessage();
int sum ( int i,int j);
......
......
......

#ifdef __cplusplus
}
#endif

2:
Now create your related “.c“file which includes all the function’s definitions which are declared in the above “.h” files. If required As well other “.c” file whose functions will be called by “.c” functions. For instance, sum( ) will call GetFirstNumber( ) that is in another “.c” file.
3:
Now You have to edit the MMP file. a) Add the filename
SOURCE
b) Add STDLIB’s header.
SYTEMINCLUDE \epoc32\include\libc
c) The import library estlib.lib is the C standard library.
LIBRARY estlib.lib
4:
Call yourFunction( ); from C++ file. This C++ file should have the “.h” of the “c” file.
5:
This is only for console based, rest of the steps are same. For, Console based application (i.e., for .exe ) The project also links to ecrt0.lib. This file provides the E32Main() entrypoint for a “.exe”
STATICLIBRARY ecrt0.lib



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=234904"

Labels: