第三版中的ETel库
受争议的ETel库在第三版中已经去掉了,去掉的库包括ETel Core和ETel MM(etel.h和etelmm.h),在第三版中之后一个公共的电话API将被提供那就是CTelephony API(etel3rdparty.h和etel3rdparty.lib)
安全共享数据及数据库加密
从Symbian OS v9.x后就不再提供数据库加密机制了,保护你数据库不被其他程序访问的唯一方法就是将数据库文件存储在你的私人数据空间。不过这样其他程序也就没法访问 到它了。
Symbian OS v9.x中所介绍的安全共享数据库的方法为,通过data caging机制保护并共享数据。
数据库是通过DBMS client-serve API来生成并被访问的。数据库文件被存储在DBMS server的data cage文件夹中。DBMS server根据与此数据库预先关联的安全法则允许其他客户端程序去访问它。这种安全法则可以规定客户端只能具有ReadDeviceData能力。为了 向数据库写入东西,客户端得具有WriteDeviceData能力,和一个给定的Secure ID(SID)
不幸的是,安全法则目前只能存放在Z盘中。这意味着第三方开发者无法定义或安装他们自己的安全法则。同样,当第三方程序需要使用一个好的方法来同享数据库 时,也没有能使用的预先配置的法则。
如果你的程序需要访问一个共享数据库,那下列选项是可以考虑的:
将数据库存放在一个共同目录下(如果不需要考虑安全性问题)
为你的服务提供一个API以访问存储在自己
If for your applications require access to a shared database, the options available are
- share a database stored in a public folder (if there are no security concerns)
- write your own server that provides an API to access a database stored in its own data cage folder.
If data encryption needs to be used, you must provide your own encryption mechanism in both cases.
S60第三版中对messaging components(MTM)的性能需求
S60第三版上,因为平台安全性的考虑,对公共DLL有很多要求。
这会在下列方面影响messaging component(MTM)的开发使用:
所有public-size MTM component都需要“ALL-TCB”属性,因为他们要被其他public-side application所加载(这些程序拥有设置其的能力)
Public-side MTM component主要为:Client MTM, UI MTM, 以及UI Data MTM.
而private-side MTM component既Server MTM,要和加载进程拥有一样的能力。你的server-side MTM component应该拥有下列能力:
ReadDeviceData, WriteDeviceData, ProtServ, NetworkControl, NetworkServices, LocalServices, ReadUserData.
Given these heavy capability requirements any MTM implementation has to go through the Symbian Signed process and will need to assign all needed UIDs from the protected UID range (0×00000000 - 0×7FFFFFFF).
实现Tab页
carbide.c++编程非常考验人的是所有的资源必须自己定义,然后在程序中引用这些自定义的资源。这让习惯了windows可视化编程的程序员非常 的头痛。不过也好,这样更能让我们清楚地了解到symbian资源文件的结构和调用方法。
实现Tab页,首先要在.rss文件中定义Tab页所需要的资源,其中包括Tab页的数量,Tab页的Title。然后在***AppUI.cpp 文件的construct函数中生成该Tab页。其次,还要在***container.cpp文件的按键处理事件中编写相关的代码,以实现Tab页的切 换。
带完整键盘的S60第三版设备上的按键映射
设备, 软件 版本: S60 3rd Edition
说明:
在一些S60第三版手机 上 有完整的键盘,其中一些键值只有通过FEP模式下编辑框才能获得
详细描述:
在Nokia E61以及E70等带全键盘的机器上运行的程序时,如果要捕捉CCoeControl派生类下的按键事件时,在FEP模式下的编辑框中是无法获取同样键值 的(通过TKeyEvent::iCode)。
这是因为QWERTY键盘的映射是依赖于当前的语言和输入模式的。例如,在Nokia E61上,CCoeControl派生类在数字键盘被按下时总是获得1,2,3。。。。而只有在FEP模式下的编辑框中(如CEikEdwin)它才能获 取字母键”r”,”t”,。。。等。
注意scan codes(TKeyEvent::iScanCode)是不会受当前语言或输入模式影响的。
解决方案:
应用程序在处理文本输入时,应该使用表示准的Avkon编辑框控件。
2007-4-11 08:11 Moving
S60第三版SDK中MMF框架API的问题
详细描述:
S60第三版SDK中缺少MMF Controller Framework头文件和库,这样的话,我们将不会搜索到关于MMF的信息和媒体格式插件,这将导致一些MMF的相关引用。如 CVideoRecorderUtility在构造时就需要Controller和格式UIDs。
解决方案:
MMF Controller Framework的支持将有望在s60第三版后面加入
SymExpat 面向OS 9.x的端口
起初我认为把SyEpxpat应用于OS 9.x的端口将会引起一系列的变化。然而,结果却并非如此。 最简单的修订是针对xmlparse.c的. 看起来expat 开发人员把返回代码枚举和错误代码枚举混为一谈,因此对于主要expat 源编码来说更改它就足够了。
一个稍微有点欺骗性的问题是由GCCE带来的。看起来其似乎对XMLCALL进行了一些定义。似乎 GCCE认为它支持微软 扩展,但实际上只 在有些情况下可行。
我认为这一问题的根源是_MSC_EXTENSIONS。因此为了修订它,首先,我们需要确定expat-config.h 是在源文件中expat.h文件之前定义的,之后便是定义XML调用并且停止运行expat-external.h使之恢复默认设定。
唯一的改变是让SyExpat.cpp 文件在包含expat.h 之前包含expat-config 文件,因为它设立了一套定义,并具体说明了功能是怎样输出的,同时由此选出那些并没有被正确处理的输出申明。
因此,我们仅定义了空的XML调用并将其补充进入编译器主题。更多信息请查看expat_config.h。
现在便可为OS9.x充分的建立SyExpat, 并且仍旧保留其向后的兼容性。不幸的是我遇到一个关于Carbide.vs 和标准C库的糟糕问题,详细情况如下:
http://discussion.forum.nokia.com/forum/showthread.php?t=75575 因此,即使项目在维护期,目前看起来需要解决的重要问题首先是对OS9相关主题进行修订。
由HelloWorld想到的
对于一个symbian GUI应用程序,必须实现四个类:
(1)应用程序类(HelloWorldApp.cpp)
该类用于定义应用程序的属性,还用于生成新的空白文档,以及传递UID信息。
(2)文档类(HelloWorldDocument.cpp)
该类表示应用程序的数据模式,负责保存和恢复应用程序的数据,以及创建应用程序的用户UI接口。
(3)应用程序UI接口类(HelloWorldAppUi.cpp)
该类是完全不可见的,它创建一个应用程序视图,并且处理菜单等32位命令的相应手段。
(4)应用程序视图类(HelloWorldContainer.cpp)
这是一个具体的控件类,它的目的是在屏幕上显示应用程序数据,并允许用户交互。
通过这几个类的作用,可以得出一个程序的启动过程如下:
HelloWorldApp.cpp—–>HelloWorldDocument.cpp——>HelloWorldAppUi.cpp——>HelloWorldContainer.cpp
周期类: Cperiodic
CPeriodic* iPeriodicTimer;
iPeriodicTimer = CPeriodic::NewL( CActive::EPriorityStandard );//这条语句一般在ConstructL()中
void CGraphicsAppView::StartTimer()//开始启动时钟
{
if ( !iPeriodicTimer->IsActive() )
{iPeriodicTimer->Start( 1, 1,
TCallBack( CGraphicsAppView::Period, this ) );//TcallBack是一个方法回调函数,从使用来看,他只能回调类中的静态方法。
}
}
TInt CGraphicsAppView::Period( TAny* aPtr )//周期启动函数,注意,这是个静态函数,但static只在头文件中才做了申明。
{
( static_cast( aPtr ) )->DoPeriodTask();
return ETrue;
}
void CGraphicsAppView::DoPeriodTask()//周期真正在做的事情
{
// Update the screen
CWindowGc& gc = SystemGc();
gc.Activate( *DrawableWindow() );
UpdateDisplay();///这个函数是关键的关键
gc.Deactivate();
}
void CGraphicsAppView::StopTiem()//停止时钟
{
if ( iPeriodicTimer->IsActive() )
{
iPeriodicTimer->Cancel();
字符串类:
HBufC* textResource;
//两种字符串附值方法
textResource = StringLoader::LoadLC( R_HEWP_TIME_FORMAT_ERROR );
textResource =iEikonEnv->AllocReadResourceL(R_EXAMPLE_TEXT_HELLO);
TBuf<32> timeAsText;
timeAsText = *textResource;
编译命令
1. bldmake bldfiles
2. abld build wins udeb
3. abld makefile vc6
4. epoc
5. abld reallyclean
有了以上的基础,我们就可以编译sis文件了. 一共分为2步:
1. 进入到/group目录下, 输入bldmake bldfiles, 和以前讲过的作用一样, 然后: abld build thumb urel, “abld build”是编译命令, “thumb urel”是编译目标, 一般手机的格式都是thumb, 用命令行为windows编译的话,就可以用 abld build wins udeb (urel). “udeb” 代表debug build, “urel”代表release build, 前者用于开发,后者用于发行。
2. 进入/sis, 输入makesis Helloworldbasic.pkg, 然后Helloworldbasic.sis就被创建了。
怎么在一个view类中响应按键消息
TKeyResponse CAknExEditorContainer9::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
{
return iListBox->OfferKeyEventL(aKeyEvent, aType);
}
Panic的含义
原意是报错,异常,紧急状态。
也就是程序的意外情况,symbian中用于弹出系统的异常对话框,并结束程序。
举例
Most of the functions here return void because if they fail the server will panic the client.
大部分函数都返回void值,这是因为如果他们出错了,那server端会通知client出了意外情况。
S60和Symbian的头文件
#include
时会直接到系统包含路径下去寻找aknappui.h
(这不同于#include “aknappui.h”,还会到用户包含路径中去寻找)。
系统包含路径也就是在工程的.mmp文件中定义的:
SYSTEMINCLUDE /epoc32/include,
其真实的路径也就是:
%EPOCROOT%/epoc32/include,
在你的机器上如果系统变量EPOCROOT=/Symbian/9.1/S60_3rd/,那么它就是/Symbian/9.1/S60_3rd/ Epoc32/include,也就是说本来是应该能找到的,但是依据你的错误,此时你的EPOCROOT=/Symbian/Symbian8.1b/ bin/bak/,你可以试试把EPOCROOT设置成/Symbian/9.1/S60_3rd/。
另外工程文件夹最好放在%EPOCROOT%/Series60Ex下。
通过Uid来获取应用程序的路径
TFileName f = EikAppUi( ).Application( )->AppFullName( );//得到当前应用的全路径名
TParse parse;
parse.Set( f,NULL,NULL );
parse.DriveAndPath( );//得到最终的纯路径
[ 本帖最后由 Moving 于 2007-4-11 08:15 编辑 ]
2007-4-11 08:17 Moving
EPOCROOT环境变量的作用和设置
.mmp经Perl脚本的处理生成VC等IDE的工程文件,Perl脚本在处理时认为EPOCROOT环境变量所指的是SDK的安装目录,由此将 include等目录的路径生成到工程文件里,只要以文本方式打开.dsp文件就能看到。
如果只有一个SDK,把EPOCROOT设置成该SDK的安装目录就好。
如果有多个SDK,使用下面的办法可以很方便地解决多SDK并存的问题:
1. 首先添加一个环境变量EPOCROOT:
EPOCROOT=/
2. 然后用SUBST把SDK的安装目录虚成一个盘:
subst x: C:/Symbian/Series60_1_2_CW
上面以Series 60 SDK 1.2默认安装的路径为例,如果装了多个SDK就虚成不同的盘,所有的操作(包括Build等)都在虚出来的盘上进行。这样在切换SDK时不需要其它额外 操作。
如果只执行了1而没有执行2就会出错,比如”C:/EPOC32/BUILD/PROJECT/TEST1″,显然它是把C盘根目录当前了SDK的安 装目录了。如果正确地虚了盘。
各种编译模式之间的区别
基于ARM设备(ARMI, ARM4和THUMB),目前有三种生成版本:
ARMI—-可执行文件将与其它两种生成版本一起工作,一般情况下,应当在生成ARMI二进制版本时,实现最大数量的真实设备兼容性.
ARM4—-生成以增加代码大小为代价获得最佳性能.
THUMB—-生成将以稍微降低执行速度为代价而减小代码大小
WINS和WINSCW编译方式是为了在模拟器上看到效果,在程序调试完成后需要使用ARMI,ARM4,THUMB三种模式中的一种编译成为能够在手机 上运行的程序,一般使用ARMI方式。
Symbian程序的生成模式
WINS和WINSCW就是编译在windows上运行的模拟器的程序,它们之间的区别仅仅是使用不同的编译器生成的而已。WINS - VC、BC; WINSCW - Code Warrior
对于在基于ARM设备的真机上运行的程序,目前则有ARMI, ARM4和THUMB这三种生成模式:
ARM4 - 最快速度优化,以增加代码大小为代价。
THUMB - 最小代码优化,以降低运行速度为代价。
ARMI - 同时执行以上两种的最大优化,一般在最终的程序都以这种方式生成,但应该在尽量多的支持设备上测试,以保证兼容性。
2007-4-17 08:13 Cotuvdi
SIS文件中的Vendor信息在软件 各版本中不应更改
说明:
当在S60第三版上升级一个程序时,在新的SIS包中的vendor信息必须和以往安装的一致。
详细描述:
Vendor信息在pkg文件中是强制需要的:
; localized vendor name(s) (corresponding to language),
; displayed during installation
%{”Vendor-EN”, …}
; non-localized (global) vendor name
:{”Unique Vendor”}
要注意的是,升级包中non-localized vendor string需要和已安装在设备中的一致。
这是为了和签名一致,防止未认证的升级包代替合法vendor.
如果vendor string新旧不一致的话,在安装时就会报告“Update error”的错误信息
在S60第三版SIS文件中指定平台依赖属性
说明:
pkg文件中需要指定平台依赖属性那行的格式在S60第三版中已经做了更改。
详细描述:
在S60第二版中,我们要在pkg中指定软件平台依赖性时,必须遵循下列格式。
; Supports S60 2nd Edition
(0×101F7960), 0, 0, 0, {”Series60ProductID”}
(0×101F7960), 0, 0, 0,
在S60第三版中,平台依赖性是从硬件依赖考虑的,而平台UID必须是用中括号来定义:
; Supports S60 3rd Edition
[0×101F7961], 0, 0, 0, {”Series60ProductID”}
而老的定义形式在S60第三版中的pkg文件中仍然有效,makesis执行时不会提示错误。不过如果要安装这样形式的SIS文件到第三版设备上将会引发 “Application not compatible” 错误。因为安装程序无法识别平台UID。
一些支持自定义产生pkg文件的工具及IDE可能仍然在使用老格式,这个需要注意。
解决方案:
检查那些为生成在S60第三版上SIS包的pkg文件中,关于平台依赖性设置的格式是否正确。
SIS包和本地化资源文件
概况:
当使用本地化资源文件为程序添加了多语言支持后,下面一个步骤就是将他们加入.pkg文件,并生成SIS包。
有两个方法来完成这个任务:
将资源打包在.pkg文件时,可选择语言相关方式也可以选择语言无关方式。
语言无关文件:
下列文件都别拷贝到目标机器上,而不管其语言设置或用户选择。
“MyApp.r01″ - “!:/system/apps/MyApp/MyApp.r01″ ; 01=English
“MyApp.r02″ - “!:/system/apps/MyApp/MyApp.r02″ ; 02=French
“MyApp.r03″ - “!:/system/apps/MyApp/MyApp.r03″ ; 03=German
; etc (see TLanguage in e32std.h for all lang. enumerations)
由程序框架根据当前语言设置决定,在程序运行时载入哪种语言。将所有资源文件都拷贝在设备将增长内存消耗,但另一个方面,程序也能支持设备当前语言(可能 需要重启后才能更改语言设置)
语言相关文件:
设计一个文件列表,只能根据用户在安装时选的语言来安装一个。文件的顺序和个数必须和.pkg文件中语言行指定的一致:
{ “MyApp.r01″,
“MyApp.r02″,
“MyApp.r03″ } - “!:/system/apps/MyApp/MyApp.rsc”
因为只有一个本地化资源文件能被拷贝,程序将不支持设备上的语言设置,改变程序的语言将需要重新安装一次。
总结:
我们在选择何种方法时应该着重考虑所有本地化资源文件加在一起的大小,以及程序是否要去支持设备上的语言设置更改。
在/private目录下存储应用程序图片文件
说明:
如果图片文件存放在受保护目录下,则在S60第三版上使用AknIconUtils加载图标或图片可能会引发错误。
详细描述:
如果图片文件aFileName存放在一个受保护目录下,如/private//下,则在S60第三版中使用AknIconUitls的下列方法 (akniconutils.h)时将会引发错误:
void CreateIconL( CFbsBitmap *&aBitmap,
CFbsBitmap *&aMask,
const TDesC &aFileName,
TInt aBitmapId,
TInt aMaskId )
这是因为Avkon icon server无法访问存放在保护目录下的文件。
案例重现:
在这种情况下AknIconUtils::CreateIconL()不会引发异常,不管怎么说,aBitmap和aMask参数将不会指向有效位图。如 果尝试使用返回的位图将会引发错误异常。
例如,尝试使用AknIconUtils::SetSize()设置位图大小时会引发error -46(KErrPermissionDenied)
解决方案:
不要将文件名传递到CAknIconUtils,程序应当完成max-in类MAknIconFileProvider,以便提供一个打开的文件句柄给 Avkon icon server.
CAknIconUtils有一个可供重载的CreateIconL()方法以便接收一个MAknIconFileProvider示例。
这里提供一个完成MAknIconFileProvider 类的示例,请S60 Platform: Scalable Screen-Drawing Example, 可在http://www.forum.nokia.com/下载
注意:包含应用程序图标的.mbm和.mif文件(会在LOCALISABLE_APP_INFO资源定义中被引用)应该永远安装在/resource /apps/.目录下。
CVideoPlayerUtility::SetRotationL()崩溃或错误现象
说明:
调用CVideoPlayerUtility中的SetRotationL()方法会产生错误结果,甚至导致设备重启。
详细描述:
使用 CVideoPlayerUtility::SetRotationL(TVideoRotation aRotation)时,将参数aRotation设置为EVideoRotationClockwise180 或EVideoRotationClockwise270,这样可能导致设备重启或旋转后的画面扭曲难看。
如果参数为EVideoRotationClockwise90 那将没有这方面的问题。
解决方案:
在CVideoPlayerUtility中使用90度顺时针方面。在7-11-2005后的版本中已经修正了这个问题。
自定义CMdaAudioInputStream的buffer大小
详细描述:
对S60 MMF客户端音频程序来说,处理S60设备中输入流时,是否可以自定义buffer的大小。
解决方案:
在S60 MMF架构中缺省的声音I/O数据buffer大小是根据声音硬件和音频编码性能来分配的。使用CMdaAudioInputStream的客户端程序将 考虑到下列局限:
但使用PCM16(缺省)格式时:
声音设备返回的input buffer总是320个字节(S60第二版,FP2和FP3)或4096字节(S60第三版)。这也是调用 CMdaAudioInputStream::ReadL()所能返回最大数据长度,因此不建议超过此限度大小。
如果传递到客户端ReadL()中的buffer小于该大小,那服务端buffer就会被组成适合大小的块以便传入。如果这样操作后还有剩余,就不会满足 这里最大长度大小。例如,当在S60第三版中使用一个
3840字节的buffer大小时,第一个返回的buffer为3840字节,而下一个就是(4096-3840)256字节,然后再这样重复继续。
当使用非PCM格式处理流时:
对一个压缩音频格式,每个返回的input buffer都典型的包括一个音频数据的单独帧。例如,当使用AMR-NB格式时(在MaiscComplete()方法):
iInputStream->SetDataTypeL(KMMFFourCCCodeAMR);
调用后,每次返回buffer将包括14个字节(一个单独的AMR-NB frame in ,5.15 kbit/s)可演绎20ms of audio data;
自签名程序的UID
S60第三版对所有安装程序引进了强制签名机制。如果一个应用程序没有capabilites属性或仅使用了开放给所有人的capabilites属性, 它可以生成一个新证书,并用它来签名。所有的免费程序都
可以这样处理。
更多关于自签名证书的信息可通过查看SDK帮助获取:Introduction to S60 3rd Edition >> How to Sign .sis Files.
使用自签名证书意味着该程序被看做不可信任的,不可信任的程序应该使用unprotected range of UIDs下的唯一标识。否则安装在第三版设备上将会导致失败。
Protected UID range: 0×00000000 … 0×7FFFFFFF
Unprotected UID range: 0×80000000 … 0xFFFFFFFF
特别要指出的是,有两组重要的未保护UID范围:
UIDs for self-signed app. releases: 0xA0000000 … 0xAFFFFFFF
UIDs for test/development use: 0xE0000000 … 0xEFFFFFFF
UID的分配是由symbian公司来管理的,要获得更多相关方面的信息请参考http://www.symbiansigned.com
RHostResolver和选择接入点对话框重复显示的问题
说明:
使用一个服务器解析服务时(RHostResolver)可能会引发选择接入点对话框的重复显示
详细描述:
在S60第三版上,当前已有连接的状态下使用服务器解析服务(RHostResolver)时将导致选择接入点对话框不停重复出现。
案例重现:
连接socket server(RSocketServ),打开一个RConnection示例:
iSocketServer.Connect();
iConnection.(iSocketServer);
这样就开始了一个internet连接:
iConnection.Start();
这时会出现一个选择接入点对话框,要选择一个适当的访问接入点。
在连接已经建立后,使用RHostResolver打开一个DNS resolver session,并开始尝试解析一个主机名:
iResolver.(iSocketServer, KAfInet, KProtocolInetUdp);
iResolver.GetByName(someHost, iResult);
这时选择接入点对话框会会再次出现。
解决方案:
传递当前RConnection示例到host resolver中:
iResolver.(iSocketServer, KAfInet, KProtocolInetUdp, iConnection);
2007-4-17 08:18 Cotuvdi
文件存取类的改进
1、用函数取文件路径
原来我使用的静态路径,这样有很大的局限性。现在改用
TFileName strFileName = NEikonEnvironment::ApplicationDriveAndPath();
strFileName.Append(KFirewallRuleFileName);
其中黑体函数是取得应用程序所在的路径。
该函数的使用需要包含头文件EikonEnvironment.h,该文件不在系统包含路径中,需要将其和对应的CPP文件从C:/Symbian /8.1a/S60_2nd_FP3/Series60Ex/helperfunctions路径中拷贝到自己的文件目录中。
(实际使用中出现了KERN-EXEC 3的错误,正在调试)
2、用BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), strFileName)判断文件的存在
原来我直接用writer.Replace(iFs, KFirewallRuleFileName, EFileWrite),该函数的特点是不论有没有该文件,都创建新的文件,那么如果文件存在则文件内容被清空,这个有点不太好,所以改之。
怎样为SettingsList赋值
为设置列表的列表项设置值,有点拗口,大体意思是,如果用户不满意自己的设置,想把它设置回默认值的操作。
问题核心:怎样为SettingsList赋值的问题。
解决方法:iListBox->LoadSettingsL()
首先看一下创建设置列表函数CreateSettingListL(TInt aIdentifier)的重载,代码如下:
1 CAknSettingItem* CFirewallSettingList::CreateSettingItemL( TInt aIdentifier)
2 {
3 CAknSettingItem* settingItem = NULL ;
4
5 switch (aIdentifier)
6 {
7 case ESettingItemSizeLogFile:
8 settingItem = new (ELeave) CAknIntegerEdwinSettingItem(aIdentifier, iData->iSizeOfLogfile) ;
9 break ;
10 case ESettingItemIsRecordLog:
11 settingItem = new (ELeave) CAknBinaryPopupSettingItem(aIdentifier, iData->iIsRecordLog) ;
12 break ;
13 case ESettingItemDefaultAction:
14 settingItem = new (ELeave) CAknEnumeratedTextPopupSettingItem(aIdentifier, iData->iDefaultAction) ;
15 break ;
16 case ESettingItemIsAutostart:
17 settingItem = new (ELeave) CAknBinaryPopupSettingItem(aIdentifier, iData->iIsAutoStart) ;
18 break ;
19 default:
20 break;
21 }
22 return settingItem ;
23 }
24 第8、11、14、17行是用来创建设置列表的列表项,可以看出我们用了三种设置列表。
例如:CAknIntegerEdwinSettingItem(aIdentifier, iData->iSizeOfLogfile) 这个函数,其中第二个参数为我们要给该项赋值的值。
通过从新设置iData的值,然后调用LoadSettingsListL()函数,就会将iData的值重新送给SettingsList,然后将新值 显示出来。
在通话时捕捉到结束键(红色键)
我们可以使用下列代码在通话时捕捉到结束键。
Please note that SwEvent capability is needed to make successful calls to the mentioned Window Server functions.
Code:
#include // link against ws32.lib
#include
…
RWindowGroup& groupWin = CCoeEnv::Static()->RootWin();
TInt endKey1 = groupWin.CaptureKeyUpAndDowns( EStdKeyNo, 0, 0 );
TInt endKey2 = groupWin.CaptureKey( EKeyNo, 0, 0 );
// -> End key can now be processed before the phone application of the device…
…
// Cancel the capture
groupWin.CancelCaptureKeyUpAndDowns( endKey1 );
groupWin.CancelCaptureKey( endKey2 );
上述代码已经在N73(SW: 2.0620.0.05)上测试通过
在ETel第三方API(CTelephony)中使用User::WaitForRequest()应注意的问题
ETel第三方API(即CTelephony)是做为异步模式来设计的,从一个活动对象调用它的方法,然后就等待这个方法的完成。做为活动对象所定义的 概念来说,一次只能有个一个active request存在。
Telephony的异步工作模式使得它无论何时检测到一个方法被调用时(这时TRequestStatus参数被传入该方法),已经是 KRequestPending状态的情况下,都会引发一个异常(Telephony 0)。
一般在Symbian程序员中流传的使异步变同步的方法就是调用User::WaitForRequest来锁定该线程直到方法完成(这个方法是不被提倡 的)
这样做主要有两个问题:
1、异步工作模式可能会花费较长的执行时间才能完成,这样线程就一直处于阻塞模式下,这样可能会引发VIEWSERV 11异常(参考Symbian FAQ-0920)
2、该异步方法的完成可能依靠同一个线城中其他活动对象的工作,而如果阻塞线程的话,那这个异步工作将永远无法完结。
我们在一个具体的CTelephony事例中来考虑问题:
CTelephony::TBatteryInfoV1 batterystrength;
CTelephony::TBatteryInfoV1Pckg battery(batterystrength);
CTelephony* tel = CTelephony::NewLC();
TRequestStatus status = KRequestPending; // (1)
tel->GetBatteryInfo(status, battery);
User::WaitForRequest(myStat); // (2)
…
CleanupStack::PopAndDestroy();
这个将意味着:
1、TRequestStatus变量被初始化为KRequestPending(第(1)行),这是一个常见的错误,会引发CTelephony报 Telephony 0错误(如上所述),注意一般来说是没有必要对TRequestStatus进行初始化的。
2、如果第(1)行被删除,那代码也永远无法回到第(2)行,因为在线程被阻塞的情况下CTelephony的异步方法是无法被完成的。
结论就是CTelephony应该一直使用异步工作模式,另外使用User::WaitForRequest时一定要谨慎。
程序的自启动的动态配置
目前,在S60第三版中,如果一个程序想要自启动,你可以通过启动列表管理API来完成它。具体信息可以在S60 3rd Edition SDK中找到。
为了进行Symbian Signed criteria的传递,你需要在你的程序中提供对自启动的取消功能。暂时没有公开的API可以帮助你解决这个问题,下面有两个解决方案:
1)设计一个启动程序,它可用来启动一个实际的应用程序。无论手机何时启动该启动程序需被自动开启。然后它检查配置文件(.ini),如果配置文件中该 boot选项被标记为开启,那就去启动响应的实际程序,如果为关闭,那就终止自己,当然也不需要去启动实际程序了。
注意在启动程序成功启动实际程序后它不能立刻将自己结束掉,否则实际程序将因此而无法成功运行。
在实际运用中,第三方程序可以找到一个公共位置去存放配置文件,或者为两个程序(启动程序和实际程序)准备一个公共的secure ID。RVCT编译程序可以帮助你解决这个问题。
2)你也可以安排手机开启后每次都去启动实际程序,在开始阶段就去检查配置文件,如果其中的flag被标记为ON,则继续运行它自己,如果flag被标记 为OFF,则需要调用CAknAppUi::Exit()函数来结束自己。
同第一个方案相比,这个方法不需要去解决两个程序同时拥有一个secure ID的问题。这样如果程序十分大,并且用户不是选择每次都自启动的话,我们可以花费更多CPU时间在加载程序上。
从Symbian Singed的角度来看,第二个方法要优于第一个。
如果控制一个进程中的堆分配
我的程序试图从堆上分配一定内存,却产生了失败。我该怎么做才能分配到更多内存呢?
我们可以在.mmp中通过EPOCHEAPSIZE命令直接来保留或压缩一定内存空间,这样进程在启动时就能使用。
Syntax: epocheapsize minimum maximum
最小值(以字节为单位,一般为4K左右)以保证进程的正常运行。
最大值说明进行所能使用内存的数量限度。
要获取更多信息可参考Symbian FAQ知识库:
http://www3.symbian.com/faq.nsf/0/8D…5?Document
在S60上编写一个有发送短信功能的程序
根据下面Forum Nokia上的示例来写一个具有短信发送能力的程序是很简单的。根据不同的目标平台,有两种方法可选择,在早期的S60和S80设备上一般使用一个客户端 的MTM API,而S60第三版中
则介绍了一个更为高级易用的API。
2nd Edition platforms:
在S60第二版和S80平台上如果要发送SMS程序可以直接使用SMS Client MTM来进行信息发送。早期的平台上对开发者来说主要的问题是其中一部分需要的API不是公开的,不过在S60 2nd和S80 2nd中已经解决了。
Forum Nokia已有SMS示例,它将教你一步步来生成并发送一个短信。可以通过下列连接查看:
S60 Platform: SMS Example
http://www.forum.nokia.com/info/sw.n…_0_en.zip.html
3rd Edition:
在S60第三版上通过新的SendAs API我们可以更加容易的发送短信。这是封装在messaging client MTMs上的API,通过它们你的程序可以去访问所有支持的messaging protocol,而不光是sms messaging。
S60第三版也支持对MTM的直接使用。
可以通过下列连接去找到在MTM方法和新的SendAs方法的示例:
S60 Platform: SMS Example
http://www.forum.nokia.com/info/sw.n…_0_en.zip.html
Related topics:
Forum Nokia Messaging examples (C++)
http://www.forum.nokia.com/main/1%2c…0_11%2c00.html
Messaging discussion on Forum Nokia C++ developer’s board
http://discussion.forum.nokia.com/fo…splay.php?f=26
Messaging in Symbian Developer Library - online API reference
http://www.symbian.com/developer/tec…reference/cpp/
2007-4-17 08:21 Cotuvdi
存放应用程序图标的文件夹名的本地化问题
应用程序可以选择安装后存放的菜单目录文件夹,在S60第一版和第二版中,文件夹的名称可在AIF_DATA资源中进行定义,在application information file(.aif)代码为:
RESOURCE AIF_DATA
{
…
groupname = “Games”;
}
在S60第三版中,该定义是放在app中完成的,registration file(_reg.rsc)代码为:
RESOURCE APP_REGISTRATION_INFO
{
…
group_name = “Games”;
}
其中有一些名字可通过组名(group_name)参数被本地化识别。如果这样使用的话,那图标将放在会放置在相应合适的目录下,该目录回根据所选语言有 个本地化名称。本地化名的文件夹们在设备和
S60平台版本系列中并不是一成不变的。但至少下列名称是被所有基于S60第二版FP1或更新版的机器所支持的:
Communications
Configurations
Games
SIM
Tools
但是你需要知道的是,同样的组名也会被不同的机器映射为不同的名称,例如,在一些S60第三版设备上会将Tool和Configurations都映射为 Tool文件夹,其他设备会将Tools映射到缺省安装的目录
下(“Extras”,“My Own”,或“Install”,具体根据设备来判断)如果该组名无法被识别或不存在,那就会产生一个新的。
并不是所有的文件夹都有个可适合本地化的组名。如果在S60第三版上使用“Office”组名,就会在非英文机上产生一个新的“Office”文件夹。
正是因为这些原因,我们一般建议为他们的图标使用缺省的组名。如果游戏类程序就用“Games”做为组名,这样被本地化并放在S60手机正确的菜单位置。
如果应用程序需要被放置在一个不能被识别的组名文件夹里,如“Office”,我们还可以去为它进行本地化注册工作。下面是一个示例,来注册 “Office”文件夹以支持英语和法语。在这样的情况
下,资源编译器将生成两个版本的注册文件,_reg.r01和_reg.r02
RESOURCE APP_REGISTRATION_INFO
{
…
#if defined(LANGUAGE_01) // English
group_name=”Office”;
#else if defined(LANGUAGE_02) // French
group_name=”Bureau”;
#else // Other languages
group_name=”Office”;
#endif
}
如何指定最大和最小堆内存
在一台手机(或SDK的模拟器)上会有一定的物理内存大小,而你的应用程序将获取一部分做为堆内存使用。
当你程序启动后产生进程,会有一个预先分配的堆给其使用。S60第三版设备上缺省大小是4KB,早期的S60平台上是1KB。
根据需要,应用程序可以自由分配更多的堆内存,程序能使用的堆大小可在1M范围内动态增加,这是操作系统所规定最高极限了,呵呵。
如果试图分配的内存超过所能最大限制,将引发KErrNoMemory异常。
大部分Symbian C++程序在这样的堆内存安排下可以正常工作,但有时间我们需要更大的堆内存来工作。我们可以通过MMP文件中使用EPOCHEAPSIZE命令来指定最 大和最小堆内存。
例如
TARGET MemoryTest.exe
TARGETTYPE exe
UID 0x00000000 KMemoryTestUID3
SECUREID KMemoryTestUID3
VENDORID 0x00000000
CAPABILITY NONE
EPOCHEAPSIZE 0x5000 0x400000
EPOCSTACKSIZE 0x5000
....
在上述代码中,应用程序描述了它所需要的最大和最小堆内存,分别是0x5000字节(20KB)和0x400000字节(4MB),现在该程序可以安全来 分配一块3MB的堆空间。
Note: As documented, prior to S60 3rd Edition the EPOCHEAPSIZE statement has no effect on WINS32 platforms.
在上述代码中,应用程序描述了它所需要的最大和最小堆内存,分别是0×5000字节(20KB)和0×400000字节(4MB),现在该程序可以安全来 分配一块3MB的堆空间。Note: As documented, prior to S60 3rd Edition the EPOCHEAPSIZE statement has no effect on WINS32 platforms.在对一张使用逐 行编码的JPG图片进行解码时,会出现“内存不够”的错误
详细描述:
在对使用逐行编码的JPG图片进行解码时将比对使用顺序编码的JPG图片解码占用更多内存。
列如当使用CImageDecoder类对一张较大的逐行编码JPEG进行解码时,CImageDecoder::Convert()将会获得 KErrNoMemory(-4)错误。
应用程序增加堆的大小将有助于这类问题的解决,我们可以在.mmp文件中使用EPOCHEAPSIZE命令进行调整,如:
EPOCHEAPSIZE 0×1000 0×200000
这样将初始化的堆大小从4KB(缺省)调整到2MB
解决方案:
我们可以通过在.mmp工程定义文件中使用epocstacksize命令行来修改缺省的8KB大小。
epocstacksize stacksize
堆栈的大小,可以通过十六进制或十进制来指定。但这对winscw/wins平台是无效的。
列如下面这行将堆栈大小增加到20KB
epocstacksize 0×5000
同样,我们也可以在产生新线程时定义该线程的堆栈大小。
S60第三版中最小缺省堆栈大小
说明:在S60第三版中缺省的堆栈大小只有8KB,这对大多数复杂程序来说是不够的
详细描述:
在symbian OS v9中缺省的堆栈大小从20kb缩减到8kb,以优化内存的消耗。这主要是因为平台安全性导致了在系统中同时运行的进程增多。
实际上,8kb的堆栈大小对任何一个稍大的S60程序来说都是不够的。如果在当前设备上缺省的堆栈能运行你的程序,那因为堆栈的溢出(平台库的消耗而引发 堆栈的增长),它也很容易引发崩溃。在S60第三版SDK中建议所有程序都增长到20KB堆栈,这需要为此重新编译。
解决方案:
我们可以通过在.mmp工程定义文件中使用epocstacksize命令行来修改缺省的8KB大小。
epocstacksize stacksize
堆栈的大小,可以通过十六进制或十进制来指定。但这对winscw/wins平台是无效的。
列如下面这行将堆栈大小增加到20KB
epocstacksize 0×5000
同样,我们也可以在产生新线程时定义该线程的堆栈大小。
蓝牙L2CAP错误-6305
详细描述:
该错误是因为物理上连接和断开事件冲突所引起的。有时间物理连接中,HCI处传输状态时,程序会出现发送间隔。S60第二版,FP3在连接实际被关闭时会 允许新的激活,这就是-6305错误所在原因。对这个问题一个解决方案是保持通道通讯而避免物理连接的空闲时间中断连接。
解决方案:
在S60第三版中该问题被修正了。
S60上不再支持CMdaAudioConvertUtility
说明:
S60上不再支持CMdaAudioConvertUtility
详细描述:
CMdaAudioConvertUility做为Symbian’ Media Client Audio API的一部分,从S60第二版SDK, FP1后就不再被支持。
当在新平台使用时,所有CMdaAudioConvertUtility::L()所返回的变量将为KErrNotSupported错误代码。
解决方案:
Audio convert utility在S60上不再被支持,流媒体程序不再需要将声音先转成PCM中间格式,取而代之的是我们可以直接将压缩的声音数据向流中传递或从中接收, 只需在初始化流对象时提供一
个被支持的数据类型(fourCC代码)。
如,使用CMdaAudioInputStream从AMR-NB格式中直接读取声音数据:
void MyStreamClass::MaiscComplete(TInt aError)
{
iInputStream->SetDataTypeL(KMMFFourCCCodeAMR);
…
}
使用Ctrl+V(粘贴)上时所引发的程序错误
说明:
在可编辑的文本输入框中拷贝粘贴文本时会引发异常
详细描述:
这个情况只在E61手机上出现,并且版本号为1.0610.04.04
一些第三方的程序复制文本到剪贴板后在可编辑文本框中进行粘贴操作时(Ctrl+V),会引发WSERV 66异常而崩溃掉。这是因为该应用程序没有SwEvent兼容性。
解决方案:
在E61机型(版本1.0610.04.04)上运行的程序,当处理Ctrl+V(粘贴)时需要SwEvent兼容来避免WSERV 66异常,不过这个问题在后继版本中被修复了。
symbian开发的一些小技巧
最新推荐文章于 2024-09-09 09:47:53 发布