6. lecke Iránytű alkalmazás

Online Android szakkör (DKRMG)


Az Android programozás egyik szépsége, hogy egy egyszerű ötlet is több millió felhasználó érdeklődésére tehet szert. Nagyszerű példa erre az iránytű alkalmazások családja, melyek közül a legnépszerűbbet a Google Play áruházban több mint ötmillió ember töltötte már le.

A mai leckében mi is elkészítünk egy ilyen iránytű alkalmazást!

A cél

A képernyő közepén szeretnénk látni egy iránytű képet, aminek a megfelelő pontja (É) mindig Észak felé mutat.

Az áruházban található iránytű alkalmazások természetesen különböző cselekkel (mint például GPS koordináták megjelenítése) próbálnak kívánatosabbá válni a letöltők szemében. Mi most csak az alap ötletre fogunk koncentrálni: forgó kép a képernyő közepén.

Hogyan állunk ennek neki…

Ez a lecke gyakorlatilag a korábban tanultakra épül. Csupán egy-két helyen találkozunk majd újdonságokkal. Ez alól kivételt képez a lecke utolsó szakasza, amely egy “About” ablak megjelenítését mutatja majd be.

Tehát a terv (nagy vonalakban):

  1. Felhasználói felület kialakítása
    • layout szerkesztőben egy ImageView elhelyezése, középre igazítása, méretezése.
    • kép kiválasztása az src tulajdonságnál.
  2. Feliratkozás az Orientation szenzorra
    • implements SensorEventListener
    • szükséges függvények elkészítése
    • feliratkozás a szenzorra
    • leiratkozás megírása
  3. Befejezni az onSensorChanged függvényt, hogy elforgassa a képet a kapott érték alapján az ImageView setRotation függvényével.
  4. Egy "about" ablak létrehozása.

Figyelmeztetések és egy pár rövid megjegyzés

Javaslat

Ha elég önbizalmat érzel magadban, akkor próbáld meg önállóan megoldani ezt a leckét, és a projekt importálását követően csak az AboutActivity résztől olvasd el a leírást. Ha nem megy, akkor természetesen bármikor leshetsz.

Segítségként összeállítottunk egy Gyorssegély lapot is, ami az eddig tanultakat foglalja össze röviden.

Iránytű App Elkészítése

Importálás

Ebben a leckében is a megszokott módon importálni fogjuk az előkészített projektet.

Felhasználói felület (layout)

layout szerkesztő

A felhasználói felületünk igen egyszerű, és nagyban hasonlít az előző leckében használtakhoz. A következőket kell tenned (ha bizonytalan vagy, ott a gyorssegély, vagy vissza is olvashatsz egy kicsit a harmadik, negyedik vagy ötödik leckére).

  1. Nyissuk meg a Layout szerkesztőt. A Design fül legyen kiválasztva.
  2. Helyezzünk el egy ImageView komponenst a telefon kijelzőjére. Az ImageView legyen pontosan középen.
    • Adjunk az ImageView-nak egy id tulajdonságot is. Mondjuk kep
    • Állítsuk be az ImageView méretét (layout:width és layout:height). Mondjuk legyen 100dp magas és 100dp széles. Vagy bármilyen más értéket is választhatsz, ami jól néz ki.
    • Válasszuk ki, hogy az ImageView az iránytű képét mutassa. Ehhez az src (source) tulajdonságnál kattints a […] gombra, és válaszd ki a "Drawable" listából a compass képet (kereső mező segít).
  3. Helyezzünk egy TextView komponenst a képernyő tetejére. Ide fogjuk kiírni a beolvasott értéket (fok)
    • Növeljük meg egy kicsit a betűméretet
    • Adjunk a TextView-nak egy id tulajdonságot is. Mondjuk felirat.
    • Adjunk meg valami kezdeti szöveget is (text). Mondjuk ez lehet "fok". Vagy "majd ide jön a fok".
  4. Futtasd a programot!

    Az Android Studio újabb verzióiban előfordulhat, hogy az alábbi hibaüzenettel találkozol

    Error:(13) No resource identifier found for attribute 'srcCompat' in package 'hu.dkrmg.android.iranytu'

    A hiba áthidalásához sajnos egy kicsit bele kell másznunk a layout fájl szöveges verziójába.

    1. Nyisd meg a layout fájlt
    2. Az ablak alján válaszd ki a Text nézetet.
    3. Ezen a ponton láthatod a layoutot leíró XML dokumentumot. Ha nem találkoztál még XML dokumentumokkal, akkor sem kell megijedni.
    4. Keresd meg az ImageView pont alá tartozó app:srcCompat="@drawable/compass" sort, és írd át erre: app:src="@drawable/compass"

