Labor 01 - Alapok (HighLowGame)¶
Az első labor rendhagyó a többihez képest. Itt kevés kóddal fogunk találkozni, inkább az alapok átnézésén van a hangsúly.
A labor célja, hogy bemutassa az Android Studio fejlesztőkörnyezetet, az alkalmazáskészítés, illetve a tesztelés és fordítás folyamatát, az alkalmazás felügyeletét, valamint az emulátor és a fejlesztőkörnyezet funkcióit. Ismertetjük egy Hello World alkalmazás elkészítésének módját és a debugoláshoz használható fontosabb eszközöket.
A labor végén egy jegyzőkönyvet kell beadni a jegy megszerzéséhez.
A mérés az alábbi témákat érinti:
- Az Android platform alapfogalmainak ismerete
- Android Studio fejlesztőkörnyezet alapok
- Android Emulátor tulajdonságai
- Android projekt létrehozása és futtatása emulátoron
- Manifest állomány felépítése
- Android Profiler
- Android App Inspection
Előkészületek¶
A feladatok megoldása során ne felejtsd el követni a feladat beadás folyamatát.
Git repository létrehozása és letöltése¶
-
Moodle-ben keresd meg a laborhoz tartozó meghívó URL-jét és annak segítségével hozd létre a saját repository-dat!
-
Várd meg, míg elkészül a repository, majd checkout-old ki!
Egyetemi laborokban, ha a checkout során nem kér a rendszer felhasználónevet és jelszót, és nem sikerül a checkout, akkor valószínűleg a gépen korábban megjegyzett felhasználónévvel próbálkozott a rendszer. Először töröld ki a mentett belépési adatokat (lásd itt), és próbáld újra.
-
Hozz létre egy új ágat
megoldas
néven, és ezen az ágon dolgozz! -
A
neptun.txt
fájlba írd bele a Neptun kódodat! A fájlban semmi más ne szerepeljen, csak egyetlen sorban a Neptun kód 6 karaktere!
Markdown fájl megnyitása¶
A feladatok megoldása során a dokumentációt markdown formátumban kell elkészíteni. Az előbb letöltött git repository-t nyisd meg egy markdown kompatibilis szerkesztővel! Javasolt a Visual Studio Code használata:
-
Indítsd el a VS Code-ot!
-
A File > Open Folder... menüvel nyisd meg a git repository könyvtárát!
-
A bal oldali fában keresük meg a
README.md
fájlt és nyissuk meg dupla kattintással! -
Ezt a fájlt szerkeszd.
-
Ha képet készítesz, azt is tedd a repository alá a többi fájl mellé. Így relatív elérési útvonallal (fájlnév) fogod tudni hivatkozni.
Fájlnév: csupa kisbetű ékezet nélkül
A képek fájlnevében ne használj ékezetes karaktereket, szóközöket, se kis- és nagybetűket keverve. A különböző platformok és a git eltérően kezelik a fájlneveket. A GitHub webes felületén akkor fog minden rendben megjelenni, ha csak az angol ábécé kisbetűit használod a fájlnevekben.
-
A kényelmes szerkesztéshez nyisd meg az előnézet funkciót (Ctrl-K + V).
Más szerkesztőeszköz
Ha nem szimpatikus ez a szerkesztő, használhatod a GitHub webes felületét is a dokumentáció szerkesztéséhez, itt is van előnézet. Ekkor a fájlok feltöltése kicsit körülményesebb lesz.
Android alapok¶
Fordítás menete Android platformon¶
A projekt létrehozása után a forráskód az app/src
könyvtárban található. A felhasználói felületet Jetpack Compose használatával, közvetlenül Kotlin kódban definiáljuk, így nincs szükség XML állományokra. Az Android projekt fordításának eredménye egy APK állomány, melyet közvetlenül telepíthetünk mobil eszközre. Jetpack Compose segítségével könnyedén elérhetjük és kezelhetjük a felületi elemeket Kotlin kódból, megkönnyítve ezzel a modern, deklaratív felületkialakítást.
Fordítás menete Android platformon
-
A fejlesztő elkészíti a Kotlin forráskódot, amelyben a felhasználói felületet Jetpack Compose segítségével definiálja. Nincs szükség külön XML alapú felhasználói felület leírásra.
-
A fejlesztőkörnyezet folyamatosan naprakészen tartja a Compose elemekhez kapcsolódó erőforrásokat és a szükséges build állományokat a fejlesztéshez és a fordításhoz.
-
A fejlesztő a Manifest állományban beállítja az alkalmazás hozzáférési jogosultságait (pl. Internet elérés, szenzorok használata, stb.), illetve ha futás idejű jogosultságok szükségesek, ezt kezeli.
-
A fordító a forráskódból, az erőforrásokból és a külső könyvtárakból előállítja az ART virtuális gép gépi kódját.
-
A gépi kódból és az erőforrásokból előáll a nem aláírt APK állomány.
-
Végül a rendszer végrehajtja az aláírást és előáll a készülékekre telepíthető, aláírt APK.
Az Android Studio a Gradle build rendszert használja ezeknek a lépéseknek az elvégézéséhez.
Megjegyzések
-
A teljes folyamat a fejlesztői gépen megy végbe, a készülékekre már csak bináris állomány jut el.
-
A külső könyvtárak általában JAR állományként, vagy egy másik projekt hozzáadásával illeszthetők az aktuális projekthez (de ezt nem kell kézzel megtennünk, a függőségek kezelésében is a Gradle fog segíteni).
-
Az APK állomány leginkább a Java világban ismert JAR állományokhoz hasonlítható.
-
A Manifest állományban meg kell adni a támogatni kívánt Android verziót, mely felfele kompatibilis az újabb verziókkal, ennél régebbi verzióra azonban az alkalmazás már nem telepíthető.
-
Az Android folyamatosan frissülő verzióival folymatosan lépést kell tartaniuk a fejlesztőknek.
-
Az Android alkalmazásokat tipikusan a Google Play Store-ban szokták publikálni, így az APK formátumban való terjesztés nem annyira elterjedt.
SDK és könyvtárai¶
A developer.android.com/studio oldalról letölthető az IDE és az SDK. Tekintsük át ennek a fontosabb mappáit, eszközeit!
SDK szerkezet:
build-tools
: Fordítást segítő eszközök API szintenkét: AIDL, AAPT2, stb.emulator
: Az Android emulátor fájljainak helye.extras
: Különböző extra szoftverek helye. Maven repository, support libes anyagok, analytics SDK, Google Android USB driver (amennyiben SDK managerrel ezt is letöltöttük) stb.platform-tools
: Fastboot és ADB binárisok helye (legtöbbet használt eszközök).platforms
,sources
,system-images
: Minden API levelhez külön almappában a platform anyagok, források, OS image-ektools
: Fordítást és tesztelést segítő eszközök, SDK manager, stb.
SDK manager¶
Az SDK kezelésére az SDK managert használjuk, ezzel lehet letölteni és frissen tartani az eszközeinket. Indítása az Android Studion keresztül lehetséges.
Az SDK Manager elérhető a Tools -> SDK Manager menüpontból:
SDK manager felülete:
Megjegyzés
Korábban létezett egy standalone SDK manager de ennek használata mára deprecated lett. Ha online forrásokban ilyet látunk ne lepődjünk meg.
Indítsuk el az AVD managert, és vizsgáljuk mel, hogy rendelkezésre áll-e minden, ami az első alkalmazásunkhoz kelleni fog.
AVD Manager¶
Az AVD az Android Virtual Device rövidítése. Ahogy arról már előadáson is szó esett, nem csak valódi eszközön futtathatjuk a kódunkat, hanem emulátoron is. (Mi is a különbség szimulátor és emulátor között?) Az AVD indítása a fejlesztői környezeten keresztül (Tools->Device Manager), illetve parancssorból is lehetséges, de ennek a használatára csak speciális esetekben van szükség.
Az AVD Manager ikonja:
Az AVD Manager felülete:
A fenti képen jobb oldalon, a kinyíló panelben, a létező virtuális eszközök listáját találjuk, bal oldalon pedig az ún. eszköz definíciókét. (Ezt az Add device fület, a Create Virtual Device opcióval tudjuk megnyitni a jobb oldalon lévő +
ikonra kattintás után.) Itt néhány előre elkészített sablon áll rendelkezésre. Magunk is készíthetünk ilyet, ha tipikusan egy adott eszközre szeretnénk fejleszteni (pl. Galaxy S24).
Készítsünk új emulátort! Értelemszerűen csak olyan API szintű eszközt készíthetünk, amilyenek rendelkezésre állnak az SDK manageren keresztül.
- A jobb oldali panelon kattintsunk a fent található Create Virtual Device... gombra!
- Válasszunk az előre definiált készülék sablonokból (pl. Pixel 9 Pro), majd nyomjuk meg a Next gombot.
- Az eszköz konfigurációja:
- A virtuális eszköz neve legyen például
Labor_1
. - Döntsük el, hogy milyen Android verziójú emulátort kívánunk használni, illetve, hogy milyen szolgáltatásokra van szükségünk. CPU/ABI alapvetően x86_64 legyen, mivel ezekhez kaphatunk hardveres gyorsítást is. Itt válasszunk a rendelkezésre állók közül egyet, majd Next.
- A virtuális eszköz neve legyen például
- Az Additional settings fül alatt alatt további opciókat találunk:
- Tetszés szerint kapcsoljuk ki vagy be a készülék keretének megjelenítését.
- Kamera opciók:
- WebcamX, hardveres kamera, ami a számítógépre van csatlakoztatva
- Emulated, egy egyszerű szoftveres megoldás, most legalább az egyik kamera legyen ilyen.
- VirtualScene, egy kifinomultabb szoftveres megoldás, amelyben egy 3D világban mozgathatjuk a kamerát.
- Hálózat: Állíthatjuk a sebességét és a késleltetését is kommunikációs technológiák szerint.
- Válasszuk ki az alapértelmezett orientációt.
- Default boot: Az Android emulátor állapotáról való pillanatkép elmentésének lehetősége. Ez azt takarja, hogy a virtuális operációs rendszer csak felfüggesztésre kerül az emulátor bezáráskor (például a megnyitott alkalmazás is megmarad, a teljes állapotával), és Quick esetben a teljes OS indítása helyett másodperceken belül elindul az emulált rendszer. Cold esetben viszont minden alkalommal leállítja és újra indítja a virtális eszköz teljes operációs rendszerét.
- Belső és külső tárhely mérete, esetleg konkrét image beállítása a tárhely tartalmáról.
- Teljesítmény:
- A használandó CPU magok száma.
- Grafikai gyorsítás típusa. (Hardveres gyorsítás csak a megfelelő driver esetén érhető el)
- VM heap: az alkalmazások virtuális gépének szól, maradhat az alapérték. Tudni kell, hogy készülékek esetében gyártónként változik.
- A kívánt bináris interface.
- Ha mindent rendben talál az ablak, akkor Finish!
Az Android Virtual Device Manager-ben megjelent az imént létrehozott eszközünk. Itt lehetőség van a korábban megadott paraméterek szerkesztésére, külső eszköz csatlakoztatására, a "készülékről" a felhasználói adatok törlésére (Wipe Data - Teljes visszaállítás), illetve az emulátor példány duplikálására vagy törlésére.
A Play gombbal indítsuk el az új emulátort!
Emulátor problémák
Amennyiben az emulátor nem indulna el, ellenőrizzük az alábbi tippeket:
- Van-e elég hely (minimum 15-20 GB) a meghajtón?
- Legfrisebb-e az Android Studio és az sdk?
- SDK manager > sdk tools: legrisebb-e az android emulator?
- Nincs-e az Android Studio vagy az sdk telepítési útjában szóköz, ékezetes betű vagy különleges karakter?
- Próbáltál-e más API-t, Play Store-ral, a nélkül?
- Virtualizáció be van-e kapcsolva/engedélyezve van-e a gépen?
- Grafikai gyorsítás típusát próbáljuk meg átállítani.
Az elindított emulátoron próbáljunk ki néhány előre telepítétt alkalmazást!
Megjegyzés
A gyári emulátoron kívül több alternatíva is létezik, mint pl. a Genymotion vagy a BigNox, viszont a Google féle emulátor a legelterjedtebb, így amennyiben ezzel nem jelentkeznek problémáink, maradjunk ennél.
Tesztelés céljából nagyon jól használható az emulátor, amely az alábbi képen látható plusz funkciókat is adja. Lehetőség van többek között egyedi hely beállítására, bejövő hívás szimulálására, virtuálisan szenzorok manipulálására, stb. A panelt a futó emulátor jobb oldalán található vezérlő gombok közül a ... gombbal lehet megnyitni:
Fejlesztői környezet¶
Android fejlesztésre a labor során a JetBrains IntelliJ alapjain nyugvó Android Studio-t fogjuk használni. A Studio-val ismerkedők számára hasznos funkció a Tip of the day, érdemes egyből kipróbálni, megnézni az adott funkciót. Induláskor alapértelmezetten a legutóbbi projekt nyílik meg, ha nincs ilyen, vagy ha minden projektünket bezártuk, akkor a nyitó képernyő. (A legutóbbi projekt újranyitását a Settings -> Appeareance & Behavior -> System Settings -> Reopen projects on startup opcióval ki is kapcsolhatjuk.)
High Low Game¶
A laborvezető segítségével készítsünk egy új alkalmazást!
Projekt létrehozása¶
Első lépésként indítsuk el az Android Studio-t, majd:
- Hozzunk létre egy új projektet, válasszuk az Empty Views Activity lehetőséget.
- A projekt neve legyen
HighLowGame
, a kezdő package pedighu.bme.aut.android.highlowgame
. - Nyelvnek válasszuk a Kotlin-t.
- A minimum API szint legyen API24: Android 7.0.
- A
Build configuration language
Kotlin DSL legyen.
FILE PATH
A projekt a repository-ban lévő HighLowGame könyvtárba kerüljön!
A laborvezető segítségével tekintsék át a létrejött projekt struktúráját!
Miután áttekintettük a projektet, valósítsuk meg a barchóba játékot! Először is kapcsoljuk be a modulunkra a ViewBinding
-ot a felületi elemek eléréhez. Az app
modulhoz tartozó build.gradle.kts
fájlban az android
tagen belülre illesszük be az engedélyezést:
android {
...
buildFeatures {
viewBinding = true
}
}
Az alkalmazásunk felülete (activity_main.xml
) a következő lesz:
- lesz két beviteli mezőnk: egy a tippnek, egy a névnek
- lesz egy gombunk a tipp leadásához
- lesz egy eredmény mező az eredmény megjelenítéséhez.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter number here">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etGuess"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/etName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter a name here" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btnGuess"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Guess" />
<TextView
android:id="@+id/tvResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="have fun :)"
android:textSize="28sp" />
</LinearLayout>
A játék kódja pedig a következőképpen alakul (MainActivity.kt
):
class MainActivity : AppCompatActivity() {
companion object {
const val KEY_NUM = "KEY_NUM"
}
lateinit var binding: ActivityMainBinding
var generatedNum = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
if (savedInstanceState != null && savedInstanceState!!.containsKey(KEY_NUM)) {
generatedNum = savedInstanceState.getInt(KEY_NUM)
} else {
generateNewNumber()
}
binding.btnGuess.setOnClickListener {
try {
if (binding.etGuess.text!!.isNotEmpty()) {
val myNum = binding.etGuess.text.toString().toInt()
if (myNum == generatedNum) {
binding.tvResult.text = "${binding.etName.text.toString()}, You have won!"
} else if (myNum < generatedNum) {
binding.tvResult.text = "The number is higher"
} else if (myNum > generatedNum) {
binding.tvResult.text = "The number is lower"
}
} else {
binding.etGuess.error = "This value is not valid"
}
} catch (e: Exception) {
binding.etGuess.error = e.message
}
}
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putInt(KEY_NUM, generatedNum)
super.onSaveInstanceState(outState)
}
fun generateNewNumber() {
val rand = Random(System.currentTimeMillis())
generatedNum = rand.nextInt(3) // 0..2
}
}
Az Activty első indulásakor sorsol egy kitalálandó számot. A tippelés gombnyomásra történik, aminek hatására frissül az eredmény mező.
Figyeljük meg, hogy a játék túléli a forgatásokat is! Ez annak köszönhető, hogy az Activity-n belül eltárolt célszámot konfiguráció váltáskor elmentjük, majd új Activity indítása esetén betöltjük.
Android Studio¶
Ez a rész azoknak szól, akik korábban már használtak más IntelliJ terméket vagy az Eclipse nevű IDE-t, és szeretnék megismerni a különbségeket az Android Studio-hoz képest.
-
Projektstruktúra: Az Android Studio Gradle-lel fordít, és más felépítést használ. Projekten belül:
.idea
: IDE fájlokapp
: forrásbuild
: fordított állományoklibs
: libraryksrc
: forráskód, azon belül is külön projekt a tesztnek, és azon belül pedigres
könyvtár, illetvejava
. Utóbbin belül már a csomagok vannak.
gradle
: Gradle fájlok
-
Hasznos funkciók:
- IntelliSense, fejlett refaktorálás támogatás
- Ha egy sorban színre, vagy képi erőforrásra hivatkozunk, a sor elejére kitesz egy miniatűr változatot.
- Ha közvetve hivatkozott erőforrást (akár
resources.get...
, akárR...
) adunk meg, összecsukja a hivatkozást és a tényleges értéket mutatja. Ha rávisszük az egeret felfedi, ha kattintunk kibontja a hivatkozást. - Névtelen belső osztályokkal is hasonlót tud, javítva a kód olvashatóságát.
- Kódkiegészítésnél szabad a kereső, a szótöredéket keresi, nem pedig a szóval kezdődő lehetőségeket (lásd képen)
- Változónév ajánlás: amikor változónévre van szükségünk, nyomjunk Ctrl+Space-t. Ha adottak a körülmények, a Studio egész jó neveket tud felajánlani.
- Szigorú lint. A Studio megengedi a warningot. Ezért szigorúbb a lint, több mindenre figyelmeztet (olyan apróságra is, hogy egy View egyik oldalán van padding, a másikon nincs)
- Layout szerkesztés. A grafikus layout építés lehetséges.
- CTRL-t lenyomva navigálhatunk a kódban, pl. osztályra, metódushívásra kattintva. Ezt a navigációt (és az egyszerű másik osztályba kattintást is) rögzíti, és a historyban előre-hátra gombokkal lehet lépkedni. Ha van az egerünkön/billentyűzetünkön ilyen gomb, és netes böngészés közben aktívan használjuk, ezt a funkciót nagyon hasznosnak fogjuk találni.
- Ha több fájl is meg van nyitva egyszerre, könnyen navigálhatunk az ALT + BAL/JOBB nyilak segítségével az fájlok között.
Billentyűkombinációk¶
- CTRL + ALT + L: Kódformázás
- CTRL + SPACE: Kódkiegészítés
- SHIFT + F6 Átnevezés (Mindenhol)
- F2: A következő error-ra ugrik. Ha nincs error, akkor warningra.
- CTRL + Z illetve CTRL + SHIFT + Z: Visszavonás és Mégis
- CTRL + P: Paraméterek mutatása
- ALT + INSERT: Metódus generálása
- CTRL + O: Metódus felüldefiniálása
- CTRL + F9: Fordítás
- SHIFT + F10: Fordítás és futtatás
- SHIFT SHIFT: Keresés mindenhol
- CTRL + N: Keresés osztályokban
- CTRL + SHIFT + N: Keresés fájlokban
- CTRL + ALT + SHIFT + N: Keresés szimbólumokban (például függvények, property-k)
- CTRL + SHIFT + A: Keresés a beállításokban, kiadható parancsokban.
- ALT + ENTER hiányzó elemek importálása/létrehozása.
Keresés
Hogy ha bármikor szükségünk van valamire, de esetleg nem találnánk a menüpontok között, akkor a dupla Shift lenyomásával (Shift+Shift) kereshetünk az Android Studioban (illetve más JetBrains IDE-kben). Próbáljuk is ki és keressünk rá a "Device Manager" opcióra.
Eszközök, szerkesztők¶
A View menü Tool Windows menüpontjában lehetőség van különböző ablakok ki- és bekapcsolására. Tekintsük át az alábbi eszközöket:
- Project
- Structure
- TODO
- Logcat
- Terminal
- Event Log
- Gradle
Lehetőség van felosztani a szerkesztőablakot, ehhez kattinsunk egy megnyitott fájl tabfülére jobb gombbal, Split Right/Down vagy csak kattintsunk rá hosszan és kezdjük el húzni a kódfelületre!
Hasznos beállítások¶
Állítsuk be a következő hasznos funkciókat:
- kis- nagybetű érzékenység kikapcsolása a kódkiegészítőben (settingsben keresés: Match case)
- "laptop mód" ki- és bekapcsolása (File -> Power Save Mode)
- sorszámozás bekapcsolása (kód melletti részen bal oldalt: jobb egérgomb, Appearance -> Show Line Numbers)
Generálható elemek¶
A Studio sok sablont tartalmaz, röviden tekintsük át a lehetőségeket:
- Projektfában, projektre jobb gombbal kattintva -> new -> module
- Projektfában, modulon belül, "java"-ra kattintva jobb gombbal -> new
- Forráskódban ALT+INSERT billentyűkombinációra
Android Profiler¶
A készülék erőforráshasználata monitorozható ezen a felületen, amelyet az említett View -> Tool Windows-ból érhetünk el.
Például részletes információt kaphatunk a processzor és a memória használatáról:
App Inspection¶
A készüléken debuggolt alkalmazásunk hálózati forgalmát és adatbázisát is meg tudjuk tekinteni. (View -> Tool Windows -> App Inspection)
Device Explorer¶
A készüléken lévő fájlrendszert is böngészhetjük. (View -> Tool Windows -> Device Explorer)
Feladatok (10 x 0.5 pont)¶
- Az új alkalmazást futtassuk emulátoron (akinek saját készüléke van, az is próbálja ki)!
- Helyezzünk breakpointot a kódba, és indítsuk el debug módban az alkalmazást! (Érdemes megyfigyelni, hogy most másik Gradle Task fut a képernyő alján.)
- Indítsunk hívást és küldjünk SMS-t az emulátorra! Mit tapasztalunk?
- Indítsunk hívást és küldjünk SMS-t az emulátorról! Mit tapasztalunk?
- Készítsünk egy képet az emulátorral és keressük meg a fájlrendszerben a Device Explorer segítségével!
- Változtassuk meg a készülék tartózkodási helyét (GPS) az emulátor megfelelő paneljének segítségével!
- Vizsgáljuk meg az elindított
HighLowGame
projekt nyitott szálait, memóriafoglalását! - Vizsgáljuk meg a Logcat panel tartalmát!
- Vizsgáljuk meg az Code -> Inspect code eredményét!
- Keressük ki a létrehozott
HighLowGame
projekt mappáját és a build könyvtáron belül vizsgálja meg az.apk
állomány tartalmát! Hol található a lefordított kód?
BEADANDÓ
A labor teljesítéséhez a fenti feladatokat kell végrehajtani és az eredményeket dokumentálni. Ezt minden egyes feladatnál egy képernyőképpel és rövid, néhány mondatos magyarázattal kell megtenni. A jegyzőkönyvet a repository-ban lévő README.md
fájlban kell elkészíteni.
A dokumentációnak a képekkel együtt helyesen kell megjelenniük a GitHub webes felületén is! Ezt ellenőrizd a beadás során: nyisd meg a repository-d webes felületét, váltsd át a megfelelő ágra, és a GitHub automatikusan renderelni fogja a README.md fájlt a képekkel együtt.