A Symbian C++ programozási nyelv

Példa programok

Hello World programm

A Symbian fejlesztése során gyakran találkozhatunk tervezési minták használatával. A legtöbb alkalmazás szerkezete például az MVC (Model-View-Controller) mintát követi. Ez azt jelenti, hogy az alkalmazás állapotát egy "M" modell tartalmazza, ezt a modellt egy vagy több "V" (View) nézeten keresztül láthatjuk, és mindkettőt a "C" (Controller) vezérlő segítségével tudjuk befolyásolni.

HelloWorld.mmp

TARGET HelloWorld.app //készítendő állomány neve TARGETTYPE app //fájltípus megadása, lehet .app .exe UID 0x100039CE 0x10002222 /* 3 rész:1-2. dll, 3. alkalmazás azonosító ami nagyobb mint 0x10000000.*/ TARGETPATH \system\apps\HelloWorld //célkönyvtár SOURCEPATH . //C++ és RSS állományok helye SOURCE HelloWorld.cpp //fordítandó C++ forrás SOURCE HelloWorldApp.cpp SOURCE HelloWorldDoc.cpp SOURCE HelloWorldAppUi.cpp SOURCE HelloWorldView.cpp USERINCLUDE . //fejlécfájlok helye SYSTEMINCLUDE \epoc32\include //rendszer fejlécfájljai RESOURCE HelloWorld.rss //erőforrás állomány LIBRARY euser.lib apparc.lib cone.lib eikcore.lib avkon.lib //összeszerkesztéshez használt könyvtárak

HelloWorld.rss

NAME HEWO //alkalmazás 4 betűs megnevezése #include // eikon grafikai könyvtár include #include #include // avkon grafikai könyvtár include #include //.rh: struktúrák definíciói //.rsg: erőforrásokra való hivatkozást segítő #define sorok RESOURCE RSS_SIGNATURE { } RESOURCE TBUF r_default_document_name { buf = ""; } //alapértelmezett dokumentumnév RESOURCE EIK_APP_INFO //grafikai felület állapota { cba = R_AVKON_SOFTKEYS_EXIT; //Command Button Array EXIT }

HelloWorld.h

#ifndef _HELLOWORLD_H_ #define _HELLOWORLD_H_ //szükséges include-ok #include #include #include #include #include class CHelloWorldApp : public CAknApplication //avkon öröklés { //Application: alkalmazás betöltése, kerete, UID megadása private: CApaDocument *CreateDocumentL();//Document példányosítása L TUid AppDllUid() const; //AppUI lekérdezése }; class CHelloWorldDoc : public CAknDocument//avkon öröklés { public: CHelloWorldDoc(CAknApplication &aApp); //konstruktor, uktor(), NewL(), NewLC(), ConstructL() is private: CEikAppUi *CreateAppUiL();//AppUi példányosítása L }; class CHelloWorldAppUi : public CAknAppUi //avkon öröklés { public: void ConstructL(); //kettős konstruktor része, kifejtve ~CHelloWorldAppUi();//destruktor kifejtve private: void HandleCommandL(TInt aCommand); //kezelő feldolgozó metódusok implementációja CCoeControl *iView; //AppView példányosítása L }; class CHelloWorldView : public CCoeControl //CCoeControl öröklés { public: static CHelloWorldView *NewL(const TRect &aRect); //NewL(),NewLC() CHelloWorldView();//konstruktor kifejtve ~CHelloWorldView();//destruktor kifejtve void ConstructL(const TRect &aRect);//ConstructL kifejtve private: void Draw(const TRect &aRect) const;// Draw metódus HBufC *iHelloMessage;//Hello Word Üzenet megadása }; #endif

HelloWorld.cpp

#include "HelloWorld.h" //két metódus független a négy osztálytól, általában az Appban EXPORT_C CApaApplication *NewApplication() //App példányosítás, nincs L, mert nincs CleanUpStack { return new CHelloWorldApp; //általános alkalmazásobjektum } GLDEF_C TInt E32Dll(TDllReason reason)//dll-k belépési pontja { return KErrNone; //nem törődünk vele, „nincs gond” }