Komponensekhez tartozó változók

Java kód

Érdemes most még az elején létrehozni a TextView és ImageView típusú változóinkat, illetve hozzárendelni őket a valódi felirathoz és képhez. Ezt javasolnánk, hogy az onCreate függvényben tedd meg a findViewById segítségével. Így a program indulásakor már túl is essünk a munka ezen részén.

Javaslatunk az, hogy legyen az ImageView változónk neve iranytuKep (mivel ez a kép mutatja magát az iránytűt), a TextView változónkat pedig kereszteljük egyszerűen fokFelirat-nak, mivel ez egy felirat, ahová az elfordulást fogjuk kiírni fokokban. Természetesen névnek bármit választhatsz (kerülve az ékezetes betűket, betartva a teve szabályt - minden betű kicsi, kivéve az egymás utáni szavak első betűi. pl. ezEgyValtozo).

A változókat az Activity osztály elején szoktuk létrehozni például ezzel a paranccsal: ImageView iranytuKep;

A findViewById parancsot többször is használtuk már. De itt van még egy példa, amit az onCreate függvénybe írjál be! iranytuKep = (ImageView) findViewById(R.id.kep);

Az Orientation szenzor

Java kód

Ez a rész egy az egyben megegyezik az előző leckének az első két feladatával, a szenzor típusától eltekintve. Javasoljuk, hogy lapozz vissza, ha bizonytalan vagy. Különben pedig itt a Gyorssegély is.

  1. írd be a public class IranytuActivity… sor megfelelő pontjára az implements SensorEventListener szavakat. Így jelezve, hogy képes az Activitynk üzeneteket fogadni.
  2. Írd meg az onSensorChanged és az onAccuracyChanged függvények vázát.
    • Kezdd el beírni az egyik függvény nevét, majd az első 4-5 betű után válaszd ki a megfelelő függvényt a felbukkanó listából. Ezek után Enter.
    • Ne felejtsd el ugyanezt megtenni a másik függvénnyel is!
  3. Hozz létre egy SensorManager típusú változót (a neve lehet sensorManager kisbetűvel), és rendeld hozzá a rendszer szenzor managerét. Ezt az onCreate függvényben tettük meg a getSystemService(SENSOR_SERVICE) függvénnyel.

    A hozzárendelés teljes parancsa szerepelt már a korábbi leckében is: sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

  4. Iratkozz fel az orientation szenzor üzeneteire / érzékeléseire.
    • Készítsd ez az onResume függvényt (az Android Studio segít, ha elkezded beírni)
    • Nézd meg, hogy az előző leckében hogyan használtuk a getDefaultSensor és a regesiterListener függvényeket. Csak annyi a dolgod, hogy átírod a TYPE_PROXIMITY-t TYPE_ORIENTATION-re. Ezzel máris nem a közelség, hanem az orientáció szenzorra iratkozunk fel.

      Tényleg megnézted az előző leckét?! Most még itt megadjuk a megoldást, de ezt a két sort vésd a fejedbe!

      
      Sensor orientation = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
      sensorManager.registerListener(this, orientation, SensorManager.SENSOR_DELAY_UI);
      
  5. Ne felejts el leiratkozni sem az üzenetekről az onPause függvényben! Ehhez először meg kell írnod az onPause függvényt (az Android Studio segít).

    sensorManager.unregisterListener(this);

Kész is! Ha elakadtál, vagy nem vagy benne biztos, hogy jól csináltad-e, akkor hasonlítsd össze az előző lecke megoldásával. Ne feledd, ezen a ponton az onSensorChanged függvényed még üres (a két kapcsos zárójel között nincs semmi).

Futtasd le a programodat! De honnan tudod, hogy működik-e?

Akik megcsinálták a negyedik lecke Logging szorgalmiját, azok remélhetőleg itt felhasználják a tudásukat. Ha te nem vagy ennek a szorgalmas társaságnak a tagja, akkor olvass tovább!

