Symbian开发中的若干问题转帖
本贴以后做为一些小问题的解决方案帖,遇到问题能够通过网络简单解决的问题会不定期的来这里更新下,给自己和有同样问题的人留个Mark:
在bld.inf和mmp中判断SDK平台版本
有时候工程中不同的SDK需要在bld.inf中选择不同的mmp,抑或不同的SDK需要在mmp中包含不同的路径。这种需求想必做跨SDK平台开发的人应该会遇到的,那么该如何解决呢?
我们知道类似__S60_50__和__SERIES60_3X__之类的宏,在bld.inf和mmp中是无法使用的,那么又该如何操作呢?有个大德从makefile的原理出发,为我们解决了这个问题,详情可以参阅如下连接的日志描述
http://www.devdiv.net/space.php?uid=8511&do=blog&id=1010
他提到的方法是纯从makefile原理出发的,相对来说高深了不少了,受后面回帖中的启发,可以比较各个平台SDK中Epoc32\include\variant\下的hrh文件(一般都是symbian_os.hrh文件),从而假如有不同的宏定义,就可以拿来用了,基于这个原理人家发现了3rd版本和5th版本SDK之间可以使用一个宏SYMBIAN_C32_SERCOMMS_V2。
受它的启发,我发现在新的Symbian ^3 SDK中epoc32\include\variant路径上多了一个platform_paths.hrh,而我们在^3SDK编译环境下,必须在mmp中增加新的头文件包含路径APP_LAYER_SYSTEMINCLUDE,而宏APP_LAYER_SYSTEMINCLUDE正好在platform_paths.hrh定义的,所以我们要把工程在^3版本SDK和其他SDK区分的时候,只要使用这个宏就可以了。形式可以采用如下一些示例
//bld.inf
#ifdef APP_LAYER_SYSTEMINCLUDE
Rp*_X3.mmp
#else
Rp*_v5.mmp
#endif
//*.mmp
#ifdef APP_LAYER_SYSTEMINCLUDE
APP_LAYER_SYSTEMINCLUDE
#endif
//.cpp
#ifdef APP_LAYER_SYSTEMINCLUDE
#include <es_enum_partner.h>
#endif
bldmake error directory epoc32 does not exist
安装好Nokia 的开发环境后,运行hello world 应用即出现如下问题:
bldmake error directory...\epoc32 does not exist
在网上查了半天,多半是需要重新安装SDK。其实,SDK和Carbide完全可以装在不同的分区。关键问题是你工作的workspace在哪。我的情况是:
hello工程位于C:\Symbian\Carbide\workspace,
而SDK在D:\S60\devices\Nokia_N97_SDK_v0.5\epoc32。
后来,我发现Carbide的File>Switch workspace菜单中显示当前的workspace指向D:\Develop\mobile\Symbian\Carbide\workspace。当我试图指向真实的workspace,即:C:\Symbian\Carbide\workspace,Carbide再次显示时,上述菜单中就根本没有该workspace。于是,我将workspace 复制到D盘,即:D:\Symbian\Carbide\workspace ,然后切换到该workspace,build成功!
结论:通过上述问题,明白了其实SDK和Carbide都不是说一定要装在C盘,但是工程文件和Workspace必须在同一个目录。
Symbian编译时的Error -1073741819错误
完整错误信息类似下面这样:
make[1]: *** [\Symbian\9.2\S60_3rd_FP1_2\EPOC32\BUILD\...\Gif_Reader.o] Error -1073741819
make[1]: *** Waiting for unfinished jobs….
make[1]: *** Waiting for unfinished jobs….
make[1]: *** Waiting for unfinished jobs….
make: *** [TARGETMGATE] Error 2
这只是在整个过程中的一部分出现,最后提示还是***Build Complete,carbide的problems里也没有任何对应的代码位置提示,很容易误解成sdk或这编译器坏了,网上有人说重装sdk,有人说clean一遍项目。其实这是由于代码里写了一些貌似合法但实际不对的写法,举个具体的例子就是拿对象类型的变量强制转换成指针使用,比如
CCoeControl& iParent;
((CTestAppView*)iParent)->foo();
这样,就会导致这种build错误。
小结:这种问题很难查,压根不好找原因,后来还是从以下博客看到的http://blog.k-res.net/?p=625
新手求助 关于Esock_client 14错误
我看了网上关于这个错误的介绍是说 描述符类型问题。但是我这个错误 感觉好像跟描述符的大小有关,代码如下 :
HBufC8* iRecvData;
void SendDataJabber::RecvInfoL()
{
TBuf8<367> buf;
TRequestStatus status(KRequestPending);
iSocket.Recv(buf, 0, status);
User::WaitForRequest(status);
User::LeaveIfError(status.Int());
delete iRecvData;
iRecvData = NULL;
iRecvData = buf.Alloc();
}
如果buf长度设为365的话,会正常进行。如果超过365在waitfor这里就会无响应,如果去掉waitfor,就会报出这个Esock_clinet14错误。我不太明白难道socket接收还会限定长度吗?
希望有前辈指点。
其实这个问题,像我们这种从事Symbian已经两三年的人确实不敢犯的,但是我们现在跨平台实现,需要使用外部buffer,那该如何使用AO的异步,下面是我采用的方案:
在类内声明成员变量
TPtr8 *iTempBuf;
在Recv的AO中使用类似如下代码
iTempBuf = new TPtr8(iBuf, iLen);
iSocket.RecvOneOrMore(*iTempBuf, 0, iStatus, iDummyLength);
否则局部变量在异步的recv操作中必然会引发
Timer in Symbian Development
(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也会在休眠状态下“损失”计时,所以在手机这种特殊的应用环境中,需要特别注意不同定时器在“休眠”状态下计时的差异。
Carbide C++中SBSv1与SBSv2的区别
自从上次装了个Symbian ^3 0.9的SDK之后,一次导入工程的时候发现Carbide编译器弹出如下的选项
一时茫然不知道该如何选择,百度一下,找到如下链接
http://hi.baidu.com/71167609/blog/item/654f71443e607b8cb2b7dc92.html
内容如下
SBSv2 only works with recent versions of Symbian OS9.5. Both SBSv1 and SBSv2 are GNU make based build systems. SBSv1 uses Perl to generate make files, while SBSv2 uses Python. Select the appropriate builder for your project. When building for SBSv2, the builder will set EPOCROOT to the absolute path (including drive letter) to the kit for the active build configuration. It will also add the path to the sbs bin directory to the start of the PATH variable. This is derived from the SBS_HOME environment variable. For SBSv2, all build configurations (platform/target), including the built-in platforms (WISNCW, ARMV5), are declared in xml files in the \sbs\lib\config directory. The Build Configurations selection page will display only those kits known to support SBSv2.
目前而言,我觉得还是选择SBSv1好些。
This Project does not support program "BUILD_HELP" for platform "GCCE"
使用Carbide C++ 2.3以上的版本,用向导生成一个新的工程中,有时编译时会碰到如题中的错误提示。这个错误的原因是Carbide中的一个bug,有时会把文件的路径中的“\”改成“/”,比如,
inf文件中正确的路径应该如下:
..\help\build_help.mk
但是Carbide C++向导中生成的错误路径如下:
../help/build_help.mk
碰到如题中的错误时,只要把路径中的“/”改成“\”就可以了。
导入工程编译时遇到"strict subs"报错问题
在导入第三方编写的工程时,如果遇到类似如下报错
Bareword "GCCE" not allowed while "strict subs" in use at \Symbian\9.1\S60_3rd_MR\EPOC32\BUILD\Symbian\Carbide\lab\SMSExample\group\/Platform.pm line 14.
Bareword "GCCE" not allowed while "strict subs" in use at \Symbian\9.1\S60_3rd_MR\EPOC32\BUILD\Symbian\Carbide\lab\SMSExample\group\/Platform.pm line 29.
Compilation failed in require at C:\Symbian\9.1\S60_3rd_MR\epoc32\tools/ABLD.PL line 161.
BEGIN failed--compilation aborted at C:\Symbian\9.1\S60_3rd_MR\epoc32\tools/ABLD.PL line 161.
通常是因为bld.inf文件中缺少PRJ_PLATFORMS项的内容导致,默认情况下可以加入如下代码解决
PRJ_PLATFORMS
DEFAULT
使用RSendAs报LaunchEditor kern-exec 3错误
由于习惯了用MTm来编辑和发送短信,所以对于其它方式不太习惯,目前有个项目需要使用到手机自带的短信编辑器发已经定稿短信内容但是没有定收件人的情况,在使用如下代码时,刚开始用的好好的,结果在E72上报LaunchEditor kern-exec 3错误。
RSendAs sendAs;
User::LeaveIfError(sendAs.Connect());
CleanupClosePushL(sendAs);
RSendAsMessage sendAsMessage;
sendAsMessage.CreateL(sendAs, KSenduiMtmSmsUid);
CleanupClosePushL(sendAsMessage);
sendAsMessage.SetBodyTextL(aText);
sendAsMessage.LaunchEditorAndCloseL();
CleanupStack::Pop(); //sendAsMessage
CleanupStack::PopAndDestroy(); //sendAs
最后通过论坛搜索到,帖子说“所有FP1 和5th手机上均正常,而在E72,6720,6730和5630等手机上只是把消息悄悄放到了草稿箱而不是打开短信编辑界面”,我查看了下,的确是这样的,草稿箱创建了好多这种短信哦。那为什么在Symbian S60 3rdFP2的机子上都会有这个蹊跷的问题呢,没有跟踪源码不知道,不过跟踪到又能怎么办,为此还是听高人说
“RSendAsMessage在5th中增加了设置编码的函数,但是据反应无效果。所以RSendAsMessage这个API无论在哪个平台,对于中文使用者来说,都不应是首选。
使用CSendUi吧,兼容性更好一点。但是要注意把CSendUi的实例作为成员变量使用,否则有些机型上会没效果。
RSendAsMessage出现无效果的情况,可以也将其作为成员变量试试。”
其实本人经过测试使用RSendAsMessage做为成员变量依然无效,而CSendUi不用成员变量也是可行的,具体代码如下
CSendUi* sendAppUi = CSendUi::NewLC();
CMessageData* message = CMessageData::NewLC();
CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
CleanupStack::PushL(paraFormatLayer);
CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
CleanupStack::PushL(charFormatLayer);
CRichText* messageBodyContent = CRichText::NewL(paraFormatLayer,
charFormatLayer);
CleanupStack::PushL(messageBodyContent);
messageBodyContent->InsertL(0, aText);
message->SetBodyTextL(messageBodyContent);
sendAppUi->CreateAndSendMessageL(KSenduiMtmSmsUid, message, KNullUid,
EFalse);
CleanupStack::PopAndDestroy(messageBodyContent);
CleanupStack::PopAndDestroy(charFormatLayer);
CleanupStack::PopAndDestroy(paraFormatLayer);
CleanupStack::PopAndDestroy(message);
CleanupStack::PopAndDestroy(sendAppUi);
如何区分安装和卸载
有些程序会有一个需求即安装和卸载的时候分别做不同的操作,简单的控制,可以通过将两个不同操作分别封装于两个后台exe程序中,将这两个exe程序在PKG中分别用“FR,RI”和“FR,RR”来标记前者安装时操作,后者卸载时操作。
但是这样并非一帆风顺,因为覆盖安装的时候,虽然不会执行带“FR,RI”标记的程序,但是会执行带“FR,RR”标记的程序,这个时候假如不影响操作的话,那就无所谓,假如需要做到区分的话,那就需要用到如何区分安装和卸载的知识点——Symbian (Check Install)判断安装程序是安装还是卸载。
可以参看如下链接的信息
http://wiki.forum.nokia.com/index.php/TSS000468_-_Receiving_notifications_for_installation_events
显然在3rd上,可以通过该方法来实现区分安装和卸载。根据之前的经历,这种应该是使用PS方式实现的,不过我们这里不用考虑实时监控,所以直接调用如下代码就可以了。
TInt instStatus = -1;
User::LeaveIfError(RProperty::Get(KUidSystemCategory,
KSAUidSoftwareInstallKeyValue, instStatus));
vBuf.Copy(_L("instStatus =0x"));
vBuf.AppendNum(instStatus, EHex);
.........
TInt appUid;
User::LeaveIfError(RProperty::Get(KUidSystemCategory, KUidSwiLatestInstallation, appUid));
vBuf.Copy(_L("instAppUid =0x"));
vBuf.AppendNum(appUid, EHex);
.........
需要包含如下两个头文件
#include <e32property.h>
#include <sacls.h>
在3rd上测试基本上是正确的,可以用如下枚举值直接进行比较。
enum TInstOp
{
EInstOpNone = 0x00000000,
EInstOpInstall = 0x00000001,
EInstOpUninstall = 0x00000002,
EInstOpRestore = 0x00000004
};
enum TInstOpStatus
{
EInstOpStatusNone = 0x00000000,
EInstOpStatusSuccess = 0x00000100,
EInstOpStatusAborted = 0x00000200
};
不过测试中也遇到过一次0x202,所以判断安装和卸载,直接跟2进行比较的方法有点欠科学,最好还是位与一下进行比较的更合适些。
posted on 2010-05-14 19:38
frank.sunny 阅读(3730)
评论(6) 编辑 收藏 引用 所属分类:
symbian 开发