HelloWorldApp.cpp

#include "HelloWorld.h" const TUid KHelloWorldUid = {0x10002222}; //UID megadása CApaDocument *CHelloWorldApp::CreateDocumentL()//Document { return new(ELeave) CHelloWorldDoc(*this); //kivétel kezeléssel } TUid CHelloWorldApp::AppDllUid() const//Uid visszaadása { return KHelloWorldUid; //leginkább használt metódushívás }

HelloWorldDoc.cpp

#include "HelloWorld.h" CHelloWorldDoc::CHelloWorldDoc(CAknApplication &aApp) : CAknDocument(aApp) {}//üres konstruktor CEikAppUi *CHelloWorldDoc::CreateAppUiL()//AppUI létrehozás { return new(ELeave) CHelloWorldAppUi(); }

HelloWorldAppUi.cpp

#include "HelloWorld.h" void CHelloWorldAppUi::ConstructL() { BaseConstructL(); //ősosztályok alapállapotba hozása iView = CHelloWorldView::NewL(ClientRect()); //kisképernyős változat, ApplicationRect() = fullscreen } CHelloWorldAppUi::~CHelloWorldAppUi() //destruktor { delete iView; //nézet törlése } void CHelloWorldAppUi::HandleCommandL(TInt aCommand) //kezelőfelület { switch(aCommand) { case EEikCmdExit://eikon felület exit gombja, persze ha //egyáltalán van ilyen gomb a készüléken case EAknSoftkeyExit://exit parancsgomb megnyomására case EAknSoftkeyBack://Back gomb, CBA EXIT erőforrás Exit(); break; } }

HelloWorldView.cpp

#include "HelloWorld.h" CHelloWorldView *CHelloWorldView::NewL(const TRect &aRect) { CHelloWorldView *self=new(ELeave)CHelloWorldView; //vagy NewLC() hívás CleanupStack::PushL(self); // CleanUpStack-re fel self->ConstructL(aRect); //ConstructL() meghívása, további hívások CleanupStack::Pop();//levétel return self;//visszatérés } CHelloWorldView::CHelloWorldView() {}//üres konstruktor CHelloWorldView::~CHelloWorldView()//destruktor { delete iHelloMessage; } _LIT(KHelloMessage,"Hello World!"); //kostans üzenet képernyőre void CHelloWorldView::ConstructL(const TRect &aRect) { CreateWindowL();//képernyő foglalása SetRect(aRect);//keret beállítása ActivateL();//jelzi hogy aktiválva van iHelloMessage=HBufC::NewL(20);//méret megadásával foglalás *iHelloMessage=KHelloMessage; } void CHelloWorldView::Draw(const TRect &aRect) const { CWindowGc &gc=SystemGc();//grafikus kontextus TRect rect=Rect();//keret lekérdezése rect.Shrink(10,10);//keret behúzása 10-el gc.Clear();//képernyő törlése gc.DrawRect(rect);//keret rajzolása const CFont *font=iEikonEnv->TitleFont();//betűkészlet gc.UseFont(font);//font erőforrás használatba gc.DrawText(*iHelloMessage,rect,//szöveg a keretbe (rect.Height()+font->HeightInPixels())/2,//méret megadás CGraphicsContext::ECenter,0);//pozíció gc.DiscardFont();//font erőforrás felszabadítása }

MyLocation programm

Alább példakód részleteket láthatunk arra, hogyan lehet meghatározni pozíciónkat a telefonunk segítségével.

CPositioner

Először is szükségünk van egy olyan osztályra, ami a pozíciók begyűjtéséért felelős. Ezt valósítjuk meg, a CPositioner osztály segítségével. (Positioner.cpp)

