Symbian开发——Symbian开发知识(转)
生活随笔
收集整理的這篇文章主要介紹了
Symbian开发——Symbian开发知识(转)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
調(diào)研時發(fā)現(xiàn)這邊文章,有很多寶貴經(jīng)驗,也收藏一下。
轉(zhuǎn)自另一個CSDN博客:http://blog.csdn.net/andy205214/archive/2008/04/11/2282675.aspx
?
General Hints / 一般提示學(xué)習(xí)S2,我的方法無非是:
·每天coding,多少小時你自己掌握,看你有多少時間了。
·coding的同時,打開SDK Help,查里面的函數(shù)庫。
·資源管理器的“搜索”功能不能少,你可以在你的安裝目錄/series60ex里面找到Series60的范例代碼,/example這里找到Symbian的范例代碼
·范例代碼我是使用UltraEdit來察看并卻穇閱的,不要畏懼Nokia長長的example,他只是為了在一個例子里面展示能牽扯到的所有的功能,你所需要的可能只是一個類的幾行使用方法,找到那一段,把它copy出來,用在你的.cpp里面理解就可以了。
前面是網(wǎng)下的,下面說說網(wǎng)上的。
·每天來這里看看首頁更新,有document就下載下來,是你所需要的就馬上看。
·看看DiscussionBoard,這里,Chinese Application Development > Symbian ,有別人的問題,你可以記住并且以后參考。
·自己遇到的問題,就在這里用AdvancedSearch找一下。
·NewLC www.newlc.com 是一個好網(wǎng)站,我發(fā)現(xiàn)的除了Forum Nokia之外唯一的S2站點。它里面的Tutior教學(xué)部分真的有很多好東西,我建議都給他離線瀏覽下載下來,我就是這么做的。不過它里面的論壇,我還 沒有看,主要是外國人太多,好像也都是提問的,真正解決問題的沒有這里那么好吧。
其它的,也沒有什么了,你要是想看市場,還有www.symbian.com和www.series60.com 。
中文問題
在模擬器或者真機上面顯示中文,這是一個不難的問題。
先 說說模擬器。因為我很久很久沒有用過0.9中文版的模擬器了,所以對其情況也忘記的差不多了。我想如果是0.9中文版的模擬器,顯示中文應(yīng)該沒有什么大問 題了,不過SDK V0.9中不全的header&lib,這個會對你開發(fā)程序造成影響吧,所以我還是不建議現(xiàn)在仍然在使用SDK V0.9。
那 么使用英文版模擬器要如何顯示中文呢?其實是不可以顯示中文的。英文版的SDK中主要是說他的模擬器沒有制作成中文版,所以如果你在菜單中寫了中文,他是 無法顯示的。但是有一個例外,就是如果你在程序中實現(xiàn)Draw函數(shù)的時候使用了DrawText或者DrawTextVertical,并且事先把中文版 模擬器中的中文字體復(fù)制到了模擬器中,那么模擬器是可以顯示中文的。注意這其實是等同于“用字體在屏幕上面‘劃*’字”,其中的實現(xiàn)機理我想我還沒有什么 研究,扯遠(yuǎn)了肯定會出錯,所以大家如果有需要的話,在英文版模擬器上面Draw中文,可以復(fù)制一下中文版中的字體文件到英文版SDK的
epoc32/release/wins/udeb/z/system/fonts(大概是這里,我現(xiàn)在手邊沒有SDK來參考)
然后在DrawText之前調(diào)用一下字體就可以了。
*因為論壇中文系統(tǒng)的訽因,我無法輸入那個關(guān)鍵的“籣”字,一橫一個田下面一個半包圍,所以暫時用這個錯別字代替了,我目的就是說明它是Draw上去的。
在真機上面,大家顯示中文無非就是按照上面那篇文檔說的,一步一步來就可以了。
大體上,在程序中顯示中文分為固定的用戶界面中文字符串和程序運行時生成字符串。第一類使用較多,而且也基本上可以代替第二類,所以我還是主張大家不要在你的.cpp里面寫中文字符串,雖然它是可以實現(xiàn)的。
用 戶界面中的字符串,Symbian系統(tǒng)是使用資源文件來保存并管理的。我們所需要知道的便是:在你的Project文件夾的data目錄下面,編糭你 的.RSS文件。這個文件中,你可以通過定義TBUF資源對象,來定義字符串。你定義的字符串,最好還是寫成一個假名,比如
RESOURCE TBUF r_myprj_str_somestring
? ? ? ? {
? ? ? ? buf=qtn_myprj_str_somestring;
? ? ? ? }
而這個qtn_myprj_str_somestring,你最好寫在myprj.loc里面,這樣:
#define qtn_myprj_str_somestring "Some String"
他的一個好處就是,你便于將你的程序作本地化/國際化處理。如果你的程序要做成很多語言的版本,那么你可以把你的用戶界面字符串寫成
myprj.en.loc
myprj.cn.loc
myprj.fr.loc
然后在編譯的時候,只需要在你的rss文件中include不同的loc就可以了。這個就是他系統(tǒng)實現(xiàn)機制的考慮所在。
準(zhǔn)備好了.RSS文件和.LOC文件并不是萬事大吉了,很多朋友在這里沒有試驗成功的一個訽因就是在.RSS文件的頭部,忘了加上
注意在RSS文件重要加入
CHARACTER_SET UTF8
或者是忘記了把.LOC文件給轉(zhuǎn)換成UTF-8的格式。
我目前使用的是Windows NotePad來轉(zhuǎn)換UTF-8格式的,需要注意是如果你使用的是英文版的Windows,那么它會在LOC文件的頭部添加3個前導(dǎo)標(biāo)示字符,你需要再用UltraEdit[非UTF-8自動辨認(rèn)模式]來刪除他們。
Descriptor/String 字符串相關(guān)
我們寫程序,幾乎很少不跟字符串打交道的,所以字符串這一塊兒自然成了一個平臺的很重要一塊兒。
因 為Symbian系統(tǒng)是面向移動設(shè)備,用設(shè)計者的話說就是:資源受限的智能設(shè)備,另外它是基于ROM和RAM操作的,所以他們對于字符串的處理也是采用了 一套自己獨創(chuàng)的方式來進(jìn)行。這樣的機制,初學(xué)者乍看起來會很不習(xí)慣,摸不到頭腦,不知道他為什么要這么做。不過可以這樣說,跟她的內(nèi)存資源處理機制相比, 字符串方面Symbian所作的改動還只是相當(dāng)于換了一個名稱而已,對于ISV級的開發(fā)者來說,它是在眾多Symbian系統(tǒng)中眾多獨有特性中最好掌握的 幾種之一。
在Symbian系統(tǒng)中,字符串被稱為Descriptor,你不用知道為什么,就把它當(dāng)作你熟悉的string也就好了。因 為要對字符串進(jìn)行操作,所以高級一些的平臺,都把字符串寫成了一個獨立的類,當(dāng)作對象來對他們處理,而不像是C中,字符串是char[],然后有一批函數(shù) 來處理它。又考慮到 Symbian系統(tǒng)所處理的字符串有在RAM中的也有在ROM中的,而RAM又是十分寶貴的,Symbian處理字符串提供了不止一個類,就在這里有了一 點點不是那么直接的地方。
下面開始具體講解一下我的理解,
在Symbian中,字符串的抽象類是TDes,它可以是TDes16 業(yè)可以是TDes8,取決于你的程序是否處理Unicode。我們可以這樣理解, TDes就是char[],不過它不以'/0'結(jié)尾,而是把長度信息保存在了頭部,并且含有一個內(nèi)存地址來表示他的位置。正如前面所述當(dāng)今高級的平臺構(gòu) 架,都會把字符串給分裝成一個類,我們是把字符串當(dāng)作一個對象來處理的,所以抽象類我們是不能直接定義一個實例來使用的,抽象類的作用,在于傳遞函數(shù)的參 數(shù),在這個時候我們可以把函數(shù)傳遞的參數(shù)當(dāng)作最基本的抽象類來進(jìn)行處理。那么要直接使用一個字符串,我們該使用什么呢?
情況分為兩種,如 果我們的字符串是比較短的,并且字符串的長度是相對已知的話,我們須要使用的是TBuf<len>,其中l(wèi)en表示長度。同樣,TBuf是一 個Unicode相關(guān)的類,他表示TBuf16或者TBuf8。定義這樣類型的一個字符串,我們使用這樣的語句
TBuf<100> buf100;
就 可以定義一個字符串了。然后,參看TBuf類在SDK文檔中的參考說明,我們就可以使用這樣的字符串了。注意,使用TBuf是事先知道他的大概長度的,使 用的時候不能溢出,否則會出現(xiàn)程序錯誤而導(dǎo)致退出。另外,據(jù)說TBuf是被分配在了很寶貴的地方,所以盡量不要分配很長的TBuf,我想如果你的 TBuf長度超過了2000,哪怕是已知長度也最好換下面的第二種方式來分配好了。模擬器里面大家試驗東西的時候可以分配很大很大的,沒有問題,只不過用 在真機上面的時候就要小心了。
另外一種,叫做HBufC,它是被分配在了Heap里面,可以在運行時才決定他的大小,不過也不能過大。定義一個HBufC我們可以使用下面的語句
HBufC* heapBuf=HBufC::NewL(100);
這樣我們就定義了一個長度為100的heap字符串,需要注意的有幾點。
1,使用它地抽象類部分,也就是把它當(dāng)作字符串使用,需要用他的Des函數(shù)來返回他的TDes類,比如
heapBuf->Des()
,這樣來調(diào)用HBufC的字符串部分。
2, 因為Heap字符串是一個新分配的對象,所以你必須在使用完之后立即手動刪除它。我使用的是delete heapBuf;來刪除的,不過我覺得如果能夠使用Symbian系統(tǒng)中提供的CleanupStack庫來進(jìn)行刪除的話,可能會更好。我因為對這一方面 還沒有什么研究,所以不敢在這里舉例子。
3,他的大小仍然是需要注意的,我的程序中分配過兩個0x8000長的Heap字符串,沒什么大問題。很 早很早年少無知的時候,曾綺在0.9SDK的模擬器中一下子分配了1MegaByte的HBufC,沒有任何問題。但是真機上面?_?_,我沒有試驗過, 大家小心嘗試~~~~
最后還有一種叫做TPtrC這樣的東西,我們可以全當(dāng)他是一個指針,指向一個TDes,其實可以當(dāng)作是節(jié)省 heapBuf->Des()的鍵盤消耗,我們可以定義一個TPtrC pBuf;然后pBuf=heapBuf->Des(); 從此我們就可以把pBuf當(dāng)作一個TDes來處理了,我很少用TPtrC,所以也不太熟悉,不敢多說了。
需要注意的,
·在Symbian中,其實字符串都是按照Unicode編碼保存的TDes16。
·我不知道為何在有的時候,定義'/n'是管用的,可是在EDWIN中,我卻需要在TDes后面追價數(shù)值為0x2029的字符才可以換行。
· 論壇中,或者其它網(wǎng)站[比如www.newlc.com],有介紹TDes16和TDes8之間的互轉(zhuǎn),請注意如果他們不是中國人,pure chinese,請注意他們是否會忽略中文處理,僅僅是簡單的拋棄了高位為0的字節(jié)。如果是這樣方法,我們最好還是考慮一下。三思而后行。
平臺號及產(chǎn)品號-pkg打包
pkg file定義了安裝文件(sis)的內(nèi)容,它包括應(yīng)用程序的UID,一個支持的語言列表,目標(biāo)產(chǎn)品的UID和打包在sis的一組文件:
; MyGame.pkg
; Specifies an installation file for MyGame
;Languages
&EN
;Header
#,(0x1000ABCD),1,0,0
; Required line for Series 60 devices. Defines the target product
; UID.
(0x101F6F88), 0, 0, 0,
“/epoc32/release/thumb/urel/MyGame.app”-“!:/system/apps/MyGame/MyGame.app”
“/epoc32/release/thumb/urel/MyGame.rsc”-“!:/system/apps/MyGame/MyGame.rsc”
“/epoc32/release/thumb/urel/MyGame.mbm”-“!:/system/apps/MyGame/MyGame.mbm”
“/epoc32/release/thumb/urel/MyGame.aif”-“!:/system/apps/MyGame/MyGame.aif”
“../MyGame/MyGameSample.wav”-“!:/system/apps/MyGame/MyGameSample.wav”
Product UID定義了應(yīng)用程序的目標(biāo)環(huán)境,大部分的s60版本是向下兼容的。
參見下表:
Nokia 7650 0x101F6F87
Nokia 3650 0x101F7962
Nokia 9210/9290 0x10005E33
Nokia N-gage 0x101F8A64
Siemens SX1 0x101F9071
Series 60 Platform v0.9 0x101F6F88
Series 60 Platform v1.0 0x101F795F
Series 60 Platform v1.1 0x101F8201
Series 60 Platform v1.2 0x101F8202
Series 60 Platform v2.0 0x101F7960
如果程序需要依據(jù)各不同的平臺來進(jìn)行安裝,那就可以使用條件語句塊來處理,這時pkg里的語句如下:
;
; Files to install
;
IF MachineUID=0x101fb3dd
; Nokia 6600 specific files
“../MyFiles/FileFor6600.dat”-“!:/system/apps/MyGame/MyData.dat”
ELSEIF MachineUID=0x101f466a
; Nokia 3650 specific files
“../MyFiles/FileFor3650.dat”-“!:/system/apps/MyGame/MyData.dat”
ELSE
; Files for other devices
“../MyFiles/FileForOthers.dat”-“!:/system/apps/MyGame/MyData.dat”
ENDIF
如上的使用你就可以生成一個支持多平臺的安裝文件,除了機器UID外,還有很多屬性,如內(nèi)存和CPU的標(biāo)識:
注意,機器UID和Product UID是不同的,見下:
Nokia 7650 0x101F4FC3
Nokia 3650 0x101F466A
Nokia 6600 0x101FB3DD
Nokia 9210/9290 0x10005E33
Nokia N-Gage 0x101F8C19
Win32 Emulator 0x10005F62
可以使用如下的代碼來找出該設(shè)備的機器UID:
#include <hal.h> //and link with hal.lib
TInt machineUid = 0;
HAL::Get(HALData::EmachineUid, machineUid);
File Manipulatating/文件操作
其 實這方面的操作相對于Symbian的某些其他部分來說還是跟其他平臺比較類似的,并無太大的不同。從最訽始的Standard C中的FILE結(jié)構(gòu)到C++中的stream,再到目前的各種各樣的流行的語言、腳本什么的,對文件的操作無非是打開一個用字符串指定文件名的文件,給出 打開方式(Binary or Text, Read or Write),然后獲得“文件對象”,你可以當(dāng)作這個文件的實例或者句柄什么的(Instance or Handle),知道意思就行了,反正就是這么一回事;p?_?_在我們目前的面向?qū)ο蟪绦蛑?#xff0c;如果要對文件進(jìn)行讀取或者寫入等操作,無非就是調(diào)用在這個 文件對象各種過程,比如寫入,讀取,Seek,之類的,等到用完了文件再用Close之類的過程關(guān)閉它以釋放資源。這個就是我們編成的時候大致的操作文件 的抽象描述。Symbian在這方面與其他平臺并無太大差別。
下面結(jié)合Code說說具體的操作:
上面說了Symbian在文件操 作方面與其他平臺差別不大,但是全無差別也是不可能的。因為Symbian系統(tǒng)是為資源受限設(shè)備設(shè)計的,這一點我相信大家都聽得耳朵起糨子了-_-,所以 他的文件資源也是由系統(tǒng)管理的,我們要通過建立FileServer來與系統(tǒng)的文件服務(wù)通信,以建立客戶端--服務(wù)器模式來訪問文件。說了那么玄,其實很 簡單地,也就是說我們在純粹的使用文件部分的時候,之前要Connet一下FileServer,之后要Close一下 FileServer,就這么簡單。
如:
Code:
RFs fs;
User::LeaveIfError(fs.Connect());
/*
* Your File Manipulatating Code Here...
*/
fs.Close();
我的Code其實并不好,如果是Symbian老手,我相信即使是簡單的fs.Connect();也會有隨后馬上進(jìn)行的CleanupStack類的操作,只是我目前還不熟悉,不敢妄自誤導(dǎo)大眾~~
下 面的就是文件了,我們在Symbian中使用的比較“低級”或者說“底層”的訽始文件對象是通過RFile類來實現(xiàn)的,大家只要參考一下 DeveloperLibrary的這個部分就清楚了,位置是:(? Developer Library ? API Reference ? C++ API reference ? File Server Client Side ? RFile)
下面給兩個例子,來說明一下文件的打開,關(guān)閉,讀,寫,Seek等操作。
Code:
RFs fs;
User::LeaveIfError(fs.Connect());
RFile file
User::LeaveIfError(file.Open(fs, _L("C://file.foo"), EFileWrite));
TBuf8<256> buf;
file.Read(buf, 256);
file.Seek(ESeekStart, 911);
file.Write(_L8("Some thing you wanna write..."));
file.Close();
fs.Close();
注: 以上代碼沒有綺過測試,沒有綺過編譯檢查,但是綺過了對照SDK DeveloperLibrary的檢查,技術(shù)上應(yīng)該不會有什么問題。有兩點要說明的,在程序中寫死(HardCode)變量長度和位置什么東西還是最好 用MACRO代替,這可能是所有programmer的常識了,我并不是在教大家而是指名我的實例代碼中的不足;另一點就是_L8(), _L()這兩個MACRO是Symbian不支持大家再使用的了,大家最好用_LIT()或者_(dá)LIT8()來代替好了,此處僅僅為了方便使用了一下。
大 家可以很容易從DeveloperLibrary看出,RFile支持的讀寫只有TDes8這種類型,也就是說它只能以byte,或byte數(shù)組的形式寫 入或者讀出數(shù)據(jù)。如果大家想使用文本文件或者二進(jìn)制數(shù)據(jù)文件的話,就要借助更高級的文件類了,他們的使用方法仍然是大同小異。
TFileText 提供了文本文件的讀寫,從他的API Reference中很容易看出來,在我們建立好的TFileText對象上,只要Set一個RFile到它本身上面,我們就可以用這個 TFileText對象來很容易的對文件(就是底層的RFile)來進(jìn)行文本文件的讀寫了。
與此類似,RFileReadStream對象,在構(gòu) 造的時候只需指明構(gòu)建在哪個RFile對象上,我們就可以方便的在這個RFile對象上進(jìn)行數(shù)據(jù)的操作,比如讀出一個32bit的整數(shù),讀出一個64比特 實型數(shù)。RFileWriteStream進(jìn)行的是寫入方面的操作,操作方式與讀入類相同,就不贅述了。
從上面的例子和說明我們可以看出,Symbian系統(tǒng)的文件操作幾乎與其他平臺沒什么太大的不同,也是符合所有的抽象文件操作要求的。對文件的操作只要我們看看DeveloperLibrary,記住幾個常用的過程,就沒有什么困難的了。
希望我寫的文字能給大家?guī)硇椭?#xff01;
為 kcomex 補充兩點:
1、symbian的所有文件名中最好不好含有空格等特殊字符,負(fù)責(zé)編譯可能出錯,我用0.9SDK是這樣的。
2、 如果編譯的時候出現(xiàn)了你不知道的文件夾,請將mmp文件所在的文件夾中的.bat和.inf文件刪掉,用.mmp重新生成這兩個文件。我一般都是使用 mmpclick這個工具來生成的,因為命令行畢竟不方便。關(guān)于mmpclick的使用,在SDK附帶的工具中有詳細(xì)的說明。
如何給模擬器發(fā)短信
建議從諾基亞論壇上下載安裝"Nokia Connectivity Framework"。我不知道它是否支持在真機和仿真器之間互發(fā)短信,但我用它在兩個仿真器之間互發(fā)過短信,下面簡要說一下當(dāng)時的配置過程。
1. 安裝SDK
安裝S60 SDK 2.2和S60 SDK 2.3
安裝"Nokia Connectivity Framework 1.2"
2. 配置環(huán)境
打 開"Nokia Connectivity Framework",將左側(cè)窗口中的"Projects"->"Terminal SDKs"->"Series 60 2nd Ed. SDK for Symbian OS FP2 ...",和"Projects"->"Terminal SDKs"->"Series 60 2nd Ed. SDK for Symbian OS FP3 ..."拖到右側(cè)的窗口中,此時右側(cè)窗口中出現(xiàn)兩個仿真器的圖標(biāo),圖標(biāo)下側(cè)列出了該仿真器的藍(lán)牙地址和MMS/SMS號碼。
然后用鼠標(biāo)從其中一個圖標(biāo)向另一個圖標(biāo)引一條連線。
3. 啟動環(huán)境
分別在兩個仿真器圖標(biāo)上單擊右鍵,然后從彈出式菜單中選擇"Start Product"啟動仿真器。
4. 發(fā)送短消息
進(jìn)入某個仿真器的"Messages"應(yīng)用程序,編寫一條短信,其中"to:"域填寫另一個仿真器的SMS號碼,然后發(fā)送該短信。首次發(fā)送時會彈出對話框要求設(shè)置服務(wù)中心的號碼,隨便填個數(shù)(我填的1),點OK就行了。
5. 接收短消息
打開另一個仿真器的"Messages"應(yīng)用程序,就能看到"Inbox"收到了剛才發(fā)的短信。
symbian下面制作DLL 的流程
首先咱們假設(shè)要封裝一個叫做CMyClass的東西。先叢工程文件入手:
MyClass.mmp
-------------------
代碼:
TARGET MyClass.dll
TARGETTYPE??dll
UID 0x1000008d 0x10004268 //注意,這里換上你的UID
SOURCEPATH? ?../src
SOURCE? ?MyClass.cpp
SYSTEMINCLUDE? ?.
SYSTEMINCLUDE? ?/epoc32/include
SYSTEMINCLUDE? ?/epoc32/include/libc
LIBRARY euser.lib
#if defined(WINS)
deffile ./MyClassWINS.def
#else if defined(ARM)
deffile ./MyClassARM.def
#endif
NOSTRICTDEF
EXPORTUNFROZEN
好,一半已經(jīng)搞定了,再堅持一下。
MyClass.h
--------------
代碼:
class CMyClass : public CBase
{
public: // 這些IMPORT_C開頭的家伙就是我們可以從別的程序中調(diào)用的函數(shù)
IMPORT_C static CMyClass* NewL();
IMPORT_C static CMyClass* NewLC();
IMPORT_C ~CMyClass();
public:
IMPORT_C void DoSomething();
private:
CMyClass();
void ConstructL();
};
很晚了,我偷個懶,上面的代碼只寫了重要的部分,那些個#include什么的麻煩看官們自己補齊吧。
MyClass.cpp
-----------------
代碼:
// DLL Entry Point。這是最重要的東西,別忘了哦,每個DLL都需要它。
GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
{
return(KErrNone);
}
EXPORT_C void CMyClass::DoSomething()
{
??// 好,我承認(rèn),這個函數(shù)也許應(yīng)該叫做DoNothing才對。:-)
??return ETrue;
}
EXPORT_C CMyClass* CMyClass::NewL()
{
? ?CMyClass* self = NewLC();
? ?CleanupStack::Pop(self);
? ?return self;
}
...
其實大家注意到了,問題關(guān)鍵就在這對IMPORT_C...EXPORT_C上。這些函數(shù)就是你的DLL所定義的API接口!
好了,基本完成了,我們編譯它!abld build wins udeb
編譯結(jié)束后,你會在epoc32的那堆目錄下找到一個MyClass.lib以及生成的DLL! 是的,就這么簡單![/code]
應(yīng)用程序總是中斷的分析
檢查內(nèi)存泄漏的方法:
__UHEAP_MARK;
你得代碼中需要檢查的部分
__UHEAP_MARKEND;
無原因退出主要有以下幾個原因:
1、沒有處理Leave異常,也就是有沒有被Trap的Leave函數(shù)。所有的Leave函數(shù)必須在程序的某個地方被TRAP, TRAPD, 或TRAP_IGNORE涵蓋到。這是最初要的原因
2、訪問了非法的內(nèi)存區(qū)域
3、修改了非法的內(nèi)存區(qū)域?qū)е孪到y(tǒng)服務(wù)出錯。這個問題可以在Symbian 9以后實現(xiàn)Platform Security之后解決
4、沒有找到需要的庫。缺少所需要的DLL文件等等
5、錯誤的資源文件,RSC文件的版本和程序中調(diào)用所需的資源文件不一致
6、調(diào)用了系統(tǒng)不支持的功能。例如類似調(diào)用Camera功能的時候要考慮到不同手機產(chǎn)品相機的差別,需要安裝相應(yīng)的FP (Feature Pack)
如何運行app和exe程序
Symbian有2種類型的本地程序:
APP是有GUI的程序,因此能夠被終端用戶使用
EXE通常是服務(wù)端或命令行程序,通常隱蔽的運行。沒有GUI,不能直接從主菜單運行
運行指南
如果你是一個終端用戶想運行APP:它會在你的電話菜單中列出如果它已經(jīng)安裝
當(dāng) 一個EXE程序在主菜單不可見時不能直接運行EXE程序。試著從INBOX運行它(如果你通過紅外或藍(lán)牙下載過它,它可能存儲在INBOX里)會導(dǎo)致一個 安全錯誤。首先,你需要安裝一個文件管理器(比如FileMan或FExplorer),瀏覽它存儲的位置(在我的3650上INBOX的目錄在E:/ system/Mail/xxx),然后運行它。
運行程序
當(dāng)你知道運行APP或EXE程序使用哪個API后是非常簡單的事。
運行EXE程序:
#include
...
_LIT(KMyAppName, "c://system//Apps//MyApp//MyApp.exe");
EikDll::StartExeL(KMyAppName);
下面的代碼運行APP比較復(fù)雜但允許執(zhí)行特定的文檔
#include
#include
...
_LIT(KMyAppName, "c://system//Apps//MyApp//MyApp.app");
_LIT(KMyDocName, "c://Documents//MyApp.dat");
CApaCommandLine * cmd=CApaCommandLine::NewL();
cmd->SetLibraryNameL(KMyAppName);
cmd->SetDocumentNameL(KMyDocName);
cmd->SetCommandL(EApaCommandRun);
EikDll::StartAppL(*cmd);
運行瀏覽其他的NOKIA程序
如果你打算開始基于Series 60的ROM 程序,在NOKIA論壇查找關(guān)于外部程序查看文檔的問答可以給你帶來收獲
下面的代碼將開始瀏覽特定的頁:
#include // apgrfx.lib
void NNewLCUtils::StartBrowser(const TDesC& aUrl)
{
? HBufC* param = HBufC::NewLC( 256 );
? param->Des().Format( _L( "4 %S" ),&aUrl );
? // Wap Browser's constants UId
? const TInt KWmlBrowserUid = 0x10008D39;
? TUid id( TUid::Uid( KWmlBrowserUid ) );
? TApaTaskList taskList( CEikonEnv::Static()->WsSession() );
? TApaTask task = taskList.FindApp( id );
? if ( task.Exists() )
? {
??? HBufC8* param8 = HBufC8::NewLC( param->Length() );
??? param8->Des().Append( *param );
??? task.SendMessage( TUid::Uid( 0 ), *param8 ); // Uid is not used
??? CleanupStack::PopAndDestroy(); // param8
? } else{
??? RApaLsSession appArcSession;
??? User::LeaveIfError(appArcSession.Connect()); // connect to AppArc server
??? TThreadId id;
??? appArcSession.StartDocument( *param, TUid::Uid( KWmlBrowserUid ), id );
??? appArcSession.Close();
? }
? CleanupStack::PopAndDestroy(); // param
}
將你的程序帶到前臺或后臺
這篇文章將向你展示如何在你的程序得到或失去屏幕焦點的時候控制它們和怎樣控制它們。
在 焦點改變的時候開始。Series 60系列的框架將在程序得到或失去屏幕焦點的時候通過CAknAppUi::HandleForegroundEventL(TBool aForeground)發(fā)出通知。當(dāng)你的程序得到焦點的時候參數(shù)aForeground為ETrue,失去焦點的時候為EFalse。
如果你需要做一些特定的操作,你需要重載這個函數(shù)。這有一個不失去焦點的例子
void CMyAppUi::HandleForegroundEventL(TBool aForeground)
{
? // Call Base class method
? CAknAppUi::HandleForegroundEventL(aForeground);
? if(aForeground) {
??? // We have gained the focus
??? ...
? } else {
??? // We have lost the focus
??? ...
? }
}
改變焦點。你總是能夠請求改變你程序的焦點使用命令TApaTask::SendToBackground() and TApaTask::BringToForeground()。下面代碼片段顯示怎樣從AppUi使用它們:
void CMyAppUi::BringToForeground()
{
// Construct en empty TApaTask object
// giving it a reference to the Window Server session
TApaTask task(iEikonEnv->WsSession( ));
// Initialise the object with the window group id of
// our application (so that it represent our app)
task.SetWgId(CEikonEnv::Static()->RootWin().Identifier());
// Request window server to bring our application
// to foreground
task.BringToForeground();
}
我沒有測試下面的代碼,但你可能可以使用下面的代碼控制其他的程序:
// Bring the application "theApp" to background
TApaTaskList tasklist(iCoeEnv->WsSession());
TApaTask task(tasklist.FindApp(_L("theApp")));
task.SendToBackground(); // or BringToForeground()
Symbian 程序編譯的過程
1. C++ BuilderX
Symbian 的開發(fā)環(huán)境似乎不是那么容易配置.不過Borland的C++ Builder對Symbian的支持比較好,里面還有專門針對Symbian開發(fā)的工具選項呢.不過由于Microsoft Visual C++我用得比較熟悉,而且,有Visual Assist這樣強大的工具支持,所以我覺得還是在Microsoft Visual C++上開發(fā)比較適合我.
2. 命令行的編譯
命令行的編譯應(yīng)該是SDK的文檔中有講解的.針對Symbian SDK中的Series60Ex的Graphics的例子還說吧.
a) 首先我們得用命令行到Series60Ex/Graphics/Group這個目錄.然后需要設(shè)置VC的環(huán)境變量,最好的辦法就是直接運行/ Microsoft Visual Studio .NET 2003/Vc7/bin/vcvars.bat這個批處理文件.我的做法就是Group這個目錄建立一個command.bat文件,里面的內(nèi)容如下
PATH=%PATH%;D:/Microsoft Visual Studio .NET 2003/Vc7/bin
Cmd
然后,我只要在Windows里雙擊這個文件,就會自動到這個目錄的命令提示符下,然后輸入vcvars32 + 回車,就設(shè)置好了VC的環(huán)境變量.
b) 輸入bldmake bldfiles.??是基于perl語言的操作,所以說一定要裝Perl才用使用SDK.
c) 如果是編譯生成模擬器運行的,那么使用
??abld build wins udeb
? ? 如果是編譯生成機器上跑的,那么就使用
??abld build armi urel
編譯后,有兩個目錄是它給你生成的.如果你想重新生成,可以通過手動刪除這兩個目錄.
工程編譯目錄:
/Symbian/6.1/Series60/Epoc32/BUILD/SYMBIAN/6.1/SERIES60/SERIES60EX/GRAPHICS/GROUP
保存的編譯的MAKE文件, OBJ文件等等.
程序在模擬器的目錄
/Symbian/6.1/Series60/Epoc32/Release/wins/UDEB/Z/SYSTEM/apps/graphics
保存了模擬器上運行的App文件,只要刪除這個目錄,模擬器上就沒有這個程序了.
3. 全局非靜態(tài)變量引起的錯誤
我在view的cpp的增加了一個Tint x;在模擬器上運行沒有任何問題.當(dāng)我用armi方式編譯到目標(biāo)機器上的時候,出現(xiàn)了一個奇怪又經(jīng)典的錯誤.
PETRAN - PE file preprocessor V01.00 (Build 183)
Copyright (c) 1996-2001 Symbian Ltd.
ERROR: Dll 'Graphics[10005BBE].APP' has initialised data.
make[1]: *** [../../../EPOC32/RELEASE/ARMI/UREL/GRAPHICSAPP] Error -2
make: *** [TARGETGRAPHICS] Error 2
make -r -f "/Symbian/6.1/Series60/EPOC32/BUILD/SYMBIAN/6.1S/SERIES60/SERIES60EX/BMPMANIP/GROUP/ARMI.make" FINAL CFG=UREL VERBOSE=-s
解決辦法: 1.把全局非靜態(tài)變量變成全局靜態(tài)變量,static
? ? 2.把全局變量編成類里面的成員變量
這樣個問題估計是Symbian的書上說的那樣,編譯成ARMI最后目標(biāo)的時候,編譯器要對代碼中的內(nèi)存使用進(jìn)行嚴(yán)格檢查所造成的.
http://discussion.forum.nokia.com/forum/showthread.php?s=&threadid=27446
從Symbian 9設(shè)備的文件管理器運行EXE文件
Symbian 9 設(shè)備將所有的Exe文件定位與“/sys/bin”文件夾下,大多數(shù)情況下,我們不能從文件管理器來訪問它。在這里有一個很好的方式來實現(xiàn)如何從一個S60 3rd的設(shè)備上啟動exe文件。
當(dāng) 我們初次拿到S60 3rd設(shè)備,準(zhǔn)備移植程序到這個平臺時,我們多次發(fā)現(xiàn)一些問題。在PKG文件腫,會發(fā)現(xiàn)一些錯誤,exe文件被寫入錯誤的文件夾。在之前的版本中,exe 文件放在“/sys/bin“目錄下,使用我們的SysExplorer(Eric Bustarret開發(fā)的文件管理系統(tǒng)),我們嘗試啟動那些可見的exe文件,我們驚奇的發(fā)現(xiàn),它啟動了,相當(dāng)與在“/sys/bin”下。
因此,如果你真的需要啟動exe文件:
1。拷貝“/sys/bin”下的exe文件
2。復(fù)制它到一個可見目錄
3。使用SysExplorer,到該目錄運行它
CCoeControl類中Draw()函數(shù)的調(diào)試
自定義控件往往通過重載CCoeControl:: Draw() 方法來實現(xiàn)它的填充。然而,當(dāng)你單步調(diào)試代碼的時候,每個指令沒有立即顯示到屏幕上,因為它是通過window服務(wù)實現(xiàn)的。
慶幸的是,你可以改變它,你可以將每次畫圖都立即顯示到屏幕上,添加這段代碼到你的AppUi::ConstructL()中:
CODE:
#ifdef _DEBUG
iEikonEnv->WsSession().SetAutoFlush(ETrue);
#endif
這段代碼將強制每個圖形上下文繪制命令,立即顯示出來,這樣可以避免window服務(wù)緩沖后刷新。
這意味著,你可以看到每次畫圖代碼而產(chǎn)生的效果,到發(fā)布版中,記住去掉它,否則他將影響程序的運行效率。
在S60 3rd的手機上顯示所有已安裝程序的Uid
一個應(yīng)用程序它可以顯示設(shè)備上所有已安裝程序的Uid。
該程序從S60 2.x 移植到 S60 3.x
S60 2.x的源代碼可以在Forum Nokia 找到,下面的代碼是S60 3.0的。
概要:
以下代碼將顯示手機上安裝的應(yīng)用程序的Uid,它使用了下面的類。
CODE:
? ?? ???RApaLsSession iLsSession;
? ?? ???MAppUidObserver& iObserver;
? ?? ???RArray<TAppInfo> iApps;
? ?? ? class TAppInfo
? ?? ???{
? ?? ?? ?? ?? ???public:
? ?? ?? ? TInt32 iAppUid;
? ?? ?? ? TApaAppCaption iAppCaption;? ?? ?? ?? ?? ?
? ?? ???};
? ?? ?? ?void CAppUidViewerEngine::AppsToUiL()
? ?? ???{
? ?? ???TApaAppInfo apaAppInfo;
? ?? ???TAppInfo appInfo;
? ?? ???iApps.Reset();
? ?? ???// Get info on all apps, then iterate through each app
? ?? ???User::LeaveIfError(iLsSession.GetAllApps());
? ?? ???while(iLsSession.GetNextApp(apaAppInfo) == KErrNone)
? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ? appInfo.iAppCaption = apaAppInfo.iCaption;
? ?? ?? ?? ?? ? appInfo.iAppUid = apaAppInfo.iUid.iUid;
? ?? ?? ?? ?? ? User::LeaveIfError(iApps.Append(appInfo));
? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?
? ?? ???//??iObserver.AppsFoundL(iApps);
? ?? ???}
以上主要代碼。
這里是源代碼文件: [attach]531[/attach]
在運行時為S60程序提供多國語言支持
我準(zhǔn)備示范,如何使應(yīng)用程序在運行時支持多國語言。下面的例子中,我使用了3種語言:英語、法語和德語。
修改MMP文件
第一步是修改MMP文件。在MMP文件中你可以看到這樣一行:
CODE:
LANG? ?? ?? ?? ?? ? SC
修改成:
CODE:
LANG? ?? ?? ?? ?? ? 01 02 03
創(chuàng)建3種語言文件
我們將支持3種語言,英語、法語、德語,本地文件的擴(kuò)展名分別為:l01,l02和l03。你可以在本地化使用所有的字符。
修改LOC文件
現(xiàn)在你需要修改成下面的LOC文件
CODE:
// 01 = (British) English
#ifdef LANGUAGE_01
? ?? ???#include "MultiLang.l01"
#endif
// 02 = French
#ifdef LANGUAGE_02
? ?? ???#include "MultiLang.l02"
#endif
// 03 = German
#ifdef LANGUAGE_03
? ?? ???#include "MultiLang.l03"
#endif
修改YourAppAif.rss文件
YourAppaif.rss 文件中需要像這樣本地化你的應(yīng)用程序標(biāo)題:
CODE:
RESOURCE AIF_DATA
? ? {
? ? caption_list=
? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ? CAPTION { code=01; caption="MultiLang"; }, // Eglish
? ?? ?? ?? ?? ? CAPTION { code=02; caption="MultiLang"; }, // French
? ?? ?? ?? ?? ? CAPTION { code=03; caption="MultiLang"; }??// German
? ?? ?? ?? ?? ? };
? ?? ?? ?? ?? ?
? ? app_uid=0x02a5dd83;
? ? num_icons=2;
? ? embeddability=KAppNotEmbeddable;
? ? newfile=KAppDoesNotSupportNewFile;
? ? }
修改由CAknApplication繼承來的類
重寫CEikApplication 中的 ResourceFileName() 函數(shù)到你的CYourApplicationApp 類.
CODE:
TFileName CMultiLangApp::ResourceFileName() const
? ?? ???{
? ?? ???return TFileName();
? ?? ???}
修改AppUi 類
首先,你需要為AppUi 類中的 ConstructL()函數(shù)的BaseConstructL() 中傳遞ENonStandardResourceFile 參數(shù):
CODE:
void CMultiLangAppUi::ConstructL()
? ? {
? ? BaseConstructL( ENonStandardResourceFile );
? ? //...
? ? }
接著,在你的AppUi類中創(chuàng)建下列新的函數(shù):
CODE:
void CMultiLangAppUi::ChooseLanguageL(TInt aLanguageIndex)
? ?? ???{
? ?? ???_LIT(KResourceFileName, "MultiLang.r%02d");
? ?? ???TFileName resFileName;
? ?? ???resFileName.Format(KResourceFileName, aLanguageIndex);
#if !defined(__WINS__) && !defined(__WINSCW__)
? ?? ???// Device
? ?? ???CompleteWithAppPath(resFileName);
#else
? ?? ???// Emulator
? ?? ???resFileName.Insert(0, KEmulatorPath);
#endif
? ?? ???if (iOffset) iCoeEnv->DeleteResourceFile(iOffset);
? ?? ???iOffset = iCoeEnv->AddResourceFileL(resFileName);
? ?? ???}
現(xiàn)在你可以調(diào)用 ChooseLanguageL([LanguageIndex]) 函數(shù)來實現(xiàn)語言的切換了。
修改PKG文件
添加以下幾行到你的打包文件中。
CODE:
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang.r01"? ?? ?? ?-"!:/system/apps/MultiLang/MultiLang.r01"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang.r02"? ?? ?? ?-"!:/system/apps/MultiLang/MultiLang.r02"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang.r03"? ?? ?? ?-"!:/system/apps/MultiLang/MultiLang.r03"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang_caption.r01" -"!:/system/apps/MultiLang/MultiLang_caption.r01"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang_caption.r02" -"!:/system/apps/MultiLang/MultiLang_caption.r02"
"/Symbian/7.0s/Series60_v21/Epoc32/data/z/system/apps/MultiLang/MultiLang_caption.r03" -"!:/system/apps/MultiLang/MultiLang_caption.r03"
如何判斷程序是否被自動啟動或者被用戶啟動
有時候能夠檢查出在系統(tǒng)啟動的時候哪些應(yīng)用程序被“Startup List Api(只有S60 3rd可以使用)”或者用戶啟動,和通過“Symbian Signed”,管理啟動程序的應(yīng)用是一個很通用的程序,這篇文章將告訴你如何做到。
首先,你必須修改程序注冊文件,并在APP_REGISTRATION_INFO資源中添加一些opaque_data字段,內(nèi)容和直并不是那么重要,你只需要按下面的方式指定:
CODE:
#include <appinfo.rh>
#include <uikon.rh>? ?
RESOURCE APP_REGISTRATION_INFO
{
??...
??opaque_data = r_startup_detect;
}? ?? ?
? ?
RESOURCE NUMBER_INT8 r_startup_detect
{
value = 1;
}
當(dāng)應(yīng)用程序運行時,opaque_data和其他運行參數(shù)將被忽略。因此,判斷是否在運行或者不允許(區(qū)分是否應(yīng)用程序被允許在啟動的時候或者被用戶啟動)。
這樣,你可以重載AppUI中的ProcessCommandParametersL()函數(shù)
T
CODE:
Bool CMyAppUi::ProcessCommandParametersL( CApaCommandLine &aCommandLine )
{
??if(aCommandLine.OpaqueData().Length() > 0)
??{
? ?? ?// Opaque data exists, app. has been manually started from the menu
??}
??else
??{
? ?? ?// App. has been auto-started -> exit if auto-start in settings is OFF
??}
? ?return CEikAppUi::ProcessCommandParametersL( aCommandLine );
}
你也要注意,通過Symbian Signed需要你的應(yīng)用程序有一個允許禁止自動啟動的屬性的選項設(shè)置。你需要加入操作代碼來實現(xiàn)它,在 Forum Nokia Technical Library中描敘得比較好。
這篇文章僅適用于 S60 3RD,接下來的版本也將支持這個屬性
如何在SYMBIAN60中編寫DLL
Prerequisites
Knowledge of C++ and COM.
Knowledge of Symbian Programming idioms
Introduction
Writing a polymorphic DLL involves the following steps:
Design and write interfaces.
Implement the interface.
Lets explore these in more detail:
Design and write interface consisting of method declarations.
An interface is essentially an abstract class. An example would clarify it:
class ICalculator {public:virtual TInt Sum(TInt, TInt) = 0;};
Above snippet declares a class ICalculator with one method Sum which would take 2 TInt parameters and would return a TInt value. Take a look at the name given to the class. This is done to follow a convention i.e. an interface name should start with an 'I'. Now if one wishes to implement interface ICalculator, he/she has to implement the method Sum.
COM programmers would be wondering that how it can be an interface without a UUID or something like that. Yes! in Symbian too, an interface requires a UUID. While writing an interface this is how UUID is given to it.
static const TUid KCalculator_DLLUID = {0x100039CE};static const TUid KCalculator_DLLUID_Ver1 = {0x0352D96B};class ICalculator {public:virtual TInt Sum(TInt, TInt) = 0;};
Your polymorphic interface is ready. You have to write it in a .h file so that it can be implemented in other .cpp files.
Implement the interface.
Writing a polymorphic DLL is half done when interface declaration is done. Now one would require to implement it. Implementing an interface is as simple as inheriting abstract classes. You have to inherit from an interface and implement pure virtual methods of the interface.
Again an example would help us understand this:
class CImpCalculator: public ICalculator {public:EXPORT_C CImpCalculator* NewImpClass();//function would be exposed through Function tableTInt Sum(TInt num1,TInt num2);};GLDEF_C TInt E32Dll(TDllReason) {return KErrNone;}EXPORT_C CImpCalculator* CImpCalculator::NewImpClass() {return new (ELeave) CImpCalculator;}TInt CImpCalculator::Sum(TInt num1,TInt num2) {return num1 + num2;}
The example above does something more than just implementing the interface. The class CImpCalculator has a method of its own, NewImpClass. This method has a qualifier EXPORT_C. Clearly this is the method which is exposed from the implementation class. In Symbian it is not required to export or expose all the methods from an interface. Only method which needs to be exposed is which returns the object of the interface (or should I say the implementor class?). Rest of the methods can be accessed from function table. The NewImpClass method returns a pointer to the newly created object.
E32Dll method has to be written in every Polymorohic DLL as it is required by the Symbian run time. You would get linking errors in case you forget to write it. This method is responsible to allocate thread local store for the DLL instance.
Now you are ready to compile and build your own DLL. Build it and start using it.
Lastly these DLLs are called polymorphic because one can write many implementations of the same interface. Further all the Symbian GUI applications are Polymorphic DLLs. Check the GUI SDK examples, you will find E32Dll method implemented.
That's all you would require to write a DLL on Symbian!! Note that I have tested the code on NOKIA Series 60 emulator.
定義類的問題
問題:
我使用CAknView定義了一個View類,
class CCameraAppView : public CAknView.....
并且在這個類中添加了一個自定義的CCoeControl的子類成員用來繪圖等。
CCoeControl的子類定義如下:
class CCameraAppBaseContainer : public CCoeControl, MCoeControlObserver, public MAknTabObserver,MConverterController
其中MConverterController是一個自定義的純虛類,用做接口用。
開始的時候我是將MConverterController寫在了MAknTabObserver的前面,即寫成了:
class CCameraAppBaseContainer : public CCoeControl, MCoeControlObserver, public MConverterController,MAknTabObserver
這時候在使用winscw udeb方式編譯的時候不會出現(xiàn)任何錯誤,但是當(dāng)使用gcce urel方式編譯的時候卻會出現(xiàn)如下錯誤:
Link Error.rodata+0xf4):undefined reference to 'non-virtual thunk to CCameraAppBaseContainer::TabChangedl(int)'
當(dāng)時研究了很久也沒弄清楚是怎么回事,后來將MConverterController和MAknTabObserver的順序改過來,就沒有錯誤了。
這個錯誤的產(chǎn)生到底是什么原因呢?
解決:
MAknTabObserver 類只有一個公有的成員函數(shù)TabChangedL(),第一種寫法因為沒有寫明從MAknTabObserver的繼承方法,所以是private繼承, 也就是所有的成員函數(shù)是派生類的私有函數(shù),所以外部無法訪問TabChangedL()這個私有函數(shù).聲明派生類時明確指出派生方式 (public,private,protected)是一個好習(xí)慣.
如何才能實現(xiàn)這個非同期處理
問:
我要實現(xiàn)如下3個函數(shù)處理
GetData(TInt aRequestId) //取得數(shù)據(jù),之后NotifyResult要使用這個requestID去通知處理結(jié)果
NotifyResult(TInt aRequestId) //通知取得的結(jié)果,這個requestID要和GetData的相一致
CancelRequest(TInt aRequestId)//根據(jù)requestID取消之前的某個請求
現(xiàn)在處理流程是這樣的,有很多的請求可以同時發(fā)出,那么我該如何根據(jù)不同的requestID去實現(xiàn)Cancel呢?
GetDataA
GetDataB
GetDataC
NotifyResultA
NotifyResultB
NotifyResultC
---------------------------------------------
答:
同時發(fā)出多個導(dǎo)步請求需要創(chuàng)建相應(yīng)數(shù)量的活動對象實例,當(dāng)然也可以創(chuàng)建一個支持請求隊列的活動對象來實現(xiàn)這個需求。
問:
我起初也想針對每一個請求創(chuàng)建一個活動對象。
不過不清楚用什么異步請求去激發(fā)每個活動對象。
初步設(shè)想是
class CMsgItem::Public CActive
CMsgItem::RunL
{deal with the request();
NotifyResult();
}
CSample::CreatMsgItem
{
a = New CMsgItem;
//★這里用什么去發(fā)出異步請求呢?原來想用Timer.After,但是覺得不妥。
a.SetActive();
}
后來又打算使用消息隊列去保存請求,然后在CIdle長線任務(wù)處理中提取msg,去處理。
不過我還是希望用第一種方法去做,
關(guān)于如何發(fā)出異步請求請指點一下,除了timer還能使用別的嗎?
創(chuàng)建出來了這些活動對象,在什么時機刪除呢?能否在Runl中調(diào)用"delete this"把自己刪除?
考慮到有可能會在RunL處理中彈出選擇對話框,有問題嗎?(考慮到RunL內(nèi)部不能停留太長時間)
還有有什么需要注意的地方,也請賜教。
-------------------------------------------
答:
活動對象的請求操作接口負(fù)責(zé)發(fā)出異步請并調(diào)用SetActive(),然后在RunL()中調(diào)用通知的函數(shù).這個通知函數(shù)的接口可以添加一個活動對象本身的指針做為參數(shù),這樣就可以在接收通知的函數(shù)中區(qū)分出是哪個活動對象發(fā)出的請求了,就像Listbox的觀察器一樣:
? ?Code:
class MEikListBoxObserver
{
public:
enum TListBoxEvent
{
EEventEnterKeyPressed,
EEventItemClicked,
EEventItemDoubleClicked,
EEventItemActioned, // reported by dir tree and dir contents listboxes
EEventEditingStarted,
EEventEditingStopped,
? ?? ???EEventPenDownOnItem,
? ?? ???EEventItemDraggingActioned
};
public:
virtual void HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType)=0;
};
Symbian中的線程、進(jìn)程及同步
全局內(nèi)存塊:跨越多個進(jìn)程直接訪問的內(nèi)存塊。
創(chuàng)建自己的全局內(nèi)存塊可以通過Rchunk API類
Rchunk chk;
_LIT(KChunkName,"My Globla Chunk");
TInt rc=chk.CreateGlobal(KChunkName,0x1000,0x5000);
其中CreateGlobal()方法第一個參數(shù)指定全局內(nèi)存塊的名稱。后面兩個參數(shù)為塊指定分配給它的物理RAM和為塊保留的虛擬內(nèi)存的數(shù)量。
再其他進(jìn)程中要訪問全局內(nèi)存塊可以這樣操作。
Rchunk chk;
_LIT(KChunkName,"My Globla Chunk");
TInt rc=chk.OpenGlobal(KChunkName,0);
TInt *ptr=(TInt *)chk.Base();
可以通過*ptr直接讀寫這塊內(nèi)存。
RChunk::OpenGlobal()第一個參數(shù)指定了全局內(nèi)存塊的名稱,第二個參數(shù)用于說明塊是為只讀(1)還是可寫的(0)
可以通過RChunk::Ajust(Tint newsize)方法來擴(kuò)大塊的提交內(nèi)存尺寸。
TInt rc=chk.CreateGlobal(KChunkName,0x1000,0x5000);
例如上面創(chuàng)建了一個塊,RAM提交給它0x1000字節(jié),塊的最大尺寸是0x5000
在這種情況下,只有用于讀寫的0x1000字節(jié)的物理RAM分配給了塊。但是隨后可以擴(kuò)充該塊,例如:
chk.Ajust(0x3000)
現(xiàn)在塊被分配了0x3000字節(jié)的內(nèi)存。
信號量:
全局信號量:
創(chuàng)建全局信號量
RSemphore::CreateGlobal(const TDesc &aname,TInt aCount,TOwnerType aType=EOwnerProcess);
第一個參數(shù)是信號量的名稱,第二個參數(shù)是信號量的標(biāo)記計數(shù)。
第三個參數(shù)指定句柄的所有權(quán)。
EOwnerProcess標(biāo)記該信號量句柄可以在進(jìn)程的任何位置進(jìn)行訪問。
EOwnerThread表示它只能被創(chuàng)建的線程訪問。
打開全局信號量
RSemphore::OpenGlobal(const TDesc &aname,TOwnerType aType=EOwnerProcess);或者
RSemphore::Open(const TFindSemphore& aFind,TOwnerType aType=EOwnerProcess);
第一個函數(shù)通過信號量全名打開它。
第二個函數(shù)使用TFindSemphore類,通過包含通配符字符的部分名稱打開它。
例如_LIT(KMatchName,"MySemphore*");
TFindSemphore semName(KMatchName);
RSemphore::Open(semName)
打開一個全局的信號量。
RSemphore::Signal()給信號量的標(biāo)記數(shù)加1
RSemphore::Wait()給信號量的標(biāo)記數(shù)減1
如果Wait()發(fā)現(xiàn)減后的標(biāo)記數(shù)為負(fù)值,則Wait()阻塞,直到調(diào)用Signal()增加標(biāo)記計數(shù)才返回。
(1)使用信號量可以做為一個直接信號,控制不同進(jìn)程之間執(zhí)行的流程。
(2)信號量也可以用來保護(hù)共享資源。
本地信號量:
創(chuàng)建本地信號量
TInt CreateLocal(Tint aTokenCount,TOwnerType aType=EOwnerProcess);
本地信號量沒有名字,不需要打開,通過創(chuàng)建它的RSemphore,就可以簡單地訪問它。
注意,如果把aType指定為EOwnerThread,但又想在另外一個線程中使用信號量,那么,就必須使用Duplicate()方法,為該線程創(chuàng)建句柄的副本。可以查看SDK文檔中的RHandleBase::Duplicate()
symbian中的幾個API
1. 定位當(dāng)前程序,并將當(dāng)前程序的優(yōu)先級調(diào)高
TInt prio = 1001; //設(shè)置一個較高的值
//將當(dāng)前程序的窗口組設(shè)計一個高的優(yōu)先級,并置為同級最前
CEikonEnv::Static()->RootWin().SetOrdinalPosition(0, prio);
2.將當(dāng)前程序的窗口組設(shè)置為最前, 可與HandleForegroundEventL 配合使用,使當(dāng)前程序使終處于最前(條件是優(yōu)先級要有足夠高,否則的話還是會被優(yōu)先級更高的程序搶占)
RWsSession ws = CEikonEnv::Static()->WsSession();
TApaTaskList tlist(ws);
TApaTask task = tlist.FindApp(KUidMyApp);??//KUidMyApp 是指要調(diào)高優(yōu)先級的程序的ID
task.BringToForeground();
或者是:
TApaTaskList taskList(CCoeEnv::Static()->WsSession());
TApaTask currentTask = taskList.FindByPos(0);
TApaTask ourAppTask = taskList.FindApp(KUidNightClockApp);
if(currentTask.ThreadId() != ourAppTask.ThreadId())
??ourAppTask.BringToForeground();
3.模擬一個按鍵消息,并發(fā)向指定窗口組
RWsSession sess=CCoeEnv::Static()->WsSession();
TWsEvent event;
TInt id=sess.FindWindowGroupIdentifier( 0, _L("*Phone?") ); //取得電話程序的窗口組
event.SetType(EEventKey);
event.SetTimeNow();
event.Key()->iCode = EKeyDownArrow; //模擬一個向下的箭頭按鍵
event.Key()->iModifiers = 0;
event.Key()->iRepeats = 0;
event.Key()->iScanCode = EStdKeyNull;
sess.SendEventToWindowGroup( id, event ); 將模擬的按鍵消息發(fā)給窗口組
給pys60以不同的屏幕顯示方式
如下就可以做到,我喜歡用全屏,嘿嘿
首先記得要裝入appuifw模塊
>>>import appuifw
然后可以選擇你想要的顯示方式
>>>appuifw.app.screen='normal' #(a normal screen with title pane and softkeys)
>>>appuifw.app.screen='large' #(only softkeys visible)
>>>appuifw.app.screen='full' #(a full screen)
Symbian平臺編碼問題
自己在開發(fā)時遇到的一些問題:<!--[if !vml]-->
1.??<!--[endif]-->將Symbian應(yīng)用程序改為中文名稱
? ? ? 修改資源文件xxx_caption.rss:
? ?? ???Code:
#include “xxx.loc”
RESOURCE CAPTION_DATA
...{
? ? caption = qtn_app_caption_string;
? ? shortcaption = qtn_app_short_caption_string;
}
? ? ? 打開xxx.loc 用記事本或UltraEdit轉(zhuǎn)成UTF-8編碼
? ?? ???Code:
CHARACTER_SET UTF8? ? //必須加這行
#define qtn_app_caption_string “程序中文名”
#define qtn_app_short_caption_string “顯示名”
2.在Nokia 7610中文機上顯示Shift-JIS編碼的日文串
? ? ? Symbian平臺以Unicode編碼,可以表示、顯示所有字符,只需將本地編碼轉(zhuǎn)為Unicode即可。
? ?? 因為中文機上沒有日文字庫,所以不能用類CcnvCharacterSetConverter提供的方法
? ???(但可實現(xiàn)GBK -> Unicode)
? ? Code:
CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewLC();
converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierShiftJis, CEikonEnv::Static()->FsSession());
/***************************************************
*上一行會異常退出,因目標(biāo)平臺沒有SJIS字庫
*但可以實現(xiàn)GBK -> Unicode,只需將KcharacterSetIdentifierShiftJis
*改為KCharacterSetIdentifierGbk
***************************************************/
TInt state = CCnvCharacterSetConverter::KStateDefault;
……
TInt ctu = converter->ConvertToUnicode(bufPtr, srcPtr, state);
? 在網(wǎng)上找了一個實現(xiàn)SJIS到Unicode轉(zhuǎn)換的函數(shù)
? ? Code: #include "cp.h"
#define is_zen(c)
? ?? ???((0x81 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0x9f)
? ?? ???|| (0xe0 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0xfc))
#define is_han(c)
? ?? ???((0xa0 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0xdf))
s32_t skip_bytes(char c)
{
??if(is_zen(c)) {
? ? return 2;
??} else if (is_han(c)) {
? ? return 1;
??}
??return 0;
}
s32_t jis2utf8(char **srcbuf, s32_t *srclen, char **outbuf, s32_t *outlen) {
??unsigned char *dst;
??unsigned char *src;
??unsigned short utf8code;
??int sjiscode;
??s32_t??len;
??unsigned char *to2;
??if (! (srcbuf && srclen && outbuf && outlen))
? ? return 0;
??src = (unsigned char *)*srcbuf;
??dst = to2 = (u8_t*)malloc(*outlen);
??while (*src && ((dst - to2) < (*outlen - 4))) {
? ? len = skip_bytes(*src);
? ? if ( len == 2 ) {
? ?? ?sjiscode = (int)(*src++ & 0xff);
? ?? ?sjiscode = (int)((sjiscode << 8)|(*src++ & 0xff));
? ? } else {
? ?? ?sjiscode = (int)(*src++ & 0xff);
? ? }
utf8code = cp[sjiscode];// convert sjis code to utf8 (cp[] is conversion table array)
? ? if ( utf8code <= 0x7f ) {
? ?? ?*dst++ = (char)(utf8code & 0xff);
? ? }
? ?else if ( utf8code <= 0x7ff ){
? ?? ?*dst++ = (char)( 0xc0 | ((utf8code >> 6) & 0xff));
? ?? ?*dst++ = (char)( 0x80 | ( utf8code & 0x3f ));
? ? } else {
? ?? ?*dst++ = (char)( 0xe0 | ((utf8code >> 12) & 0x0f));
? ?? ?*dst++ = (char)( 0x80 | ((utf8code >> 6)??& 0x3f));
? ?? ?*dst++ = (char)( 0x80 | (utf8code & 0x3f));
? ? }
??}
??*dst++='';
??memcpy(*outbuf,to2,*outlen);
??free(to2);
??return strlen(*outbuf);
}
<!--[endif]-->
symbian代碼編寫方面的提醒
給自己在symbian代碼編寫方面的提醒:
(1)在控件環(huán)境下進(jìn)行文件操作,建議不要連接文件服務(wù)器,而應(yīng)該直接利用 CEikonEnv::FsSession()這樣省去了連接文件服務(wù)器的開銷;
(2)常量的判斷語句,常量應(yīng)該放在==的左邊,這樣的好處是萬一程序員誤將==寫成=也可以檢查出來,因為常量不能被賦值的;
(3)在程序中要善于運用條件編譯,使得同樣的一份代碼可以適應(yīng)模擬器調(diào)試和真機的運行;
(4)提醒自己寫函數(shù)時要注意考慮函數(shù)退出的問題,含可能退出代碼的函數(shù),函數(shù)名應(yīng)以L結(jié)尾。
如何顯示s60 3rd中文菜單
sword 222??問:
1。如何在真機中顯示中文菜單啊?
我在.rss文件中,寫上CHARACTER_SET UTF8
將rls文件存儲成u8-dos格式。編譯GCCE過不了,說我文件有非法字符。
2.在模擬器上如何顯示中文?
我的sdk是s60 3.0 maint的。用的是vs.net2003+carbide 2.1
beover1984 答:
最好使用EditPlus把文件轉(zhuǎn)換成UTF-8編碼
sword 222??問:
我用UE轉(zhuǎn)成的就是UTF8啊。編譯不過。郁悶中。
提示非法字符如下:
..//data//HotelAd.rls(1) : *** Unknown character '? (value 0xffffffef)
..//data//HotelAd.rls(1) : *** Unknown character '? (value 0xffffffbb)
..//data//HotelAd.rls(1) : *** Unknown character '? (value 0xffffffbf)
還有其他可能不對嗎?
60 2.0版本的我用UE轉(zhuǎn)換是對的。極度郁悶中。謝謝beover1984的回復(fù)。
beover1984 答:
用UE轉(zhuǎn)換的在3.0上可能也存在問題,我換成EditPlus就好了.
sword 222??問:
用edit plus轉(zhuǎn)換成utf8編譯通過。
謝謝beover1984的回復(fù)。
我用EPlus轉(zhuǎn)換,可以編譯了,但是,真機上運行不了,顯示系統(tǒng)錯誤。我自簽名,只用了ReadUserData能力。在亂碼的時候,我還是可以在真機上使用的。在模擬器上可以運行,但是依舊是亂碼。有沒有模擬器顯示中文的辦法?
beover1984 答:
執(zhí)行abld reallyclean清理一下工程,然后重新生成一下.
cdutly 答:
如 果你用UE的話,那么在"高級--配置"中將"當(dāng)保存時寫入UTF-8 BOM頭到所有UTF-8文件"去掉,再去掉"自動檢測UTF-8". 設(shè)置好以后重新打開loc文件,你會發(fā)現(xiàn)在文件頭部會有一些亂碼字符,刪掉. 但如果你的loc是中文的話,中文將會變成很奇怪的字,不要擔(dān)心,再將"自 動檢測UTF-8"選種然后重新打開loc及可,試試看.
如何選擇編輯器中的一段文本
問題:
比如一個用來顯示聊天記錄的編輯器,通過上下鍵需要能每次選中一段文本進(jìn)行復(fù)制或其它操作,請問要如何實現(xiàn)呢?
解決:
CEikEdwin::SetSelectionL()
void SetSelectionL(TInt aCursorPos, TInt aAnchorPos);
Description
Sets the text selection. Highlights the selected area and makes the new cursor position visible. Any previous selection is cancelled. This function also updates the scroll bar thumbs if present.
用什么函數(shù)來獲得當(dāng)前剩余堆內(nèi)存
問題:
現(xiàn)在的問題就是要檢測系統(tǒng)的內(nèi)存容量,當(dāng)內(nèi)存的剩余量達(dá)到一個臨界值的時候做出相應(yīng)處理。可是找不到什么辦法。搜了站內(nèi)的帖子,找到一個說是Available()可以實現(xiàn)的,但是我不能通過SDK help解決問題,最好有高人給個代碼片斷。
解決:
下面的代碼可以得到可用內(nèi)存的數(shù)量。
Code:
TMemoryInfoV1Buf info;
UserHal::MemoryInfo(info);
TInt freeMemory = info().iFreeRamInBytes;
如何對描述符讀寫數(shù)值型數(shù)據(jù)
saintrui :
TInt num = 123456;
TBuf8<64> buf;
buf.AppendNum(num);
上 面的代碼把TInt型的數(shù)字num存在描述符里后,buf中就有6個字節(jié)的數(shù)據(jù)了,每個字節(jié)分別是num中的一個數(shù)字,本來TInt是占4個字節(jié)的,我想 讓描述符用4個字節(jié)存儲這個num,即按num的4個字節(jié)不變地儲存在buf的四個字節(jié)中,而不是6個字節(jié),該如何做?
上面的問題是我在寫socket通信中碰到的,還有個問題,假如pc服務(wù)器上發(fā)送過來的數(shù)據(jù)中有個數(shù)字123456,那么手機接收后存在TBuf8的描述符中,我想把這個數(shù)字從該描述符中讀到一個TInt變量里,該怎樣讀呢?
saintrui :
解決了,symbian中不提供這樣的函數(shù),只好自己轉(zhuǎn)換。太依賴symbian了,c++的類型轉(zhuǎn)換都差點忘了。
把a的二進(jìn)制值寫到描述符中:
TInt a =123456;
TUint8* ch = (TUint8*)(&a);
TBuf8<20> buf;
buf.Append(ch,4);
從描述符中讀取二進(jìn)制TInt值:
TUint8* p = &(buf[0]);
TInt* b = (TInt*)(p);
ch2000pro:
從描述符讀出來可以這樣做:
TLex iLex(iBuf);
TInt iNum2;
iLex.Val(iNum2);
SymbianLn:
樓住的最初的做法
AppendNum就是把數(shù)字轉(zhuǎn)換成字符串存儲,所以就變成了6個字符。
讓描述符直接指向存儲地址,就可以了。
因為指針描述符既能指向字符,也能指向內(nèi)存地址。
可以使用TPtr8等等。
在程序啟動后先彈出確定使用文字頁面,然后確定后繼續(xù)運行
windnoway? 問:
---------------------------------------------------------------
我們的程序做好了
但是我想在程序剛啟動的時候
彈出一個文字頁面“歡迎使用授權(quán)軟件”,點擊同意后再繼續(xù)啟動程序
怎么來做到程序還沒有啟動的時候顯示呢?
用甚么函數(shù)寫在甚么地方 給個例子看看?
-----------------------------------------------------------------
beover1984?? 回答:
---------------------------------------------------------------------
Code:
HBufC *header = StringLoader::LoadLC( R_ABOUT_HEADER, iCoeEnv );
HBufC *body = StringLoader::LoadLC( R_ABOUT_TEXT, iCoeEnv );
CAknMessageQueryDialog *dlg = CAknMessageQueryDialog::NewL( *body );
dlg->PrepareLC( R_AVKON_MESSAGE_QUERY_DIALOG );
dlg->SetHeaderTextL( *header );
dlg->RunLD();
CleanupStack::PopAndDestroy( 2, header );
上面的代碼可以彈出一個帶"確定"和"取消"的對話框,在UI的ConstructL()中判斷dlg->RunLD();的返回值就可以了.
--------------------------------------------------------------------------------------------
windnoway? 問:
------------------------------------------------------------------------------------------
兄弟您看一下是否正確
我在**appui.cpp中加入
#include<avkon.rsg> //for R_AVKON_MESSAGE_QUERY_DIALOG
_LIT(R_ABOUT_HEADER,"message");
_LIT(R_ABOUT_TEXT,"Copyright 2006 SE");
HBufC *header = StringLoader::LoadLC( R_ABOUT_HEADER, iCoeEnv );
HBufC *body = StringLoader::LoadLC( R_ABOUT_TEXT, iCoeEnv );
CAknMessageQueryDialog *dlg = CAknMessageQueryDialog::NewL( *body );
dlg->PrepareLC( R_AVKON_MESSAGE_QUERY_DIALOG );
dlg->SetHeaderTextL( *header );
dlg->RunLD();
CleanupStack::PopAndDestroy( 2, header );
void CFreeJoyAppUi::ConstructL()
{
BaseConstructL();
if (dlg->RunLD())
{
//這里就寫明啟動的時候啟動的程序了
}
}
//兄弟這樣寫沒有錯誤吧
-------------------------------------------------------------------------------------------------------
beover1984?? 回答:
----------------------------------------------------------------------------------------------------
Code:
.......
if( !dlg->RunLD() )? //選擇"取消"退出程序
{
??? Exit();
}
VC中的CString類,在symbian中用什么解決
問題:
在VC中的CString類,可以用什么代替呢?請大家指教
解決:
Symbian平臺上提供了描述符用于處理字符串,其中HBufC是在heap上創(chuàng)建的,并且提供了ReAlloc()用于重新分配空間,但是不會像CString那樣在空間不夠時自動分配,需要自己做處理.
關(guān)于在手機上安裝的問題
問題:
我用自己的SIS文件在手機上安裝之后,只出現(xiàn)圖標(biāo),但是老是打不開程序,請問是什么原因。
我的SIS文件是在C:/Symbian/8.0a/S60_2nd_FP2_SC/epoc32/tools下創(chuàng)建的,為什么在其他目錄下用不了makesis的? 老是提示出錯。
解決:
把 C:/Symbian/8.0a/S60_2nd_FP2_SC/epoc32/tools這個路徑加到環(huán)境變量path中,然后重啟一下就能在任意目錄 使用makesis了,程序不能在真機上啟動很可能是打包時少打了一些資源文件引起的,建議檢查一下PKG文件,或者編譯打包一個例子試一下.
不通過rss文件,程序手動構(gòu)建CEikEdwin的問題
問題:
我不想用rss來構(gòu)建CEikEdwin,因為CEikEdwin會經(jīng)常改變輸入限制。所以考程序來設(shè)置比較好。
但我一個只讓輸入英文的輸入框構(gòu)建如下:
iPSEdwin = new (ELeave) CEikEdwin;
iPSEdwin->SetContainerWindowL(*this);
iPSEdwin->ConstructL(EAknEditorFlagDefault,16,16,1);
iPSEdwin->SetInputCapabilitiesL(TCoeInputCapabilities::EWesternAlphabetic );
可運行后發(fā)現(xiàn),只能輸入數(shù)字,右上腳的輸入法提示也沒有了。
但另外一個只讓輸入數(shù)字的輸入框構(gòu)建如下:
iIDEdwin = new (ELeave) CEikEdwin;
iIDEdwin->SetContainerWindowL(*this);
iIDEdwin->ConstructL(EAknEditorFlagDefault,16,16,1);
iIDEdwin->SetInputCapabilitiesL(TCoeInputCapabilities::EWesternNumericIntegerPositive);
這就是正常的,只有數(shù)字輸入,右上角的輸入法提示也是正確的。
我該如何設(shè)置CEikEdwin的輸入限制,不通過rss來構(gòu)建
解決:
可以使用下面的代碼實現(xiàn)只能輸入字母的限制:
Code:
iPSEdwin = new (ELeave) CEikEdwin;
iPSEdwin->SetContainerWindowL(*this);
iPSEdwin->ConstructL(EAknEditorFlagDefault,16,16,1);
iPSEdwin->SetAknEditorFlags(EAknEditorFlagLatinInputModesOnly);
壓縮SVG文件
我們可以在S60第二版,FP3的SDK中通過SVGTBINENCODE.EXE程序來對Scalable Vector Graphics(SVG)圖形文件進(jìn)行二進(jìn)制編碼和壓縮。
SVGTBINENCODE的使用方法為:
1、備份你的.svg文件——你將使用一個不可編輯的壓縮版本覆蓋原來的那個。
2、對.svg文件在模擬器目錄中進(jìn)行拷貝。如%EPOCROOT%/epoc32/winscw/c/system/temp/
3、在命令行方式下,運行svgtbinencode壓縮程序。
cd %EPOCROOT%/epoc32/release/winscw/udeb svgtbinencode -Dnogui -- c:/system/temp/sourceimage.svg
這將在同樣目錄下生成一個二進(jìn)制編碼版本的SVG圖形文件,其擴(kuò)展名為.svgb
將這個.svgb文件拷貝到原來.svg文件所在位置。
刪除老的.SVG文件,因為你將要用壓縮版本去替代它。
將這個.svgb文件重命名為.svg擴(kuò)展名。
運行MifConv.exe程序來生成一個multi-icon文件(.MIF),如果使用擴(kuò)展過的makefile(icons.mk),那這些在編譯過程中會自動完成。
注意,MifConv無法識別.svgb擴(kuò)展名,如果你沒將其改名為.svg擴(kuò)展名那它將無法識別接收這個二進(jìn)制編碼的SVG文件。
調(diào)用掛機鍵時行為發(fā)生變化
標(biāo)題: 調(diào)用掛機鍵時行為發(fā)生變化
設(shè)備, 軟件 版本: S60 2nd Edition, Feature Pack 3? S60 3rd Edition
說明:
從S60第二版,FP3開始向后,按下掛機鍵將導(dǎo)致程序關(guān)閉。
詳細(xì)描述:
在早期S60設(shè)備上,當(dāng)我們按下掛機鍵時(就是紅色的end鍵),當(dāng)前程序?qū)袚Q到后臺而不會被關(guān)閉。但從S60第二版,FP3開始,當(dāng)我們按下掛機鍵時將導(dǎo)致當(dāng)前運行的程序關(guān)閉。
情景重現(xiàn):
運行一個第三方程序,按下掛機鍵,程序?qū)魂P(guān)閉,設(shè)備會切換到主畫面。
解決方案:
這是一個改進(jìn)的特性,因此無法饒過掛機鍵操作所引發(fā)的行為。如果需要切換程序時,終端用戶應(yīng)該使用菜單鍵去處理以避免掛機鍵導(dǎo)致程序的關(guān)閉。通過按1到2次菜單鍵來切換程序或返回待機畫面。
在異常發(fā)生后音頻流處于不穩(wěn)定狀態(tài)
標(biāo)題: 在異常發(fā)生后音頻流處于不穩(wěn)定狀態(tài)
設(shè)備, 軟件 版本: S60 2nd Edition, FP1, FP2, and FP3
說明:
如果程序因為異常而終止了音頻播放,那重新打開它的話將會引發(fā)錯誤。
詳細(xì)描述:
如果程序因為一個音頻流操作(使用CMdaAudioOutputStream或CMMFDevSound對象打開或運行)引起中斷并終止運行,那如果再次試圖使用如CMdaAudioOutputStream::OpenL去打開它時就會引發(fā)錯誤。
如果想要成功再次打開那個音頻流,我們需要將設(shè)備重新啟動。
情景重現(xiàn):
在音頻流播放出現(xiàn)異常中斷后,嘗試去調(diào)用CMdaAudioOutputStream::OpenL(),將無法得到返回,程序因此會掛起。
當(dāng)鍵盤鎖定被取消時可能會導(dǎo)致無意中將程序切換到后臺
標(biāo)題: 當(dāng)鍵盤鎖定被取消時可能會導(dǎo)致無意中將程序切換到后臺
設(shè)備, 軟件 版本: S60 2nd Edition, FP2, Nokia 6630, Nokia 6680
S60 2nd Edition, FP3, N70, N90
說明:
當(dāng)使用CAknAppUi::SetKeyBlockMode()取消鍵盤鎖定功能時,一些按鍵的組合可能會導(dǎo)致程序被切換到后臺。
詳細(xì)描述:
大部分S60游戲都會將鍵鎖定模式取消,以便多鍵同時按下時不影響游戲。這可以通過調(diào)用應(yīng)用程序UI(CAknAppUi)來完成:
SetKeyBlockMode(ENoKeyBlock)
在S60第二版FP2或更新的版本中,如果為鍵盤鎖定模式取消狀態(tài),那下列按鍵組合被同時按下會導(dǎo)致程序被切換到后臺:
‘7’ + ‘8’ + ‘0’ + ‘*’
‘9’ + ‘0’ + ‘#’
解決方案:
目前沒有好的解決方案,游戲設(shè)計中應(yīng)該避免用戶偶然按下上述按鍵組合。
導(dǎo)入工程到IDE時圖象資源無法生成
標(biāo)題: 導(dǎo)入工程到IDE時圖象資源可能無法生成
設(shè)備, 軟件 版本: S60 2nd Edition, FP3,S60 3rd Edition
說明:
當(dāng)我們將一個Symbian應(yīng)用程序工程導(dǎo)入到IDE時(如MetroWorks CodeWarrior或Microsoft Visual Studio),試圖編譯它,但bitmap資源會無法生成。
詳細(xì)描述:
在 S60第三版上,multi-image文件(.mbm或.mif)以及相關(guān)的image header files(.mbg)是通過mifconv圖象轉(zhuǎn)換工具生成的。是bld.inf中通過一個擴(kuò)展的makefile來完成的,這個方法在S60 2nd Edition, Feature Pack 3.就開始被支持。
這些擴(kuò)展的makefile不會在IDE中隨著工程的編譯而被執(zhí)行,因此圖片文件和頭文件將不會在編譯時自動產(chǎn)生,通常這就導(dǎo)致工程因為缺少.mbg文件而失敗。
解決方案:
我們可以通過abld命令去生成這些圖片資源,到/group目錄下,輸入
bldmake bldefiles
abld resource
在此后,工程就能被順利導(dǎo)入IDE并被編譯,注意如果圖片資源(source bitmaps或SVG images)被修改了,那這個過程還要重復(fù)做一次。
? 轉(zhuǎn)自:http://www.cppblog.com/khan/archive/2007/06/18/26572.html
總結(jié)
以上是生活随笔為你收集整理的Symbian开发——Symbian开发知识(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中readlines是什么意
- 下一篇: 英语专业有计算机课程吗,英语专业转行学计