Érték kiírása

ez az onSensorChanged függvényben történik

Ezen a ponton nehéz megmondani, hogy helyes-e a programunk. Előfordulhat ugyanis, hogy szintaktikai hibát nem vétettünk, tehát nem írtunk be a Java fordító számára értelmezhetetlen dolgokat, és a programunk mégsem azt teszi, mint amit szeretnénk (például biztosan átírtad az érzékelő típusát ORIENTATION-re PROXIMITY-ről?)

Most azonban mindjárt kiderül, hogy minden működik-e. Ugyanis megpróbáljuk kiírni az érzékelő által beolvasott értéket a fokFelirat feliratunkba (TextView). Ha te más nevet adtál a változódnak, akkor most nézd meg gyorsan, hogy mi volt az!

Az előző leckével azonos módon fogjuk megkaparintani az érzékelő által küldött adatot. Mivel minket ismét csak egy szám érdekel (hány fokot fordultunk el Észak felől), használhatjuk az előző lecke kódját is.


            

Ez létrehoz a függvényünkön belül egy float típusú változót (ertek névvel). A float típus ugyebár egy olyan típus volt, ami képes nem-egész számok tárolására is (pl 0.2357).

Az ertek változóhoz pedig rögtön hozzá is rendeljük az érzékelő által küldött értékek közül az elsőt. Az event.values, mint a múltkor is említettük, egy tömb, melynek az event.values[0] az első eleme. Érdekességként az Orientation érzékelő több adatot is küldd nekünk egyszerre, nem csak az Északtól való elfordulásunkat. A többi értéket majd a következő leckében használni is fogjuk.

Az ilyen függvényen belül létrehozott változóknál akár cselesen össze is vonhatjuk ezt a két sort:

float ertek = event.values[0];

Tehát most az ertek változóban van, hogy hány fokra vagyunk az északi iránytól. Írjuk ezt ki a TextView változónk setText belső függvényével!

Ehhez használd az alábbi parancsot

valtozo.setText(ertek+"°"); // a ° karakter az AltGr+7 kombinációval érhető el :)

A változó nevét, aminek a feliratát megváltoztatjuk, neked kell beírnod. Az új felirat pedig nem más, mint az érték egy csinos kis fok jellel.

Kép elforgatása a helyes irányba

Most már tényleg minden készen áll ahhoz, hogy megírjuk az iránytű alkalmazásunk azon egy sorát, ami felhasználók millióit tudta lázba hozni: ez az iránytű képének elforgatása.

Ha a telefonunk Android 3.0 (API 11), vagy annál újabb rendszert futtat, akkor nagyon egyszerűen elforgathatjuk az ImageView komponenseinket. Annyit kell csak tennünk, hogy meghívjuk az ImageView setRotation függvényét, amivel megmondhatjuk, hogy a kép hány fokkal legyen elforgatva eredeti állapotából.

Például ha van egy kepecske nevű ImageView változóm, akkor a kepecske.setRotation(30) elforgatja harminc fokkal a képemet az óramutató járásával megegyező irányban

kepecske.setRotation(30);

Ha esetleg egy kicsit öregebb telefonod lenne, akkor se csüggedj. Van mód a képek elforgatására így is, bár kicsit bonyolultabb. Hogy ne érjen hátrány ebben a leckében, így írtunk neked egy segédfüggvényt, ami elvégzi helyetted a piszkos munkát.

A változó.setRotation(fok); parancs helyett használd ezt:

ImageViewHelper.setImageViewRotation(változó, fok);

Futtasd le a programot, és ellenőrizd, hogy működik-e az iránytűd! Forog a kép a telefon kijelzőjéhez képest? És az északi irányhoz képest?

Egy gyakori hiba: túl gyorsan forog az iránytű, amikor forgatom a telefont.

Na ez vajon miért lehet? Ha elfordulsz tíz fokot Északhoz képest és a képet további tíz fokkal forgatod, akkor a kép nem fog Észak felé mutatni! Itt mit lehetne inkább csinálni?

hmmm... -ertek

About Activity

Amikor kilépünk az egy ablakos programok világából.