// User include #include "Positioner.h" // Constants const TInt KUpdateTimeout = 5000000; // in microseconds
Kétfázisú konstrukció
CPositioner* CPositioner::NewL( RPositionServer& aPosServ, const TPositionModuleId& aModuleId, TTimeIntervalMicroSeconds32 aUpdateInterval, MPositionInformationSink& aSink ) { CPositioner* self = CPositioner::NewLC( aPosServ, aModuleId, aUpdateInterval, aSink ); CleanupStack::Pop( self ); return self; } CPositioner* CPositioner::NewLC( RPositionServer& aPosServ, const TPositionModuleId& aModuleId, TTimeIntervalMicroSeconds32 aUpdateInterval, MPositionInformationSink& aSink ) { CPositioner* self = new ( ELeave ) CPositioner( aPosServ, aUpdateInterval, aSink ); CleanupStack::PushL( self ); self->ConstructL( aModuleId ); return self; } void CPositioner::ConstructL( const TPositionModuleId& aModuleId ) { //Cancel(); User::LeaveIfError( iPositioner.Open( iPosServ, aModuleId ) ); User::LeaveIfError( iPositioner.SetRequestor( CRequestor::ERequestorService, CRequestor::EFormatApplication, _L( "CellLocator" ) ) ); TInt64 a( 30 ); TTimeIntervalMicroSeconds intv( a ); TPositionUpdateOptions posUpOp( intv, TTimeIntervalMicroSeconds( KUpdateTimeout ) ); TInt err = iPositioner.SetUpdateOptions( posUpOp ); User::LeaveIfError( err ); User::LeaveIfError( iUpdateTimer.CreateLocal() ); } CPositioner::CPositioner( RPositionServer& aPosServ, TTimeIntervalMicroSeconds32 aUpdateInterval, MPositionInformationSink& aSink ) : CActive( CActive::EPriorityStandard ), PosServ( aPosServ ), iUpdateInterval( aUpdateInterval ), iSink( aSink ) { //add to Active Scheduler CActiveScheduler::Add( this ); }

Nem feledkezhetünk meg a destuktorról sem.

CPositioner::~CPositioner() { Stop(); iUpdateTimer.Close(); iPositioner.Close(); }
Szolgáltatásindítás, és leállítás

A StartL függvény segítségével indíthatjuk el a pozicionálást

void CPositioner::StartL(TTimeIntervalMicroSeconds32* aUpdateInterval) { //There can only be one outstanding request if( IsActive() ) { Cancel(); } //Configure positioner ( system service ) if( aUpdateInterval ) { User::LeaveIfError( iPositioner.SetUpdateOptions( TPositionUpdateOptions( TTimeIntervalMicroSeconds( aUpdateInterval->Int() ), TTimeIntervalMicroSeconds( KUpdateTimeout ) ) ) ); } //Set internal state iState = ERequestingPosition; //Asyncron Request is Started here!! iPositioner.NotifyPositionUpdate( iLastPositionInfo, iStatus ); //flag our ActiveObject as active SetActive(); }

Ha le szeretnénk állítani az automatizált pozíciógyűjtést, akkor azt a következő függvény segítségével tehetjük meg:

void CPositioner::Stop() { //Cancel outstanding request. DoCancell is going to be called by the framework Cancel(); }
Az Aktív objektumok lényege

Minthogy minden aktív objektumnak kötelezően a CActive osztályból kell származnia, a következő 3 függvényt kötelezően meg kell valósítania.

A DoCancel felelős azért, hogy amikor le akarjuk állítani az aktív objektumunk működését, akkor az eltárolt belsőállapot segítségével eldönti, milyen módon tudja ezt megtenni, és meg is teszi.

void CPositioner::DoCancel() { //Canceling process is depends on internal state switch( iState ) { case EWaiting : { iUpdateTimer.Cancel(); break; } case ERequestingPosition : { iPositioner.CancelRequest( EPositionerNotifyPositionUpdate ); break; } } iState = EInitialized; }

A RunError fog visszahívódni, ha a RunL leavel. Az egyszerűség kedvéért most csak továbbítjuk a hiba okát.

TInt CPositioner::RunError( TInt aError ) { return aError; }

A RunL felelős azért, hogy az egyes részeseményeket kezelje, és eldöntse, mi a következő lépés. Jelen esetben két részre oszthatjuk a működését. Az első fázisban elindul a pozícionálás, azaz megkérjük a rendszer által biztosított pozícionáló szervert, hogy adja meg az aktuális koordinátánkat. Amikor ez az aszinkron hívás visszatér, a második fázisban, elindítunk egy időzítőt, mely lejárta után újra az első fázisba kerülünk át.

void CPositioner::RunL() { //Handle request completion switch( iState ) { case EWaiting : { //Timeout expired, request next location iState = ERequestingPosition; iPositioner.NotifyPositionUpdate( iLastPositionInfo, iStatus ); SetActive(); break; } case ERequestingPosition : { //Got location info, notify observer TInt i = iStatus.Int(); if( iStatus.Int() == KErrNone ) { iSink.PositinoInformationAvailable( this, iLastPositionInfo, iStatus.Int() ); } //Start timeout timer iState = EWaiting; iUpdateTimer.After( iStatus, iUpdateInterval ); SetActive(); break; } } }

Location Provider

Ez az osztály, ahogy a neve is mutatja helymeghatározással kapcsolatos szolgáltatásokat nyújtja.

// User includes #include "LocationProvider.h" #include "Positioner.h" // Constants #define KModuleNotPresent NULL; const TInt KGPSPositionerId = 0; const TInt KNetworkPositionerId = 1;
Kétfázisú konstrukció
CLocationProvider* CLocationProvider::NewL( TInt aGPSUpdateInterval, TInt aNetworkUpdateInterval, MLocationListener& aListener ) { CLocationProvider* self = CLocationProvider::NewLC( aGPSUpdateInterval, aNetworkUpdateInterval, aListener ); CleanupStack::Pop( self ); return self; } CLocationProvider* CLocationProvider::NewLC( TInt aGPSUpdateInterval, TInt aNetworkUpdateInterval, MLocationListener& aListener ) { CLocationProvider* self = new ( ELeave ) CLocationProvider( aListener ); CleanupStack::PushL( self ); self->ConstructL( aGPSUpdateInterval, aNetworkUpdateInterval ); return self; } CLocationProvider::CLocationProvider( MLocationListener& aListener ) : iListener( aListener ) { iModules[ KNetworkPositionerId ] = KModuleNotPresent; iModules[ KGPSPositionerId ] = KModuleNotPresent; } void CLocationProvider::ConstructL( TInt aGPSUpdateInterval, TInt aNetworkUpdateInterval ) { // connect to position server User::LeaveIfError( iPosServ.Connect() ); // open positioner instances TInt moduleCount = 0; moduleCount += OpenNetworkModule( aNetworkUpdateInterval ) != KErrNone ? 0 : 1 ; moduleCount += OpenSateliteModule( aGPSUpdateInterval ) != KErrNone ? 0 : 1; // no location module can be opened if( !moduleCount ) { User::Leave( KErrNotFound ); } if( iModules[ KNetworkPositionerId ] ) { iModules[ KNetworkPositionerId ]->StartL(); } if( iModules[ KGPSPositionerId ] ) { iModules[ KGPSPositionerId ]->StartL(); } }

Természetesen a detruktor sem maradhat ki

CLocationProvider::~CLocationProvider() { for( TInt i = 0; i < KMaxPositionerCount; ++i ) { delete iModules[ i ]; } iPosServ.Close(); }
Pozícionáló modulok elindítása

A lehető legoptimálisabb eredmény elérésének érdekében, két fajta pozícionálást indítunk el. Az assisted GPS segítségével, viszonylag gyorsan, pontos koordinátákhoz juthatunk, míg a hálózati pozícionálással gyors, de nem túl pontos pozíciókhoz juthatunk.

TInt CLocationProvider::OpenNetworkModule( TInt aUpdateInterval ) { TPositionModuleId id; TUint cnt; TInt err; // failed to get the number of modules if( ( err = iPosServ.GetNumModules( cnt ) ) != KErrNone ) { return err; } // there are no positioners if( !cnt ) { return KErrNotFound; } // find network based positioner module TBool found = EFalse; for( TInt i = 0; i < cnt && !found; ++i ) { TPositionModuleInfo info; iPosServ.GetModuleInfoByIndex( i, info ); /* * 0x1 - GPS * 0x2 - Network * 0x4 - Assisted GPS */ found = ( info.IsAvailable() && ( info.TechnologyType() & TPositionModuleInfo::ETechnologyNetwork ) ); if( found ) { id = info.ModuleId(); } } // no appropriate positioner found if( !found ) { return KErrNotFound; } TTimeIntervalMicroSeconds32 interval( aUpdateInterval * 1000000 ); TRAP( err, iModules[ KNetworkPositionerId ] = CPositioner::NewL( iPosServ, id, interval, *this ) ); return err; } TInt CLocationProvider::OpenSateliteModule( TInt aUpdateInterval ) { TInt err; TPositionModuleId id; TUint cnt; if( ( err = iPosServ.GetNumModules( cnt ) ) != KErrNone ) { return err; } if( !cnt ) { return KErrNotFound; } // search for assisted TBool found = EFalse; for( TInt i = 0; i < cnt && !found; ++i ) { TPositionModuleInfo info; iPosServ.GetModuleInfoByIndex( i, info ); found = ( info.IsAvailable() && info.DeviceLocation() == TPositionModuleInfo::EDeviceInternal && ( info.TechnologyType() & TPositionModuleInfo::ETechnologyAssisted )); if( found ) { id = info.ModuleId(); } } //non assisted if( !found ) { //look for (non assisted) GPS for( TInt i = 0; < cnt && !found; ++i ) { TPositionModuleInfo info; iPosServ.GetModuleInfoByIndex( i, info ); found = ( info.IsAvailable() && info.DeviceLocation() == TPositionModuleInfo::EDeviceInternal && ( info.TechnologyType() & TPositionModuleInfo::ETechnologyTerminal ) ); if( found ) { id = info.ModuleId(); } } } if( !found ) { return KErrNotFound; } TTimeIntervalMicroSeconds32 interval( aUpdateInterval * 1000000 ); TRAP( err, iModules[ KGPSPositionerId ] = CPositioner::NewL( iPosServ, id, interval, *this ) ); return err; }

És végül, de nem utolsó sorban eljutottunk ahhoz a ponthoz, amikor is tudjuk, hogy a pozícionáló válaszolt a kérésünkre.

Amennyiben a GPS pozícionáló modul értesített minket, hogy a hívásunk sikertelen volt, azaz nem tudtunk korlátos időn belül GPS adatokhoz jutni (pl. nem látjuk jól a műholdakat), akkor párhuzamosan elindítjuk a hálózati pozícionálást, hogy addig is legyen valami adatunk, ha nem is olyan pontos.
Természetesen abban az esetben, ha a GPS modultól értékes adatokat kaptunk, nincs tovább szükségünk a hálózati pozícionálásra, így leállítjuk azt. És ez így mehet a végtelenségig, illetve amíg le nem állítjuk az alkalmazásunkat.

void CLocationProvider::PositinoInformationAvailable( CPositioner* aPositioner, const TPositionInfo& aPositionInformation, TInt aError ) { TLocationInformationType moduleType = ELocationInformationTypeNone; //Network positioner called us back if( aPositioner == iModules[ KNetworkPositionerId ] ) { moduleType = ELocationInformationTypeNetwork; } //GPS positioner called us back else if( aPositioner == iModules[ KGPSPositionerId ] ) { moduleType = ELocationInformationTypeSatelite; if( aError == KErrNone ) { // GPS coordinares are more reliable, don't need cell positions iModules[ KNetworkPositionerId ]->Stop(); } else { //error while acquiring GPS coordinate, restart network positioner TRAP_IGNORE( iModules[ KNetworkPositionerId ]->StartL() ); } } if( moduleType == ELocationInformationTypeNone || aError != KErrNone ) { return; } TPosition pos; aPositionInformation.GetPosition( pos ); iListener.PositinoInformationAvailable( pos, moduleType ); }