Mobil alkalmazások fejlesztése Készítette: Szabóné Nacsa Rozália
S60 és UIQ Application suites UI implementation UI framework S 60 UIQ MOAP Symbian OS HW adaptation Hardware Symbian Symbian OS S60 C++ 2
Okos telefonok erős processzor nagyméretű kijelző viszonylag nagy memória információ kezelő programok egyéni alkalmazások egyszerű kezelhetőség megbízhatóság erőforrásaival nem pazarló (memória, szolgáltatások, energia fogyasztás) gyors reakcióidő folyamatos üzemmód
Elvárosok megbízható nincs adatvesztés nem dobja el a vonalat optimális a memória felhasználás nincs memória szivárgás minden hibát értelmesen kezel nyitott a külső fejlesztések irányába
Symbian OS felépítése Felhasználói interfész szinkronizáció UI alkalmazás keretrendszer UI eszközkészlet MIDP CLDC Alkalmazás szintű szolgáltatások PIM Böngészés Üzenetkezelés Adatszinkron JVM Java Operációs rendszer szolgáltatásai Általános szolgáltatások Kommunikációs szolgáltatások Grafikai szolgáltatások PC-s kapcsolat szolgáltatásai Alapszolgáltatások Alacsonyszintű szolgáltatások Fájlszerver Kernel és hardware integráció Kernel szolgáltatások Eszközmeghajtók 5
Symbian C++ sajátosságok Kódolási minták a memóriaszivárgás kiszűrésére: kétfázisú konstrukció, CleanUpStack Nincs kivétel. Helyette: TRAP és User::Leave Saját elnevezési konvenciók: nem a változó típusa, hanem szerepe szerint történik az elnevezés (T,C,R,M) (( dekorált osztálynevek) memóriakezelés segítése függvénynevekkel: prefixek, postfixek ( dekorált eljárásnevek) String helyett deszkriptorok Többszálúság kezelése: ActiveObject, Thread 6
Osztálytípusok T: egyszerű típus; nincs destruktora; csak T-ből, vagy M-ből öröklődhet; értékként átadható; stack-en tárolható C: csak a heapen foglalható; van destruktora; pontosan egy C és tetszőleges M osztályból származhat; nem adható át értékként M: interfész; csak virtuális metódusok; nincsenek tagváltozók; nem példányosítható R: erőforrás, melyet meg kell nyitni és be kell zárni 7
Kivételkezelés Standard kivételkezelés A kivétel keletkezésekor egy objektumot dobunk Egy try blokkban vagy az abból hívott függvényekben keletkező kivételt a catch blokkban elkaphatjuk és lekezelhetjük. A kivétel keletkezésekor a vezérlés visszatér a hívó blokkba, majd az azt hívóba fel és fel, amíg kivételt le nem kezeljük. Közben a verem memória (stack) visszafejtésre kerül, az abból kikerülő objektumok destruktorai meghívódnak. Symbianos Leave-elés A kivétel keletkezésekor egy egész szám (hiba kód) generálódik. Egy TRAP vagy TRAPD makróval meghívott függvényben vagy abból hívott függvényekben keletkező kivételt a makróban lekezelhetjük. A kivétel keletkezésekor a vezérlés visszatér a hívó blokkba, majd az azt hívóba fel és fel, amíg kivételt le nem kezeljük. Közben a verem memória kiürül, de az abból kikerülő objektumok destruktorai sem hívódnak meg. 8
Kivétel keletkezése Leave-elő függvények A Symbian-ban a kivétel kiváltására (ún. leave-elésre ) a User könyvtár Leave metódusa szolgál: User::Leave Ilyen leave-elés keletkezhet akkor is, ha a new operator helyett a new(eleave) metódussal foglalunk helyet a szabad memóriában. Természetesen mindazon függvények futása során számíthatunk leave-elésre, amelyek vagy közvetlenül meghívják a User::Leave() függvényt vagy közvetlenül meghívják a new (ELeave) metódust vagy egyéb leave-elésre képes függvényt hívnak meg. Ezeket a függvényeket leave-elő függvényeknek nevezzük. Tartsuk be azt a névkonvenciót, hogy minden leave-elő függvény neve L betűre végződjön. 9
Leave-elő mechanizmus Leave-elésnél bekövetkező memória szivárgást úgy kerülhetjük el, hogy egy leave-elő függvényben végrehajtott dinamikus helyfoglalások pointereit elhelyezzük egy úgynevezett CleanUpStack verembe. Leave-eléskor ugyanis a CleanUpStack-beli pointerek által mutatott terület automatikusan felszabadul, miközben a CleanUpStack kiürül. Ha nem következik be leave-elés, akkor nekünk kell a CleanUpStack-et kiüríteni. 10
new (ELeave) operátor LOCAL_C void MainL() CMyClass* myptr = new CMyClass; if(myptr) myptr->foo(); //Can safely access data & functions delete myptr; LOCAL_C void MainL() CMyClass* myptr = new (ELeave) CMyClass; myptr->foo();... Hiba esetén abbahagyja a végrehajtást. delete myptr; 11
Hibakezelés csapdázással, leaveléssel case ECleanupCmdUse3: CX* x=new(eleave) CX; TRAPD (error, x->usel()); if(error) delete x; User::Leave(error); delete x; Több függvényhívás esetén minden egyes függvényhívást külön-külön csapdázni kell. case ECleanupCmdUse3: CX* x=new(eleave) CX; CleanupStack::PushL(x); x->usel(); x->usel(); x->usel(); CleanupStack::PopAndDestroy(x); A CleanupStack segítségével egy csokorba gyűjthetjük a leavelő függvényhívásokat. 12
Kétfázisú konstrukció Az osztály standard konstruktorában nem hívunk leave-elő kódot. A leave-elő hívásokat egy külön második fázisú konstruktorba tesszük. (ConstructL) Az osztály példányosítását becsomagoljuk a NewL() illetve NewLC() statikus metódusokba: Meghívjuk a standard konstruktort (new) első fázis A félig létrejött objektumot feltesszük a CleanupStack-re Meghívjuk a második fázisú konstruktort (ConstructL) második fázis Levesszük a CleanupStack-ről (ezt csak a NewL teszi meg)
Kétfázisú konstrukció megvalósítása... CY* y = new(eleave) CY; CleanupStack::PushL(y);... CleanupStack::PopAndDestroy(y); class CX : class CBasis public: TInt iint; class CY : class CBasis public: CX *ix; static CY* NewL(); static CY* NewLC(); void ConsructL() ix = new (ELEAVE) CX;; ~CY() delete ix; CY* CY::NewL() CY* self = new(eleave) CY; CleanupStack::PushL(self); self->constructl() CleanupStack::Pop(); return self; CY* CY::NewLC() CY* self = new(eleave) CY; CleanupStack::PushL(self); self->constructl() return self;
Cleanup-safe HelloWorld int HelloWorldL() CConsoleBase* console = Console::NewL(_L("Hello World"),TSize(KConsFullScreen,KConsFullScreen)); console->printf(ktxtmessage); console->printf(ktxtpressanykey); console->getch(); // get and ignore character delete console; return 0; Konzolos alkalmazásnál a CleanupStack-et nekünk kell létrehozni. TInt E32Main() UHEAP_MARK; CTrapCleanup* cleanup = CTrapCleanup::New(); TInt retval = KErrNone; if(cleanup) TRAP(retVal,HelloWorldL()); ASSERT_ALWAYS(!retVal, User::Panic(_L("Hello World Panic"),retVal)); delete cleanup; UHEAP_MARKEND; return retval; int main() printf("hello world!\n"; return 0;
Fájl kezelés Hívó kliens File szerver kliens oldali része mytest.exe efsrsv.dll szolgáltatás kérés (API hívások) pl.: RFs::Connect() Process boundary File server efile.exe //File I/O in Symbian OS RFs fsession; User::LeaveIfError(fSession.Connect()); RFile file; ret = file.open(fsession, _L( file.txt ), EFileWrite); if (ret) ret = file.create(fsession, _L( file.txt ), EFileWrite); if (!ret) file.write(_l8( Write some data )); file.close(); fsession.close(); Kliens-szerver kommunikáció (Kernel által felügyelt) int main() File* fp = fopen("file.txt",w); if (fp) fprintf(fp, "Write some data"); fclose(); return 0;
Futtaható program modularizálása Forráskód.exe Forráskód.exe Futtató környezet.exe Kép Kép Erőforrás szöveg Erőforrás szöveg Kód Fájl szerver Ablak szerver... indexek Kód Fájl szerver Ablak szerver...
A fordítás és szerkesztés folyamata.bmp <.h>.h.rsg.hrh.rh.rls Bmp konverter.cpp.rss.bmp.mbm.rss C++ fordító Erőforrás fordító Bmp konverter Aif fordító.obj.lib.rsc.pkg.mbm.aif linker.exe;.dll Sis készítő.sis
Kisokos User::Leave (standard: throw) TRAP, TRAPD (standard: try-catch) záró L (standard: függvénydeklarációbeli throw( )) new (Eleave) metódus (standard: new) Leave-elő kódban létrehozott példányokat a CleanUpStack-be A leave-elő kód normális befejezésekor kiürítjük a CleanUpStack-t Kétfázisú konstruktor (ConstructL) és az azt lebonyolító NewL, NewLC elkészítése 19