Symbian 入门
这学期专业实践要做一个关于Symbian S60的手机软件,所以我选择了CarbideV1.2 OEM和S60 SDK 3rd FP1来作为自己的开发环境,具体的环境搭配如下:
1.首先安装Carbide,选择OEM版本,至于License的话在网上可以查的出来,大家自己去找,然后会出现release_notes提示安装Perl和SDK等.
2.安装Perl,选择activeperl 5.6.1的版本安装,否则会出现下面的网络上面常见的问题:
使用Carbide用向导新建了Symbian OSC++ Project,选择3rd Ed. GUI Application模版,根据步 骤建立了工程,选择Emulator Debug,编译时出现下如问题:
make[1]: *** No rule to make target `\Symbian\9.2\S60_3rd_FP1_2\EPOC32\BUILD\Symbian\carbide\workspace\test\group\TEST\WINSCW\TEST.WINSCW'. Stop. test line 0这样的问题,如果选择5.6.1 的话就不会出现上面的问题。(所以软件不是最新版本就是最好的阿!).
3.安装SDK最好在他的默认目录,而且这几个都是最好在一起,我选择的是C盘安装软件和操作系统,给了35G的大小。D盘存取数据。所以这些我都是安装在他的默认目录下面。Carbide和Perl 安装在C 盘program files.SDK 就直接安装在了C盘上面了。这样的话基本上就差不多了。
4.打开Carbide,要将工作的空间选取在和自己安装carbide的盘符相同的盘下面。否则的话会出现下面的错误:
WARNING: EPOCROOT does not specify an existing directory
BLDMAKE ERROR: Directory "\Symbian\9.2\S60_3rd_FP1\EPOC32\" does not exist
上面的是我在配置Symbian开发环境时候的一点经验之谈,希望能够对大家有一些帮助,也欢迎大家给与指教,给我这个菜鸟一些帮助,在此先感谢大家了。
PS:我是一个菜鸟,也是刚开始学习Symbian开发相关,所以对Symbian开发不太了解,之所以在这里写博客是我发现里面有很多Symbian开发的高手,所以希望大家能够给与我一些帮助,在此再次感谢了!!~-~
----------------------------------------------------------------------------------------------------
开发软件来编译程序,编写程序。即Integrated Development Environment (IDE) ,它包括编辑器,编译器和连接器。
推荐用Nokia’s Carbide.c++ Express Edition (based on the Eclipse IDE)或者Visual Studio .NET 2003。
需要软件开发工具包,即Software Development Kit (SDK),它允许你写,创建程序为你的手机。
对N73,需要S60 2nd Edition FP2version 9.1 introduced a complete break from older versions.
To work on Symbian OS version 9.1 or later, applications must be slightly modified andrecompiled.
不同的Symbian os用户界面user interface (UI)是不一样的。因此要选择正确的SDK。
• S60 3rd Edition Feature Pack 1 - Symbian OS v9.2
• S60 3rd Edition - Symbian OS v9.1
• S60 2nd Edition Feature Pack 3 - Symbian OS v8.1
• S60 2nd Edition Feature Pack 2 - Symbian OS v8.0a
• S60 2nd Edition Feature Pack 1 - Symbian OS v7.0s
enhanced
• S60 2nd Edition - Symbian OS v7.0s
• S60 1st Edition - Symbian OS v6.1
由于我们的os是v9.1的,所以需要S60 3rd Edition。
可以在http://developer.symbian.com/main/tools/sdks/s60/index.jsp上下载
下载IDE CodeWarrior Development Studio for Symbian os 3.1(OEM,Professional and Personal)
下载地址为:http://www.forum.nokia.com/info/sw.nokia.com/id/4d2d8611-c490-4f6e-a931-
ea37ba4f040d/CodeWarrior_Development_Studio_for_Symbian_OS_Personal_Edition_Version_3_1.html
安装其个人版,可试用90天。
安装SDK
验证SDK的安装
1、用devices命令设置S60 3rd Edition SDK for Symbian OS for C++ 作为默认的设备
例如:devices -setdefault @S60_3rd:com.nokia.S60
2、到包含helloworldbasic的目录下 默认安装下为cd C:\Symbian\9.1\S60_3rd\S60Ex\helloworldbasic
3、再进到group目录下,该目录下包含bld.inf和helloworldbasic.mmp文件
4、验证编程环境
运行—〉输入cmd—〉输入epoc—〉出现模拟器则表示安装成功。
注:参看Getting_Started_final.pdf
-------------------------------------------------------------------------------------------------------------------------
Nokia根据手机的屏幕大小和价格高低把手机分成了多个系列,现在使用的系列有:Series 40、Series 60、Series 80 和Series 90。60系列
采用Symbian os 6.1,然后又根据手机屏幕的特点对UI做了一些修改,这个被修改了的Symbian就被称为Nokia的60系列平台。使用60系列的手
机型号包括:Nokia 6670、 Nokia 6630、 Nokia 6260 、Nokia N-Gage QD™ 、Nokia 7610 、Nokia 6620 、Nokia 3620 、Nokia 3660 、
Nokia 6600 、Nokia 3600、Nokia 3650、Nokia 7650、Nokia N-Gage™等。
下面我们就以60系列为例,介绍SDK的安装过程。
2.1.1 安装SDK
第一步,到Nokia论坛注册,下载最新的SDK。Nokia 网站提供的Series 60 SDK for Symbian OS Nokia Edition SDK最新版本是v1.2,Series
60 SDK for Symbian OS的最新版本是v2.1。下载网址:http://www.forum.nokia.com/main/0,6566,034-4,00.html
第二步,到http://www.activestate.com 网站下载最新的Active Perl Script 安装程序。到http://www.java.com/en/download/manual.jsp
下载最新的J2RE。
第三步:安装SDK,推荐为Symbian开发单独建一个目录,例如d:\Symbian而不是使用C:\program files等这样的目录。
第四步:安装Active Perl和J2RE,安装到默认目录即可。
第五步:检查环境变量设定。打开系统环境变量tab,然后看看有没有EPOCROOT,如果有的话,把它手动改成“\” 。改完之后应该是这个样子
的:
EPOCROOT = \
然后,在系统PATH中加入 \epoc32\tools目录以及\epoc32\gcc\bin目录就可以了。
实际上,Symbian SDK根本不用安装,直接把epoc32目录拷贝到一个机器上,然后照上述方法设定目录和环境变量就可以了。
2.1.2 配置VC
如果我们使用的是VC 6.0,我们要保证系统至少打了SP3补丁,否则系统会有警告提示。如果我们使用的是VS.NET2003, 我们就只能安装Series
60 SDK for Symbian OS v2.1,因为Series 60 SDK for Symbian OS Nokia Edition SDK v1.2在VS.NET2003无法正确建立工程。
如果要直接在vc6里创建新项目,要把\Symbian\6.1\Series60\Series60Tools\ Application Wizard目录下的 AvkonAppWiz.awx和
AVKONAPPWIZ.HLP文件拷贝到vc6的模板目录C:\Program Files\ Microsoft Visual Studio\ Common\ MSDev98\ Template下。这样我们就可以
在VC的新建工程中看到Series 60 AppWizard v 1.9这个选项.
填入Project Name 以后,确认。
一路“Next”,一个最简单的Symbian应用程序就建立好了。
如果要将已经建立好的工程导入到VC6.0中,比如我们将SDK中的例子HelloWorld转换成一个VC6的项目,我们首先进入\Symbian\6.1\Series60
\Series60Ex\HelloWorld目录。在这里我们可以看到,在Symbian中,一个Project通常是按inc, src, group等目录组织,group目录里通常放
的是项目文件,所以编译时要先到这里。用命令提示符模式进入刚才说的那个目录下,然后执行:
bldmake bldfiles
这个命令会在group目录下生成一个abld.bat的批处理文件,并且会在\Symbian \6.1\Series60\Epoc32\BUILD下生成\Symbian\6.1\Series60
\Epoc32\BUILD\SYMBIAN\6.1\ SERIES60\SERIES60EX\HELLOWORLD\GROUP这个目录,并在最底层目录下生成一堆 .make文件。
然后,我们在同一个目录运行刚才生成的abld.bat:
abld makefile vc6
这样就会自动生成vc6的dsw文件,位置在\Symbian\6.1\Series60\Epoc32\BUILD\ SYMBIAN\6.1\ SERIES60
\SERIES60EX\HELLOWORLD\GROUP\HELLOWORLD\WINS。然后我们就可以在VC6种打开这个Symbian工程了。
2.2 编译
我们可以直接使用SDK提供的工具编译Symbian 工程,也可以使用VC6提供的集成环境来编译转化过的Symbian 工程。编译的结果存放在
\Symbian\6.1\Series60\Epoc32\ Release\wins\UDEB\Z\SYSTEM\apps目录中。
2.2.1使用SDK提供的工具编译Symbian 工程
我们在上一节的那个位置继续输入:
abld build wins udeb
这个命令会编译我们的程序,最后在\Symbian\6.1\Series60\Epoc32\Release\wins\UDEB目录下生成我们的helloworld,然后我们可以从开始
菜单里运行模拟器的debug版,在模拟其中就可以运行helloworld了。
2.2.2 使用VC6编译Symbian 工程
我们直接打开运行abld makefile vc6后生成的dsw文件,VC自动装载转化过的工程。按F7便可以直接编译工程,编译结果同样放在
\Symbian\6.1\Series60\Epoc32\Release\ wins\UDEB目录中。然后我们打开模拟器debug 版,就可以看到我们编译好的工程了。
2.3 打包
我们以SDK 1.2提供的HelloWorld为例,制作可以在手机中安装的.SIS文件:
2.3.1.检查程序
首先,在命令行格式下,进入HelloWorld工程mmp文件所在目录,输入bldmake bldfiles和abld build wins udeb,然后打开模拟器,检测程序
有无错误。
2.3.2.编译工程
在程序无错误后,在命令行输入abld build armi urel 。执行这个命令之后会在目录d:\symbian\6.1\series60\epoc32\release\armi\urel生
成HELLOWORLD.APP和HELLOWORLD.RSC两个文件。
2.3.3.建立.pkg文件
在d:\Symbian\6.1\Series60\Series60Ex\helloworld\sis 用记事本建立或者修改工程的pkg文件,内容如下:
; HelloWorld.pkg
;
;Language - standard language definitions
&EN
; standard SIS file header
#{"HelloWorld"},(0x10005B91),1,0,0
;Supports Series 60 v 1.2
(0x101F8202), 0, 0, 0, {"Series60ProductID"}
;
"d:\symbian\6.1\series60\epoc32\release\armi\urel\HelloWorld.APP"-"!:\system\apps\HelloWorld\HelloWorld.app"
"d:\symbian\6.1\series60\epoc32\release\armi\urel\HELLOWORLD.rSC"-"!:\system\apps\HelloWorld\HELLOWORLD.rSC"
其中,前面"d:\symbian\6.1\series60\epoc32\release\armi\urel\HELLOWORLD.rSC"是要打包安装的文
件,"!:\system\apps\HelloWorld\HELLOWORLD.rSC"是安装的目标位置。在其中要注意的是,我们在目标位置中用“!”代替了实际的盘符。
这样做得好处是在用户安装的时候,手机系统会提示用户选择要安装的位置,这就给了用户更大的灵活度。另外,在Symbian 系统中,安装的
应用程序默认位置是“!:\system\apps ”。
编辑好pkg文件后,保存至相应目录。
2.3.4.打包程序
在命令行中,转至pkg文件所在目录,运行命令makesis HelloWorld.pkg。之后我们就在同一目录下得到了打包好的.sis文件。
2.4 手机测试
将打包好地.sis文件上传至手机中,然后在手机的应用程序管理器中就可以看到我们打包好的文件。选择“安装”命令,系统会提示用户要安
装的位置,选择安装位置后,我们制作的应用程序就安装到手机中了。
我们回到手机的主菜单,就会发现新安装的HelloWorld 应用程序。打开运行,结果和在模拟器中看到的基本是一样的。
---------------------------------------------------------------------------------------------------------------------
第一篇:Symbian UI 程序框架
Symbian UI 程序的框架基本上是统一的。大家只要学习一种简单的框架就可以进行大部分的Symbian开发了。我这里先介绍一个概念。
1.1 MVC 架构
Symbian 基本上使用MVC架构来搭建控件。Symbian UI程序设计主要讲究的也是如何使用控件。而No kia没有做好的一个方面就是有关UI
Control的帮助太少了。SDK提供的帮助里面根本就没有资源文件的写法。这一张里面我会介绍一些控件例如Dialog,Text Listbox等等资源文
件的写法。同时也会告诉大家应该到SDK的哪里才能找到这些资源的描述。
但是首先,我先介绍一下MVC架构。MVC并不是个新东西。他是Model - View - Control的缩写。在以前smalltalk中就已经开始用了。其主要的
想法是在构造类的时候把显示,控制以及模型分开。Symbian对其作了小的改动。在Nokia提供的Series 90控件组(就是CKON,以后我再提CKON
的时候大家要知道指得是S90的控件)中Model主要用来存储数据,以及封装对数据的操作。也就是对于对象实体的操作。View当然是负责显示
。Control被抽象成一个或多个纯虚类(Mixin)其它对象通过重写虚函数来得到对象内部的状态以及控制对象。Series 90的Text Listbox类
CEikTextListBox很好的说明了这个构架。比如你可以调用CEikTestListBox中的Model()函数得到一个Model的指针,然后你就可以访问其中的
CDesArrayFlat数组了。
1.2 Symbian的工程文件
1.2.1工程引导文件bld.inf
这个东东其实就是一个脚本,它告诉Build环境在做Build之前需要准备或知道一些什么东西。最普通的
一种写法是:
PRJ_MMPFILES
project.mmp
这是告诉Build环境:你马上要处理的工程文件名字叫project.mmp。大家如果做比较复杂的程序可能需要同时Build所有的库,那么就在这里把
你所有需要Build的工程都列出来:
PRJ_MMPFILES
project.mmp
project_lib1.mmp
project_lib2.mmp
另外的一个常用的标记是PRJ_PLATFORMS这个东东告诉编译环境,以下的这些平台(Targets)是需要编译的。你可以在这个标记的下一行列出
需要的平台例如:
PRJ_PLATFORMS
WINS ARMI WINSCW
或者直接用
PRJ_PLATFORMS
DEFAULT
注意,如果你不作PRJ_PLATFORMS这个标记其效果等于PRJ_PLATFORMS DEFAULT,所以这个不是必须
的。
第三个常用标记是PRJ_EXPORTS这个东西告诉编译环境在编译之前需要把哪些文件先拷贝到指定位置。我举个简单的例子大家就知道什么意思了
。比如你的工程中需要include一个第三方的*.inl的文件,那么如果编译之 前这个文件不存在就会编译不过。你可以这么写:
PRJ_EXPORTS
.\nk_set.inl \epoc32\include
那么在你编译的时候,一个Perl脚本会先把你工程目录下的nk_set.inl文件拷贝到\epoc32\include目录下,然后再 编译工程。
大多数工程只要用这三个标记就可以了。还有一点小技巧这个bld.inf文件中是可以写#if #else 等等东西的。
比如:
#if defined(WINS)
..... 注意没有{}
#else
.....
#endif
---------------------------------------------------------------------------------------------------------------------
Avkon Series60 extensions and modifications to Symbian's Uikon and other parts of the Symbian OS Application Framework
Symbian中的应用程序通常分为两个部分,engine和UI,如此的划分增加了可维护性和灵活性,engine就好象是程序的核心,它主要处理运算和
数据,而UI(应该是User Interface)主要处理数据的显示和所有行为(操作行为应该是)。
engine不谈,它是程序起作用的灵魂,这个是因程序而异的,我们来看应用程序外观,它可以分为三种体系结构:
一、传统的symbianOS控制体系结构
二、基于对话框的体系结构
三、视图体系结构
看看好象跟MFC搞的似的,也有个View和Dialog,不过也是Symbian就是用C++写的,面向对象特性非常好。
运用什么样的界面取决于程序和界面布局的需要,就不多说了。只是不管你使用哪种,都是从一个基类继承而来的,就好象是CView一样。
[传统SymbianOS应用程序的体系结构]
传 统意义上,SymbianOS应用程序是在CCoeControl类的基础上派生出我们自己的view controls,这些都存放在应用程序的 control stack中
,也就是我们应用程序的视图。这些controls会根据应用程序的需要来创建释放或显示隐藏,以产生相应的操作。
[Dialog体系结构]
如果主体应用是对话框,那我们更应该使用这样的体系结构,使用dialogs的好处是我们光可以靠改变resource文件来修改内容和布局,而不需
要重新编译那c++代码。
注意,如果不小心规划,那嵌套的对话框将耗去大量的堆栈空间。
另外,如果dialog体系结构被用于主要视图,那建议讲其设计为非模态对话框。(它不垄断用户的输入,用户打开非模态对话框后,仍然可以与
其它界面进行交互。)如果你要生成一个主界面对话框,要求是满屏,并提供多页设计,那应该包括如下features:
RESOURCE DIALOG r_dlgapp_main_dialog
{
flags = EEikDialogFlagNoDrag | EEikDialogFlagNoTitleBar |
EEikDialogFlagFillAppClientRect |
EEikDialogFlagCbaButtons | EEikDialogFlagModelss;
buttons = r_dlgapp_softkeys_options_home;
pages = r_dlgapp_main_pages;
}
如果要创建一个对话框应该如下:
void CDlgappAppUi::ConstructL()
{
BaseConstructL();
iAppView = new(ELeave) CDlgAppMainView;
iAppView->ExecuteLD(R_DLGAPP_MAIN_DIALOG);
AddToStackL(iAppView);
}
ExecuteLD()在调用后立即返回,并且对话框必须要加到control stack中——使用AddToStack函数,因为非模态对话框不会自己处理这些。
[View体系结构]
使用view的应用程序每次只能有一个活动的view,当另一个view要激活时,当前的view就要被释放。当一个view被释放后,所以的菜单,对话
框以及包含的应用都将被关闭。
每 个view都被当作一个应用UI对待,它必须提供一个Id()函数以便为系统所标识,它也要重载DoActivateL(),DoDeactivate
(),HandleForegroundEventL(),HandlCommandL()和HandleStatusPaneSizeChange() 函数以处理各种事件。
下面一个个的看
DoActivateL()
当客户端要求你的view激活时,它就要被调用。 client可能发送消息参数给你的view,如果你的view已经是激活了,那只有当client明确要求
再次激活时才被调用,所以你的 DoActivateL()实现得应付这种情况,ie已经激活了view。如果你不打算显示view或者你的view不想处理任何
消息,那一个简单的检查 和return即可。
DoDeactive()
这个函数当你的view被注销时调用,view被注销时通常有两种情况:一是你的应用程序要退出了,二是相同程序里另一个view要被激活。这个
函数很重要,咱们可不能忘记了:)
HandleForegroundEventL()
这 个函数主要是在你的view被激活时调用(即在DoActivateL()和DoDeactivate()之间被调用)。当你的view在前台时,它将是
HanleForegroundEvent(ETrue),当你的view移出前台时,它将为HandleForegroundEvent (EFalse),只有当前台状态确实改变时这个函数才会
被调用。
HandleCommandL()
当view菜单产生一个命令后本函数将被调用。
HandleStatusPaneSizeChange()
当client的尺寸由于status pane而改变时,本函数被调用了就。
下面是一个view在接受事件的典型调用顺序
1.DoActivateL()
2.HandleForegroundEventL(ETrue)
3.HandleForegroundEventL(EFalse)
4.DoDeactivate()
其中一对HandleForegrounEventL在view被激活的过程中会发生多次调用。
而DoActivateL()在DoDeactivate()被调用前可能会被多次调用。
View Resources
如果你要使用view来显示pages,那唯一的途径是创建出自己的AVKON_VIEW资源,里面有自己的CBA和菜单,把这个资源的id传递给view的
BaseContructL()函数即可。
RESOURCE AVKON_VIEW r_viewapp_view1
{
hotkeys = r_viewapp_hotkeys;
menubar = r_viewapp_view1_menubar;
cba = R_AVKON_SOFTKEYS_OPTIONS_BACK;
}
注意如果没有给定的menubar资源,那就会使用确省的系统menubar
Construction
下面这个例程是用的AppUI object's ConstructL来构造出view的,使用了AddView来登记,最后把第一个创建的view做为缺省的view了:
void CMyViewArchAppUi::ConstructL()
{
BaseConstructL();
CMyViewArchAppView1* view1 = new(ELeave) CMyViewArchAppView1;
CleanupStack::PushL(view1);
view1->ConstructL();
AddViewL(view1); //Add view1 to CAknAppUi; transfers ownership
CleanupStack::Pop();
CMyViewArchAppView2* view2 = new(ELeave) CMyViewArchAppView2;
AddViewL(View2); // transfer ownership to CAknAppUi
CleanupStack::Pop();
CMyViewArchAppView3* view3 = new(ELeave) CMyViewArchAppView3;
AddViewL(View2); // transfer ownership to CAknAppUi
CleanupStack::Pop();
SetDefaultViewL(*view1);
.......(more code)
要让view发挥作用(注意,一个view自身是没有绘图能力的),它必须拥有得到一个从CCoeControl派生的containers,譬如
class CMyViewArchAppView1Container: public CCoeControl, MCoeControlObserver
下面这个例程将展现编程者自己的CAknView派生类
class CMyViewArchAppView1: public CAknVIew
{
.....
private:
CMyViewArchAppView1Container* iVIew;
}
大家可以看出App里产生了View,View类中有我们必须的Container.
当前激活的view在HandleCommandL()处理命令,这些是自定义功能键和菜单所生成的命令。
void CMyAppView1::HandleCommandL(TInt aCommand)
{
switch (aCommand)
{
case EMyAppCmdSwitchView:
AppUi()->ActivateLocalViewL(KView2Id);
break;
case EAknSoftKeyOk:
{
......
break;
}
case EAknSoftKeyBack:
{
((MEikCommandObserver*)AppUi())->ProcessCommandL(EEikCmdExit);
break;
}
default:
AppUi()->HandleCommandL(aCommand);
break;
}
}
Local View Switching
如果你要切换view,你得提供view的UID
//Now switch the view to view2
iAvkonViewAppUi->ActivateLocalViewL(TUid::Uid(2));
事实上,每个view都有自己的菜单系统,如果你要使用它,应当在AVKON_VIEW资源结构中设置,前面已经讲过了。
而且不管怎么说,如果要使用系统菜单,它的内容在切换之前是一定要更新一次的。
//Switch to a new menu system for the new view
iEikonEnv->AppUiFactory()->MenuBar()->SetMenuTitleResourceId(R_MY_VIEW_ARCH_APP_VIEW2_MENU);
//Now swtich the view to view2
如果要进行远程的视图切换,那就要调用CCoeAppUi::ActivateViewL()函数,并传递了一个包含目标应用程序UID和目标视图UID的TVwsViewId
Leave recovery
Avkon 视图体系结构在DoActivateL()退出时会有个自动的回复机制。系统会调用DoDeactivate()在当前view离去时,回复前一个 view,并把
用户带到之前他们所在的地方。如果程序并没有前一个view的存在,那它就会退出,如果程序前个view就是当前的view(也就是说他们 是重激
活的),则应用程序会试图恢复缺省的view.
说了这么多,那我们在什么情况下采用合适的体系结构那?下面的内容将会有所帮助。
使用传统的SymbianOS体系结构,你要花费大量的时间研究代码是怎么工作的,但大部分交互和错误处理的引擎代码都是现成,可以降低你的开
发难度。
Do you have an acyclic graph shaped navigation structure?
如果你视图程序中的navigation能够as an acyclic gragh,那最好使用dialog体系结构。
Are all the application screens dialog like?
如果你的应用程序想使用对话框,那建议你使用dialog体系结构,注意如果要有一个选择列表,那最好写成包含在dialog中的选择列表。
Does the application have multiple views or modes, which deal with different sorts of data at the top level?
如果是这样,那最好使用传统或view体系结构。
Do external applications need to switch to different views of your application?
如果是采用view体系结构写的程序,那它一定支持多个不同的view,而且是外部程序能访问的。如果你从头开始写一个应用程序,那建议你使
用view体系结构,
否则给我看看有没有现成的代码可利用,不要一味的傻写呵呵。注意,如果一个外部程序使用的显示页面是你的程序所提供的,那你应该在DLL
中处理这个显示页,这个DLL应该是外部程序所能访问的。
Can all of the applications views be exited without loosing user data?
使用view体系的程序必须有能力处理因外部程序而引起的views的释放。如果程序不能自动的释放这些view,那就要考虑其他两种体系了,要么
使用view体系as a message passing system,要么让app UI在传统体系中管理view。
Do external applications need complex interactions with the data in your app?
如果外部程序和你的程序有大量的数据交互,那你最好选择client/server系统。它将减小view的使用量。大量现有的复杂应用,如短信,web
以及通讯录都使用这样的机制,这是个很好的构想,总比要重写他们要好:)
Is there only a single complex main view in the app?
如果是这种情况,那还是使用传统的体系。
<一些例子>
这里给出一些假象例子的解决方案。
App launcher
这种程序可以单独运行并且能切换到其他程序,它只有一个view ,并且不接受外部程序的访问,如果这样会中断它。这样的程序不需要消息的
传递或外部程序需要的views.
Fast swap window
一个在运行时刻的弹出窗口,这是一个睡眠的弹出对话框其实,它没有状态。
Email app
电 子邮件程序可以读或写电子邮件。这个程序有外部使用views,内部可切换的views,并能做中断操作。Notifier信息能告知程序显示一个新
的信 息给用户,所以该程序要有处理此请求的机制,即使在做其他事情时。编辑框可以做为其他程序的view显示,使用DLL形式,我们就可以
做到外部程序的调用 自如。SymbianOS的messaging程序就是一个client/server机制可以在其他程序中被调用。当然要实现内嵌在外部程序中
有许多工 作要做的。当你在写邮件时,很可能又收到新邮件的同志,这个时候新邮件是做为一个嵌套的对话框似的组件显示在里面的,注意,
做这个工作时要特别依赖 inter-application interaction model。
Contacts app
通讯录程序允许进行通讯录的显示、编辑和选择。选择后的结果可以做为其他程序所用。注意它不能因外部view的切换而中断。
通过一个外部程序可访问的dll,通讯录就可以被外部程序所访问。程序本身并不需要views,所以最好使用传统的体系结构编写,而用dialog
应付所有的编辑窗口。
web browser
web浏览器可以做为单一的web上网工具,也可以内嵌在其他的文档中。web浏览器可以通过外部程序可以访问的dll来提供一个UI control,但
并不给外部提供可用的全屏应用。它必须能够应付外界的访问,譬如说应付在点击mail连接后撰写电子邮件的过程。
主体程序主要是用传统的体系结构,也可以采用view体系来应付访问页面的需求。
Settings
我们要关心的是全局设置和特定应用程序的设置。他们不是一回事情。经管他们可能共享一个库,实际上他们互不相干。
设置程序并不需要为外部的访问做什么处理提供什么界面,因此他的编写很简单,用传统的或者基于dialog的体系都可以。而局部设置要注意
必须小心对待外部可能出现的中断,并且他有可能做为一个模态dialog而处理。
Telephony app
电话号码簿程序并不提供外部view,但他必须要处理外部资源的请求。有时候直接用传统的体系去写即可,大部分的外部交互可以通过ETEL
Server.
[应用程序的启动]
从CEikApplication派生的类CAknApplication,他有几个必须重载的函数:
PreDocContructL()
OpenIniFileLC(RFs& aFs)
PreDocConstructL,主要是处理已经构造好的应用程序实体是否正确准备好了。如果已经准备好了,那应用程序可以切换到实体上。注意,这
个函数只检查非内嵌程序。
通常,ini文件并不被series60所支持,如果要处理,那就要强制性的调用CEikApplication::OpenIniFileC
[BASE CLASSES]
CAknDocument
这个类是做为应用程序文档的基类准备的。用这个函数访问文档可以不用初始化。这个是访问Avkon应用程序的比较好的途径。
CAknAppUi
所有的Avkon应用程序必须从这个类派生。
这个类支持下面几个特定应用函数:
KeySound support
Accessories for CBA and StatusPane
TextResolver-Avkon-specific error reporting from CAknAppUI::HandleError()
Avkon view architectrue integration
Control dumping - Debug feature
CAknViewAppUi
所有的视图结构必须由此派生。
《S60_Platform_Application_Framework_Handbook_V20_en.pdf》,其中有些翻译不甚恰当,不过基本上表达了原版的意思。
------------------------------------------------------------------------------------------------------------------
1、开发文档不是很齐全,虽然每个api都能找到说明,但基本上只是很简单的介绍。
实现某个功能根据sdk中的文档,基本上不可能完成。必须寻找相应的demo和其他的源代码来参考。
2、中文资料很少,基本都是英文,对于国内的开发人员来说,这又是一道坎。
3、必须注意内存的操作。比如PushL 和 Pop等等,一些Symbian中特有的机制需要熟练掌握。
4、多线程支持不是很好,多线程中启动的函数必须为静态的或者全局的,
就这点就给一些需要多线城支持的solution带来了很多不便或者根本不能实现。
5、掌握了整个Symbian的framework的基本原理之后,整个机制还是比较明了清晰的。重要的地方是AppUI和View和Container这三个类。
6、www.newlc.com是一个不错的技术网站。强力推荐。
7、一般www.forum.nokia.com上都会有相关的例子demo可以下载,只是比较浅显。
8、注意rss文件中资源的定义和程序中ui控件的结合,很容易出错无法发现。
9、mmp文件的修改之后,必须要重新生成项目文件,不然会导致link 2001之类的错误。
-----------------------------------------------------------------------------------------------------------------
在symbian中,用RThread来操作线程,一个RThread对象代表一个线程的句柄。常用RThead对象来创建或操作其他线程。 RThread的基类是
RHandleBase类,该类封装了句柄的行为。RThread,RProcess,RMutex和RSession-Base都继承自RHandleBase。
创建一个线程
/* Name of the new thread */
_LIT(KThreadName, "MyFirstThread");
/* 下面的函数是线程将要执行的。 参数parm是要传递给线程的数据,它的类型为TAny*,相当标准C中的void* 指针 */
TInt CThreadExampleAppUi::ThreadEntryPoint(TAny* param){ TInt* para = static_cast<TInt *>(param); *para = 1; return 1;}
/* 创建一个属于当前进程的线程,并打开句柄. */
TInt res = iThread.Create(KThreadName, ThreadEntryPoint, KDefaultStackSize, NULL, &iVariable);
/* 线程被创建以后进入等待状态,并不能立即执行. 如果要线程执行,需要调用它的Resume方法*/
iThread.Resume();
停止、删除一个运行的线程。可以调用 Suspend() 来停止一个线程. 但它仍然存在,可以调用 Resume()来继续.如果要彻底删除一个线程,
可调用Kill或Terminate。如果进程的主线程被删除,那么程序也会被终止。
---------------------------------------------------------------------------------------------------------------------
在symbian os上运行的四种软件
应用程序
服务
引擎
内核
symbian系统使用活动对象与客户-服务器对事件处理系统进行了优化
硬件资源:
一个cpu,32位arm
一个rom(只读存储器),里面有操作系统与内建的中间件和应用程序
ROM盘被映射到z:盘,所有的文件都可以通过Z:盘访问。
系统RAM.系统RAM用于两个方面,一是被当前活动的程序和系统核心使用,另一个是当成”C”盘的磁盘空间。这两个部分的大小是变化的,不可
以保留某个的大小。由于RAM通常只有8MB到16MB,所以内存可能用完,因此经常出现内存越界错误或是(写文件时)磁盘已满错误
IO设备,包括带数字笔输入的触摸屏,键盘,记忆卡(被当成D盘),rs232串口,红外口,蓝牙。
电源,包括电池与外接电源
symbian os与pc系统的区别如下:
资源限制:cpu太慢与太少内存
没有硬盘,不能使用写到硬盘的虚拟内存,不能保证有足够的空间保存程序或是数据文件
电源条件严格.
symbian软件环境如下:
server | server| Application| Application | Application Dll
| | +————–+————- boundary
| | | |
| | | Enghine | Engine
——–+———+————+————–+————– Privilege
boundary
Kernel
kernel工作在高级别,管理机器所有硬件资源。对其它软件模块提供访问这些硬件资源的接口
其它应用程序工作在用户模式
上面如果理解普通操作系统如linux的话,那跟普通操作系统没有区别
应用程序是一个有用户界面的程序,在独立的进程中运行
这与普通操作系统也没有区别
服务是没有用户界面的程序.服务管理一个或多个资源,并提供api,让客户可以访问它的服务.服务的客户可以是一个程序或是其它服务.每个服
务也运行在独立的进程空间中。
在symbian中,使用服务的形式提供类似其它操作系统上用驱动程序或是内核程序提供的功能。如文件系统的访问也是客户/服务类型的。(微内
核 )
引擎是一个应用程序中操作数据而不是与用户交互的部分.通常你可以把一个程序分成引擎部分和一个GUI部分,多部symbian内带的程序都是这
样做的。
一个应用程序引擎可以是一个独立的代码模块或是一个独立的dll,或是几个dll.
引擎和应用程序间的边界是模块或dll的边界。
所以在symbian中有四个组件类型与三个边界类型。dll或是模块组件对交叉引用来说很方便。它们使系统模块化与保持封装。
权限边界对交叉引用比较费资源,但是保证系统对用户太程序隐藏内核与设备
进程边界是所有的交叉中最昂贵的,它们保证在ram中分开每个程序
可执行文件的格式
在symbian中有两种类型的可执行文件:
exe,每个程序都有一个主入口E32main()(看上面的例子),它在独立的进程中运行
dll,提供多个入口,由系统或是已存在的线程(进程)调用
有两种类型的dll,
共享库dll,为一个或多个程序提供固定的api,这些dll多数后缀是.dll,当程序启动时就被读到内存中。
多态dll,这些dll实现抽象的api,如一个打印机驱动,socket协议或是一个应用程序。它们的扩展名多不是.dll,而是.prn或.prt或.app等。它
们从与dll相关的类继承,并通常只有在程序需要它们时才读入。
从技术上看起来与普通系统上动态库的静态载入与动态载入没有区别
但是从功能上看就不一样了,一种是实现某种特殊功能的,从某个相关类继承的dll,另一个是普通dll
代码执行
如果程序代码在rom上,则直接执行,不然需要读到ram中(与普通操作系统不同,普通操作系统都需要读到ram中
不能直接在硬盘上执行)
可执行代码包括三种类型的二进制数据:
程序代码
只读静态数据
可写静态数据
在symbian中对待.exe与.dll是不同的
由于.exe是不可共享的,如果它在ram中执行,那与普通pc系统没有区别,如果在ram中执行,那它在ram中为可写静态数据分配内存
而.dll是共享的,当dll首次读入内存中时,它被分配到一个特殊的地址,第二个线程需要这个dll时它只要访问已经存在的这份copy就可以。
在所有使用它的进程中dll的地址都是相同的。symbian系统维护一个引用计数,当没有其它线程引用时才将它unload.
在rom上的dll像rom上的exe一样直接在rom上执行
为了对dll的大小进行优化,symbbian进行如下操作;
多数系统支持通过名字与通过数字访问dll提供的入口,由于名字太长,浪费空间,所以symbian只提供通过数字访问,当然在link时可以通过
名字link.也就是说在.dll中没有名字访问办法,在.lib(引导库,引导linker正确的link这个dll,这个是在windows中使用的概念,在win下每
创建一个dll都会创建一个用户引导链接的同名.lib)中有,你的程序link时link的是.lib,link完成后编译器会自动把引用dll的代码变成数字引
用
如果dll被读到ram,那重定位信息(把dll
load到什么地址)也必须包含在可执行文件格式中,这个的影响就是你不能把一个在rom中执行的程序放到ram中执行的程序.(rom中执行的多是
oem厂家,所以普通开发者多不用关心)
多数应用程序有自己有exe来创建进程,其它的程序使用动态库(DL)L的形式,在主服务线程中调用自己的线程
多数gui程序都是多态(polymorphic)dll,有一个主入口点NewApplication(),这个入口点创建并返回一个继承自CEikAppication的对象.这样的
程序被apprun.exe调用,app文件名为参数传入。
电源管理
电源必须高效使用
在系统已经关机时,确定程序仍然可以运行。如闹钤,关机后,到时时仍然可以开机
电源突然关掉时,关键数据应该可以保存
设备驱动
虽然一般不会了解它,但是理解一下还是很有用的
设备驱动工作在两个级别
第一个是中断服务程序(ISR),ISR必须很短,并且不能做很多事情,因为它可能在任何时间出现,甚至在内核服务中。通常它只是通知设备产
生了中断并设置一个标志,要求内核为第二阶段的处理运行一个延迟的函数调用(delayed function call DFC)
在方便的时候内核调度DFC.DFC可以使用多数的核心api,通常只是工作了后向用户线程通知io操作已经完成
定时器
` 内核支持真机上64hz的时钟与模拟器上10hz的时钟
时钟中断是最高优先级中断,它可以通过User::After或是RTime::After访问。时钟中断在关机时停止,所以如果你请求5s后的定时操作,然后
跑2s,关机,再开机时它也要等3s
内核同时支持日期/时间时钟,你可以使用User::At或是RTime::At。这个定时器很准确。在关机时,如果时间到了,那它会开机,这对闹钟很
合适。
内存
symbian使用内存管理单元(memory management unit MMU)管理内存
ROM被映射到z:盘,被映射到一个固定的地址。
物理RAM被MMU分在4k的页,每个物理页可以用于:
用户进程的虚地址空间。
内核服务的虚地址空间
ram盘,盘符是c:,ram盘只可通过文件服务进程访问
如果dll不在rom中,那它被读到ram,dll被读到ram里面后页面标记为只读只读的。
MMU的页面转换表.如果想理解的话学习一下操作系统原理
自由页表
每个进程的地址空间可以分成下面三类:
系统范围的内存,如系统的rom或是读到ram中的dll
进程范围的内存,如进程的.exe映象和它的可写的静态数据
每个线程的内存,包括线程的栈与线程默认的堆(使用线程默认堆的原因只是为了提高内存分配与释放的速度,从开发角度来看,它与系统里面
的内存没有区别)。
注意没有交换文件,所以所有的内存都是直接使用。同时,也可能会发生内存不够或是磁盘(c 已满错误
每个线程的默认栈很小,只有12k,所以在symbian开发中,不要放太多东西到栈中,一般对象都是在堆中分配的。
线程创建后,它的栈大小就不可再改变。
线程可以使用new或是User::Alloc从线程默认堆中分配内存.如果希望从其它堆中分配内存,只能使用new
动态库(DLL)
symbian中dll不支持可写的静态数据,所以你在里面不可能使用可写的全局变量或是静态变量.
为什么不支持呢?如果支持,那每个进程调用这个dll时,都需要为这个进程分配一个独立的堆,而堆最小单位是4k,系统中有很多堆,并且有很
多程序,所以内存消费基金是很大的。所以就不支持了
这样开发时不是很不方便?因为在dll中有时需要保存自己的状态,进行交互
为了解决这个问题,symbian中引入了线程本地数据(thread-local storage
TLS)概念(查看Dll::Tls
Dll;;SetTls)。但是调用TLS性能比较慢.tls的最大大小是1.8k 通常这够用了。
文件:
c: flash ram盘
z: rom盘
d: 记忆棒之类的外挂盘
事件处理
事件处理模型如下图:
keyborad |—————————
|interrupt
|
kernel/driver–+-isr/dfc
|
key event
|
|
window serv—–handle key event———–+update window
| |
|key event draw |request
application +—————– handle ———-+
key event
在symbian中使用活动对象(active object)来处理事件
在symbian os中,所有的symbian
os线程都是事件处理器,每个线程有一个活动调度对象,加上一个或多个活动对象来处理从设备或其它程序发过来的事件。
每个活动对象都有一个虚拟的成员函数RunL(),在这个函数里面处理事件。
多任务与抢占式
symbian os实现抢占式多线程。
活动对象用于在单个线程内实现非抢占式多任务
--------------------------------------------------------------------------------------------------------------------
SymbianOS6.X Series60界面的智能手机基本手机构造..
SymbianOS6.X Series60界面的智能手机,在插入MMC之后,系统一般存在4个逻辑存储驱动器:C(手机本身的用户存储,SX1有4M),D(虚拟
盘,使用空闲运行内存虚拟的缓冲盘),E(MMC),Z(手机的系统ROM只读)。
4个盘之中,C E Z盘的文件结构大同小异。而D驱动器是高速的虚拟驱动器,主要用来保存剪贴板、wap缓存、和一些临时交换文件,一般情
况下,由系统自动调用,与用户联系不多,不作详细介绍。下面我具体的将C E Z三个驱动器的目录结构和功能讲解一下。 随着安装软件的增
多,C和E盘的目录文件会变得纷繁复杂,我们抛开一些软件自动生成的次要的文件和目录抓住系统的结构谈一些主要的东西:
E盘根目录下:IMAGES SOUNDS VIDEOS目录,顾名思义就是保存了图片铃声视频剪辑,这3个目录等效的出现在C和Z的Nokia目录下,也就是
说把相应类型的文件拷贝到对应的目录都可以被系统识别(Z盘只读除外),举例说明:midi文件或者wav文件拷贝在E:\sounds\digital\或者
C:\nokia\sounds\digital\就可以像Z:\Nokia\Sounds\digital\中固化的音乐文件一样,出现在情景模式铃声的选择项目中。
C:\Nokia是个无关紧要的目录,你完全可以删掉它而没有影响,但是这个目录会经常自动生成。原因是,C盘的Nokia目录中有特别的目录:
INSTALL,很显然这个是为了安装软件而设置的。众所周知,Symbian系统的软件是打成SIS压缩包传入手机的某个存储器中(C、E)然后解包安
装的,系统往往在C:\NOKIA\INSTALL目录下保存一个安装副本,以备安装时遇到不可预见的错误(如突然没电)或者用户中断时能够恢复系统
安全,这也就是很多情况下,在空余很大空间的E盘安装软件时,仍然出现“存储空间已满”的原因,保持C盘有1M以上的空余空间是个很好的
习惯。另外不使用系统的manager转而使用SeleQ进行SIS安装也可以避免产生这个副本。
下面以分析一下结构最为复杂的系统核心C:\system目录。System目录由十几个目录和若干文件组成:
※APPS目录:该目录下的子目录保存了软件的主体即:用户交互可执行文件.app、 资源文件.rsc、 图标文件.aif 、无界面可执行程
序.exe以及运行所需的其他文件。安装在E盘的软件除了在E:\System\Apps\目录下保存软件主体之外,往往会在C:\System\Apps\同名目录下创
建一些配置文件。值得注意的是C:\System\apps\phone\oplogo保存了营运商的标志,如果该目录保存了97*25的bmp图像,则在待机状态下将以
该图片代替“中国移动”之类的营运商标志(需要重新启动手机);
※BootData目录:系统的启动参数和日志;
※Data目录:极其繁杂的目录,保存了各种各样的数据,简单介绍几个,backgroundimage.mbm壁纸,btstate.dat蓝牙配对信息,
Calender日历,clockapp.dat时间参数,Contacts.cdb联系人,以及很多软件的配置文件和wap信息;
※favourites目录:收藏夹;
※install目录:保存了全部的软件安装信息,每安装一个软件,就在该目录下保存一个同名sis文件索引,大小在几百b到几K不等,假如
删除这个sis文件,在程序管理中就不会出现这个软件的安装信息,也就无法通过程序管理删除,但是仍然可以在apps目录中直接删除软件主体
和配置文件,有必要的话在libs目录中删除相应运行库,在programs目录中删除相应辅助运行文件,从而彻底卸载软件;
※libs目录:保存某些软件运行时需要的连接库文件,一般由软件安装;
※mail目录:信息目录,结构复杂费解,除了一些短信、彩信、EMail设置文件之外,收件箱、发件箱、草稿箱、发送报告、附件等等分布
在丛深复杂的目录之中。值得一提的是,S60的信息概念比较广,短信彩信Email甚至红外蓝牙传输的文件都属于“信息”,因此接受到的红外
蓝牙的文件,保存在mail目录下,而且可以由查看该信息触发相应的“安装”、“观看”、“编辑”等动作;
※MIDIets目录:java配置文件;
※midp目录:java程序主体安装在这里,如果全部java安装在E盘,C:\system\将不会出现这个目录;
※Programs目录:保存辅助运行文件,和一些无界面程序exe、动态连接库dll;
※Recogs目录:关联目录,里面的mdl文件标识了文件关联。如QuickWord.mdl标识了系统中的doc文件默认由quickword打开,另外有些mdl
文件会驱动程序运行,如eLoader.mdl驱动了miniGPS、ExtendProfile等ePsint公司开发的软件,没有这个mdl文件,以上两个软件不能自动加
载;
※Schedules目录:顾名思义,保存了日程安排;
※SharedData目录:全部是软件的配置文件.ini,对用户作用不大,但是可以通过修改其中的某些数值和路径从而使必须安装在C盘的软件
(多半是7650的软件,它没有mmc)安装到mmc;
※Temp目录:临时文件。
E:\system目录结构与C:\system基本一致,不同的是,少了intsall目录。
Z:\system比之C:\system更加庞大复杂,它保存了系统的全部自带程序、资源文件、硬件驱动、字体字库、国际化设置和初始参数设置。
在待机状态下输入*#7370#,将初始化手机,基本过程就是清空C盘,复制Z盘某些内容至C。某种程度上说Z是系统的初始备份。(新手机的第
一幅待机图就保存在Z:\system\data\apac.mbm)
关于路径问题。由于三个盘的system目录结构是相似的,所以同名路径所起到的作用相同,比如E:\system\recogs目录下的关联文件同样
可以起到关联作用,libs等目录类同(有些情况下将C的内容移动到E相应路径中,需要在C:\system\SharedData\对相应的ini文件进行修改)
,而在E(C):\system\下建立Fonts目录则可以加入新的系统字体。只有install目录仅仅在C:\system\下才有效。
了解S60系统的文件结构,对于我们使用手机有着很大帮助,可以最大限度的获取运行空间、了解错误产生的原因,有意识的避免可能会带
来伤害的操作。本文仅仅对文件结构做了初步的探讨和应用层面上的解释,进一步的研究可以在西门子和诺基亚论坛的官方文档得到全面解答
。希望有所帮助。
---------------------------------------------------------------------------------------------------------
数据类型 描述
TInt8, TUint8 8位 整数
TInt16, TUint16 16位 整数
TInt32, TUint32 32位 整数
TInt, TUint (32位)整数
TReal32,TReal64 实数
TText8, TText16 字符, 相当于 unsigned char, unsigned short int
TBool 布尔
TAny 相当于void
代码规范
Symbian OS 使用很多代码规范, 使用他们可以增强Symbain 代码的可读性, 有些规范甚至是需要严格遵守的, 比如类的命名:
Symbian OS的类一共有6种: 种类 例子 描述
T classes TDesC, TPoint 这个类可以向基本类型一样使用,因为他们通常很小,而且不使用heap所以也没有析构函数
C classes CConsoleBase, CActive 这个类是Symbian使用最多的类,C代表他们从CBase类继承而来, 他们必须有析构函数因为他们的对象创
建在heap中
R classes RFile, RTimer R代表资源(Resource),它们只是一个系统资源的句柄,他们本身被创建在Stack上, 但是他们所使用的资源被创
建在heap上,使用完毕需要Close()
M classes MEikMenuObserver 这个类是一个空的接口,使用的时候需要从它继承
static classes User, Math 这个类只有静态函数, 一般都是库函数
Structs SEikControlInfo c - struct
变量命名:
种类 例子 描述
枚举 EMonday,ETuesday E代表枚举
定量 KMaxFileName K代表定量
成员变量 iDevice, iX i代表成员变量
参数 aDevice, aX a代表参数
局部变量 device, x 局部变量没有固定的规范
-------------------------------------------------------------------------------------------------------
对Symbian一无所知,当然只能从基础学起了,也许看一个例子再来看看基础更简单些。而我这人比较守旧,就是学不会这种方法,还只能从基
础开始。
Symbian的字符串和描述符:
TPtrC、TBufC、HBufC 是从TDesC派生而来的具体的描述符类型。TPtr和TBuf这两个都是从TDes派生来,而TDes又是从TDesC派生而来。因此
TDes在TDesC上加了一些常量便利函数。
TDesC
/ | \
/ TBufCBase TDes
TPtrC
| | \
TBufC、HBufC Tptr TBuf
TDesC和TDes是抽象类。
_LIT它把一个符号和一个文字值联合起来,并且产生TlitC,TlitC的二进制形式与TBuf的二进制形式是一样的,因此可以把TLitC作为TDesC类
来代替。_LIT(he,"he"); const TDesc& hehe = he;
_L产生一个TPtrC,并且不用制定名称也可以用。 const TDesC& he = _L("he");
_L与_LIT的区别就在于,_L需要开辟临时的栈区。