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 );
}