Egészen idáig az alkalmazásaink mindig egyetlen Activityt használtak. Egyetlen képernyőt tölthettek meg tartalommal. Sokszor előfordul azonban, hogy ez a megkötés egyszerűen túl szigorú. Például a programunk beállításait, vagy további tartalmat érdemes lehet külön ablakokba helyezni.

Gondolhatsz erre úgy, mint az asztali számítógépednél az ablakokra. Amikor elindítod például az Android Studio-t, megjelenik egy ablak. Ha rámész az importálásra, akkor felugrik egy újabb ablak.

Egy másik hasonlat a honlapok működése. Minden oldalnak van egy kezdő lapja (például a szakkör kezdőlapja), ahonnan aztán újabb tartalmas oldalakra ugrálhatunk (például az első vagy a második lecke).

A programok gyakran rendelkeznek egy úgynevezett "About" ablakkal. Az applikációnk ezen ablakának egyetlen szerepe van: tájékoztatni a kedves felhasználót, hogy ki is készítette a programot!

Mi is szeretnénk, hogy legyen egy about ablakunk. Az Android világában az ablakoknak vagy oldalaknak az Activityk felelnek meg; így hát nincs mit tenni, létre kell hoznunk egy újabb Activityt, ami gombnyomásra nyílik meg az iránytűs ablakból.

Eddig ugyebár egy darab Activityvel dolgoztunk, amit ebben a leckében IranytuActivitynek hívnak. A terv most az, hogy létrehozunk egy új activityt, amit az IranytuActivity-ből érünk el egy gombnyomással.

Új activity létrehozása

Az új Activityt néhány lépéssel létre lehet hozni. Figyelj, nehogy elronts valamit, mert ezen a ponton nehéz utólag javítani a hibákat.

  1. Jobb gombbal kattints az app pontra a projektedben
  2. Válaszd ki a New -> Activity -> Empty Activiy pontot. Ezzel annyit mondtunk, hogy egy üres Activityt szeretnénk létrehozni.
  3. Az Activity dialógusban adjuk meg az Activity nevét. Ez legyen mondjuk AboutActivity. Generate Layout File mellett maradjon a pipa, hogy megkapjuk a könnyen szerkeszthető layout fájlunkat az új Actvitity-hez is.
  4. Láthatjuk, hogy a projektünkben született egy új layout fájl (activity_about) és egy új java kód fájl (AboutActivity). Ezek teljesen függetlenek az IranytuActivity-nktől! A két új fájl az új AboutActivity kinézetét és viselkedését szabják meg.

Ne is féljünk az új Activitytől (nem harap), nyissuk meg a layout szerkesztőjét, és írjuk át a hello world szöveget valami tartalmasabbra. Például hogy ki mikor és miért készítette ezt az alkalmazást.

AboutActivity megnyitása

Ha most elindítod a programodat, akkor láthatod, hogy látszólag semmi nem változott. Ugyanúgy az IranytuActivity indul el. Kész szerencse, hiszen nem is akarnánk mást. Mi most viszont azt szeretnénk, hogy egy gombnyomásra hirtelen megjelenjen az új AboutActivity!

  1. Először is ehhez el kell helyezünk egy gombot az IranytuActivity layout szerkesztőjével. Ezek a lépések remélhetőleg ismerősek, gomboknak onClick függvényt már sokat írtunk!
    • Gomb elhelyezése, szöveg átírása stb.
    • Készítsünk egy aboutOnClick függvényt az IranytuActivity java kódjában
    • Állítsuk be a gombunk onClick tulajdonságát az új függvényre (aboutOnClick)
  2. Ha ez megvan, akkor nincs más dolgunk, mint befejezni az aboutOnClick függvényünket.
    
                    

A kódrészlet pontos működése most nem érdekes számunkra. Az viszont remélhetőleg egyértelműen látszik, hogy hol határozzuk meg az elindításra váró Activity-t (AboutActivity).

Most futtasd le a programodat, hogy valóban sikerült-e jól befejezned a feladatot. Ha lenyomod a gombot, akkor elindul az AboutActivity ablakunk? Ha vissza szeretnél térni az IranytuActivity-re, csak nyomd meg a vissza gombot a telefonodon :)

Ha végeztél és minden működik, töltsd fel a projektedet tömörített (pl zip) formátumban a szakkör feltöltő oldalán keresztül!