Symbian開發(fā)中的若干問(wèn)題轉(zhuǎn)帖
本貼以后做為一些小問(wèn)題的解決方案帖,遇到問(wèn)題能夠通過(guò)網(wǎng)絡(luò)簡(jiǎn)單解決的問(wèn)題會(huì)不定期的來(lái)這里更新下,給自己和有同樣問(wèn)題的人留個(gè)Mark:
在bld.inf和mmp中判斷SDK平臺(tái)版本
有時(shí)候工程中不同的SDK需要在bld.inf中選擇不同的mmp,抑或不同的SDK需要在mmp中包含不同的路徑。這種需求想必做跨SDK平臺(tái)開發(fā)的人應(yīng)該會(huì)遇到的,那么該如何解決呢?
我們知道類似__S60_50__和__SERIES60_3X__之類的宏,在bld.inf和mmp中是無(wú)法使用的,那么又該如何操作呢?有個(gè)大德從makefile的原理出發(fā),為我們解決了這個(gè)問(wèn)題,詳情可以參閱如下連接的日志描述
http://www.devdiv.net/space.php?uid=8511&do=blog&id=1010
他提到的方法是純從makefile原理出發(fā)的,相對(duì)來(lái)說(shuō)高深了不少了,受后面回帖中的啟發(fā),可以比較各個(gè)平臺(tái)SDK中Epoc32\include\variant\下的hrh文件(一般都是symbian_os.hrh文件),從而假如有不同的宏定義,就可以拿來(lái)用了,基于這個(gè)原理人家發(fā)現(xiàn)了3rd版本和5th版本SDK之間可以使用一個(gè)宏SYMBIAN_C32_SERCOMMS_V2。
受它的啟發(fā),我發(fā)現(xiàn)在新的Symbian ^3 SDK中epoc32\include\variant路徑上多了一個(gè)platform_paths.hrh,而我們?cè)?span lang=EN-US>^3SDK編譯環(huán)境下,必須在mmp中增加新的頭文件包含路徑APP_LAYER_SYSTEMINCLUDE,而宏APP_LAYER_SYSTEMINCLUDE正好在platform_paths.hrh定義的,所以我們要把工程在^3版本SDK和其他SDK區(qū)分的時(shí)候,只要使用這個(gè)宏就可以了。形式可以采用如下一些示例
//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 的開發(fā)環(huán)境后,運(yùn)行hello world 應(yīng)用即出現(xiàn)如下問(wèn)題:
bldmake error directory...\epoc32 does not exist
在網(wǎng)上查了半天,多半是需要重新安裝SDK。其實(shí),SDK和Carbide完全可以裝在不同的分區(qū)。關(guān)鍵問(wèn)題是你工作的workspace在哪。我的情況是:
hello工程位于C:\Symbian\Carbide\workspace,
而SDK在D:\S60\devices\Nokia_N97_SDK_v0.5\epoc32。
后來(lái),我發(fā)現(xiàn)Carbide的File>Switch workspace菜單中顯示當(dāng)前的workspace指向D:\Develop\mobile\Symbian\Carbide\workspace。當(dāng)我試圖指向真實(shí)的workspace,即:C:\Symbian\Carbide\workspace,Carbide再次顯示時(shí),上述菜單中就根本沒(méi)有該workspace。于是,我將workspace 復(fù)制到D盤,即:D:\Symbian\Carbide\workspace ,然后切換到該workspace,build成功!
結(jié)論:通過(guò)上述問(wèn)題,明白了其實(shí)SDK和Carbide都不是說(shuō)一定要裝在C盤,但是工程文件和Workspace必須在同一個(gè)目錄。
Symbian編譯時(shí)的Error -1073741819錯(cuò)誤
完整錯(cuò)誤信息類似下面這樣:
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
這只是在整個(gè)過(guò)程中的一部分出現(xiàn),最后提示還是***Build Complete,carbide的problems里也沒(méi)有任何對(duì)應(yīng)的代碼位置提示,很容易誤解成sdk或這編譯器壞了,網(wǎng)上有人說(shuō)重裝sdk,有人說(shuō)clean一遍項(xiàng)目。其實(shí)這是由于代碼里寫了一些貌似合法但實(shí)際不對(duì)的寫法,舉個(gè)具體的例子就是拿對(duì)象類型的變量強(qiáng)制轉(zhuǎn)換成指針使用,比如
CCoeControl& iParent;
((CTestAppView*)iParent)->foo();
這樣,就會(huì)導(dǎo)致這種build錯(cuò)誤。
小結(jié):這種問(wèn)題很難查,壓根不好找原因,后來(lái)還是從以下博客看到的http://blog.k-res.net/?p=625
新手求助 關(guān)于Esock_client 14錯(cuò)誤
我看了網(wǎng)上關(guān)于這個(gè)錯(cuò)誤的介紹是說(shuō) 描述符類型問(wèn)題。但是我這個(gè)錯(cuò)誤 感覺(jué)好像跟描述符的大小有關(guān),代碼如下 :
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長(zhǎng)度設(shè)為365的話,會(huì)正常進(jìn)行。如果超過(guò)365在waitfor這里就會(huì)無(wú)響應(yīng),如果去掉waitfor,就會(huì)報(bào)出這個(gè)Esock_clinet14錯(cuò)誤。我不太明白難道socket接收還會(huì)限定長(zhǎng)度嗎?
希望有前輩指點(diǎn)。
其實(shí)這個(gè)問(wèn)題,像我們這種從事Symbian已經(jīng)兩三年的人確實(shí)不敢犯的,但是我們現(xiàn)在跨平臺(tái)實(shí)現(xiàn),需要使用外部buffer,那該如何使用AO的異步,下面是我采用的方案:
在類內(nèi)聲明成員變量
TPtr8 *iTempBuf;
在Recv的AO中使用類似如下代碼
iTempBuf = new TPtr8(iBuf, iLen);
iSocket.RecvOneOrMore(*iTempBuf, 0, iStatus, iDummyLength);
否則局部變量在異步的recv操作中必然會(huì)引發(fā)
Timer in Symbian Development
(1)TTime::HomeTime() / TTime::UniversalTime()
最常見的時(shí)間獲取手段,精度不高;因涉及一定的運(yùn)算過(guò)程,效率較低。適用于需要以常規(guī)“年月日時(shí)分秒”方式使用時(shí)間的場(chǎng)合。在EKA2平臺(tái)下,其精度與低階系統(tǒng)時(shí)鐘(Nanokernel Timer)一致,通常為微妙級(jí)別。通過(guò) HAL::Get(HAL::ENanoTickPeriod, result) 可以獲的具體精度。
注意:它們使用的是系統(tǒng)時(shí)間,這是可以被其它進(jìn)程修改的。
(2)User::TickCount()
傳統(tǒng)的Tick計(jì)數(shù)器,精度通常僅為1/64秒(可能隨硬件有差異),適用于精度要求較低的場(chǎng)合。通過(guò) HAL::Get(HAL::ESystemTickPeriod, result) 可以獲得具體精度。
注意:在休眠(Standby)狀態(tài)下,TickCount將停止計(jì)數(shù),所以User::TickCount()在休眠狀態(tài)下將“損失”計(jì)時(shí)!
(3)User::NTickCount()
低階系統(tǒng)時(shí)鐘(Nanokernel Timer),通常提供微妙級(jí)Tick。通過(guò) HAL::Get(HAL::ENanoTickPeriod, result) 可以獲得具體精度。
注意:Symbian OS 6.x 沒(méi)有此API。與TickCount不同的是,User::NTickCount()在休眠狀態(tài)下不“損失”計(jì)時(shí)。
精度為微妙級(jí),但是函數(shù)返回時(shí)毫秒級(jí)的數(shù)值。
(4)User::FastCounter()
返回值類似于Tick,提供Symbian OS所能支持的最高精度,通常比TTime::HomeTime()更準(zhǔn)確。(如果硬件不支持high resolution timer,則毫秒級(jí)時(shí)鐘替代)而且,因?yàn)樗捎每焖俚?/span>exec call讀取一個(gè)硬件寄存器的數(shù)值,效率很高。通過(guò) HAL::Get(HALData::EFastCounterFrequency, result) 可以獲得其具體精度。
注意:在每次終端從休眠狀態(tài)激活后,它將同步至正確的數(shù)值,也就是說(shuō)User::FastCounter()在休眠狀態(tài)下其實(shí)也是不“損失”計(jì)時(shí)的。
另外,User::After(), CPeriodic也會(huì)在休眠狀態(tài)下“損失”計(jì)時(shí),所以在手機(jī)這種特殊的應(yīng)用環(huán)境中,需要特別注意不同定時(shí)器在“休眠”狀態(tài)下計(jì)時(shí)的差異。
Carbide C++中SBSv1與SBSv2的區(qū)別
自從上次裝了個(gè)Symbian ^3 0.9的SDK之后,一次導(dǎo)入工程的時(shí)候發(fā)現(xiàn)Carbide編譯器彈出如下的選項(xiàng)
一時(shí)茫然不知道該如何選擇,百度一下,找到如下鏈接
http://hi.baidu.com/71167609/blog/item/654f71443e607b8cb2b7dc92.html
內(nèi)容如下
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.
目前而言,我覺(jué)得還是選擇SBSv1好些。
This Project does not support program "BUILD_HELP" for platform "GCCE"
使用Carbide C++ 2.3以上的版本,用向?qū)梢粋€(gè)新的工程中,有時(shí)編譯時(shí)會(huì)碰到如題中的錯(cuò)誤提示。這個(gè)錯(cuò)誤的原因是Carbide中的一個(gè)bug,有時(shí)會(huì)把文件的路徑中的“\”改成“/”,比如,
inf文件中正確的路徑應(yīng)該如下:
..\help\build_help.mk
但是Carbide C++向?qū)е猩傻腻e(cuò)誤路徑如下:
../help/build_help.mk
碰到如題中的錯(cuò)誤時(shí),只要把路徑中的“/”改成“\”就可以了。
導(dǎo)入工程編譯時(shí)遇到"strict subs"報(bào)錯(cuò)問(wèn)題
在導(dǎo)入第三方編寫的工程時(shí),如果遇到類似如下報(bào)錯(cuò)
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.
通常是因?yàn)?/span>bld.inf文件中缺少PRJ_PLATFORMS項(xiàng)的內(nèi)容導(dǎo)致,默認(rèn)情況下可以加入如下代碼解決
PRJ_PLATFORMS
DEFAULT
使用RSendAs報(bào)LaunchEditor kern-exec 3錯(cuò)誤
由于習(xí)慣了用MTm來(lái)編輯和發(fā)送短信,所以對(duì)于其它方式不太習(xí)慣,目前有個(gè)項(xiàng)目需要使用到手機(jī)自帶的短信編輯器發(fā)已經(jīng)定稿短信內(nèi)容但是沒(méi)有定收件人的情況,在使用如下代碼時(shí),剛開始用的好好的,結(jié)果在E72上報(bào)LaunchEditor kern-exec 3錯(cuò)誤。
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
最后通過(guò)論壇搜索到,帖子說(shuō)“所有FP1 和5th手機(jī)上均正常,而在E72,6720,6730和5630等手機(jī)上只是把消息悄悄放到了草稿箱而不是打開短信編輯界面”,我查看了下,的確是這樣的,草稿箱創(chuàng)建了好多這種短信哦。那為什么在Symbian S60 3rdFP2的機(jī)子上都會(huì)有這個(gè)蹊蹺的問(wèn)題呢,沒(méi)有跟蹤源碼不知道,不過(guò)跟蹤到又能怎么辦,為此還是聽高人說(shuō)
“RSendAsMessage在5th中增加了設(shè)置編碼的函數(shù),但是據(jù)反應(yīng)無(wú)效果。所以RSendAsMessage這個(gè)API無(wú)論在哪個(gè)平臺(tái),對(duì)于中文使用者來(lái)說(shuō),都不應(yīng)是首選。
使用CSendUi吧,兼容性更好一點(diǎn)。但是要注意把CSendUi的實(shí)例作為成員變量使用,否則有些機(jī)型上會(huì)沒(méi)效果。
RSendAsMessage出現(xiàn)無(wú)效果的情況,可以也將其作為成員變量試試。”
其實(shí)本人經(jīng)過(guò)測(cè)試使用RSendAsMessage做為成員變量依然無(wú)效,而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);
如何區(qū)分安裝和卸載
有些程序會(huì)有一個(gè)需求即安裝和卸載的時(shí)候分別做不同的操作,簡(jiǎn)單的控制,可以通過(guò)將兩個(gè)不同操作分別封裝于兩個(gè)后臺(tái)exe程序中,將這兩個(gè)exe程序在PKG中分別用“FR,RI”和“FR,RR”來(lái)標(biāo)記前者安裝時(shí)操作,后者卸載時(shí)操作。
但是這樣并非一帆風(fēng)順,因?yàn)楦采w安裝的時(shí)候,雖然不會(huì)執(zhí)行帶“FR,RI”標(biāo)記的程序,但是會(huì)執(zhí)行帶“FR,RR”標(biāo)記的程序,這個(gè)時(shí)候假如不影響操作的話,那就無(wú)所謂,假如需要做到區(qū)分的話,那就需要用到如何區(qū)分安裝和卸載的知識(shí)點(diǎn)——Symbian (Check Install)判斷安裝程序是安裝還是卸載。
可以參看如下鏈接的信息
http://wiki.forum.nokia.com/index.php/TSS000468_-_Receiving_notifications_for_installation_events
顯然在3rd上,可以通過(guò)該方法來(lái)實(shí)現(xiàn)區(qū)分安裝和卸載。根據(jù)之前的經(jīng)歷,這種應(yīng)該是使用PS方式實(shí)現(xiàn)的,不過(guò)我們這里不用考慮實(shí)時(shí)監(jiān)控,所以直接調(diào)用如下代碼就可以了。
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);
.........
需要包含如下兩個(gè)頭文件
#include <e32property.h>
#include <sacls.h>
在3rd上測(cè)試基本上是正確的,可以用如下枚舉值直接進(jìn)行比較。
enum TInstOp
{
EInstOpNone = 0x00000000,
EInstOpInstall = 0x00000001,
EInstOpUninstall = 0x00000002,
EInstOpRestore = 0x00000004
};
enum TInstOpStatus
{
EInstOpStatusNone = 0x00000000,
EInstOpStatusSuccess = 0x00000100,
EInstOpStatusAborted = 0x00000200
};
不過(guò)測(cè)試中也遇到過(guò)一次0x202,所以判斷安裝和卸載,直接跟2進(jìn)行比較的方法有點(diǎn)欠科學(xué),最好還是位與一下進(jìn)行比較的更合適些。
posted on 2010-05-14 19:38
frank.sunny 閱讀(3761)
評(píng)論(6) 編輯 收藏 引用 所屬分類:
symbian 開發(fā)