<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="sk">
	<id>http://www.kiwiki.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Matus</id>
	<title>Kiwiki - Príspevky používateľa [sk]</title>
	<link rel="self" type="application/atom+xml" href="http://www.kiwiki.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Matus"/>
	<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php/%C5%A0peci%C3%A1lne:Pr%C3%ADspevky/Matus"/>
	<updated>2026-05-03T10:07:05Z</updated>
	<subtitle>Príspevky používateľa</subtitle>
	<generator>MediaWiki 1.34.0</generator>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Testovanie_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12805</id>
		<title>Testovanie aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Testovanie_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12805"/>
		<updated>2020-09-03T20:59:19Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|5|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
Finálnou fázou vývoja aplikácie bolo jej testovanie a následné nasadenie do praxe. Testovanie aplikácie bolo zamerané výhradne na používateľské testy, ktoré boli rozdelené na dve kategórie: testovanie scenármi a testovanie používateľských rozhraní. Počas celého procesu vývoja aplikácie boli používané logovacie správy (konzolové výpisy), pomocou ktorých sa sledovali sekvencie vykonávaných krokov aplikácie. Vďaka použitiu logovacích správ bolo možné odstrániť logické chyby a výrazne optimalizovať jednotlivé funkcionality aplikácie. Vo finálnej verzii aplikácie boli všetky logovacie správy odstránené.&lt;br /&gt;
&lt;br /&gt;
==== Testovacie scenáre ====&lt;br /&gt;
&lt;br /&gt;
Podstatou tejto skupiny testov bolo testovanie funkcií a správania aplikácie na základe vopred definovaných scenárov. Každý testovací scenár mal vopred definované vstupy a akcie, ktoré bolo nutné vykonať. Po vykonaní vstupných akcií sa sledovalo správanie aplikácie a jej vhodné zareagovanie na výstupe.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.1 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - pokus o pripojenie na server so zle zadanou adresou.&lt;br /&gt;
* '''Vstup''' - zadaná neplatná webová adresa Sensorical servera.&lt;br /&gt;
* '''Výstup''' - aplikácia zareagovala správne, zobrazila upozornenie, že daný server nebol rozpoznaný a vyzvala používateľa na opravu zadaných údajov.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.2 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - pokus o prihlásenie do aplikácie bez vyplnenia prihlasovacích údajov.&lt;br /&gt;
* '''Vstup''' - prázdne polia prihlasovacích údajov.&lt;br /&gt;
* '''Výstup''' - aplikácia zobrazila oznámenie s nevhodným textom: “Nesprávne zadané prihlasovacie meno alebo heslo”.&lt;br /&gt;
* '''Oprava''' - text oznámenia bol zmenený na: “Musíte vyplniť všetky polia”.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.3 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - odhlásenie a opätovné prihlásenie do aplikácie.&lt;br /&gt;
* '''Vstup''' - výber akcie z kontextového menu “Odhlásiť sa”.&lt;br /&gt;
* '''Výstup''' - v aplikácii boli zapamätané prihlasovacie údaje naposledy prihláseného používateľa a týmito údajmi boli automaticky predvyplnené polia prihlasovacej obrazovky.&lt;br /&gt;
* '''Oprava''' - chyba bola odstránená: po odhlásení z aplikácie sú odstránené údaje o naposledy prihlásenom používateľovi.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.4 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - spustenie aplikácie bez internetového pripojenia.&lt;br /&gt;
* '''Vstup''' - používateľ je prihlásený - otvorená obrazovka prehľadu.&lt;br /&gt;
* '''Výstup''' - aplikácia zareagovala správne, zobrazila dialóg o nedostupnosti internetového pripojenia a ponúkla možné riešenia (pokračovať s naposledy stiahnutými údajmi, aktivácia internetového pripojenia).&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.5 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - prioritné otvorenie prehľadu obľúbených senzorov.&lt;br /&gt;
* '''Vstup''' - používateľ pridá ľubovoľný senzor do zoznamu obľúbených, ukončí a znova spustí aplikáciu.&lt;br /&gt;
* '''Výstup''' - aplikácia zareagovala správne, po spustení prednostne otvorila používateľom vytvorený prehľad obľúbených senzorov.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.6 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - zmena orientácie obrazovky zariadenia.&lt;br /&gt;
* '''Vstup''' - používateľ zmení orientáciu obrazovky zariadenia z vertikálnej na horizontálnu a naopak.&lt;br /&gt;
* '''Výstup''' - aplikácia zareagovala správne, zmenila rozloženie obrazovky. Pre horizontálnu orientáciu boli použité horizontálne rozloženia, pre vertikálnu orientáciu, rozloženia vertikálne.&lt;br /&gt;
&lt;br /&gt;
==== Testovanie na rôznych zariadeniach ====&lt;br /&gt;
&lt;br /&gt;
Druhá skupina testov bola zameraná na grafické používateľské rozhranie jednotlivých obrazoviek aplikácie. Tieto testy zahŕňali inštaláciu aplikácie na zariadeniach s rôznymi verziami OS Android (5.0 Lollipop až 9.0 Pie) a následné testovanie správneho zobrazenia jednotlivých komponentov na obrazovke. Aplikácia bola testovaná celkovo na 8 rôznych zariadeniach:&lt;br /&gt;
&lt;br /&gt;
==== Telefóny ====&lt;br /&gt;
&lt;br /&gt;
* Samsung Galaxy S9: OS - 9.0 Pie, uhlopriečka - 5.8&amp;amp;quot;, rozlíšenie - 1440x2960 px&lt;br /&gt;
* Sony Xperia XZ2: OS - 9.0 Pie, uhlopriečka - 5.7&amp;amp;quot;, rozlíšenie - 1080x2160 px&lt;br /&gt;
* Samsung Galaxy S7: OS - 8.1 Oreo, uhlopriečka - 5.1&amp;amp;quot;, rozlíšenie - 1440x2560 px&lt;br /&gt;
* Huawei P10: OS - 9 Pie, uhlopriečka - 5.1&amp;amp;quot;, rozlíšenie - 1080x1920 px&lt;br /&gt;
* Huawei P Smart: OS - 8.0 Oreo, uhlopriečka - 5.65&amp;amp;quot;, rozlíšenie - 1080x2160 px&lt;br /&gt;
* Samsung Galaxy S5: OS - 6.0.1 Marshmallow, uhlopriečka - 5.1&amp;amp;quot;, rozlíšenie - 1080x1920 px&lt;br /&gt;
* Google Pixel XL (emulátor) - OS - 9 Pie, uhlopriečka - 5.5&amp;amp;quot;, rozlíšenie - 1440x2560 px&lt;br /&gt;
* Google Pixel 2 XL (emulátor): OS - 5.0 Lollipop, uhlopriečka - 6.0&amp;amp;quot;, rozlíšenie - 1440x2880 px&lt;br /&gt;
* Nexus 6P (emulátor): OS - 9 Pie, uhlopriečka - 5.7&amp;amp;quot;, rozlíšenie - 1440x2560 px&lt;br /&gt;
&lt;br /&gt;
==== Tablety ====&lt;br /&gt;
&lt;br /&gt;
* Samsung Galaxy Tab S2: OS - 7.0 Nougat, uhlopriečka - 9.7&amp;amp;quot;, rozlíšenie - 1536x2048 px&lt;br /&gt;
* Nexus 10 (emulátor): OS - 9.0 Pie, uhlopriečka - 10.1&amp;amp;quot;, rozlíšenie - 2560x1600 px&lt;br /&gt;
&lt;br /&gt;
Výsledkom týchto testov boli odhalené nasledujúce chyby: texty pri spustení aplikácie na tablete boli príliš veľké, rozhádzané rozloženie komponentov prihlasovacej obrazovky pri horizontálnej orientácii obrazovky zariadenia. Všetky odhalené chyby boli opravené.&lt;br /&gt;
&lt;br /&gt;
= Záver =&lt;br /&gt;
&lt;br /&gt;
Výstupom tejto bakalárskej práce je funkčná Android aplikácia pre prístup a vizuálnu prezentáciu dát meracieho systému Sensorical. Aplikácia má interné využitie obmedzené len na používateľov evidovaných v tomto systéme.&lt;br /&gt;
&lt;br /&gt;
Každý používateľ má možnosť voľby adresy servera, ku ktorému sa chce prihlásiť a ktorého dáta chce zobraziť. Najnovšie dáta sú zo servera sťahované automaticky vždy pri spustení resp. prihlásení do aplikácie. V prípade nedostupnosti internetového pripojenia sú používateľovi zobrazené naposledy stiahnuté dáta uložené v SQLite databáze. Obsah zobrazený prihlásenému používateľovi je filtrovaný na základe prístupových oprávnení, ktoré má každý používateľ pridelené administrátorom systému.&lt;br /&gt;
&lt;br /&gt;
Výsledná aplikácia disponuje funkcionalitami ako vykresľovanie grafov nameraných hodnôt za zvolené obdobie, zobrazovanie trendov nameraných hodnôt, zobrazovanie štatistík nameraných hodnôt za zvolené obdobie (priemerná, maximálna, minimálna hodnota) a iné. Každý používateľ má taktiež možnosť vytvoriť si vlastný zoznam obľúbených senzorov, ktorý mu bude zobrazovaný prioritne. Aplikácia bola implementovaná s dôrazom na intuitívne používateľské rozhranie vytvorené podľa sprievodcu Material Design. Pre vyšší používateľský komfort a pre efektívnejšie využívanie rozložení obrazoviek boli vytvorené rôzne rozloženia komponentov pre vertikálnu a horizontálnu orientáciu obrazovky. Aplikácia bola implementovaná v dvoch jazykových mutáciách anglickej a slovenskej, medzi ktorými sa prepína automaticky podľa predvoleného jazyka zariadenia.&lt;br /&gt;
&lt;br /&gt;
Po vytvorení bola aplikácia podrobená používateľským testom. Na základe týchto testov boli odstránené nedostatky a chyby. Tieto testy taktiež poskytli viaceré námety na zlepšenie (napr. zmena štýlu tlačidla pre pridanie senzora do obľúbených), ktoré boli zakomponované do finálnej verzie aplikácie. Odladená verzia aplikácie bola nasadená do praxe a prevádzkovaná na dvoch rôznych serveroch. Jeden zo serverov prijímal namerané dáta s miernymi výpadkami s čím si aplikácia dokázala poradiť a zobrazovala správne hodnoty adekvátne realite.&lt;br /&gt;
&lt;br /&gt;
Z vyššie uvedených funkcií a vlastností môžeme konštatovať, že výsledná aplikácia spĺňa všetky požiadavky, ktoré boli pre jej vývoj definované. Na druhú stranu existujú funkcie, ktoré by mohli byť v budúcnosti a v prípade záujmu pridané ako napr. administrátorská časť systému, alebo možnosť registrácie do systému priamo cez aplikáciu.&lt;br /&gt;
&lt;br /&gt;
Vývoj tejto mobilnej aplikácie bol pre mňa veľkým prínosom. Oboznámil som sa so základnými princípmi tvorby mobilných aplikácií pre platformu Android, naučil som sa pracovať s efektívnymi Android knižnicami Room a RxJava a rozšíril som svoje znalosti v objektovo orientovanom programovaní a jazyku Java.&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Snackbar.png&amp;diff=12804</id>
		<title>Súbor:Snackbar.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Snackbar.png&amp;diff=12804"/>
		<updated>2020-09-03T20:50:21Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Testovanie_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12803</id>
		<title>Testovanie aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Testovanie_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12803"/>
		<updated>2020-09-03T20:49:49Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|5|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
Finálnou fázou vývoja aplikácie bolo jej testovanie a následné nasadenie do praxe. Testovanie aplikácie bolo zamerané výhradne na používateľské testy, ktoré boli rozdelené na dve kategórie: testovanie scenármi a testovanie používateľských rozhraní. Počas celého procesu vývoja aplikácie boli používané logovacie správy (konzolové výpisy), pomocou ktorých sa sledovali sekvencie vykonávaných krokov aplikácie. Vďaka použitiu logovacích správ bolo možné odstrániť logické chyby a výrazne optimalizovať jednotlivé funkcionality aplikácie. Vo finálnej verzii aplikácie boli všetky logovacie správy odstránené.&lt;br /&gt;
&lt;br /&gt;
==== Testovacie scenáre ====&lt;br /&gt;
&lt;br /&gt;
Podstatou tejto skupiny testov bolo testovanie funkcií a správania aplikácie na základe vopred definovaných scenárov. Každý testovací scenár mal vopred definované vstupy a akcie, ktoré bolo nutné vykonať. Po vykonaní vstupných akcií sa sledovalo správanie aplikácie a jej vhodné zareagovanie na výstupe.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.1 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - pokus o pripojenie na server so zle zadanou adresou.&lt;br /&gt;
* '''Vstup''' - zadaná neplatná webová adresa Sensorical servera.&lt;br /&gt;
* '''Výstup''' - aplikácia zareagovala správne, zobrazila upozornenie, že daný server nebol rozpoznaný a vyzvala používateľa na opravu zadaných údajov.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.2 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - pokus o prihlásenie do aplikácie bez vyplnenia prihlasovacích údajov.&lt;br /&gt;
* '''Vstup''' - prázdne polia prihlasovacích údajov.&lt;br /&gt;
* '''Výstup''' - aplikácia zobrazila oznámenie s nevhodným textom: “Nesprávne zadané prihlasovacie meno alebo heslo”.&lt;br /&gt;
* '''Oprava''' - text oznámenia bol zmenený na: “Musíte vyplniť všetky polia”.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.3 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - odhlásenie a opätovné prihlásenie do aplikácie.&lt;br /&gt;
* '''Vstup''' - výber akcie z kontextového menu “Odhlásiť sa”.&lt;br /&gt;
* '''Výstup''' - v aplikácii boli zapamätané prihlasovacie údaje naposledy prihláseného používateľa a týmito údajmi boli automaticky predvyplnené polia prihlasovacej obrazovky.&lt;br /&gt;
* '''Oprava''' - chyba bola odstránená: po odhlásení z aplikácie sú odstránené údaje o naposledy prihlásenom používateľovi.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.4 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - spustenie aplikácie bez internetového pripojenia.&lt;br /&gt;
* '''Vstup''' - používateľ je prihlásený - otvorená obrazovka prehľadu.&lt;br /&gt;
* '''Výstup''' - aplikácia zareagovala správne, zobrazila dialóg o nedostupnosti internetového pripojenia a ponúkla možné riešenia (pokračovať s naposledy stiahnutými údajmi, aktivácia internetového pripojenia).&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.5 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - prioritné otvorenie prehľadu obľúbených senzorov.&lt;br /&gt;
* '''Vstup''' - používateľ pridá ľubovoľný senzor do zoznamu obľúbených, ukončí a znova spustí aplikáciu.&lt;br /&gt;
* '''Výstup''' - aplikácia zareagovala správne, po spustení prednostne otvorila používateľom vytvorený prehľad obľúbených senzorov.&lt;br /&gt;
&lt;br /&gt;
==== Testovací scenár č.6 ====&lt;br /&gt;
&lt;br /&gt;
* '''Akcia''' - zmena orientácie obrazovky zariadenia.&lt;br /&gt;
* '''Vstup''' - používateľ zmení orientáciu obrazovky zariadenia z vertikálnej na horizontálnu a naopak.&lt;br /&gt;
* '''Výstup''' - aplikácia zareagovala správne, zmenila rozloženie obrazovky. Pre horizontálnu orientáciu boli použité horizontálne rozloženia, pre vertikálnu orientáciu, rozloženia vertikálne.&lt;br /&gt;
&lt;br /&gt;
==== Testovanie na rôznych zariadeniach ====&lt;br /&gt;
&lt;br /&gt;
Druhá skupina testov bola zameraná na grafické používateľské rozhranie jednotlivých obrazoviek aplikácie. Tieto testy zahŕňali inštaláciu aplikácie na zariadeniach s rôznymi verziami OS Android (5.0 Lollipop až 9.0 Pie) a následné testovanie správneho zobrazenia jednotlivých komponentov na obrazovke. Aplikácia bola testovaná celkovo na 8 rôznych zariadeniach:&lt;br /&gt;
&lt;br /&gt;
==== Telefóny ====&lt;br /&gt;
&lt;br /&gt;
* Samsung Galaxy S9: OS - 9.0 Pie, uhlopriečka - 5.8&amp;amp;quot;, rozlíšenie - 1440x2960 px&lt;br /&gt;
* Sony Xperia XZ2: OS - 9.0 Pie, uhlopriečka - 5.7&amp;amp;quot;, rozlíšenie - 1080x2160 px&lt;br /&gt;
* Samsung Galaxy S7: OS - 8.1 Oreo, uhlopriečka - 5.1&amp;amp;quot;, rozlíšenie - 1440x2560 px&lt;br /&gt;
* Huawei P10: OS - 9 Pie, uhlopriečka - 5.1&amp;amp;quot;, rozlíšenie - 1080x1920 px&lt;br /&gt;
* Huawei P Smart: OS - 8.0 Oreo, uhlopriečka - 5.65&amp;amp;quot;, rozlíšenie - 1080x2160 px&lt;br /&gt;
* Samsung Galaxy S5: OS - 6.0.1 Marshmallow, uhlopriečka - 5.1&amp;amp;quot;, rozlíšenie - 1080x1920 px&lt;br /&gt;
* Google Pixel XL (emulátor) - OS - 9 Pie, uhlopriečka - 5.5&amp;amp;quot;, rozlíšenie - 1440x2560 px&lt;br /&gt;
* Google Pixel 2 XL (emulátor): OS - 5.0 Lollipop, uhlopriečka - 6.0&amp;amp;quot;, rozlíšenie - 1440x2880 px&lt;br /&gt;
* Nexus 6P (emulátor): OS - 9 Pie, uhlopriečka - 5.7&amp;amp;quot;, rozlíšenie - 1440x2560 px&lt;br /&gt;
&lt;br /&gt;
==== Tablety ====&lt;br /&gt;
&lt;br /&gt;
* Samsung Galaxy Tab S2: OS - 7.0 Nougat, uhlopriečka - 9.7&amp;amp;quot;, rozlíšenie - 1536x2048 px&lt;br /&gt;
* Nexus 10 (emulátor): OS - 9.0 Pie, uhlopriečka - 10.1&amp;amp;quot;, rozlíšenie - 2560x1600 px&lt;br /&gt;
&lt;br /&gt;
Výsledkom týchto testov boli odhalené nasledujúce chyby: texty pri spustení aplikácie na tablete boli príliš veľké, rozhádzané rozloženie komponentov prihlasovacej obrazovky pri horizontálnej orientácii obrazovky zariadenia. Všetky odhalené chyby boli opravené.&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Graph_view_land.png&amp;diff=12802</id>
		<title>Súbor:Graph view land.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Graph_view_land.png&amp;diff=12802"/>
		<updated>2020-09-03T20:34:16Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Graph_view.png&amp;diff=12801</id>
		<title>Súbor:Graph view.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Graph_view.png&amp;diff=12801"/>
		<updated>2020-09-03T20:33:26Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Recycler_view_dashboard_edit.png&amp;diff=12800</id>
		<title>Súbor:Recycler view dashboard edit.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Recycler_view_dashboard_edit.png&amp;diff=12800"/>
		<updated>2020-09-03T20:32:34Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Favourites.png&amp;diff=12799</id>
		<title>Súbor:Favourites.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Favourites.png&amp;diff=12799"/>
		<updated>2020-09-03T20:32:23Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Api_call_diagram_final.png&amp;diff=12798</id>
		<title>Súbor:Api call diagram final.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Api_call_diagram_final.png&amp;diff=12798"/>
		<updated>2020-09-03T20:31:48Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Completable_class_final.png&amp;diff=12797</id>
		<title>Súbor:Completable class final.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Completable_class_final.png&amp;diff=12797"/>
		<updated>2020-09-03T20:31:30Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Implement%C3%A1cia_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12796</id>
		<title>Implementácia aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Implement%C3%A1cia_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12796"/>
		<updated>2020-09-03T20:31:09Z</updated>

		<summary type="html">&lt;p&gt;Matus: /* Vytvorenie, odoslanie a spracovanie požiadavky */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|4|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
Implementácia používateľského rozhrania a jednotlivých funkcionalít aplikácie vychádza zo špecifikácie požiadaviek a navrhnutej štruktúry aplikácie v kapitole [[#navrh|[navrh]]]. V tejto kapitole sú postupne opísané: implementácia používateľského rozhrania aplikácie, práca s dátami, komunikácia so serverom a samotná vizualizácia dát v aplikácii.&lt;br /&gt;
&lt;br /&gt;
== Používateľské rozhranie aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Jednotlivé obrazovky tvoriace používateľské rozhranie aplikácie, prostredníctvom ktorých používateľ s aplikáciou interaguje, sú implementované podľa navrhnutej štruktúry aplikácie (časť [[#navrh_aktivity|[navrh_aktivity]]]) ako jednotlivé triedy Android aktivít. Tieto Android aktivity rozdeľujú aplikáciu na dve časti: primárnu a sekundárnu.&lt;br /&gt;
&lt;br /&gt;
Aktivity primárnej časti poskytujú používateľovi priamy prístup k prehľadu aktuálneho stavu meracieho systému Sensorical. Aktivity sekundárnej časti predstavujú pomocné aktivity, ktoré sú však nevyhnutné pre prístup do primárnej časti, tj. nutnosť výberu adresy servera, ku ktorému sa chce používateľ pripojiť, ako aj samotné prihlásenie do aplikácie. '''Android aktivity primárnej časti'''&lt;br /&gt;
&lt;br /&gt;
* Dashboard - aktivita, ktorá sprostredkováva prehľad všetkých aktuálne dostupných senzorov a ich údajov, kategorizovaných v rámci oblastí a sektorov&lt;br /&gt;
* Favourites - aktivita, ktorá zobrazuje prehľad vybraných, obľúbených senzorov a ich údaje&lt;br /&gt;
* GraphView - aktivita ktorá zobrazuje detailný prehľad konkrétneho senzora, históriu nameraných hodnôt (grafy a štatistiky)&lt;br /&gt;
&lt;br /&gt;
'''Android aktivity sekundárnej časti'''&lt;br /&gt;
&lt;br /&gt;
* ServerSelect - aktivita pre výber adresy servera&lt;br /&gt;
* Login - aktivita pre prihlásenie do aplikácie&lt;br /&gt;
* About - aktivita zobrazujúca doplňujúce informácie o aplikácií&lt;br /&gt;
&lt;br /&gt;
=== Android a Material Design ===&lt;br /&gt;
&lt;br /&gt;
Material Design predstavuje dizajnérsky jazyk vyvinutý spoločnosťou Google v roku 2014, ktorý priniesol množstvo inovácií a zmien do spôsobu tvorby grafických používateľských rozhraní. Filozofia konceptu Material Design vychádza z fyzikálnych vlastností reálnych objektov ako 3D kontúry, odraz svetla, tiene…&lt;br /&gt;
&lt;br /&gt;
Medzi inovácie, ktoré Material Design prináša patria nové komponenty ako napr. karty (Cards), plávajúce tlačidlo (Floating action button), oznámenia (Snackbars), animácie, prechody a iné. Najväčšou zmenou, ktorú Material Design priniesol je tzv. efekt hĺbky resp. používanie osi z. Jednotlivé komponenty sú zobrazované v pomyselných vrstvách v rôznych hladinách (radené nad sebou). Najdôležitejší komponent, s ktorým môže požívateľ aktuálne pracovať je zobrazený ponad ostatné komponenty (vo vyššej hladine osi z). Výhodou používateľských rozhraní, využívajúcich princíp radenia komponentov do vrstiev, je intuitívne prostredie, v ktorom sa používateľ ľahko zorientuje, s ktorými komponentmi môže aktuálne pracovať.&lt;br /&gt;
&lt;br /&gt;
=== Implementácia Material Design v aplikácii ===&lt;br /&gt;
&lt;br /&gt;
Pri implementácii používateľského rozhrania aplikácie boli odporúčania Material Design aplikované priamo v jednotlivých grafických rozhraniach Android aktivít a ich komponentoch. Tieto odporúčania (napr. odsadenie, vyvýšenie, farby, tlačidlá a tvary) presne definujú prípady použitia - kedy a ako môže byť daný komponent použitý, ako má vyzerať a ako sa má správať.&lt;br /&gt;
&lt;br /&gt;
Pri tvorbe grafických používateľských rozhraní a taktiež pre exaktný popis parametrov jednotlivých komponentov sú používané abstraktné jednotky - dp (density pixel). Jednotky dp sú prepočítavané k referenčnému rozlíšeniu v pixeloch: 1dp=1 pixel na obrazovke s rozlíšením 160dpi (bodov na palec).&lt;br /&gt;
&lt;br /&gt;
=== Material Design komponenty využité v aplikácii ===&lt;br /&gt;
&lt;br /&gt;
==== Cards ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' Cards (Karty) zobrazujú obsah a akcie súvisiace s jedným senzorom (). Každá karta senzora zobrazuje: názov senzora, tlačidlo pre akciu pridania/odstránenia do/zo zoznamu obľúbených senzorov, priemernú hodnotu, poslednú nameranú hodnotu a dátum kedy bola nameraná. Na karte senzora je taktiež vykresľovaný trend meraní daného senzora. Trend predstavuje smer rastu resp. poklesu nameraných hodnôt za poslednú hodinu.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Vyvýšenie karty od 1dp do 8dp, optimálne 2dp.&lt;br /&gt;
* Ak sú v karte použité oddeľovače obsahu, nemali by prechádzať cez celú kartu, ale len cez jej časť.&lt;br /&gt;
&lt;br /&gt;
[[File:card_sensor.png|thumb|none|510px|alt=Karta zobrazujúca údaje jedného senzora|Karta zobrazujúca údaje jedného senzora]]&lt;br /&gt;
&lt;br /&gt;
==== Floating Action Button ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' plávajúce tlačidlo (FAB) je používané na vyhľadávanie v aktivitách prehľadu (Dashboard, Favourites). Tlačidlo je štandardne viditeľné, avšak pri posunutí v zozname smerom dolu je skryté, z dôvodu úplnej viditeľnosti údajov poslednej karty zoznamu. Pri posunutí v zozname smerom hore sa stane tlačidlo znova viditeľné.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* FAB je zobrazené ponad všetok ostatný obsah, štandardne v pravom dolnom rohu.&lt;br /&gt;
* Optimálne rodičovské rozloženie - CoordinatorLayout (umožňuje automatické posunutie FAB smerom hore, napr. v prípade zobrazenia Snackbar oznámenia).&lt;br /&gt;
* Odporúčaná veľkosť je 56x56dp pre zariadenia s rozlíšením nad 460dp, pre zariadenia s nižším rozlíšením 46x46dp.&lt;br /&gt;
* Farba plávajúceho tlačidla je rovnaká ako hlavná farebná schéma aplikácie.&lt;br /&gt;
* Odsadenie od okraja obrazovky 16dp, vyvýšenie ponad ostatný obsah do 6dp.&lt;br /&gt;
&lt;br /&gt;
==== AppBar ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' horná nástrojová lišta sprostredkováva informácie a akcie súvisiace s aktuálnou obrazovkou. Zobrazuje názov aktuálnej obrazovky, rýchle akcie (napr. otvorenie zoznamu obľúbených) a kontextové menu.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Názov obrazovky je umiestnený na ľavej strane nástrojovej lišty.&lt;br /&gt;
* Kontextové akcie sú umiestnené na pravú stranu.&lt;br /&gt;
* Ak je použité kontextové menu, je umiestené úplne na pravej strane.&lt;br /&gt;
* Vyvýšenie nástrojovej lišty je štandardne 4dp.&lt;br /&gt;
&lt;br /&gt;
==== Snackbar ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' rýchle oznámenia ukotvené k spodnej časti obrazovky, ktoré informujú o aktuálnom dianí v aplikácii.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Optimálne rodičovské rozloženie - CoordinatorLayout.&lt;br /&gt;
* Snackbar má byť zobrazený len po určitú dobu, bez nutnosti explicitného zrušenia používateľom.&lt;br /&gt;
&lt;br /&gt;
[[File:snackbar.png|207px|Material Design komponenty použité v aplikácii: Snackbar (aktivita Login), AppBar, Card a FAB (aktivita Dashboard)]] [[File:card_app_bar_fab.png|207px|Material Design komponenty použité v aplikácii: Snackbar (aktivita Login), AppBar, Card a FAB (aktivita Dashboard)]]&lt;br /&gt;
&lt;br /&gt;
== Práca s dátami v aplikácii ==&lt;br /&gt;
&lt;br /&gt;
Dáta, s ktorými aplikácia pracuje sú sťahované zo vzdialených serverov a po stiahnutí sú ukladané do SQLite databázy, z ktorej sú sprostredkovávané v aplikácii. Sťahovanie najaktuálnejších meraní prebieha automaticky vždy po spustení resp. prihlásení do aplikácie. V prípade potreby manuálnej aktualizácie nameraných hodnôt, prípadne synchronizácie všetkých dát s aktuálne dostupnými dátami daného servera sú v aplikácii implementované dva rôzne spôsoby manuálnej synchronizácie: aktualizácia len nameraných hodnôt alebo synchronizácia všetkých dát.&lt;br /&gt;
&lt;br /&gt;
Pre zefektívnenie a zrýchlenie sťahovania nameraných hodnôt sa v aplikácii vytvárajú záznamy o dátumoch, za ktoré boli namerané hodnoty úspešne stiahnuté. Vždy pred každým ďalším sťahovaním nových meraní sú tieto záznamy prečítané a stiahnu sa len merania tých dátumov, ktoré nie sú evidované ako stiahnuté.&lt;br /&gt;
&lt;br /&gt;
Keďže aplikácia slúži na monitorovanie aktuálneho stavu a krátkodobejších trendov, maximálny rozsah zobrazenia nameraných hodnôt bol stanovený na jeden týždeň. Aby sa predišlo prílišnému zväčšeniu veľkosti aplikácie dôsledkom sťahovania množstva údajov, sú po každom stiahnutí najnovších nameraných hodnôt vymazané nepotrebné záznamy (merania) staršie ako jeden týždeň.&lt;br /&gt;
&lt;br /&gt;
=== Implementácia SQLite databázy ===&lt;br /&gt;
&lt;br /&gt;
SQLite databáza, ktorá slúži na archiváciu stiahnutých dát a ich následnú prezentáciu v aplikácii, bola vytvorená pomocou knižnice Room (viď [[#room|[room]]]), pričom je implementovaná tak, aby presne korešpondovala s dátovým modelom systému Sensorical (). Aplikácia je navrhnutá tak, že umožňuje vytvárať a pracovať s ľubovoľným počtom SQLite databáz, ktoré sú vytvárané na základe webovej adresy servera, ku ktorej je používateľ aktuálne prihlásený.&lt;br /&gt;
&lt;br /&gt;
Každý server, ku ktorému sa používateľ prihlási, má v aplikácii vytvorenú vlastnú SQLite databázu. Vždy po úspešnom prihlásení k niektorému zo serverov sa aplikácia pokúsi vytvoriť novú databázu s názvom webovej adresy daného servera. Ak už databáza s takýmto názvom existuje, aplikácia ju použije a otvorí.&lt;br /&gt;
&lt;br /&gt;
Pri samotnej implementácii SQLite databázy v aplikácii, boli ako prvé vytvorené jednotlivé triedy reprezentujúce entity databázy ([[#listing:entity|[listing:entity]]]). Každá trieda entity obsahuje premenné, ktoré predstavujú jednotlivé atribúty danej entity. Každá premenná triedy entity je prístupná prostredníctvom metód get a set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Entity(tableName = &amp;quot;area&amp;quot;)&lt;br /&gt;
    public class Area {&lt;br /&gt;
        @PrimaryKey&lt;br /&gt;
        private int id;&lt;br /&gt;
        private String name;&lt;br /&gt;
&lt;br /&gt;
        public void setId(int id) { this.id = id; }&lt;br /&gt;
        public int getId() { return id; }&lt;br /&gt;
        public String getName() { return name; }&lt;br /&gt;
        public void setName(String name) { this.name = name; }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako ďalšie boli vytvorené potrebné DAO rozhrania ([[#listing:dao|[listing:dao]]] rozhranie AreaDao) a ich metódy pre prístup k dátam databázy. Návratové typy týchto metód boli zvolené na základe očakávaného výsledku SQL dotazu, ktorý daná metóda vykonáva. V prípade DAO metód, ktoré slúžia na výber údajov z SQLite databázy, sú návratové typy zabalené do generickej triedy Maybe, knižnice RxJava, ktorá umožňuje vykonávať prácu týchto metód asynchrónne v paralelných vláknach.&lt;br /&gt;
&lt;br /&gt;
DAO metódy, ktoré do SQLite databázy vkladajú záznamy nameraných hodnôt, využívajú v prípade konfliktu hodnôt primárnych kľúčov parameter IGNORE (ignorovať). Parameter IGNORE zabezpečí neprepísanie existujúceho záznamu v SQLite databáze, pretože nameraná hodnota nemôže byť spätne modifikovaná a teda nie je nutné už existujúce záznamy prepisovať (skrátenie času vykonávania operácie).&lt;br /&gt;
&lt;br /&gt;
DAO metódy zabezpečujúce vkladanie ostatných údajov, majú v prípade konfliktu hodnôt primárnych kľúčov nastavený parameter REPLACE (nahradiť). V prípade modifikácie záznamu na strane servera sa síce nemení hodnota jeho primárneho kľúča, ale hodnota niektorého z atribútov je zmenená. Parameter REPLACE v takomto prípade zabezpečí prepísanie záznamu uloženého v SQLite databáze modifikovaným záznamom stiahnutým zo servera.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Dao&lt;br /&gt;
    public interface AreaDao {&lt;br /&gt;
        @Insert(onConflict = OnConflictStrategy.REPLACE)&lt;br /&gt;
        void insertAllAreas(List&amp;lt;Area&amp;gt; areas);&lt;br /&gt;
&lt;br /&gt;
        @Query(&amp;quot;select group_view.area_id from group_view&lt;br /&gt;
        where group_view.user_id=:userID&amp;quot;)&lt;br /&gt;
        Maybe&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; getAllAreaIDsforUser(int userID); &lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako posledná bola implementovaná abstraktná trieda databázy ([[#listing:database|[listing:database]]]), ktorá je potomkom triedy RoomDatabase. Trieda databázy v aplikácii využíva návrhový vzor Singleton, ktorý zabezpečí vytvorenie a dostupnosť jedinej inštancie triedy databázy počas behu aplikácie. Inštanciu triedy databázy je možné vytvoriť (získať) prostredníctvom statickej metódy getInstance().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Database(entities = {Area.class, Sensor.class}, version = 1)&lt;br /&gt;
    public abstract class AppDatabase extends RoomDatabase {&lt;br /&gt;
        public abstract AreaDao areaDao();&lt;br /&gt;
        private static AppDatabase INSTANCE;&lt;br /&gt;
        &lt;br /&gt;
        public static AppDatabase getInstance(final Context context){&lt;br /&gt;
            synchronized (AppDatabase.class) {&lt;br /&gt;
                if (INSTANCE == null){&lt;br /&gt;
                  INSTANCE = buildDatabase(context.getApplicationContext()); }&lt;br /&gt;
        } return INSTANCE; }&lt;br /&gt;
        &lt;br /&gt;
        private static AppDatabase buildDatabase(final Context context){&lt;br /&gt;
          String DATABASE_NAME = context&lt;br /&gt;
            .getSharedPreferences(&amp;quot;preferences&amp;quot;, Context.MODE_PRIVATE)&lt;br /&gt;
            .getString(&amp;quot;server_name&amp;quot;, &amp;quot;default_name&amp;quot;);&lt;br /&gt;
          return Room.databaseBuilder(&lt;br /&gt;
            context, AppDatabase.class, DATABASE_NAME).build(); }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
V triede databázy sú zadefinované všetky Java triedy jednotlivých entít, z ktorých SQLite databáza pozostáva a taktiež abstraktné metódy všetkých DAO rozhraní, prostredníctvom ktorých môžno vytvoriť inštancie rozhraní v iných triedach. V aplikácii je v triede databázy implementovaná metóda buildDatabase(), ktorá zisťuje názov aktuálneho webového servera (čítanie zo SharedPreferences - ukladanie menších dát formou kľúč - hodnota), ku ktorému je používateľ prihlásený a tento názov použije pre vytvorenie resp. otvorenie databázy s daným názvom, volaním metódy build().&lt;br /&gt;
&lt;br /&gt;
=== Práca s SQLite databázou ===&lt;br /&gt;
&lt;br /&gt;
Práca s SQLite databázou, konkrétne vykonávanie dotazov na výber údajov pre niektorú z aktivít prehľadu (Dashboard, Favourites, GraphView) je v aplikácii realizované sekvenčne. Najskôr sa vykoná referenčný výber, pričom všetky ostatné dotazy čakajú vo fronte. V momente, kedy sa aktuálny výber dokončí, začne sa vykonávať nasledujúci (čakajúci). Sekvenčný spôsob vykonávania práce je zvolený z dôvodu závislosti vstupných parametrov (podmienok pre vykonanie) čakajúceho dotazu, na výsledku jemu predchádzajúcemu výberu.&lt;br /&gt;
&lt;br /&gt;
Aby aplikácia zobrazila len ten obsah, na ktorý má prihlásený používateľ pridelené práva je využitý jedinečný identifikátor každého používateľa aplikácie - ID. Hodnota ID daného používateľa je využitá práve pri referenčnom výbere, na základe ktorého sú vybrané len tie vstupné parametre, na ktoré má používateľ definované oprávnenia.&lt;br /&gt;
&lt;br /&gt;
demonštruje postupnosť volania DAO metód, ktoré vyberajú z SQLite databázy údaje pre aktivitu Dashboard. Obdobným spôsobom sú riešené výbery pre ostatné dve aktivity prehľadov (Favourites a GraphView).&lt;br /&gt;
&lt;br /&gt;
[[File:load_data_for_dashboard_data_flow_final.png|thumb|none|529px|alt=Volanie DAO metód na výber dát z SQLite databázy pre aktivitu Dashboard|Volanie DAO metód na výber dát z SQLite databázy pre aktivitu Dashboard]]&lt;br /&gt;
&lt;br /&gt;
Referenčný výber pre aktivitu Dashboard je výber zoznamu ID všetkých oblastí na základe ID prihláseného používateľa. Následne sa sekvenčne vykonávajú ďalšie výbery, ktorých parametrami sú vždy výsledky predchádzajúceho výberu. V metóde createDashboardData() sa vytvára dátová štruktúra, ktorá obsahuje vlastnosti potrebné pre zobrazenie údajov v Dashboard aktivite: názvy oblastí, sektorov a senzorov, fyzikálne jednotky senzorov, namerané hodnoty a ďalšie. Naplnená dátová štruktúra je odoslaná triede adaptéra (viď [[#vizualizacia|1.3]]), ktorá tieto dáta vizualizuje.&lt;br /&gt;
&lt;br /&gt;
Vykonávanie výberov dát z SQLite databázy prostredníctvom DAO metód predstavuje časovo náročnejšie operácie, ktoré musia prebiehať asynchrónne, v paralelnom vlákne. Pre účel vykonávania DAO metód v paralelnom vlákne je v aplikácii využitá RxJava generická trieda Maybe. znázorňuje princíp návrhového vzoru Observer, ktorý je implementovaný knižnicou RxJava a ktorý je v aplikácii využívaný pre vykonávanie dotazov na výber dát z SQLite databázy použitím triedy Maybe. Tento návrhový vzor zabezpečuje sledovanie priebehu práce časovo náročných DAO metód vykonávaných v paralelných vláknach ([[#listing:rx_operators|[listing:rx_operators]]], metóda getAllAreaIDsForUser()). Po dokončení práce týchto metód dôjde k automatickej notifikácii vlákna špecifikovaného operátorom observeOn() ([[#listing:rx_operators|[listing:rx_operators]]] - hlavné vlákno), na ktoré sú publikované výsledky prostredníctvom rozhrania Consumer a jeho metódy accept(). Metóda accept() prijíma prostredníctvom parametra výsledky vykonaného SQL dotazu danej DAO metódy.&lt;br /&gt;
&lt;br /&gt;
[[File:dao_class_final.png|thumb|none|x188px|alt=Návrhový vzor Observer využitý na výber dát z SQLite databázy|Návrhový vzor Observer využitý na výber dát z SQLite databázy]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    areaDao.getAllAreaIDsForUser(userID)&lt;br /&gt;
        .subscribeOn(Schedulers.io())&lt;br /&gt;
            .observeOn(AndroidSchedulers.mainThread())&lt;br /&gt;
                .subscribe(new Consumer&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt;() {&lt;br /&gt;
                @Override&lt;br /&gt;
                 public void accept(List&amp;lt;Integer&amp;gt; areaIDs) { } &lt;br /&gt;
            });&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Komunikácia so vzdialeným serverom ===&lt;br /&gt;
&lt;br /&gt;
Pre komunikáciu aplikácie so serverovým API je využitý socketový dátový prenos. Požiadavky/odpovede sú odosielané/prijímané v textovom formáte JSON. Po prijatí odpovede sa prechádza tá časť odpovede, ktorá obsahuje relevantné dáta (hodnota kľúča JSON objektu “data”). Časť odpovede “data” a jej hodnoty sa prechádzajú a ukladajú do dátových štruktúr (triedy jednotlivých entít), ktoré sú po naplnení vložené do SQLite databázy.&lt;br /&gt;
&lt;br /&gt;
==== Vytvorenie, odoslanie a spracovanie požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Vytvorenie a odoslanie požiadavky na API a následné spracovanie odpovede zabezpečujú v aplikácii tri triedy (ClientSocket, ApiResponses, ApiDataPresenter), ktorých zjednodušenú štruktúru znázorňuje diagram tried na obrázku [[#fig:class_diagram|1.6]].&lt;br /&gt;
&lt;br /&gt;
* trieda '''ClientSocket''' (odoslanie požiadavky) - konvertuje požiadavku do formátu JSON, otvára spojenie so serverom, odosiela požiadavku, čaká na odpoveď a vracia ju späť metóde triedy ApiResponses, ktorá požiadavku vyvolala.&lt;br /&gt;
* trieda '''ApiResponses''' (vytvorenie požiadavky) - vytvára a posiela triede ClientSocket údaje potrebné pre odoslanie požiadavky prostredníctvom parameterov metódy sendRequest(). Trieda ApiResponses zároveň prijíma a vracia späť textovú odpoveď metóde triedy ApiDataPresenter, ktorá danú požiadavku vyvolala.&lt;br /&gt;
* trieda '''ApiDataPresenter''' (spracovanie odpovede) - inicializuje proces vytvárania požiadavky volaním príslušnej metódy triedy ApiResponses, transformuje prijatú odpoveď na JSON objekt, ktorého hodnoty ukladá do dátovej štruktúry.&lt;br /&gt;
&lt;br /&gt;
[[File:class_diagram.png|thumb|none|x205px|alt=Zjednodušený diagram tried zabezpečujúcich komunikáciu so serverovým API|Zjednodušený diagram tried zabezpečujúcich komunikáciu so serverovým API]]&lt;br /&gt;
&lt;br /&gt;
Proces komunikácie so vzdialeným serverom je časovo náročná operácia, ktorá musí byť vykonávaná asynchrónne, v paralelnom vlákne. V aplikácii je pre tento účel využitá RxJava trieda Completable. znázorňuje návrhový vzor Observer, ktorý je implementovaný knižnicou RxJava a ktorý je v aplikácii využívaný pre komunikáciu so serverovým API použitím triedy Completable. Podstata tohoto návrhového vzoru spočíva v tom, že po ukončení časovo náročnej metódy ([[#listing:completable|[listing:completable]]] riadok 3, metóda run()) dôjde k automatickej notifikácii vlákna špecifikovaného operátorom observeOn(). Notifikáciu špecifikovaného vlákna ([[#listing:completable|[listing:completable]]] - hlavné vlákno) zabezpečuje rozhranie CompletableObserver a jeho metóda onComplete(), ktorá je zavolaná, ak komunikácia so serverom a spracovanie odpovede prebehli v poriadku. Samotná komunikácia so serverom prebieha v tele metódy run() volaním metódy apiDataPresenter.getAreas(), ktorá vyvolá konkrétnu požiadavku.&lt;br /&gt;
&lt;br /&gt;
[[File:completable_class_final.png|thumb|none|x188px|alt=Návrhový vzor Observer využitý na komunikáciu so serverovým API|Návrhový vzor Observer využitý na komunikáciu so serverovým API]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    Completable.fromRunnable(new Runnable() {&lt;br /&gt;
                @Override&lt;br /&gt;
                public void run() {&lt;br /&gt;
                areaDao.insertAllAreas(apiDataPresenter.getAreas());&lt;br /&gt;
                }&lt;br /&gt;
            }).subscribeOn(Schedulers.io())&lt;br /&gt;
                .observeOn(AndroidSchedulers.mainThread()&lt;br /&gt;
                    .subscribe(new CompletableObserver() {&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onSubscribe(Disposable d) { }&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onComplete() { }&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onError(Throwable e) { } });&amp;lt;/source&amp;gt;&lt;br /&gt;
Textový formát odpovede z API je vrátený do triedy ApiDataPresenter, v ktorej sa transformuje na JSON objekt ([[#listing:api_data_presenter|[listing:api_data_presenter]]], metóda parseAreaResponse()). V tejto metóde sa prechádza pole hodnôt s hodnotou kľúča “data”, pričom jednotlivé hodnoty tohto poľa sú opäť polia, ktorých hodnoty sa ukladajú do dátovej štruktúry, ktorá je vrátená späť do miesta volania ([[#listing:completable|[listing:completable]]], riadok 4). Spôsob vytvárania JSON objektu z prijatej odpovede, prechádzanie a ukladanie jeho hodnôt do dátovej štruktúry zobrazuje [[#listing:api_data_presenter|[listing:api_data_presenter]]]. Postupnosť prechodu medzi triedami a formát dát v jednotlivých triedach počas komunikácie s API znázorňuje .&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    public ArrayList&amp;lt;Area&amp;gt; getAreas() { &lt;br /&gt;
        parseAreaResponse(); &lt;br /&gt;
        return this.areaList; &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    private void parseAreaResponse() {&lt;br /&gt;
        String serverResponse = apiResponses.getAreaResponse();&lt;br /&gt;
        if (!serverResponse.isEmpty()) {&lt;br /&gt;
            JSONObject response = new JSONObject(serverResponse);&lt;br /&gt;
            JSONArray array = response.getJSONArray(&amp;quot;data&amp;quot;);&lt;br /&gt;
            for (int i = 0; i &amp;lt; array.length(); i++) {&lt;br /&gt;
                Area area = new Area();&lt;br /&gt;
                area.setId(array.getJSONArray(i).getInt(0));&lt;br /&gt;
                area.setName(array.getJSONArray(i).getString(1));&lt;br /&gt;
                this.areaList.add(area);&lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:api_call_diagram_final.png|thumb|none|585px|alt=Prenos a formát dát v jednotlivých triedach počas komunikácie s API|Prenos a formát dát v jednotlivých triedach počas komunikácie s API]]&lt;br /&gt;
&lt;br /&gt;
== Vizualizácia dát v aplikácii ==&lt;br /&gt;
&lt;br /&gt;
Prezentáciu dát v aktivitách prehľadu (Dashboard, Favourites) zabezpečujú komponenty - CardView, RecyclerView a Adaptér. V aktivite detailného prehľadu konkrétneho senzora (GraphView) sú dáta vizualizované prostredníctvom grafov - knižnica MPAndroidChart.&lt;br /&gt;
&lt;br /&gt;
=== Vizualizácia dát v aktivitách Dashboard a Favourites ===&lt;br /&gt;
&lt;br /&gt;
==== CardView ====&lt;br /&gt;
&lt;br /&gt;
CardView je grafická reprezentácia karty (Card [[#design|1.1.2]]), predstavuje rodičovské rozloženie pre všetky v nej obsiahnuté View prvky (textové polia, tlačidlá, obrázky…).&lt;br /&gt;
&lt;br /&gt;
==== RecyclerView ====&lt;br /&gt;
&lt;br /&gt;
RecylerView predstavuje model, ktorý umožňuje zobraziť väčšie množstvo údajov vo forme zoznamu. V aplikácii sú ako jednotlivé položky zobrazené v RecyclerView použité karty. Výhodou používania RecyclerView je jeho rýchlosť, pretože sa nevykresľujú (nevytvárajú) naraz všetky karty, ale vytvárajú sa len tie, ktoré sa aktuálne zmestia na obrazovku. Pre naplnenie RecyclerView kartami a ich následné zobrazenie sa využívajú návrhové vzory (triedy) ViewHolder a Adaptér. Jednotlivé karty zobrazené v RecyclerView sú reprezentované objektmi nazývanými view holders. Tieto objekty sú inštanciami tried, ktoré sú potomkami triedy RecyclerView.ViewHolder.&lt;br /&gt;
&lt;br /&gt;
==== ViewHolder ====&lt;br /&gt;
&lt;br /&gt;
ViewHolder je návrhový vzor, ktorý zabezpečuje vytvorenie objektu daného CardView rozloženia spolu s jej View prvkami. Takto vytvorený objekt môže byť použitý viacnásobne, bez nutnosti opakovanej inicializácie View prvkov tohto objektu, volaním metódy findViewById(), čo znižuje pamäťovú náročnosť a zároveň výrazne zrýchľuje proces listovania v RecyclerView. Vytvorené view holder objekty reprezentujú karty, ktoré sú zobrazené v RecyclerView. Tento návrhový vzor možno použiť vytvorením vnútornej triedy, potomok triedy RecyclerView.ViewHolder, v triede adaptéra.&lt;br /&gt;
&lt;br /&gt;
==== Adaptér ====&lt;br /&gt;
&lt;br /&gt;
Adaptér je návrhový vzor, ktorý funguje ako most medzi používateľským rozhraním a dátami. V Androide predstavuje adaptér triedu, ktorá sprostredkováva dáta RecyclerView. Trieda adaptéra (potomok triedy RecyclerView.Adapter) zabezpečuje správu jednotlivých view holder objektov prostredníctvom preťažených metód rodičovskej triedy: vytvorenie view holder objektov - metóda onCreateViewHolder, pridávanie vytvorených view holder objektov do RecyclerView - metóda onBindViewHolder().&lt;br /&gt;
&lt;br /&gt;
V aplikácii sú vytvorené dve triedy adaptérov, kde každá z nich sprostredkováva dáta konkrétnej aktivite: DashboardAdapter (Dashboard aktivita), FavouritesAdapter (Favourites aktivita). Triedy adaptérov v aplikácii využívajú návrhový vzor Singleton, pričom vytvorenie (získanie) inštancie triedy oboch adaptérov je možné prostredníctvom statickej metódy getInstance(). Spôsob implementácie triedy adaptéra v aplikácii je demonštrovaný na jednoduchšej triede FavouritesAdapter, ktorá vykresľuje len jeden typ view holder objektu (len karta senzora, vľavo). Trieda DashboardAdapter vykresľuje tri typy view holder objektov, kde každý z nich reprezentuje kartu: oblasti, sektoru, alebo senzora ( vpravo).&lt;br /&gt;
&lt;br /&gt;
Vytvorenie inštancie triedy FavouritesAdapter a následné nastavenie tejto inštancie ako adaptér objektu recylerView demonštruje kód [[#listing:adapter|[listing:adapter]]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    RecyclerView recyclerView = findViewById(R.id.recycler_view);&lt;br /&gt;
    FavouritesAdapter adapter = FavouritesAdapter.getInstance();&lt;br /&gt;
    recyclerView.setAdapter(adapter);&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:favourites.png|x264px|RecyclerView - aktivita Dashboard (vpravo), aktivita Favourites (vľavo)]] [[File:recycler_view_dashboard_edit.png|x264px|RecyclerView - aktivita Dashboard (vpravo), aktivita Favourites (vľavo)]]&lt;br /&gt;
&lt;br /&gt;
Nasledujúca ukážka ([[#listing:viewHolder|[listing:viewHolder]]]) zobrazuje implementáciu návrhového vzoru ViewHolder v triede adaptéra (FavouritesAdapter), vytvorením vnútornej triedy DataViewHolder. Trieda DataViewHolder inicializuje jednotlivé View prvky CardView rozloženia karty senzora. Každý vytvorený objekt tejto triedy reprezentuje jednu kartu v RecyclerView.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    public static class DataViewHolder extends RecyclerView.ViewHolder {&lt;br /&gt;
        private TextView textViewSensorName;&lt;br /&gt;
        // iné View prvky CardView rozloženia karty senzora...&lt;br /&gt;
        public DataViewHolder(@NonNull final View itemView) {&lt;br /&gt;
          super(itemView);&lt;br /&gt;
          textViewSensorName = &lt;br /&gt;
          itemView.findViewById(R.id.text_view_sensor_name);&lt;br /&gt;
        }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Metóda triedy adaptéra - onCreateViewHolder() ([[#listing:onCreate|[listing:onCreate]]]) slúži pre dynamické vytváranie view holder objektov. Táto metóda vytvára len taký počet view holder objektov (kariet), koľko sa aktuálne zmestí na obrazovku. Pri listovaní v RecyclerView sú dynamicky vytvárané ďalšie potrebné objekty, pričom nahrádzajú tie, ktoré už na obrazovke nie sú vidieť (recycling).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @NonNull&lt;br /&gt;
    @override&lt;br /&gt;
    public RecyclerView.ViewHolder onCreateViewHolder(&lt;br /&gt;
    @NonNull ViewGroup viewGroup, int i) {&lt;br /&gt;
                View v;&lt;br /&gt;
                LayoutInflater mInflater = &lt;br /&gt;
                LayoutInflater.from(viewGroup.getContext());&lt;br /&gt;
                v = mInflater.inflate(&lt;br /&gt;
                R.layout.card_view_sensor, viewGroup, false);&lt;br /&gt;
                return new FavouritesAdapter.DataViewHolder(v); }&amp;lt;/source&amp;gt;&lt;br /&gt;
Samotné pridanie vytvoreného view holder objektu do RecyclerView zabezpečuje metóda - onBindViewHolder() ([[#listing:onBind|[listing:onBind]]]). Každý view holder objekt v RecyclerView má definovanú pozíciu, na ktorej sa nachádza. Hodnotu aktuálnej pozície, na ktorú má byť ďalší view holder objekt pridaný/vykreslený prijíma metóda onBindViewHolder() prostredníctvom parametra. Na základe pozície je možné naviazať konkrétny view holder objekt na dáta.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @override&lt;br /&gt;
    public void onBindViewHolder(&lt;br /&gt;
    @NonNull RecyclerView.ViewHolder viewHolder, int position) {&lt;br /&gt;
        ((DataViewHolder) viewHolder).&lt;br /&gt;
        textViewSensorName.setText(&lt;br /&gt;
        filteredList.get(position).getSensorName()); }&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Vizualizácia dát v aktivite GraphView ===&lt;br /&gt;
&lt;br /&gt;
Prezentáciu dát v aktivite GraphView zabezpečujú grafy, vytvárané pomocou knižnice MPAndroidChart. Táto knižnica umožňuje vytvárať rôzne typy grafov: koláčové, stĺpcové, čiarové a iné. V aplikácii je využitý čiarový graf - LineChart. V aplikácii sú v grafe vykresľované dva typy čiar: LimitLine - horizontálna čiara pre zobrazenie priemernej hodnoty a samotná čiara grafu LineChart pre vykreslenie priebehu meraných hodnôt. Hodnoty osi x sú reprezentované časovými značkami jednotlivých meraní, ktoré sú explicitne konvertované na textový formát dátumu, ktorý je v grafe zobrazený ako legenda osi x. Hodnoty osi y sú reprezentované nameranými hodnotami. Jednotlivé body grafu sú vytvárané ako usporiadaná dvojica [časová značka, hodnota] ([[#listing:graph_creation|[listing:graph_creation]]] trieda Entry). Tieto usporiadané dvojice hodnôt sú postupne pridávané do poľa ([[#listing:graph_creation|[listing:graph_creation]]] objekt xyValues), ktoré je po naplnení priradené vytváranému objektu triedy LineDataSet v jej konštruktore. Metódy triedy LineDataSet umožňujú nastaviť požadované parametre čiary grafu (hrúbka, farba a iné). Objekt triedy LineDataSet je nakoniec priradený samotnému objektu grafu inicializovaného prostredníctvom metódy findViewById(). V aplikácii je v grafoch implementovaná možnosť zoomovania a taktiež možnosť zobrazenia hodnoty konkrétneho bodu pri kliknutí na ľubovoľnú hodnotu v grafe ( vpravo).&lt;br /&gt;
&lt;br /&gt;
[[File:graph_view.png|151px|Vykresľovanie priebehu nameraných hodnôt v aktivite GraphView]] [[File:graph_view_land.png|264px|Vykresľovanie priebehu nameraných hodnôt v aktivite GraphView]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    ArrayList&amp;lt;Entry&amp;gt; xyValues = new ArrayList&amp;lt;&amp;gt;();&lt;br /&gt;
        for (int i = 0; i &amp;lt; values.size; i++) {&lt;br /&gt;
            Entry xy = new Entry(values.get(i).getDate().getTime(),&lt;br /&gt;
                values.getValue());&lt;br /&gt;
            xyValues.add(xy);&lt;br /&gt;
        }&lt;br /&gt;
    LineDataSet dataSet = new LineDataSet(xyValues, &amp;quot;hodnoty&amp;quot;);&lt;br /&gt;
    dataSet.setLineWidth(2f);&lt;br /&gt;
    // iné nastavenia vlastností dataSetu... &lt;br /&gt;
    LineData lineData = new LineData(dataSet);&lt;br /&gt;
    LineChart chart = findViewById(R.id.chart);&lt;br /&gt;
    chart.setData(lineData);&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Class_diagram.png&amp;diff=12795</id>
		<title>Súbor:Class diagram.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Class_diagram.png&amp;diff=12795"/>
		<updated>2020-09-03T20:30:43Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Dao_class_final.png&amp;diff=12794</id>
		<title>Súbor:Dao class final.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Dao_class_final.png&amp;diff=12794"/>
		<updated>2020-09-03T20:30:17Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Load_data_for_dashboard_data_flow_final.png&amp;diff=12793</id>
		<title>Súbor:Load data for dashboard data flow final.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Load_data_for_dashboard_data_flow_final.png&amp;diff=12793"/>
		<updated>2020-09-03T20:29:58Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Card_app_bar_fab.png&amp;diff=12792</id>
		<title>Súbor:Card app bar fab.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Card_app_bar_fab.png&amp;diff=12792"/>
		<updated>2020-09-03T20:28:47Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Implement%C3%A1cia_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12791</id>
		<title>Implementácia aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Implement%C3%A1cia_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12791"/>
		<updated>2020-09-03T20:28:31Z</updated>

		<summary type="html">&lt;p&gt;Matus: /* Snackbar */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|4|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
Implementácia používateľského rozhrania a jednotlivých funkcionalít aplikácie vychádza zo špecifikácie požiadaviek a navrhnutej štruktúry aplikácie v kapitole [[#navrh|[navrh]]]. V tejto kapitole sú postupne opísané: implementácia používateľského rozhrania aplikácie, práca s dátami, komunikácia so serverom a samotná vizualizácia dát v aplikácii.&lt;br /&gt;
&lt;br /&gt;
== Používateľské rozhranie aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Jednotlivé obrazovky tvoriace používateľské rozhranie aplikácie, prostredníctvom ktorých používateľ s aplikáciou interaguje, sú implementované podľa navrhnutej štruktúry aplikácie (časť [[#navrh_aktivity|[navrh_aktivity]]]) ako jednotlivé triedy Android aktivít. Tieto Android aktivity rozdeľujú aplikáciu na dve časti: primárnu a sekundárnu.&lt;br /&gt;
&lt;br /&gt;
Aktivity primárnej časti poskytujú používateľovi priamy prístup k prehľadu aktuálneho stavu meracieho systému Sensorical. Aktivity sekundárnej časti predstavujú pomocné aktivity, ktoré sú však nevyhnutné pre prístup do primárnej časti, tj. nutnosť výberu adresy servera, ku ktorému sa chce používateľ pripojiť, ako aj samotné prihlásenie do aplikácie. '''Android aktivity primárnej časti'''&lt;br /&gt;
&lt;br /&gt;
* Dashboard - aktivita, ktorá sprostredkováva prehľad všetkých aktuálne dostupných senzorov a ich údajov, kategorizovaných v rámci oblastí a sektorov&lt;br /&gt;
* Favourites - aktivita, ktorá zobrazuje prehľad vybraných, obľúbených senzorov a ich údaje&lt;br /&gt;
* GraphView - aktivita ktorá zobrazuje detailný prehľad konkrétneho senzora, históriu nameraných hodnôt (grafy a štatistiky)&lt;br /&gt;
&lt;br /&gt;
'''Android aktivity sekundárnej časti'''&lt;br /&gt;
&lt;br /&gt;
* ServerSelect - aktivita pre výber adresy servera&lt;br /&gt;
* Login - aktivita pre prihlásenie do aplikácie&lt;br /&gt;
* About - aktivita zobrazujúca doplňujúce informácie o aplikácií&lt;br /&gt;
&lt;br /&gt;
=== Android a Material Design ===&lt;br /&gt;
&lt;br /&gt;
Material Design predstavuje dizajnérsky jazyk vyvinutý spoločnosťou Google v roku 2014, ktorý priniesol množstvo inovácií a zmien do spôsobu tvorby grafických používateľských rozhraní. Filozofia konceptu Material Design vychádza z fyzikálnych vlastností reálnych objektov ako 3D kontúry, odraz svetla, tiene…&lt;br /&gt;
&lt;br /&gt;
Medzi inovácie, ktoré Material Design prináša patria nové komponenty ako napr. karty (Cards), plávajúce tlačidlo (Floating action button), oznámenia (Snackbars), animácie, prechody a iné. Najväčšou zmenou, ktorú Material Design priniesol je tzv. efekt hĺbky resp. používanie osi z. Jednotlivé komponenty sú zobrazované v pomyselných vrstvách v rôznych hladinách (radené nad sebou). Najdôležitejší komponent, s ktorým môže požívateľ aktuálne pracovať je zobrazený ponad ostatné komponenty (vo vyššej hladine osi z). Výhodou používateľských rozhraní, využívajúcich princíp radenia komponentov do vrstiev, je intuitívne prostredie, v ktorom sa používateľ ľahko zorientuje, s ktorými komponentmi môže aktuálne pracovať.&lt;br /&gt;
&lt;br /&gt;
=== Implementácia Material Design v aplikácii ===&lt;br /&gt;
&lt;br /&gt;
Pri implementácii používateľského rozhrania aplikácie boli odporúčania Material Design aplikované priamo v jednotlivých grafických rozhraniach Android aktivít a ich komponentoch. Tieto odporúčania (napr. odsadenie, vyvýšenie, farby, tlačidlá a tvary) presne definujú prípady použitia - kedy a ako môže byť daný komponent použitý, ako má vyzerať a ako sa má správať.&lt;br /&gt;
&lt;br /&gt;
Pri tvorbe grafických používateľských rozhraní a taktiež pre exaktný popis parametrov jednotlivých komponentov sú používané abstraktné jednotky - dp (density pixel). Jednotky dp sú prepočítavané k referenčnému rozlíšeniu v pixeloch: 1dp=1 pixel na obrazovke s rozlíšením 160dpi (bodov na palec).&lt;br /&gt;
&lt;br /&gt;
=== Material Design komponenty využité v aplikácii ===&lt;br /&gt;
&lt;br /&gt;
==== Cards ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' Cards (Karty) zobrazujú obsah a akcie súvisiace s jedným senzorom (). Každá karta senzora zobrazuje: názov senzora, tlačidlo pre akciu pridania/odstránenia do/zo zoznamu obľúbených senzorov, priemernú hodnotu, poslednú nameranú hodnotu a dátum kedy bola nameraná. Na karte senzora je taktiež vykresľovaný trend meraní daného senzora. Trend predstavuje smer rastu resp. poklesu nameraných hodnôt za poslednú hodinu.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Vyvýšenie karty od 1dp do 8dp, optimálne 2dp.&lt;br /&gt;
* Ak sú v karte použité oddeľovače obsahu, nemali by prechádzať cez celú kartu, ale len cez jej časť.&lt;br /&gt;
&lt;br /&gt;
[[File:card_sensor.png|thumb|none|510px|alt=Karta zobrazujúca údaje jedného senzora|Karta zobrazujúca údaje jedného senzora]]&lt;br /&gt;
&lt;br /&gt;
==== Floating Action Button ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' plávajúce tlačidlo (FAB) je používané na vyhľadávanie v aktivitách prehľadu (Dashboard, Favourites). Tlačidlo je štandardne viditeľné, avšak pri posunutí v zozname smerom dolu je skryté, z dôvodu úplnej viditeľnosti údajov poslednej karty zoznamu. Pri posunutí v zozname smerom hore sa stane tlačidlo znova viditeľné.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* FAB je zobrazené ponad všetok ostatný obsah, štandardne v pravom dolnom rohu.&lt;br /&gt;
* Optimálne rodičovské rozloženie - CoordinatorLayout (umožňuje automatické posunutie FAB smerom hore, napr. v prípade zobrazenia Snackbar oznámenia).&lt;br /&gt;
* Odporúčaná veľkosť je 56x56dp pre zariadenia s rozlíšením nad 460dp, pre zariadenia s nižším rozlíšením 46x46dp.&lt;br /&gt;
* Farba plávajúceho tlačidla je rovnaká ako hlavná farebná schéma aplikácie.&lt;br /&gt;
* Odsadenie od okraja obrazovky 16dp, vyvýšenie ponad ostatný obsah do 6dp.&lt;br /&gt;
&lt;br /&gt;
==== AppBar ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' horná nástrojová lišta sprostredkováva informácie a akcie súvisiace s aktuálnou obrazovkou. Zobrazuje názov aktuálnej obrazovky, rýchle akcie (napr. otvorenie zoznamu obľúbených) a kontextové menu.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Názov obrazovky je umiestnený na ľavej strane nástrojovej lišty.&lt;br /&gt;
* Kontextové akcie sú umiestnené na pravú stranu.&lt;br /&gt;
* Ak je použité kontextové menu, je umiestené úplne na pravej strane.&lt;br /&gt;
* Vyvýšenie nástrojovej lišty je štandardne 4dp.&lt;br /&gt;
&lt;br /&gt;
==== Snackbar ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' rýchle oznámenia ukotvené k spodnej časti obrazovky, ktoré informujú o aktuálnom dianí v aplikácii.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Optimálne rodičovské rozloženie - CoordinatorLayout.&lt;br /&gt;
* Snackbar má byť zobrazený len po určitú dobu, bez nutnosti explicitného zrušenia používateľom.&lt;br /&gt;
&lt;br /&gt;
[[File:snackbar.png|207px|Material Design komponenty použité v aplikácii: Snackbar (aktivita Login), AppBar, Card a FAB (aktivita Dashboard)]] [[File:card_app_bar_fab.png|207px|Material Design komponenty použité v aplikácii: Snackbar (aktivita Login), AppBar, Card a FAB (aktivita Dashboard)]]&lt;br /&gt;
&lt;br /&gt;
== Práca s dátami v aplikácii ==&lt;br /&gt;
&lt;br /&gt;
Dáta, s ktorými aplikácia pracuje sú sťahované zo vzdialených serverov a po stiahnutí sú ukladané do SQLite databázy, z ktorej sú sprostredkovávané v aplikácii. Sťahovanie najaktuálnejších meraní prebieha automaticky vždy po spustení resp. prihlásení do aplikácie. V prípade potreby manuálnej aktualizácie nameraných hodnôt, prípadne synchronizácie všetkých dát s aktuálne dostupnými dátami daného servera sú v aplikácii implementované dva rôzne spôsoby manuálnej synchronizácie: aktualizácia len nameraných hodnôt alebo synchronizácia všetkých dát.&lt;br /&gt;
&lt;br /&gt;
Pre zefektívnenie a zrýchlenie sťahovania nameraných hodnôt sa v aplikácii vytvárajú záznamy o dátumoch, za ktoré boli namerané hodnoty úspešne stiahnuté. Vždy pred každým ďalším sťahovaním nových meraní sú tieto záznamy prečítané a stiahnu sa len merania tých dátumov, ktoré nie sú evidované ako stiahnuté.&lt;br /&gt;
&lt;br /&gt;
Keďže aplikácia slúži na monitorovanie aktuálneho stavu a krátkodobejších trendov, maximálny rozsah zobrazenia nameraných hodnôt bol stanovený na jeden týždeň. Aby sa predišlo prílišnému zväčšeniu veľkosti aplikácie dôsledkom sťahovania množstva údajov, sú po každom stiahnutí najnovších nameraných hodnôt vymazané nepotrebné záznamy (merania) staršie ako jeden týždeň.&lt;br /&gt;
&lt;br /&gt;
=== Implementácia SQLite databázy ===&lt;br /&gt;
&lt;br /&gt;
SQLite databáza, ktorá slúži na archiváciu stiahnutých dát a ich následnú prezentáciu v aplikácii, bola vytvorená pomocou knižnice Room (viď [[#room|[room]]]), pričom je implementovaná tak, aby presne korešpondovala s dátovým modelom systému Sensorical (). Aplikácia je navrhnutá tak, že umožňuje vytvárať a pracovať s ľubovoľným počtom SQLite databáz, ktoré sú vytvárané na základe webovej adresy servera, ku ktorej je používateľ aktuálne prihlásený.&lt;br /&gt;
&lt;br /&gt;
Každý server, ku ktorému sa používateľ prihlási, má v aplikácii vytvorenú vlastnú SQLite databázu. Vždy po úspešnom prihlásení k niektorému zo serverov sa aplikácia pokúsi vytvoriť novú databázu s názvom webovej adresy daného servera. Ak už databáza s takýmto názvom existuje, aplikácia ju použije a otvorí.&lt;br /&gt;
&lt;br /&gt;
Pri samotnej implementácii SQLite databázy v aplikácii, boli ako prvé vytvorené jednotlivé triedy reprezentujúce entity databázy ([[#listing:entity|[listing:entity]]]). Každá trieda entity obsahuje premenné, ktoré predstavujú jednotlivé atribúty danej entity. Každá premenná triedy entity je prístupná prostredníctvom metód get a set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Entity(tableName = &amp;quot;area&amp;quot;)&lt;br /&gt;
    public class Area {&lt;br /&gt;
        @PrimaryKey&lt;br /&gt;
        private int id;&lt;br /&gt;
        private String name;&lt;br /&gt;
&lt;br /&gt;
        public void setId(int id) { this.id = id; }&lt;br /&gt;
        public int getId() { return id; }&lt;br /&gt;
        public String getName() { return name; }&lt;br /&gt;
        public void setName(String name) { this.name = name; }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako ďalšie boli vytvorené potrebné DAO rozhrania ([[#listing:dao|[listing:dao]]] rozhranie AreaDao) a ich metódy pre prístup k dátam databázy. Návratové typy týchto metód boli zvolené na základe očakávaného výsledku SQL dotazu, ktorý daná metóda vykonáva. V prípade DAO metód, ktoré slúžia na výber údajov z SQLite databázy, sú návratové typy zabalené do generickej triedy Maybe, knižnice RxJava, ktorá umožňuje vykonávať prácu týchto metód asynchrónne v paralelných vláknach.&lt;br /&gt;
&lt;br /&gt;
DAO metódy, ktoré do SQLite databázy vkladajú záznamy nameraných hodnôt, využívajú v prípade konfliktu hodnôt primárnych kľúčov parameter IGNORE (ignorovať). Parameter IGNORE zabezpečí neprepísanie existujúceho záznamu v SQLite databáze, pretože nameraná hodnota nemôže byť spätne modifikovaná a teda nie je nutné už existujúce záznamy prepisovať (skrátenie času vykonávania operácie).&lt;br /&gt;
&lt;br /&gt;
DAO metódy zabezpečujúce vkladanie ostatných údajov, majú v prípade konfliktu hodnôt primárnych kľúčov nastavený parameter REPLACE (nahradiť). V prípade modifikácie záznamu na strane servera sa síce nemení hodnota jeho primárneho kľúča, ale hodnota niektorého z atribútov je zmenená. Parameter REPLACE v takomto prípade zabezpečí prepísanie záznamu uloženého v SQLite databáze modifikovaným záznamom stiahnutým zo servera.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Dao&lt;br /&gt;
    public interface AreaDao {&lt;br /&gt;
        @Insert(onConflict = OnConflictStrategy.REPLACE)&lt;br /&gt;
        void insertAllAreas(List&amp;lt;Area&amp;gt; areas);&lt;br /&gt;
&lt;br /&gt;
        @Query(&amp;quot;select group_view.area_id from group_view&lt;br /&gt;
        where group_view.user_id=:userID&amp;quot;)&lt;br /&gt;
        Maybe&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; getAllAreaIDsforUser(int userID); &lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako posledná bola implementovaná abstraktná trieda databázy ([[#listing:database|[listing:database]]]), ktorá je potomkom triedy RoomDatabase. Trieda databázy v aplikácii využíva návrhový vzor Singleton, ktorý zabezpečí vytvorenie a dostupnosť jedinej inštancie triedy databázy počas behu aplikácie. Inštanciu triedy databázy je možné vytvoriť (získať) prostredníctvom statickej metódy getInstance().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Database(entities = {Area.class, Sensor.class}, version = 1)&lt;br /&gt;
    public abstract class AppDatabase extends RoomDatabase {&lt;br /&gt;
        public abstract AreaDao areaDao();&lt;br /&gt;
        private static AppDatabase INSTANCE;&lt;br /&gt;
        &lt;br /&gt;
        public static AppDatabase getInstance(final Context context){&lt;br /&gt;
            synchronized (AppDatabase.class) {&lt;br /&gt;
                if (INSTANCE == null){&lt;br /&gt;
                  INSTANCE = buildDatabase(context.getApplicationContext()); }&lt;br /&gt;
        } return INSTANCE; }&lt;br /&gt;
        &lt;br /&gt;
        private static AppDatabase buildDatabase(final Context context){&lt;br /&gt;
          String DATABASE_NAME = context&lt;br /&gt;
            .getSharedPreferences(&amp;quot;preferences&amp;quot;, Context.MODE_PRIVATE)&lt;br /&gt;
            .getString(&amp;quot;server_name&amp;quot;, &amp;quot;default_name&amp;quot;);&lt;br /&gt;
          return Room.databaseBuilder(&lt;br /&gt;
            context, AppDatabase.class, DATABASE_NAME).build(); }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
V triede databázy sú zadefinované všetky Java triedy jednotlivých entít, z ktorých SQLite databáza pozostáva a taktiež abstraktné metódy všetkých DAO rozhraní, prostredníctvom ktorých môžno vytvoriť inštancie rozhraní v iných triedach. V aplikácii je v triede databázy implementovaná metóda buildDatabase(), ktorá zisťuje názov aktuálneho webového servera (čítanie zo SharedPreferences - ukladanie menších dát formou kľúč - hodnota), ku ktorému je používateľ prihlásený a tento názov použije pre vytvorenie resp. otvorenie databázy s daným názvom, volaním metódy build().&lt;br /&gt;
&lt;br /&gt;
=== Práca s SQLite databázou ===&lt;br /&gt;
&lt;br /&gt;
Práca s SQLite databázou, konkrétne vykonávanie dotazov na výber údajov pre niektorú z aktivít prehľadu (Dashboard, Favourites, GraphView) je v aplikácii realizované sekvenčne. Najskôr sa vykoná referenčný výber, pričom všetky ostatné dotazy čakajú vo fronte. V momente, kedy sa aktuálny výber dokončí, začne sa vykonávať nasledujúci (čakajúci). Sekvenčný spôsob vykonávania práce je zvolený z dôvodu závislosti vstupných parametrov (podmienok pre vykonanie) čakajúceho dotazu, na výsledku jemu predchádzajúcemu výberu.&lt;br /&gt;
&lt;br /&gt;
Aby aplikácia zobrazila len ten obsah, na ktorý má prihlásený používateľ pridelené práva je využitý jedinečný identifikátor každého používateľa aplikácie - ID. Hodnota ID daného používateľa je využitá práve pri referenčnom výbere, na základe ktorého sú vybrané len tie vstupné parametre, na ktoré má používateľ definované oprávnenia.&lt;br /&gt;
&lt;br /&gt;
demonštruje postupnosť volania DAO metód, ktoré vyberajú z SQLite databázy údaje pre aktivitu Dashboard. Obdobným spôsobom sú riešené výbery pre ostatné dve aktivity prehľadov (Favourites a GraphView).&lt;br /&gt;
&lt;br /&gt;
[[File:load_data_for_dashboard_data_flow_final.png|thumb|none|529px|alt=Volanie DAO metód na výber dát z SQLite databázy pre aktivitu Dashboard|Volanie DAO metód na výber dát z SQLite databázy pre aktivitu Dashboard]]&lt;br /&gt;
&lt;br /&gt;
Referenčný výber pre aktivitu Dashboard je výber zoznamu ID všetkých oblastí na základe ID prihláseného používateľa. Následne sa sekvenčne vykonávajú ďalšie výbery, ktorých parametrami sú vždy výsledky predchádzajúceho výberu. V metóde createDashboardData() sa vytvára dátová štruktúra, ktorá obsahuje vlastnosti potrebné pre zobrazenie údajov v Dashboard aktivite: názvy oblastí, sektorov a senzorov, fyzikálne jednotky senzorov, namerané hodnoty a ďalšie. Naplnená dátová štruktúra je odoslaná triede adaptéra (viď [[#vizualizacia|1.3]]), ktorá tieto dáta vizualizuje.&lt;br /&gt;
&lt;br /&gt;
Vykonávanie výberov dát z SQLite databázy prostredníctvom DAO metód predstavuje časovo náročnejšie operácie, ktoré musia prebiehať asynchrónne, v paralelnom vlákne. Pre účel vykonávania DAO metód v paralelnom vlákne je v aplikácii využitá RxJava generická trieda Maybe. znázorňuje princíp návrhového vzoru Observer, ktorý je implementovaný knižnicou RxJava a ktorý je v aplikácii využívaný pre vykonávanie dotazov na výber dát z SQLite databázy použitím triedy Maybe. Tento návrhový vzor zabezpečuje sledovanie priebehu práce časovo náročných DAO metód vykonávaných v paralelných vláknach ([[#listing:rx_operators|[listing:rx_operators]]], metóda getAllAreaIDsForUser()). Po dokončení práce týchto metód dôjde k automatickej notifikácii vlákna špecifikovaného operátorom observeOn() ([[#listing:rx_operators|[listing:rx_operators]]] - hlavné vlákno), na ktoré sú publikované výsledky prostredníctvom rozhrania Consumer a jeho metódy accept(). Metóda accept() prijíma prostredníctvom parametra výsledky vykonaného SQL dotazu danej DAO metódy.&lt;br /&gt;
&lt;br /&gt;
[[File:dao_class_final.png|thumb|none|x188px|alt=Návrhový vzor Observer využitý na výber dát z SQLite databázy|Návrhový vzor Observer využitý na výber dát z SQLite databázy]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    areaDao.getAllAreaIDsForUser(userID)&lt;br /&gt;
        .subscribeOn(Schedulers.io())&lt;br /&gt;
            .observeOn(AndroidSchedulers.mainThread())&lt;br /&gt;
                .subscribe(new Consumer&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt;() {&lt;br /&gt;
                @Override&lt;br /&gt;
                 public void accept(List&amp;lt;Integer&amp;gt; areaIDs) { } &lt;br /&gt;
            });&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Komunikácia so vzdialeným serverom ===&lt;br /&gt;
&lt;br /&gt;
Pre komunikáciu aplikácie so serverovým API je využitý socketový dátový prenos. Požiadavky/odpovede sú odosielané/prijímané v textovom formáte JSON. Po prijatí odpovede sa prechádza tá časť odpovede, ktorá obsahuje relevantné dáta (hodnota kľúča JSON objektu “data”). Časť odpovede “data” a jej hodnoty sa prechádzajú a ukladajú do dátových štruktúr (triedy jednotlivých entít), ktoré sú po naplnení vložené do SQLite databázy.&lt;br /&gt;
&lt;br /&gt;
==== Vytvorenie, odoslanie a spracovanie požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Vytvorenie a odoslanie požiadavky na API a následné spracovanie odpovede zabezpečujú v aplikácii tri triedy (ClientSocket, ApiResponses, ApiDataPresenter), ktorých zjednodušenú štruktúru znázorňuje diagram tried na obrázku [[#fig:class_diagram|1.6]].&lt;br /&gt;
&lt;br /&gt;
* trieda '''ClientSocket''' (odoslanie požiadavky) - konvertuje požiadavku do formátu JSON, otvára spojenie so serverom, odosiela požiadavku, čaká na odpoveď a vracia ju späť metóde triedy ApiResponses, ktorá požiadavku vyvolala.&lt;br /&gt;
* trieda '''ApiResponses''' (vytvorenie požiadavky) - vytvára a posiela triede ClientSocket údaje potrebné pre odoslanie požiadavky prostredníctvom parameterov metódy sendRequest(). Trieda ApiResponses zároveň prijíma a vracia späť textovú odpoveď metóde triedy ApiDataPresenter, ktorá danú požiadavku vyvolala.&lt;br /&gt;
* trieda '''ApiDataPresenter''' (spracovanie odpovede) - inicializuje proces vytvárania požiadavky volaním príslušnej metódy triedy ApiResponses, transformuje prijatú odpoveď na JSON objekt, ktorého hodnoty ukladá do dátovej štruktúry.&lt;br /&gt;
&lt;br /&gt;
[[File:class_diagram.png|thumb|none|x205px|alt=Zjednodušený diagram tried zabezpečujúcich komunikáciu so serverovým API|Zjednodušený diagram tried zabezpečujúcich komunikáciu so serverovým API]]&lt;br /&gt;
&lt;br /&gt;
Proces komunikácie so vzdialeným serverom je časovo náročná operácia, ktorá musí byť vykonávaná asynchrónne, v paralelnom vlákne. V aplikácii je pre tento účel využitá RxJava trieda Completable. znázorňuje návrhový vzor Observer, ktorý je implementovaný knižnicou RxJava a ktorý je v aplikácii využívaný pre komunikáciu so serverovým API použitím triedy Completable. Podstata tohoto návrhového vzoru spočíva v tom, že po ukončení časovo náročnej metódy ([[#listing:completable|[listing:completable]]] riadok 3, metóda run()) dôjde k automatickej notifikácii vlákna špecifikovaného operátorom observeOn(). Notifikáciu špecifikovaného vlákna ([[#listing:completable|[listing:completable]]] - hlavné vlákno) zabezpečuje rozhranie CompletableObserver a jeho metóda onComplete(), ktorá je zavolaná, ak komunikácia so serverom a spracovanie odpovede prebehli v poriadku. Samotná komunikácia so serverom prebieha v tele metódy run() volaním metódy apiDataPresenter.getAreas(), ktorá vyvolá konkrétnu požiadavku.&lt;br /&gt;
&lt;br /&gt;
[[File:obrazky/completable_class_final.png|thumb|none|x188px|alt=Návrhový vzor Observer využitý na komunikáciu so serverovým API|Návrhový vzor Observer využitý na komunikáciu so serverovým API]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    Completable.fromRunnable(new Runnable() {&lt;br /&gt;
                @Override&lt;br /&gt;
                public void run() {&lt;br /&gt;
                areaDao.insertAllAreas(apiDataPresenter.getAreas());&lt;br /&gt;
                }&lt;br /&gt;
            }).subscribeOn(Schedulers.io())&lt;br /&gt;
                .observeOn(AndroidSchedulers.mainThread()&lt;br /&gt;
                    .subscribe(new CompletableObserver() {&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onSubscribe(Disposable d) { }&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onComplete() { }&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onError(Throwable e) { } });&amp;lt;/source&amp;gt;&lt;br /&gt;
Textový formát odpovede z API je vrátený do triedy ApiDataPresenter, v ktorej sa transformuje na JSON objekt ([[#listing:api_data_presenter|[listing:api_data_presenter]]], metóda parseAreaResponse()). V tejto metóde sa prechádza pole hodnôt s hodnotou kľúča “data”, pričom jednotlivé hodnoty tohto poľa sú opäť polia, ktorých hodnoty sa ukladajú do dátovej štruktúry, ktorá je vrátená späť do miesta volania ([[#listing:completable|[listing:completable]]], riadok 4). Spôsob vytvárania JSON objektu z prijatej odpovede, prechádzanie a ukladanie jeho hodnôt do dátovej štruktúry zobrazuje [[#listing:api_data_presenter|[listing:api_data_presenter]]]. Postupnosť prechodu medzi triedami a formát dát v jednotlivých triedach počas komunikácie s API znázorňuje .&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    public ArrayList&amp;lt;Area&amp;gt; getAreas() { &lt;br /&gt;
        parseAreaResponse(); &lt;br /&gt;
        return this.areaList; &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    private void parseAreaResponse() {&lt;br /&gt;
        String serverResponse = apiResponses.getAreaResponse();&lt;br /&gt;
        if (!serverResponse.isEmpty()) {&lt;br /&gt;
            JSONObject response = new JSONObject(serverResponse);&lt;br /&gt;
            JSONArray array = response.getJSONArray(&amp;quot;data&amp;quot;);&lt;br /&gt;
            for (int i = 0; i &amp;lt; array.length(); i++) {&lt;br /&gt;
                Area area = new Area();&lt;br /&gt;
                area.setId(array.getJSONArray(i).getInt(0));&lt;br /&gt;
                area.setName(array.getJSONArray(i).getString(1));&lt;br /&gt;
                this.areaList.add(area);&lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:api_call_diagram_final.png|thumb|none|585px|alt=Prenos a formát dát v jednotlivých triedach počas komunikácie s API|Prenos a formát dát v jednotlivých triedach počas komunikácie s API]]&lt;br /&gt;
&lt;br /&gt;
== Vizualizácia dát v aplikácii ==&lt;br /&gt;
&lt;br /&gt;
Prezentáciu dát v aktivitách prehľadu (Dashboard, Favourites) zabezpečujú komponenty - CardView, RecyclerView a Adaptér. V aktivite detailného prehľadu konkrétneho senzora (GraphView) sú dáta vizualizované prostredníctvom grafov - knižnica MPAndroidChart.&lt;br /&gt;
&lt;br /&gt;
=== Vizualizácia dát v aktivitách Dashboard a Favourites ===&lt;br /&gt;
&lt;br /&gt;
==== CardView ====&lt;br /&gt;
&lt;br /&gt;
CardView je grafická reprezentácia karty (Card [[#design|1.1.2]]), predstavuje rodičovské rozloženie pre všetky v nej obsiahnuté View prvky (textové polia, tlačidlá, obrázky…).&lt;br /&gt;
&lt;br /&gt;
==== RecyclerView ====&lt;br /&gt;
&lt;br /&gt;
RecylerView predstavuje model, ktorý umožňuje zobraziť väčšie množstvo údajov vo forme zoznamu. V aplikácii sú ako jednotlivé položky zobrazené v RecyclerView použité karty. Výhodou používania RecyclerView je jeho rýchlosť, pretože sa nevykresľujú (nevytvárajú) naraz všetky karty, ale vytvárajú sa len tie, ktoré sa aktuálne zmestia na obrazovku. Pre naplnenie RecyclerView kartami a ich následné zobrazenie sa využívajú návrhové vzory (triedy) ViewHolder a Adaptér. Jednotlivé karty zobrazené v RecyclerView sú reprezentované objektmi nazývanými view holders. Tieto objekty sú inštanciami tried, ktoré sú potomkami triedy RecyclerView.ViewHolder.&lt;br /&gt;
&lt;br /&gt;
==== ViewHolder ====&lt;br /&gt;
&lt;br /&gt;
ViewHolder je návrhový vzor, ktorý zabezpečuje vytvorenie objektu daného CardView rozloženia spolu s jej View prvkami. Takto vytvorený objekt môže byť použitý viacnásobne, bez nutnosti opakovanej inicializácie View prvkov tohto objektu, volaním metódy findViewById(), čo znižuje pamäťovú náročnosť a zároveň výrazne zrýchľuje proces listovania v RecyclerView. Vytvorené view holder objekty reprezentujú karty, ktoré sú zobrazené v RecyclerView. Tento návrhový vzor možno použiť vytvorením vnútornej triedy, potomok triedy RecyclerView.ViewHolder, v triede adaptéra.&lt;br /&gt;
&lt;br /&gt;
==== Adaptér ====&lt;br /&gt;
&lt;br /&gt;
Adaptér je návrhový vzor, ktorý funguje ako most medzi používateľským rozhraním a dátami. V Androide predstavuje adaptér triedu, ktorá sprostredkováva dáta RecyclerView. Trieda adaptéra (potomok triedy RecyclerView.Adapter) zabezpečuje správu jednotlivých view holder objektov prostredníctvom preťažených metód rodičovskej triedy: vytvorenie view holder objektov - metóda onCreateViewHolder, pridávanie vytvorených view holder objektov do RecyclerView - metóda onBindViewHolder().&lt;br /&gt;
&lt;br /&gt;
V aplikácii sú vytvorené dve triedy adaptérov, kde každá z nich sprostredkováva dáta konkrétnej aktivite: DashboardAdapter (Dashboard aktivita), FavouritesAdapter (Favourites aktivita). Triedy adaptérov v aplikácii využívajú návrhový vzor Singleton, pričom vytvorenie (získanie) inštancie triedy oboch adaptérov je možné prostredníctvom statickej metódy getInstance(). Spôsob implementácie triedy adaptéra v aplikácii je demonštrovaný na jednoduchšej triede FavouritesAdapter, ktorá vykresľuje len jeden typ view holder objektu (len karta senzora, vľavo). Trieda DashboardAdapter vykresľuje tri typy view holder objektov, kde každý z nich reprezentuje kartu: oblasti, sektoru, alebo senzora ( vpravo).&lt;br /&gt;
&lt;br /&gt;
Vytvorenie inštancie triedy FavouritesAdapter a následné nastavenie tejto inštancie ako adaptér objektu recylerView demonštruje kód [[#listing:adapter|[listing:adapter]]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    RecyclerView recyclerView = findViewById(R.id.recycler_view);&lt;br /&gt;
    FavouritesAdapter adapter = FavouritesAdapter.getInstance();&lt;br /&gt;
    recyclerView.setAdapter(adapter);&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:favourites.png|x264px|RecyclerView - aktivita Dashboard (vpravo), aktivita Favourites (vľavo)]] [[File:recycler_view_dashboard_edit.png|x264px|RecyclerView - aktivita Dashboard (vpravo), aktivita Favourites (vľavo)]]&lt;br /&gt;
&lt;br /&gt;
Nasledujúca ukážka ([[#listing:viewHolder|[listing:viewHolder]]]) zobrazuje implementáciu návrhového vzoru ViewHolder v triede adaptéra (FavouritesAdapter), vytvorením vnútornej triedy DataViewHolder. Trieda DataViewHolder inicializuje jednotlivé View prvky CardView rozloženia karty senzora. Každý vytvorený objekt tejto triedy reprezentuje jednu kartu v RecyclerView.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    public static class DataViewHolder extends RecyclerView.ViewHolder {&lt;br /&gt;
        private TextView textViewSensorName;&lt;br /&gt;
        // iné View prvky CardView rozloženia karty senzora...&lt;br /&gt;
        public DataViewHolder(@NonNull final View itemView) {&lt;br /&gt;
          super(itemView);&lt;br /&gt;
          textViewSensorName = &lt;br /&gt;
          itemView.findViewById(R.id.text_view_sensor_name);&lt;br /&gt;
        }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Metóda triedy adaptéra - onCreateViewHolder() ([[#listing:onCreate|[listing:onCreate]]]) slúži pre dynamické vytváranie view holder objektov. Táto metóda vytvára len taký počet view holder objektov (kariet), koľko sa aktuálne zmestí na obrazovku. Pri listovaní v RecyclerView sú dynamicky vytvárané ďalšie potrebné objekty, pričom nahrádzajú tie, ktoré už na obrazovke nie sú vidieť (recycling).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @NonNull&lt;br /&gt;
    @override&lt;br /&gt;
    public RecyclerView.ViewHolder onCreateViewHolder(&lt;br /&gt;
    @NonNull ViewGroup viewGroup, int i) {&lt;br /&gt;
                View v;&lt;br /&gt;
                LayoutInflater mInflater = &lt;br /&gt;
                LayoutInflater.from(viewGroup.getContext());&lt;br /&gt;
                v = mInflater.inflate(&lt;br /&gt;
                R.layout.card_view_sensor, viewGroup, false);&lt;br /&gt;
                return new FavouritesAdapter.DataViewHolder(v); }&amp;lt;/source&amp;gt;&lt;br /&gt;
Samotné pridanie vytvoreného view holder objektu do RecyclerView zabezpečuje metóda - onBindViewHolder() ([[#listing:onBind|[listing:onBind]]]). Každý view holder objekt v RecyclerView má definovanú pozíciu, na ktorej sa nachádza. Hodnotu aktuálnej pozície, na ktorú má byť ďalší view holder objekt pridaný/vykreslený prijíma metóda onBindViewHolder() prostredníctvom parametra. Na základe pozície je možné naviazať konkrétny view holder objekt na dáta.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @override&lt;br /&gt;
    public void onBindViewHolder(&lt;br /&gt;
    @NonNull RecyclerView.ViewHolder viewHolder, int position) {&lt;br /&gt;
        ((DataViewHolder) viewHolder).&lt;br /&gt;
        textViewSensorName.setText(&lt;br /&gt;
        filteredList.get(position).getSensorName()); }&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Vizualizácia dát v aktivite GraphView ===&lt;br /&gt;
&lt;br /&gt;
Prezentáciu dát v aktivite GraphView zabezpečujú grafy, vytvárané pomocou knižnice MPAndroidChart. Táto knižnica umožňuje vytvárať rôzne typy grafov: koláčové, stĺpcové, čiarové a iné. V aplikácii je využitý čiarový graf - LineChart. V aplikácii sú v grafe vykresľované dva typy čiar: LimitLine - horizontálna čiara pre zobrazenie priemernej hodnoty a samotná čiara grafu LineChart pre vykreslenie priebehu meraných hodnôt. Hodnoty osi x sú reprezentované časovými značkami jednotlivých meraní, ktoré sú explicitne konvertované na textový formát dátumu, ktorý je v grafe zobrazený ako legenda osi x. Hodnoty osi y sú reprezentované nameranými hodnotami. Jednotlivé body grafu sú vytvárané ako usporiadaná dvojica [časová značka, hodnota] ([[#listing:graph_creation|[listing:graph_creation]]] trieda Entry). Tieto usporiadané dvojice hodnôt sú postupne pridávané do poľa ([[#listing:graph_creation|[listing:graph_creation]]] objekt xyValues), ktoré je po naplnení priradené vytváranému objektu triedy LineDataSet v jej konštruktore. Metódy triedy LineDataSet umožňujú nastaviť požadované parametre čiary grafu (hrúbka, farba a iné). Objekt triedy LineDataSet je nakoniec priradený samotnému objektu grafu inicializovaného prostredníctvom metódy findViewById(). V aplikácii je v grafoch implementovaná možnosť zoomovania a taktiež možnosť zobrazenia hodnoty konkrétneho bodu pri kliknutí na ľubovoľnú hodnotu v grafe ( vpravo).&lt;br /&gt;
&lt;br /&gt;
[[File:graph_view.png|151px|Vykresľovanie priebehu nameraných hodnôt v aktivite GraphView]] [[File:graph_view_land.png|264px|Vykresľovanie priebehu nameraných hodnôt v aktivite GraphView]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    ArrayList&amp;lt;Entry&amp;gt; xyValues = new ArrayList&amp;lt;&amp;gt;();&lt;br /&gt;
        for (int i = 0; i &amp;lt; values.size; i++) {&lt;br /&gt;
            Entry xy = new Entry(values.get(i).getDate().getTime(),&lt;br /&gt;
                values.getValue());&lt;br /&gt;
            xyValues.add(xy);&lt;br /&gt;
        }&lt;br /&gt;
    LineDataSet dataSet = new LineDataSet(xyValues, &amp;quot;hodnoty&amp;quot;);&lt;br /&gt;
    dataSet.setLineWidth(2f);&lt;br /&gt;
    // iné nastavenia vlastností dataSetu... &lt;br /&gt;
    LineData lineData = new LineData(dataSet);&lt;br /&gt;
    LineChart chart = findViewById(R.id.chart);&lt;br /&gt;
    chart.setData(lineData);&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Card_sensor.png&amp;diff=12790</id>
		<title>Súbor:Card sensor.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Card_sensor.png&amp;diff=12790"/>
		<updated>2020-09-03T20:27:31Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Implement%C3%A1cia_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12789</id>
		<title>Implementácia aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Implement%C3%A1cia_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12789"/>
		<updated>2020-09-03T20:27:09Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|4|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
Implementácia používateľského rozhrania a jednotlivých funkcionalít aplikácie vychádza zo špecifikácie požiadaviek a navrhnutej štruktúry aplikácie v kapitole [[#navrh|[navrh]]]. V tejto kapitole sú postupne opísané: implementácia používateľského rozhrania aplikácie, práca s dátami, komunikácia so serverom a samotná vizualizácia dát v aplikácii.&lt;br /&gt;
&lt;br /&gt;
== Používateľské rozhranie aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Jednotlivé obrazovky tvoriace používateľské rozhranie aplikácie, prostredníctvom ktorých používateľ s aplikáciou interaguje, sú implementované podľa navrhnutej štruktúry aplikácie (časť [[#navrh_aktivity|[navrh_aktivity]]]) ako jednotlivé triedy Android aktivít. Tieto Android aktivity rozdeľujú aplikáciu na dve časti: primárnu a sekundárnu.&lt;br /&gt;
&lt;br /&gt;
Aktivity primárnej časti poskytujú používateľovi priamy prístup k prehľadu aktuálneho stavu meracieho systému Sensorical. Aktivity sekundárnej časti predstavujú pomocné aktivity, ktoré sú však nevyhnutné pre prístup do primárnej časti, tj. nutnosť výberu adresy servera, ku ktorému sa chce používateľ pripojiť, ako aj samotné prihlásenie do aplikácie. '''Android aktivity primárnej časti'''&lt;br /&gt;
&lt;br /&gt;
* Dashboard - aktivita, ktorá sprostredkováva prehľad všetkých aktuálne dostupných senzorov a ich údajov, kategorizovaných v rámci oblastí a sektorov&lt;br /&gt;
* Favourites - aktivita, ktorá zobrazuje prehľad vybraných, obľúbených senzorov a ich údaje&lt;br /&gt;
* GraphView - aktivita ktorá zobrazuje detailný prehľad konkrétneho senzora, históriu nameraných hodnôt (grafy a štatistiky)&lt;br /&gt;
&lt;br /&gt;
'''Android aktivity sekundárnej časti'''&lt;br /&gt;
&lt;br /&gt;
* ServerSelect - aktivita pre výber adresy servera&lt;br /&gt;
* Login - aktivita pre prihlásenie do aplikácie&lt;br /&gt;
* About - aktivita zobrazujúca doplňujúce informácie o aplikácií&lt;br /&gt;
&lt;br /&gt;
=== Android a Material Design ===&lt;br /&gt;
&lt;br /&gt;
Material Design predstavuje dizajnérsky jazyk vyvinutý spoločnosťou Google v roku 2014, ktorý priniesol množstvo inovácií a zmien do spôsobu tvorby grafických používateľských rozhraní. Filozofia konceptu Material Design vychádza z fyzikálnych vlastností reálnych objektov ako 3D kontúry, odraz svetla, tiene…&lt;br /&gt;
&lt;br /&gt;
Medzi inovácie, ktoré Material Design prináša patria nové komponenty ako napr. karty (Cards), plávajúce tlačidlo (Floating action button), oznámenia (Snackbars), animácie, prechody a iné. Najväčšou zmenou, ktorú Material Design priniesol je tzv. efekt hĺbky resp. používanie osi z. Jednotlivé komponenty sú zobrazované v pomyselných vrstvách v rôznych hladinách (radené nad sebou). Najdôležitejší komponent, s ktorým môže požívateľ aktuálne pracovať je zobrazený ponad ostatné komponenty (vo vyššej hladine osi z). Výhodou používateľských rozhraní, využívajúcich princíp radenia komponentov do vrstiev, je intuitívne prostredie, v ktorom sa používateľ ľahko zorientuje, s ktorými komponentmi môže aktuálne pracovať.&lt;br /&gt;
&lt;br /&gt;
=== Implementácia Material Design v aplikácii ===&lt;br /&gt;
&lt;br /&gt;
Pri implementácii používateľského rozhrania aplikácie boli odporúčania Material Design aplikované priamo v jednotlivých grafických rozhraniach Android aktivít a ich komponentoch. Tieto odporúčania (napr. odsadenie, vyvýšenie, farby, tlačidlá a tvary) presne definujú prípady použitia - kedy a ako môže byť daný komponent použitý, ako má vyzerať a ako sa má správať.&lt;br /&gt;
&lt;br /&gt;
Pri tvorbe grafických používateľských rozhraní a taktiež pre exaktný popis parametrov jednotlivých komponentov sú používané abstraktné jednotky - dp (density pixel). Jednotky dp sú prepočítavané k referenčnému rozlíšeniu v pixeloch: 1dp=1 pixel na obrazovke s rozlíšením 160dpi (bodov na palec).&lt;br /&gt;
&lt;br /&gt;
=== Material Design komponenty využité v aplikácii ===&lt;br /&gt;
&lt;br /&gt;
==== Cards ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' Cards (Karty) zobrazujú obsah a akcie súvisiace s jedným senzorom (). Každá karta senzora zobrazuje: názov senzora, tlačidlo pre akciu pridania/odstránenia do/zo zoznamu obľúbených senzorov, priemernú hodnotu, poslednú nameranú hodnotu a dátum kedy bola nameraná. Na karte senzora je taktiež vykresľovaný trend meraní daného senzora. Trend predstavuje smer rastu resp. poklesu nameraných hodnôt za poslednú hodinu.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Vyvýšenie karty od 1dp do 8dp, optimálne 2dp.&lt;br /&gt;
* Ak sú v karte použité oddeľovače obsahu, nemali by prechádzať cez celú kartu, ale len cez jej časť.&lt;br /&gt;
&lt;br /&gt;
[[File:card_sensor.png|thumb|none|510px|alt=Karta zobrazujúca údaje jedného senzora|Karta zobrazujúca údaje jedného senzora]]&lt;br /&gt;
&lt;br /&gt;
==== Floating Action Button ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' plávajúce tlačidlo (FAB) je používané na vyhľadávanie v aktivitách prehľadu (Dashboard, Favourites). Tlačidlo je štandardne viditeľné, avšak pri posunutí v zozname smerom dolu je skryté, z dôvodu úplnej viditeľnosti údajov poslednej karty zoznamu. Pri posunutí v zozname smerom hore sa stane tlačidlo znova viditeľné.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* FAB je zobrazené ponad všetok ostatný obsah, štandardne v pravom dolnom rohu.&lt;br /&gt;
* Optimálne rodičovské rozloženie - CoordinatorLayout (umožňuje automatické posunutie FAB smerom hore, napr. v prípade zobrazenia Snackbar oznámenia).&lt;br /&gt;
* Odporúčaná veľkosť je 56x56dp pre zariadenia s rozlíšením nad 460dp, pre zariadenia s nižším rozlíšením 46x46dp.&lt;br /&gt;
* Farba plávajúceho tlačidla je rovnaká ako hlavná farebná schéma aplikácie.&lt;br /&gt;
* Odsadenie od okraja obrazovky 16dp, vyvýšenie ponad ostatný obsah do 6dp.&lt;br /&gt;
&lt;br /&gt;
==== AppBar ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' horná nástrojová lišta sprostredkováva informácie a akcie súvisiace s aktuálnou obrazovkou. Zobrazuje názov aktuálnej obrazovky, rýchle akcie (napr. otvorenie zoznamu obľúbených) a kontextové menu.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Názov obrazovky je umiestnený na ľavej strane nástrojovej lišty.&lt;br /&gt;
* Kontextové akcie sú umiestnené na pravú stranu.&lt;br /&gt;
* Ak je použité kontextové menu, je umiestené úplne na pravej strane.&lt;br /&gt;
* Vyvýšenie nástrojovej lišty je štandardne 4dp.&lt;br /&gt;
&lt;br /&gt;
==== Snackbar ====&lt;br /&gt;
&lt;br /&gt;
'''Funkcia:''' rýchle oznámenia ukotvené k spodnej časti obrazovky, ktoré informujú o aktuálnom dianí v aplikácii.&lt;br /&gt;
&lt;br /&gt;
'''Material Design odporúčania:'''&lt;br /&gt;
&lt;br /&gt;
* Optimálne rodičovské rozloženie - CoordinatorLayout.&lt;br /&gt;
* Snackbar má byť zobrazený len po určitú dobu, bez nutnosti explicitného zrušenia používateľom.&lt;br /&gt;
&lt;br /&gt;
[[File:snackbar.png|207px|Material Design komponenty použité v aplikácii: Snackbar (aktivita Login), AppBar, Card a FAB (aktivita Dashboard)]] [[File:obrazky/card_app_bar_fab.png|207px|Material Design komponenty použité v aplikácii: Snackbar (aktivita Login), AppBar, Card a FAB (aktivita Dashboard)]]&lt;br /&gt;
&lt;br /&gt;
== Práca s dátami v aplikácii ==&lt;br /&gt;
&lt;br /&gt;
Dáta, s ktorými aplikácia pracuje sú sťahované zo vzdialených serverov a po stiahnutí sú ukladané do SQLite databázy, z ktorej sú sprostredkovávané v aplikácii. Sťahovanie najaktuálnejších meraní prebieha automaticky vždy po spustení resp. prihlásení do aplikácie. V prípade potreby manuálnej aktualizácie nameraných hodnôt, prípadne synchronizácie všetkých dát s aktuálne dostupnými dátami daného servera sú v aplikácii implementované dva rôzne spôsoby manuálnej synchronizácie: aktualizácia len nameraných hodnôt alebo synchronizácia všetkých dát.&lt;br /&gt;
&lt;br /&gt;
Pre zefektívnenie a zrýchlenie sťahovania nameraných hodnôt sa v aplikácii vytvárajú záznamy o dátumoch, za ktoré boli namerané hodnoty úspešne stiahnuté. Vždy pred každým ďalším sťahovaním nových meraní sú tieto záznamy prečítané a stiahnu sa len merania tých dátumov, ktoré nie sú evidované ako stiahnuté.&lt;br /&gt;
&lt;br /&gt;
Keďže aplikácia slúži na monitorovanie aktuálneho stavu a krátkodobejších trendov, maximálny rozsah zobrazenia nameraných hodnôt bol stanovený na jeden týždeň. Aby sa predišlo prílišnému zväčšeniu veľkosti aplikácie dôsledkom sťahovania množstva údajov, sú po každom stiahnutí najnovších nameraných hodnôt vymazané nepotrebné záznamy (merania) staršie ako jeden týždeň.&lt;br /&gt;
&lt;br /&gt;
=== Implementácia SQLite databázy ===&lt;br /&gt;
&lt;br /&gt;
SQLite databáza, ktorá slúži na archiváciu stiahnutých dát a ich následnú prezentáciu v aplikácii, bola vytvorená pomocou knižnice Room (viď [[#room|[room]]]), pričom je implementovaná tak, aby presne korešpondovala s dátovým modelom systému Sensorical (). Aplikácia je navrhnutá tak, že umožňuje vytvárať a pracovať s ľubovoľným počtom SQLite databáz, ktoré sú vytvárané na základe webovej adresy servera, ku ktorej je používateľ aktuálne prihlásený.&lt;br /&gt;
&lt;br /&gt;
Každý server, ku ktorému sa používateľ prihlási, má v aplikácii vytvorenú vlastnú SQLite databázu. Vždy po úspešnom prihlásení k niektorému zo serverov sa aplikácia pokúsi vytvoriť novú databázu s názvom webovej adresy daného servera. Ak už databáza s takýmto názvom existuje, aplikácia ju použije a otvorí.&lt;br /&gt;
&lt;br /&gt;
Pri samotnej implementácii SQLite databázy v aplikácii, boli ako prvé vytvorené jednotlivé triedy reprezentujúce entity databázy ([[#listing:entity|[listing:entity]]]). Každá trieda entity obsahuje premenné, ktoré predstavujú jednotlivé atribúty danej entity. Každá premenná triedy entity je prístupná prostredníctvom metód get a set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Entity(tableName = &amp;quot;area&amp;quot;)&lt;br /&gt;
    public class Area {&lt;br /&gt;
        @PrimaryKey&lt;br /&gt;
        private int id;&lt;br /&gt;
        private String name;&lt;br /&gt;
&lt;br /&gt;
        public void setId(int id) { this.id = id; }&lt;br /&gt;
        public int getId() { return id; }&lt;br /&gt;
        public String getName() { return name; }&lt;br /&gt;
        public void setName(String name) { this.name = name; }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako ďalšie boli vytvorené potrebné DAO rozhrania ([[#listing:dao|[listing:dao]]] rozhranie AreaDao) a ich metódy pre prístup k dátam databázy. Návratové typy týchto metód boli zvolené na základe očakávaného výsledku SQL dotazu, ktorý daná metóda vykonáva. V prípade DAO metód, ktoré slúžia na výber údajov z SQLite databázy, sú návratové typy zabalené do generickej triedy Maybe, knižnice RxJava, ktorá umožňuje vykonávať prácu týchto metód asynchrónne v paralelných vláknach.&lt;br /&gt;
&lt;br /&gt;
DAO metódy, ktoré do SQLite databázy vkladajú záznamy nameraných hodnôt, využívajú v prípade konfliktu hodnôt primárnych kľúčov parameter IGNORE (ignorovať). Parameter IGNORE zabezpečí neprepísanie existujúceho záznamu v SQLite databáze, pretože nameraná hodnota nemôže byť spätne modifikovaná a teda nie je nutné už existujúce záznamy prepisovať (skrátenie času vykonávania operácie).&lt;br /&gt;
&lt;br /&gt;
DAO metódy zabezpečujúce vkladanie ostatných údajov, majú v prípade konfliktu hodnôt primárnych kľúčov nastavený parameter REPLACE (nahradiť). V prípade modifikácie záznamu na strane servera sa síce nemení hodnota jeho primárneho kľúča, ale hodnota niektorého z atribútov je zmenená. Parameter REPLACE v takomto prípade zabezpečí prepísanie záznamu uloženého v SQLite databáze modifikovaným záznamom stiahnutým zo servera.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Dao&lt;br /&gt;
    public interface AreaDao {&lt;br /&gt;
        @Insert(onConflict = OnConflictStrategy.REPLACE)&lt;br /&gt;
        void insertAllAreas(List&amp;lt;Area&amp;gt; areas);&lt;br /&gt;
&lt;br /&gt;
        @Query(&amp;quot;select group_view.area_id from group_view&lt;br /&gt;
        where group_view.user_id=:userID&amp;quot;)&lt;br /&gt;
        Maybe&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; getAllAreaIDsforUser(int userID); &lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako posledná bola implementovaná abstraktná trieda databázy ([[#listing:database|[listing:database]]]), ktorá je potomkom triedy RoomDatabase. Trieda databázy v aplikácii využíva návrhový vzor Singleton, ktorý zabezpečí vytvorenie a dostupnosť jedinej inštancie triedy databázy počas behu aplikácie. Inštanciu triedy databázy je možné vytvoriť (získať) prostredníctvom statickej metódy getInstance().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @Database(entities = {Area.class, Sensor.class}, version = 1)&lt;br /&gt;
    public abstract class AppDatabase extends RoomDatabase {&lt;br /&gt;
        public abstract AreaDao areaDao();&lt;br /&gt;
        private static AppDatabase INSTANCE;&lt;br /&gt;
        &lt;br /&gt;
        public static AppDatabase getInstance(final Context context){&lt;br /&gt;
            synchronized (AppDatabase.class) {&lt;br /&gt;
                if (INSTANCE == null){&lt;br /&gt;
                  INSTANCE = buildDatabase(context.getApplicationContext()); }&lt;br /&gt;
        } return INSTANCE; }&lt;br /&gt;
        &lt;br /&gt;
        private static AppDatabase buildDatabase(final Context context){&lt;br /&gt;
          String DATABASE_NAME = context&lt;br /&gt;
            .getSharedPreferences(&amp;quot;preferences&amp;quot;, Context.MODE_PRIVATE)&lt;br /&gt;
            .getString(&amp;quot;server_name&amp;quot;, &amp;quot;default_name&amp;quot;);&lt;br /&gt;
          return Room.databaseBuilder(&lt;br /&gt;
            context, AppDatabase.class, DATABASE_NAME).build(); }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
V triede databázy sú zadefinované všetky Java triedy jednotlivých entít, z ktorých SQLite databáza pozostáva a taktiež abstraktné metódy všetkých DAO rozhraní, prostredníctvom ktorých môžno vytvoriť inštancie rozhraní v iných triedach. V aplikácii je v triede databázy implementovaná metóda buildDatabase(), ktorá zisťuje názov aktuálneho webového servera (čítanie zo SharedPreferences - ukladanie menších dát formou kľúč - hodnota), ku ktorému je používateľ prihlásený a tento názov použije pre vytvorenie resp. otvorenie databázy s daným názvom, volaním metódy build().&lt;br /&gt;
&lt;br /&gt;
=== Práca s SQLite databázou ===&lt;br /&gt;
&lt;br /&gt;
Práca s SQLite databázou, konkrétne vykonávanie dotazov na výber údajov pre niektorú z aktivít prehľadu (Dashboard, Favourites, GraphView) je v aplikácii realizované sekvenčne. Najskôr sa vykoná referenčný výber, pričom všetky ostatné dotazy čakajú vo fronte. V momente, kedy sa aktuálny výber dokončí, začne sa vykonávať nasledujúci (čakajúci). Sekvenčný spôsob vykonávania práce je zvolený z dôvodu závislosti vstupných parametrov (podmienok pre vykonanie) čakajúceho dotazu, na výsledku jemu predchádzajúcemu výberu.&lt;br /&gt;
&lt;br /&gt;
Aby aplikácia zobrazila len ten obsah, na ktorý má prihlásený používateľ pridelené práva je využitý jedinečný identifikátor každého používateľa aplikácie - ID. Hodnota ID daného používateľa je využitá práve pri referenčnom výbere, na základe ktorého sú vybrané len tie vstupné parametre, na ktoré má používateľ definované oprávnenia.&lt;br /&gt;
&lt;br /&gt;
demonštruje postupnosť volania DAO metód, ktoré vyberajú z SQLite databázy údaje pre aktivitu Dashboard. Obdobným spôsobom sú riešené výbery pre ostatné dve aktivity prehľadov (Favourites a GraphView).&lt;br /&gt;
&lt;br /&gt;
[[File:load_data_for_dashboard_data_flow_final.png|thumb|none|529px|alt=Volanie DAO metód na výber dát z SQLite databázy pre aktivitu Dashboard|Volanie DAO metód na výber dát z SQLite databázy pre aktivitu Dashboard]]&lt;br /&gt;
&lt;br /&gt;
Referenčný výber pre aktivitu Dashboard je výber zoznamu ID všetkých oblastí na základe ID prihláseného používateľa. Následne sa sekvenčne vykonávajú ďalšie výbery, ktorých parametrami sú vždy výsledky predchádzajúceho výberu. V metóde createDashboardData() sa vytvára dátová štruktúra, ktorá obsahuje vlastnosti potrebné pre zobrazenie údajov v Dashboard aktivite: názvy oblastí, sektorov a senzorov, fyzikálne jednotky senzorov, namerané hodnoty a ďalšie. Naplnená dátová štruktúra je odoslaná triede adaptéra (viď [[#vizualizacia|1.3]]), ktorá tieto dáta vizualizuje.&lt;br /&gt;
&lt;br /&gt;
Vykonávanie výberov dát z SQLite databázy prostredníctvom DAO metód predstavuje časovo náročnejšie operácie, ktoré musia prebiehať asynchrónne, v paralelnom vlákne. Pre účel vykonávania DAO metód v paralelnom vlákne je v aplikácii využitá RxJava generická trieda Maybe. znázorňuje princíp návrhového vzoru Observer, ktorý je implementovaný knižnicou RxJava a ktorý je v aplikácii využívaný pre vykonávanie dotazov na výber dát z SQLite databázy použitím triedy Maybe. Tento návrhový vzor zabezpečuje sledovanie priebehu práce časovo náročných DAO metód vykonávaných v paralelných vláknach ([[#listing:rx_operators|[listing:rx_operators]]], metóda getAllAreaIDsForUser()). Po dokončení práce týchto metód dôjde k automatickej notifikácii vlákna špecifikovaného operátorom observeOn() ([[#listing:rx_operators|[listing:rx_operators]]] - hlavné vlákno), na ktoré sú publikované výsledky prostredníctvom rozhrania Consumer a jeho metódy accept(). Metóda accept() prijíma prostredníctvom parametra výsledky vykonaného SQL dotazu danej DAO metódy.&lt;br /&gt;
&lt;br /&gt;
[[File:dao_class_final.png|thumb|none|x188px|alt=Návrhový vzor Observer využitý na výber dát z SQLite databázy|Návrhový vzor Observer využitý na výber dát z SQLite databázy]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    areaDao.getAllAreaIDsForUser(userID)&lt;br /&gt;
        .subscribeOn(Schedulers.io())&lt;br /&gt;
            .observeOn(AndroidSchedulers.mainThread())&lt;br /&gt;
                .subscribe(new Consumer&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt;() {&lt;br /&gt;
                @Override&lt;br /&gt;
                 public void accept(List&amp;lt;Integer&amp;gt; areaIDs) { } &lt;br /&gt;
            });&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Komunikácia so vzdialeným serverom ===&lt;br /&gt;
&lt;br /&gt;
Pre komunikáciu aplikácie so serverovým API je využitý socketový dátový prenos. Požiadavky/odpovede sú odosielané/prijímané v textovom formáte JSON. Po prijatí odpovede sa prechádza tá časť odpovede, ktorá obsahuje relevantné dáta (hodnota kľúča JSON objektu “data”). Časť odpovede “data” a jej hodnoty sa prechádzajú a ukladajú do dátových štruktúr (triedy jednotlivých entít), ktoré sú po naplnení vložené do SQLite databázy.&lt;br /&gt;
&lt;br /&gt;
==== Vytvorenie, odoslanie a spracovanie požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Vytvorenie a odoslanie požiadavky na API a následné spracovanie odpovede zabezpečujú v aplikácii tri triedy (ClientSocket, ApiResponses, ApiDataPresenter), ktorých zjednodušenú štruktúru znázorňuje diagram tried na obrázku [[#fig:class_diagram|1.6]].&lt;br /&gt;
&lt;br /&gt;
* trieda '''ClientSocket''' (odoslanie požiadavky) - konvertuje požiadavku do formátu JSON, otvára spojenie so serverom, odosiela požiadavku, čaká na odpoveď a vracia ju späť metóde triedy ApiResponses, ktorá požiadavku vyvolala.&lt;br /&gt;
* trieda '''ApiResponses''' (vytvorenie požiadavky) - vytvára a posiela triede ClientSocket údaje potrebné pre odoslanie požiadavky prostredníctvom parameterov metódy sendRequest(). Trieda ApiResponses zároveň prijíma a vracia späť textovú odpoveď metóde triedy ApiDataPresenter, ktorá danú požiadavku vyvolala.&lt;br /&gt;
* trieda '''ApiDataPresenter''' (spracovanie odpovede) - inicializuje proces vytvárania požiadavky volaním príslušnej metódy triedy ApiResponses, transformuje prijatú odpoveď na JSON objekt, ktorého hodnoty ukladá do dátovej štruktúry.&lt;br /&gt;
&lt;br /&gt;
[[File:class_diagram.png|thumb|none|x205px|alt=Zjednodušený diagram tried zabezpečujúcich komunikáciu so serverovým API|Zjednodušený diagram tried zabezpečujúcich komunikáciu so serverovým API]]&lt;br /&gt;
&lt;br /&gt;
Proces komunikácie so vzdialeným serverom je časovo náročná operácia, ktorá musí byť vykonávaná asynchrónne, v paralelnom vlákne. V aplikácii je pre tento účel využitá RxJava trieda Completable. znázorňuje návrhový vzor Observer, ktorý je implementovaný knižnicou RxJava a ktorý je v aplikácii využívaný pre komunikáciu so serverovým API použitím triedy Completable. Podstata tohoto návrhového vzoru spočíva v tom, že po ukončení časovo náročnej metódy ([[#listing:completable|[listing:completable]]] riadok 3, metóda run()) dôjde k automatickej notifikácii vlákna špecifikovaného operátorom observeOn(). Notifikáciu špecifikovaného vlákna ([[#listing:completable|[listing:completable]]] - hlavné vlákno) zabezpečuje rozhranie CompletableObserver a jeho metóda onComplete(), ktorá je zavolaná, ak komunikácia so serverom a spracovanie odpovede prebehli v poriadku. Samotná komunikácia so serverom prebieha v tele metódy run() volaním metódy apiDataPresenter.getAreas(), ktorá vyvolá konkrétnu požiadavku.&lt;br /&gt;
&lt;br /&gt;
[[File:obrazky/completable_class_final.png|thumb|none|x188px|alt=Návrhový vzor Observer využitý na komunikáciu so serverovým API|Návrhový vzor Observer využitý na komunikáciu so serverovým API]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    Completable.fromRunnable(new Runnable() {&lt;br /&gt;
                @Override&lt;br /&gt;
                public void run() {&lt;br /&gt;
                areaDao.insertAllAreas(apiDataPresenter.getAreas());&lt;br /&gt;
                }&lt;br /&gt;
            }).subscribeOn(Schedulers.io())&lt;br /&gt;
                .observeOn(AndroidSchedulers.mainThread()&lt;br /&gt;
                    .subscribe(new CompletableObserver() {&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onSubscribe(Disposable d) { }&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onComplete() { }&lt;br /&gt;
                        @Override&lt;br /&gt;
                        public void onError(Throwable e) { } });&amp;lt;/source&amp;gt;&lt;br /&gt;
Textový formát odpovede z API je vrátený do triedy ApiDataPresenter, v ktorej sa transformuje na JSON objekt ([[#listing:api_data_presenter|[listing:api_data_presenter]]], metóda parseAreaResponse()). V tejto metóde sa prechádza pole hodnôt s hodnotou kľúča “data”, pričom jednotlivé hodnoty tohto poľa sú opäť polia, ktorých hodnoty sa ukladajú do dátovej štruktúry, ktorá je vrátená späť do miesta volania ([[#listing:completable|[listing:completable]]], riadok 4). Spôsob vytvárania JSON objektu z prijatej odpovede, prechádzanie a ukladanie jeho hodnôt do dátovej štruktúry zobrazuje [[#listing:api_data_presenter|[listing:api_data_presenter]]]. Postupnosť prechodu medzi triedami a formát dát v jednotlivých triedach počas komunikácie s API znázorňuje .&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    public ArrayList&amp;lt;Area&amp;gt; getAreas() { &lt;br /&gt;
        parseAreaResponse(); &lt;br /&gt;
        return this.areaList; &lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    private void parseAreaResponse() {&lt;br /&gt;
        String serverResponse = apiResponses.getAreaResponse();&lt;br /&gt;
        if (!serverResponse.isEmpty()) {&lt;br /&gt;
            JSONObject response = new JSONObject(serverResponse);&lt;br /&gt;
            JSONArray array = response.getJSONArray(&amp;quot;data&amp;quot;);&lt;br /&gt;
            for (int i = 0; i &amp;lt; array.length(); i++) {&lt;br /&gt;
                Area area = new Area();&lt;br /&gt;
                area.setId(array.getJSONArray(i).getInt(0));&lt;br /&gt;
                area.setName(array.getJSONArray(i).getString(1));&lt;br /&gt;
                this.areaList.add(area);&lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:api_call_diagram_final.png|thumb|none|585px|alt=Prenos a formát dát v jednotlivých triedach počas komunikácie s API|Prenos a formát dát v jednotlivých triedach počas komunikácie s API]]&lt;br /&gt;
&lt;br /&gt;
== Vizualizácia dát v aplikácii ==&lt;br /&gt;
&lt;br /&gt;
Prezentáciu dát v aktivitách prehľadu (Dashboard, Favourites) zabezpečujú komponenty - CardView, RecyclerView a Adaptér. V aktivite detailného prehľadu konkrétneho senzora (GraphView) sú dáta vizualizované prostredníctvom grafov - knižnica MPAndroidChart.&lt;br /&gt;
&lt;br /&gt;
=== Vizualizácia dát v aktivitách Dashboard a Favourites ===&lt;br /&gt;
&lt;br /&gt;
==== CardView ====&lt;br /&gt;
&lt;br /&gt;
CardView je grafická reprezentácia karty (Card [[#design|1.1.2]]), predstavuje rodičovské rozloženie pre všetky v nej obsiahnuté View prvky (textové polia, tlačidlá, obrázky…).&lt;br /&gt;
&lt;br /&gt;
==== RecyclerView ====&lt;br /&gt;
&lt;br /&gt;
RecylerView predstavuje model, ktorý umožňuje zobraziť väčšie množstvo údajov vo forme zoznamu. V aplikácii sú ako jednotlivé položky zobrazené v RecyclerView použité karty. Výhodou používania RecyclerView je jeho rýchlosť, pretože sa nevykresľujú (nevytvárajú) naraz všetky karty, ale vytvárajú sa len tie, ktoré sa aktuálne zmestia na obrazovku. Pre naplnenie RecyclerView kartami a ich následné zobrazenie sa využívajú návrhové vzory (triedy) ViewHolder a Adaptér. Jednotlivé karty zobrazené v RecyclerView sú reprezentované objektmi nazývanými view holders. Tieto objekty sú inštanciami tried, ktoré sú potomkami triedy RecyclerView.ViewHolder.&lt;br /&gt;
&lt;br /&gt;
==== ViewHolder ====&lt;br /&gt;
&lt;br /&gt;
ViewHolder je návrhový vzor, ktorý zabezpečuje vytvorenie objektu daného CardView rozloženia spolu s jej View prvkami. Takto vytvorený objekt môže byť použitý viacnásobne, bez nutnosti opakovanej inicializácie View prvkov tohto objektu, volaním metódy findViewById(), čo znižuje pamäťovú náročnosť a zároveň výrazne zrýchľuje proces listovania v RecyclerView. Vytvorené view holder objekty reprezentujú karty, ktoré sú zobrazené v RecyclerView. Tento návrhový vzor možno použiť vytvorením vnútornej triedy, potomok triedy RecyclerView.ViewHolder, v triede adaptéra.&lt;br /&gt;
&lt;br /&gt;
==== Adaptér ====&lt;br /&gt;
&lt;br /&gt;
Adaptér je návrhový vzor, ktorý funguje ako most medzi používateľským rozhraním a dátami. V Androide predstavuje adaptér triedu, ktorá sprostredkováva dáta RecyclerView. Trieda adaptéra (potomok triedy RecyclerView.Adapter) zabezpečuje správu jednotlivých view holder objektov prostredníctvom preťažených metód rodičovskej triedy: vytvorenie view holder objektov - metóda onCreateViewHolder, pridávanie vytvorených view holder objektov do RecyclerView - metóda onBindViewHolder().&lt;br /&gt;
&lt;br /&gt;
V aplikácii sú vytvorené dve triedy adaptérov, kde každá z nich sprostredkováva dáta konkrétnej aktivite: DashboardAdapter (Dashboard aktivita), FavouritesAdapter (Favourites aktivita). Triedy adaptérov v aplikácii využívajú návrhový vzor Singleton, pričom vytvorenie (získanie) inštancie triedy oboch adaptérov je možné prostredníctvom statickej metódy getInstance(). Spôsob implementácie triedy adaptéra v aplikácii je demonštrovaný na jednoduchšej triede FavouritesAdapter, ktorá vykresľuje len jeden typ view holder objektu (len karta senzora, vľavo). Trieda DashboardAdapter vykresľuje tri typy view holder objektov, kde každý z nich reprezentuje kartu: oblasti, sektoru, alebo senzora ( vpravo).&lt;br /&gt;
&lt;br /&gt;
Vytvorenie inštancie triedy FavouritesAdapter a následné nastavenie tejto inštancie ako adaptér objektu recylerView demonštruje kód [[#listing:adapter|[listing:adapter]]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    RecyclerView recyclerView = findViewById(R.id.recycler_view);&lt;br /&gt;
    FavouritesAdapter adapter = FavouritesAdapter.getInstance();&lt;br /&gt;
    recyclerView.setAdapter(adapter);&amp;lt;/source&amp;gt;&lt;br /&gt;
[[File:favourites.png|x264px|RecyclerView - aktivita Dashboard (vpravo), aktivita Favourites (vľavo)]] [[File:recycler_view_dashboard_edit.png|x264px|RecyclerView - aktivita Dashboard (vpravo), aktivita Favourites (vľavo)]]&lt;br /&gt;
&lt;br /&gt;
Nasledujúca ukážka ([[#listing:viewHolder|[listing:viewHolder]]]) zobrazuje implementáciu návrhového vzoru ViewHolder v triede adaptéra (FavouritesAdapter), vytvorením vnútornej triedy DataViewHolder. Trieda DataViewHolder inicializuje jednotlivé View prvky CardView rozloženia karty senzora. Každý vytvorený objekt tejto triedy reprezentuje jednu kartu v RecyclerView.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    public static class DataViewHolder extends RecyclerView.ViewHolder {&lt;br /&gt;
        private TextView textViewSensorName;&lt;br /&gt;
        // iné View prvky CardView rozloženia karty senzora...&lt;br /&gt;
        public DataViewHolder(@NonNull final View itemView) {&lt;br /&gt;
          super(itemView);&lt;br /&gt;
          textViewSensorName = &lt;br /&gt;
          itemView.findViewById(R.id.text_view_sensor_name);&lt;br /&gt;
        }&lt;br /&gt;
    }&amp;lt;/source&amp;gt;&lt;br /&gt;
Metóda triedy adaptéra - onCreateViewHolder() ([[#listing:onCreate|[listing:onCreate]]]) slúži pre dynamické vytváranie view holder objektov. Táto metóda vytvára len taký počet view holder objektov (kariet), koľko sa aktuálne zmestí na obrazovku. Pri listovaní v RecyclerView sú dynamicky vytvárané ďalšie potrebné objekty, pričom nahrádzajú tie, ktoré už na obrazovke nie sú vidieť (recycling).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @NonNull&lt;br /&gt;
    @override&lt;br /&gt;
    public RecyclerView.ViewHolder onCreateViewHolder(&lt;br /&gt;
    @NonNull ViewGroup viewGroup, int i) {&lt;br /&gt;
                View v;&lt;br /&gt;
                LayoutInflater mInflater = &lt;br /&gt;
                LayoutInflater.from(viewGroup.getContext());&lt;br /&gt;
                v = mInflater.inflate(&lt;br /&gt;
                R.layout.card_view_sensor, viewGroup, false);&lt;br /&gt;
                return new FavouritesAdapter.DataViewHolder(v); }&amp;lt;/source&amp;gt;&lt;br /&gt;
Samotné pridanie vytvoreného view holder objektu do RecyclerView zabezpečuje metóda - onBindViewHolder() ([[#listing:onBind|[listing:onBind]]]). Každý view holder objekt v RecyclerView má definovanú pozíciu, na ktorej sa nachádza. Hodnotu aktuálnej pozície, na ktorú má byť ďalší view holder objekt pridaný/vykreslený prijíma metóda onBindViewHolder() prostredníctvom parametra. Na základe pozície je možné naviazať konkrétny view holder objekt na dáta.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    @override&lt;br /&gt;
    public void onBindViewHolder(&lt;br /&gt;
    @NonNull RecyclerView.ViewHolder viewHolder, int position) {&lt;br /&gt;
        ((DataViewHolder) viewHolder).&lt;br /&gt;
        textViewSensorName.setText(&lt;br /&gt;
        filteredList.get(position).getSensorName()); }&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Vizualizácia dát v aktivite GraphView ===&lt;br /&gt;
&lt;br /&gt;
Prezentáciu dát v aktivite GraphView zabezpečujú grafy, vytvárané pomocou knižnice MPAndroidChart. Táto knižnica umožňuje vytvárať rôzne typy grafov: koláčové, stĺpcové, čiarové a iné. V aplikácii je využitý čiarový graf - LineChart. V aplikácii sú v grafe vykresľované dva typy čiar: LimitLine - horizontálna čiara pre zobrazenie priemernej hodnoty a samotná čiara grafu LineChart pre vykreslenie priebehu meraných hodnôt. Hodnoty osi x sú reprezentované časovými značkami jednotlivých meraní, ktoré sú explicitne konvertované na textový formát dátumu, ktorý je v grafe zobrazený ako legenda osi x. Hodnoty osi y sú reprezentované nameranými hodnotami. Jednotlivé body grafu sú vytvárané ako usporiadaná dvojica [časová značka, hodnota] ([[#listing:graph_creation|[listing:graph_creation]]] trieda Entry). Tieto usporiadané dvojice hodnôt sú postupne pridávané do poľa ([[#listing:graph_creation|[listing:graph_creation]]] objekt xyValues), ktoré je po naplnení priradené vytváranému objektu triedy LineDataSet v jej konštruktore. Metódy triedy LineDataSet umožňujú nastaviť požadované parametre čiary grafu (hrúbka, farba a iné). Objekt triedy LineDataSet je nakoniec priradený samotnému objektu grafu inicializovaného prostredníctvom metódy findViewById(). V aplikácii je v grafoch implementovaná možnosť zoomovania a taktiež možnosť zobrazenia hodnoty konkrétneho bodu pri kliknutí na ľubovoľnú hodnotu v grafe ( vpravo).&lt;br /&gt;
&lt;br /&gt;
[[File:graph_view.png|151px|Vykresľovanie priebehu nameraných hodnôt v aktivite GraphView]] [[File:graph_view_land.png|264px|Vykresľovanie priebehu nameraných hodnôt v aktivite GraphView]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;    ArrayList&amp;lt;Entry&amp;gt; xyValues = new ArrayList&amp;lt;&amp;gt;();&lt;br /&gt;
        for (int i = 0; i &amp;lt; values.size; i++) {&lt;br /&gt;
            Entry xy = new Entry(values.get(i).getDate().getTime(),&lt;br /&gt;
                values.getValue());&lt;br /&gt;
            xyValues.add(xy);&lt;br /&gt;
        }&lt;br /&gt;
    LineDataSet dataSet = new LineDataSet(xyValues, &amp;quot;hodnoty&amp;quot;);&lt;br /&gt;
    dataSet.setLineWidth(2f);&lt;br /&gt;
    // iné nastavenia vlastností dataSetu... &lt;br /&gt;
    LineData lineData = new LineData(dataSet);&lt;br /&gt;
    LineChart chart = findViewById(R.id.chart);&lt;br /&gt;
    chart.setData(lineData);&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Testovanie_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12788</id>
		<title>Testovanie aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Testovanie_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12788"/>
		<updated>2020-09-03T20:12:06Z</updated>

		<summary type="html">&lt;p&gt;Matus: Vytvorená stránka „{{Praca_uvod|5|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSori…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|5|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Implement%C3%A1cia_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12787</id>
		<title>Implementácia aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Implement%C3%A1cia_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12787"/>
		<updated>2020-09-03T20:11:55Z</updated>

		<summary type="html">&lt;p&gt;Matus: Vytvorená stránka „{{Praca_uvod|3|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSori…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|3|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=N%C3%A1vrh_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12785</id>
		<title>Návrh aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=N%C3%A1vrh_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12785"/>
		<updated>2020-09-03T20:10:48Z</updated>

		<summary type="html">&lt;p&gt;Matus: /* Funkčné požiadavky */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|3|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
V tejto kapitole sú postupne opísané jednotlivé fázy návrhu aplikácie ako: špecifikácia funkčných a nefunkčných požiadaviek, definícia minimálnych požiadaviek na inštaláciu, identifikácia prípadov použitia, návrh štruktúry, funkcionality a spôsob práce jednotlivých samostatných častí aplikácie. Výsledná aplikácia nebude zahŕňať akcie spojené s administráciou systému, tie budú i naďalej dostupné len cez desktopovú aplikáciu.&lt;br /&gt;
&lt;br /&gt;
== Špecifikácia požiadaviek aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Definované požiadavky pre vývoj aplikácie boli rozdelené na dve skupiny: funkčné - popisujúce funkcie a vlastnosti, ktoré musí aplikácia poskytovať a nefunkčné požiadavky - bližšie špecifikujúce nároky na spôsob realizácie funkčných vlastností aplikácie.&lt;br /&gt;
&lt;br /&gt;
==== Funkčné požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Zoznam funkčných požiadaviek bol vytvorený na základe požadovaných funkcií, ktoré musí aplikácia zabezpečovať a poskytovať. Pri definovaní jednotlivých funkčných požiadaviek aplikácie sa vychádzalo z jej primárnej úlohy - prístup k dátam rôznych serverov systému Sensorical a ich vizuálna reprezentácia v aplikácii. Tabuľka 3.2 zobrazuje zoznam funkčných požiadaviek.&lt;br /&gt;
&lt;br /&gt;
Tabuľka 3.2: Nefunkčné požiadavky aplikácie aAurela&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!&lt;br /&gt;
!Funkčné požiadavky&lt;br /&gt;
!Doplňujúce informácie&lt;br /&gt;
|-&lt;br /&gt;
|R01&lt;br /&gt;
|Voľba vzdialeného servera&lt;br /&gt;
|Možnosť zvoliť si ľubovoľný Sensorical server, ku ktorému sa má aplikácia pripojiť&lt;br /&gt;
|-&lt;br /&gt;
|R02&lt;br /&gt;
|Zobrazenie relevantných údajov&lt;br /&gt;
|Prihlásenému používateľovi sú zobrazené len tie údaje, ku ktorým má definované prístupové práva&lt;br /&gt;
|-&lt;br /&gt;
|R03&lt;br /&gt;
|Kategorizácia umiestnenia&lt;br /&gt;
|Kategorizácia jednotlivých senzorov v rámci hierarchie umiestnenia (zaradenie do oblasti a sektoru)&lt;br /&gt;
|-&lt;br /&gt;
|R04&lt;br /&gt;
|Zobrazovanie nameraných hodnôt&lt;br /&gt;
|Zobrazenie nameraných hodnôt jednotlivých senzorov spolu s údajmi o dátume a čase kedy meranie prebehlo&lt;br /&gt;
|-&lt;br /&gt;
|R05&lt;br /&gt;
|Zobrazovanie trendov&lt;br /&gt;
|Zobrazenie trendov nameraných hodnôt jednotlivých senzorov za poslednú hodinu merania&lt;br /&gt;
|-&lt;br /&gt;
|R06&lt;br /&gt;
|Vytvorenie zoznamu obľúbených&lt;br /&gt;
|Možnosť vytvorenia vlastného zoznamu obľúbených resp. dôležitých senzorov&lt;br /&gt;
|-&lt;br /&gt;
|R07&lt;br /&gt;
|Editácia zoznamu obľúbených&lt;br /&gt;
|Možnosť pridania/odstránenia senzorov do/zo zoznamu obľúbených&lt;br /&gt;
|-&lt;br /&gt;
|R08&lt;br /&gt;
|Vyhľadávanie v prehľade&lt;br /&gt;
|Možnosť vyhľadávať v prehľade všetkých dostupných senzorov a v používateľom vytvorenom zozname obľúbených&lt;br /&gt;
|-&lt;br /&gt;
|R09&lt;br /&gt;
|Zobrazenie grafov&lt;br /&gt;
|Vykresľovanie grafov nameraných hodnôt jednotlivých senzorov ako závislosť zmeny nameranej hodnoty za časový horizont&lt;br /&gt;
|-&lt;br /&gt;
|R10&lt;br /&gt;
|Zmena časového rozpätia&lt;br /&gt;
|Možnosť zmeniť časové rozpätie, za ktoré má aplikácia zobraziť namerané hodnoty senzorov v prehľadoch a grafoch&lt;br /&gt;
|-&lt;br /&gt;
|R11&lt;br /&gt;
|Offline dostupnosť údajov&lt;br /&gt;
|Aplikácia umožní prehliadať archivované dáta aj bez dostupnosti internetového pripojenia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Nefunkčné požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Zoznam nefunkčných požiadaviek bol zostavený na základe doplnkových požiadaviek a nárokov na aplikáciu. Definovanie týchto požiadaviek je spojené so špecifikáciou samotnej platformy, pre ktorú je aplikácia určená, ako aj jednotlivých nárokov na používateľské rozhranie a distribúciu aplikácie. Tabuľka 3.2 zobrazuje zoznam nefunkčných požiadaviek.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tabuľka 3.2: Nefunkčné požiadavky aplikácie aAurela&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!&lt;br /&gt;
!Nefunkčné požiadavky&lt;br /&gt;
!Doplňujúce informácie&lt;br /&gt;
|-&lt;br /&gt;
|R01&lt;br /&gt;
|Aplikácia pre platformu Android&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|R02&lt;br /&gt;
|Implementácia odporúčaní Material Design&lt;br /&gt;
|Použitie odporúčaní Material Design pre tvorbu grafických používateľských rozhraní&lt;br /&gt;
|-&lt;br /&gt;
|R03&lt;br /&gt;
|Implementácia aplikácie v jazykových mutáciách&lt;br /&gt;
|Implementácia aplikácie v slovenskej a anglickej jazykovej mutácii&lt;br /&gt;
|-&lt;br /&gt;
|R04&lt;br /&gt;
|Možnosť budúceho rozšírenia&lt;br /&gt;
|Implementácia aplikácie tak, aby bolo možné jej budúce rozšírenie o ďalšie funkcie&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Minimálne požiadavky na inštaláciu aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Pre aplikáciu bola ako minimálna podporovaná verzia systému Android zvolená verzia 5.0 Lollipop (API 21) a ako cielená verzia, verzia 9.0 Pie (API 28). Minimálna podporovaná verzia systému bola vybraná na základe štatistík spoločnosti Google Inc tak, aby bežala na značnej väčšine zariadení. V čase vývoja aplikácie je API 21 a vyššie používané na viac ako 85% všetkých zariadení s OS Android.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;tab_nefunkcne_poziadavky&amp;quot; label=&amp;quot;tab_nefunkcne_poziadavky&amp;quot;&amp;gt;[tab_nefunkcne_poziadavky]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Funkcionality a štruktúra aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Na základe definovaných funkčných požiadaviek a nárokov na aplikáciu boli identifikované jednotlivé prípady použitia aplikácie. Táto podkapitola je venovaná bližšiemu opisu identifikovaných aktivít z prípadov použitia, ich významu resp. podstate. V tejto podkapitole je taktiež opísaná navrhnutá štruktúra aplikácie, funkcionality a princíp práce jednotlivých jej častí.&lt;br /&gt;
&lt;br /&gt;
=== Prípady použitia ===&lt;br /&gt;
&lt;br /&gt;
'''Aktéri''' - aktéri sú všetci používatelia, ktorí môžu v aplikácii vykonávať jednotlivé aktivity. V prípade aplikácie aAurela, ktorá má interné využitie, boli ako aktéri identifikovaní používatelia, ktorí sú evidovaní v databáze na vzdialenom serveri a majú tak oprávnenie systém a teda aj aplikáciu používať. '''Aktivity''' - predstavujú akcie, ktoré môžu aktéri s aplikáciou vykonávať. Jednotlivé aktivity boli navrhnuté tak, aby boli zabezpečené všetky funkčné požiadavky špecifikované v Tabuľke [[#tab_funkcne_poziadavky|[tab_funkcne_poziadavky]]]. zobrazuje vrcholový diagram prípadov použitia aplikácie aAurela.&lt;br /&gt;
&lt;br /&gt;
[[File:vrcholovy_use_case.png|thumb|none|566px|alt=Diagram prípadov použitia aplikácie aAurela|Diagram prípadov použitia aplikácie aAurela]]&lt;br /&gt;
&lt;br /&gt;
==== Aktivity prípadov použitia ====&lt;br /&gt;
&lt;br /&gt;
* Výber adresy servera - zadanie webovej adresy vzdialeného servera, ku ktorému sa má aplikácia pripojiť.&lt;br /&gt;
* Prihlásiť sa - zadanie mena a hesla pre autentifikáciu na zvolenom serveri a prihlásenie sa do aplikácie.&lt;br /&gt;
* Zobraziť hlavný prehľad - zobrazenie a prechádzanie zoznamu všetkých dostupných senzorov kategorizovaných v rámci umiestnenia spolu so základnými údajmi naposledy nameraných hodnôt.&lt;br /&gt;
* Zobraziť prehľad obľúbených - zobrazenie a prechádzanie vytvoreného zoznamu obľúbených senzorov spolu so základnými údajmi naposledy nameraných hodnôt.&lt;br /&gt;
* Zobraziť graf - zobrazenie detailného pohľadu na históriu nameraných hodnôt vybraného senzora formou grafu a rôznych štatistík meraní.&lt;br /&gt;
* Editovať obľúbené - pridanie/odstránenie senzora do/zo zoznamu obľúbených.&lt;br /&gt;
* Aktualizovať merané hodnoty - stiahnutie najaktuálnejších nameraných hodnôt zo servera.&lt;br /&gt;
* Synchronizovať všetky údaje - synchronizácia všetkých údajov aplikácie s aktuálne dostupnými údajmi na serveri.&lt;br /&gt;
* Zmeniť zobrazovaný rozsah - zmena počtu dní, za ktoré má aplikácia zobrazovať a vyhodnocovať namerané hodnoty.&lt;br /&gt;
* Zobraziť informácie o aplikácii - zobrazenie informačnej obrazovky s bližším popisom o aplikácii.&lt;br /&gt;
* Odhlásiť sa - odhlásenie sa z aplikácie.&lt;br /&gt;
&lt;br /&gt;
=== Návrh štruktúry aplikácie ===&lt;br /&gt;
&lt;br /&gt;
Štruktúra aplikácie bola navrhnutá na základe vymedzenia hlavných aktivít z prípadov použitia. Každá z týchto aktivít predstavuje samostatnú časť (obrazovku) aplikácie, kde každá z obrazoviek slúži pre prístup do samostatnej, funkčne a logicky oddelenej časti, v ktorej je možné vykonávať rôzne ďalšie aktivity. Aplikáciu aAurela tvoria nasledujúce obrazovky:&lt;br /&gt;
&lt;br /&gt;
* ServerSelect - obrazovka pre výber adresy servera&lt;br /&gt;
* Login - obrazovka pre prihlásenie do aplikácie&lt;br /&gt;
* Dashboard - obrazovka hlavného prehľadu&lt;br /&gt;
* Favourites - obrazovka prehľadu obľúbených senzorov&lt;br /&gt;
* GraphView - obrazovka pre zobrazenie grafov a štatistík merania&lt;br /&gt;
* About - informačná obrazovka&lt;br /&gt;
&lt;br /&gt;
Takto definované funkčné časti aplikácie sú vo fáze implementácie implementované ako jednotlivé triedy Android aktivít.&lt;br /&gt;
&lt;br /&gt;
=== Funkcie a spôsob práce jednotlivých častí aplikácie ===&lt;br /&gt;
&lt;br /&gt;
==== Výber adresy servera a prihlásenie do aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Skôr, ako používateľ získa v aplikácii prístup k dátam, musí prejsť voľbou adresy servera, ku ktorému sa chce pripojiť a následne prihlásiť. Pre výber adresy servera a následné prihlásenie do aplikácie slúžia obrazovky ServerSelect a Login.&lt;br /&gt;
&lt;br /&gt;
==== ServerSelect ====&lt;br /&gt;
&lt;br /&gt;
Pri prvotnom spustení aplikácie bude používateľ vyzvaný na zadanie adresy vzdialeného Sensorical servera, ku ktorému sa chce pripojiť. Po zadaní údajov aplikácia overí správnosť a dostupnosť zadanej adresy. Ak sú zadané údaje správne, používateľ bude presmerovaný na prihlasovaciu obrazovku (Login) a zadané údaje sa uložia pre rýchle načítanie pri ďalšom spustení aplikácie. V prípade nesprávne zadaných údajov nebude používateľ pripustený k prihláseniu, ale bude vyzvaný na opravu zle zadanej adresy.&lt;br /&gt;
&lt;br /&gt;
==== Login ====&lt;br /&gt;
&lt;br /&gt;
Po otvorení prihlasovacej obrazovky sa používateľovi zobrazia polia pre zadanie prihlasovacieho mena a hesla. Po zadaní údajov aplikácia odošle na server autentifikačnú požiadavku so zadanými prihlasovacími údajmi. Ak sú zadané údaje správne, používateľ bude prihlásený. Ak zadané údaje nie sú správne, zobrazí sa oznámenie o zle zadaných prihlasovacích údajoch. Používateľ bude mať pred prihlásením možnosť voľby zapamätania prihlasovacích údajov pre automatické prihlásenie pri ďalšom spustení aplikácie.&lt;br /&gt;
&lt;br /&gt;
==== Diagram aktivít ServerSelect a Login ====&lt;br /&gt;
&lt;br /&gt;
Pri spustení aplikácie bude vždy otvorená obrazovka pre výber adresy servera - ServerSelect. Po úspešnom overení zadanej adresy sa bude pokračovať na prihlasovaciu obrazovku - Login. Prihlasovacou obrazovkou používateľ neprechádza v prípade, keď už bol do aplikácie prihlásený a zvolil možnosť zapamätania prihlásenia. Celý proces výberu adresy servera a následné prihlásenie do aplikácie znázorňuje diagram aktivít na obrázku [[#fig:activity_diagram_before_login|1.2]].&lt;br /&gt;
&lt;br /&gt;
[[File:state_diagram_befor_login.png|thumb|none|566px|alt=Diagram aktivít - práca aplikácie pred prihlásením|Diagram aktivít - práca aplikácie pred prihlásením]]&lt;br /&gt;
&lt;br /&gt;
==== Po prihlásení do aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Po zadaní správnej adresy servera a následnom úspešnom prihlásení do aplikácie získa používateľ prístup k dátam systému Sensorical. Možnosť prístupu k dátam bude mať prostredníctvom troch obrazoviek: Dashboard, Favourites a GraphView.&lt;br /&gt;
&lt;br /&gt;
==== Dashboard ====&lt;br /&gt;
&lt;br /&gt;
Obrazovka, ktorá bude štandardne zobrazená prihlásenému používateľovi. Slúži na sprostredkovanie celkového prehľadu základných dostupných dát systému. Používateľ tu uvidí zoznam všetkých jemu dostupných senzorov, kategorizovaných v rámci hierarchie prvej úrovne (oblasti) a druhej úrovne (sektoru). Obrazovka Dashboard taktiež zobrazí údaje o naposledy nameraných hodnotách jednotlivých senzorov za zvolené časové obdobie, priemernú hodnotu a trendy nameraných hodnôt jednotlivých senzorov za poslednú hodinu.&lt;br /&gt;
&lt;br /&gt;
==== Favourites ====&lt;br /&gt;
&lt;br /&gt;
Obrazovka, ktorá zobrazí prehľad používateľom vytvoreného zoznamu obľúbených senzorov. Používateľ bude mať k tejto obrazovke umožnený prístup len v prípade, ak má vytvorený vlastný zoznam obľúbených senzorov. Po prvotnom prihlásení do aplikácie nebude k dispozícii žiadny zoznam obľúbených senzorov. Ak však používateľ pridá v hlavnom prehľade (Dashboard) alebo obrazovke konkrétneho senzoru (GraphView) ľubovolný senzor do obľúbených, bude obrazovka Favourties zobrazovaná prednostne. To znamená, ak bude mať používateľ vytvorený zoznam obľúbených senzorov, zobrazí sa tento prehľad prioritne po prihlásení do aplikácie. Obrazovka Favourites taktiež zobrazí údaje o naposledy nameraných hodnotách jednotlivých senzorov za zvolené časové obdobie, priemernú hodnotu a trendy nameraných hodnôt jednotlivých senzorov za poslednú hodinu, podobne ako obrazovka Dashboard.&lt;br /&gt;
&lt;br /&gt;
==== GraphView ====&lt;br /&gt;
&lt;br /&gt;
Táto obrazovka slúži pre zobrazenie detailného náhľadu na históriu meraní konkrétneho senzora. Obrazovka GraphView bude zobrazená pri výbere ľubovoľného senzoru z prehľadu, či už na obrazovke Dashboard alebo Favourites. Podstatou obrazovky GraphView je zobraziť priebeh hodnôt meranej veličiny v závislosti od času vizuálnou formou (graf), ako aj štatistiky meraní daného senzora formou extrémov meraní.&lt;br /&gt;
&lt;br /&gt;
==== Diagram aktivít Dashboard, Favourites, GraphView ====&lt;br /&gt;
&lt;br /&gt;
Po prihlásení do aplikácie dôjde k overeniu, či má prihlásený používateľ vytvorený zoznam obľúbených senzorov. Ak má takýto zoznam vytvorený, bude prednostne otvorená obrazovka prehľadu obľúbených senzorov - Favourites. Ak takýto zoznam používateľ vytvorený nemá, bude otvorená obrazovka s prehľadom všetkých senzorov - Dashboard. Obe tieto obrazovky poskytnú používateľovi možnosť zobraziť detailný náhľad ľubovoľného, dostupného senzoru z prehľadu - GraphView. Postupnosť prechodu medzi obrazovkami Dashboard, Favourites a GraphView znázorňuje diagram aktivít na obrázku [[#fig:activity_diagram_after_login|1.3]].&lt;br /&gt;
&lt;br /&gt;
[[File:state_diagram_after_login.png|thumb|none|566px|alt=Diagram aktivít - práca aplikácie po úspešnom prihlásení|Diagram aktivít - práca aplikácie po úspešnom prihlásení]]&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:State_diagram_after_login.png&amp;diff=12782</id>
		<title>Súbor:State diagram after login.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:State_diagram_after_login.png&amp;diff=12782"/>
		<updated>2020-09-03T19:53:45Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:State_diagram_befor_login.png&amp;diff=12781</id>
		<title>Súbor:State diagram befor login.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:State_diagram_befor_login.png&amp;diff=12781"/>
		<updated>2020-09-03T19:53:28Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Vrcholovy_use_case.png&amp;diff=12780</id>
		<title>Súbor:Vrcholovy use case.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Vrcholovy_use_case.png&amp;diff=12780"/>
		<updated>2020-09-03T19:52:42Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=N%C3%A1vrh_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12779</id>
		<title>Návrh aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=N%C3%A1vrh_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12779"/>
		<updated>2020-09-03T19:52:11Z</updated>

		<summary type="html">&lt;p&gt;Matus: /*  */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|3|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
V tejto kapitole sú postupne opísané jednotlivé fázy návrhu aplikácie ako: špecifikácia funkčných a nefunkčných požiadaviek, definícia minimálnych požiadaviek na inštaláciu, identifikácia prípadov použitia, návrh štruktúry, funkcionality a spôsob práce jednotlivých samostatných častí aplikácie. Výsledná aplikácia nebude zahŕňať akcie spojené s administráciou systému, tie budú i naďalej dostupné len cez desktopovú aplikáciu.&lt;br /&gt;
&lt;br /&gt;
== Špecifikácia požiadaviek aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Definované požiadavky pre vývoj aplikácie boli rozdelené na dve skupiny: funkčné - popisujúce funkcie a vlastnosti, ktoré musí aplikácia poskytovať a nefunkčné požiadavky - bližšie špecifikujúce nároky na spôsob realizácie funkčných vlastností aplikácie.&lt;br /&gt;
&lt;br /&gt;
==== Funkčné požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Zoznam funkčných požiadaviek bol vytvorený na základe požadovaných funkcií, ktoré musí aplikácia zabezpečovať a poskytovať. Pri definovaní jednotlivých funkčných požiadaviek aplikácie sa vychádzalo z jej primárnej úlohy - prístup k dátam rôznych serverov systému Sensorical a ich vizuálna reprezentácia v aplikácii. Tabuľka [[#tab_funkcne_poziadavky|[tab_funkcne_poziadavky]]] zobrazuje zoznam funkčných požiadaviek.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;tab_funkcne_poziadavky&amp;quot; label=&amp;quot;tab_funkcne_poziadavky&amp;quot;&amp;gt;[tab_funkcne_poziadavky]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nefunkčné požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Zoznam nefunkčných požiadaviek bol zostavený na základe doplnkových požiadaviek a nárokov na aplikáciu. Definovanie týchto požiadaviek je spojené so špecifikáciou samotnej platformy, pre ktorú je aplikácia určená, ako aj jednotlivých nárokov na používateľské rozhranie a distribúciu aplikácie. Tabuľka [[#tab_nefunkcne_poziadavky|[tab_nefunkcne_poziadavky]]] zobrazuje zoznam nefunkčných požiadaviek.&lt;br /&gt;
&lt;br /&gt;
==== Minimálne požiadavky na inštaláciu aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Pre aplikáciu bola ako minimálna podporovaná verzia systému Android zvolená verzia 5.0 Lollipop (API 21) a ako cielená verzia, verzia 9.0 Pie (API 28). Minimálna podporovaná verzia systému bola vybraná na základe štatistík spoločnosti Google Inc tak, aby bežala na značnej väčšine zariadení. V čase vývoja aplikácie je API 21 a vyššie používané na viac ako 85% všetkých zariadení s OS Android.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;tab_nefunkcne_poziadavky&amp;quot; label=&amp;quot;tab_nefunkcne_poziadavky&amp;quot;&amp;gt;[tab_nefunkcne_poziadavky]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Funkcionality a štruktúra aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Na základe definovaných funkčných požiadaviek a nárokov na aplikáciu boli identifikované jednotlivé prípady použitia aplikácie. Táto podkapitola je venovaná bližšiemu opisu identifikovaných aktivít z prípadov použitia, ich významu resp. podstate. V tejto podkapitole je taktiež opísaná navrhnutá štruktúra aplikácie, funkcionality a princíp práce jednotlivých jej častí.&lt;br /&gt;
&lt;br /&gt;
=== Prípady použitia ===&lt;br /&gt;
&lt;br /&gt;
'''Aktéri''' - aktéri sú všetci používatelia, ktorí môžu v aplikácii vykonávať jednotlivé aktivity. V prípade aplikácie aAurela, ktorá má interné využitie, boli ako aktéri identifikovaní používatelia, ktorí sú evidovaní v databáze na vzdialenom serveri a majú tak oprávnenie systém a teda aj aplikáciu používať. '''Aktivity''' - predstavujú akcie, ktoré môžu aktéri s aplikáciou vykonávať. Jednotlivé aktivity boli navrhnuté tak, aby boli zabezpečené všetky funkčné požiadavky špecifikované v Tabuľke [[#tab_funkcne_poziadavky|[tab_funkcne_poziadavky]]]. zobrazuje vrcholový diagram prípadov použitia aplikácie aAurela.&lt;br /&gt;
&lt;br /&gt;
[[File:vrcholovy_use_case.png|thumb|none|566px|alt=Diagram prípadov použitia aplikácie aAurela|Diagram prípadov použitia aplikácie aAurela]]&lt;br /&gt;
&lt;br /&gt;
==== Aktivity prípadov použitia ====&lt;br /&gt;
&lt;br /&gt;
* Výber adresy servera - zadanie webovej adresy vzdialeného servera, ku ktorému sa má aplikácia pripojiť.&lt;br /&gt;
* Prihlásiť sa - zadanie mena a hesla pre autentifikáciu na zvolenom serveri a prihlásenie sa do aplikácie.&lt;br /&gt;
* Zobraziť hlavný prehľad - zobrazenie a prechádzanie zoznamu všetkých dostupných senzorov kategorizovaných v rámci umiestnenia spolu so základnými údajmi naposledy nameraných hodnôt.&lt;br /&gt;
* Zobraziť prehľad obľúbených - zobrazenie a prechádzanie vytvoreného zoznamu obľúbených senzorov spolu so základnými údajmi naposledy nameraných hodnôt.&lt;br /&gt;
* Zobraziť graf - zobrazenie detailného pohľadu na históriu nameraných hodnôt vybraného senzora formou grafu a rôznych štatistík meraní.&lt;br /&gt;
* Editovať obľúbené - pridanie/odstránenie senzora do/zo zoznamu obľúbených.&lt;br /&gt;
* Aktualizovať merané hodnoty - stiahnutie najaktuálnejších nameraných hodnôt zo servera.&lt;br /&gt;
* Synchronizovať všetky údaje - synchronizácia všetkých údajov aplikácie s aktuálne dostupnými údajmi na serveri.&lt;br /&gt;
* Zmeniť zobrazovaný rozsah - zmena počtu dní, za ktoré má aplikácia zobrazovať a vyhodnocovať namerané hodnoty.&lt;br /&gt;
* Zobraziť informácie o aplikácii - zobrazenie informačnej obrazovky s bližším popisom o aplikácii.&lt;br /&gt;
* Odhlásiť sa - odhlásenie sa z aplikácie.&lt;br /&gt;
&lt;br /&gt;
=== Návrh štruktúry aplikácie ===&lt;br /&gt;
&lt;br /&gt;
Štruktúra aplikácie bola navrhnutá na základe vymedzenia hlavných aktivít z prípadov použitia. Každá z týchto aktivít predstavuje samostatnú časť (obrazovku) aplikácie, kde každá z obrazoviek slúži pre prístup do samostatnej, funkčne a logicky oddelenej časti, v ktorej je možné vykonávať rôzne ďalšie aktivity. Aplikáciu aAurela tvoria nasledujúce obrazovky:&lt;br /&gt;
&lt;br /&gt;
* ServerSelect - obrazovka pre výber adresy servera&lt;br /&gt;
* Login - obrazovka pre prihlásenie do aplikácie&lt;br /&gt;
* Dashboard - obrazovka hlavného prehľadu&lt;br /&gt;
* Favourites - obrazovka prehľadu obľúbených senzorov&lt;br /&gt;
* GraphView - obrazovka pre zobrazenie grafov a štatistík merania&lt;br /&gt;
* About - informačná obrazovka&lt;br /&gt;
&lt;br /&gt;
Takto definované funkčné časti aplikácie sú vo fáze implementácie implementované ako jednotlivé triedy Android aktivít.&lt;br /&gt;
&lt;br /&gt;
=== Funkcie a spôsob práce jednotlivých častí aplikácie ===&lt;br /&gt;
&lt;br /&gt;
==== Výber adresy servera a prihlásenie do aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Skôr, ako používateľ získa v aplikácii prístup k dátam, musí prejsť voľbou adresy servera, ku ktorému sa chce pripojiť a následne prihlásiť. Pre výber adresy servera a následné prihlásenie do aplikácie slúžia obrazovky ServerSelect a Login.&lt;br /&gt;
&lt;br /&gt;
==== ServerSelect ====&lt;br /&gt;
&lt;br /&gt;
Pri prvotnom spustení aplikácie bude používateľ vyzvaný na zadanie adresy vzdialeného Sensorical servera, ku ktorému sa chce pripojiť. Po zadaní údajov aplikácia overí správnosť a dostupnosť zadanej adresy. Ak sú zadané údaje správne, používateľ bude presmerovaný na prihlasovaciu obrazovku (Login) a zadané údaje sa uložia pre rýchle načítanie pri ďalšom spustení aplikácie. V prípade nesprávne zadaných údajov nebude používateľ pripustený k prihláseniu, ale bude vyzvaný na opravu zle zadanej adresy.&lt;br /&gt;
&lt;br /&gt;
==== Login ====&lt;br /&gt;
&lt;br /&gt;
Po otvorení prihlasovacej obrazovky sa používateľovi zobrazia polia pre zadanie prihlasovacieho mena a hesla. Po zadaní údajov aplikácia odošle na server autentifikačnú požiadavku so zadanými prihlasovacími údajmi. Ak sú zadané údaje správne, používateľ bude prihlásený. Ak zadané údaje nie sú správne, zobrazí sa oznámenie o zle zadaných prihlasovacích údajoch. Používateľ bude mať pred prihlásením možnosť voľby zapamätania prihlasovacích údajov pre automatické prihlásenie pri ďalšom spustení aplikácie.&lt;br /&gt;
&lt;br /&gt;
==== Diagram aktivít ServerSelect a Login ====&lt;br /&gt;
&lt;br /&gt;
Pri spustení aplikácie bude vždy otvorená obrazovka pre výber adresy servera - ServerSelect. Po úspešnom overení zadanej adresy sa bude pokračovať na prihlasovaciu obrazovku - Login. Prihlasovacou obrazovkou používateľ neprechádza v prípade, keď už bol do aplikácie prihlásený a zvolil možnosť zapamätania prihlásenia. Celý proces výberu adresy servera a následné prihlásenie do aplikácie znázorňuje diagram aktivít na obrázku [[#fig:activity_diagram_before_login|1.2]].&lt;br /&gt;
&lt;br /&gt;
[[File:state_diagram_befor_login.png|thumb|none|566px|alt=Diagram aktivít - práca aplikácie pred prihlásením|Diagram aktivít - práca aplikácie pred prihlásením]]&lt;br /&gt;
&lt;br /&gt;
==== Po prihlásení do aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Po zadaní správnej adresy servera a následnom úspešnom prihlásení do aplikácie získa používateľ prístup k dátam systému Sensorical. Možnosť prístupu k dátam bude mať prostredníctvom troch obrazoviek: Dashboard, Favourites a GraphView.&lt;br /&gt;
&lt;br /&gt;
==== Dashboard ====&lt;br /&gt;
&lt;br /&gt;
Obrazovka, ktorá bude štandardne zobrazená prihlásenému používateľovi. Slúži na sprostredkovanie celkového prehľadu základných dostupných dát systému. Používateľ tu uvidí zoznam všetkých jemu dostupných senzorov, kategorizovaných v rámci hierarchie prvej úrovne (oblasti) a druhej úrovne (sektoru). Obrazovka Dashboard taktiež zobrazí údaje o naposledy nameraných hodnotách jednotlivých senzorov za zvolené časové obdobie, priemernú hodnotu a trendy nameraných hodnôt jednotlivých senzorov za poslednú hodinu.&lt;br /&gt;
&lt;br /&gt;
==== Favourites ====&lt;br /&gt;
&lt;br /&gt;
Obrazovka, ktorá zobrazí prehľad používateľom vytvoreného zoznamu obľúbených senzorov. Používateľ bude mať k tejto obrazovke umožnený prístup len v prípade, ak má vytvorený vlastný zoznam obľúbených senzorov. Po prvotnom prihlásení do aplikácie nebude k dispozícii žiadny zoznam obľúbených senzorov. Ak však používateľ pridá v hlavnom prehľade (Dashboard) alebo obrazovke konkrétneho senzoru (GraphView) ľubovolný senzor do obľúbených, bude obrazovka Favourties zobrazovaná prednostne. To znamená, ak bude mať používateľ vytvorený zoznam obľúbených senzorov, zobrazí sa tento prehľad prioritne po prihlásení do aplikácie. Obrazovka Favourites taktiež zobrazí údaje o naposledy nameraných hodnotách jednotlivých senzorov za zvolené časové obdobie, priemernú hodnotu a trendy nameraných hodnôt jednotlivých senzorov za poslednú hodinu, podobne ako obrazovka Dashboard.&lt;br /&gt;
&lt;br /&gt;
==== GraphView ====&lt;br /&gt;
&lt;br /&gt;
Táto obrazovka slúži pre zobrazenie detailného náhľadu na históriu meraní konkrétneho senzora. Obrazovka GraphView bude zobrazená pri výbere ľubovoľného senzoru z prehľadu, či už na obrazovke Dashboard alebo Favourites. Podstatou obrazovky GraphView je zobraziť priebeh hodnôt meranej veličiny v závislosti od času vizuálnou formou (graf), ako aj štatistiky meraní daného senzora formou extrémov meraní.&lt;br /&gt;
&lt;br /&gt;
==== Diagram aktivít Dashboard, Favourites, GraphView ====&lt;br /&gt;
&lt;br /&gt;
Po prihlásení do aplikácie dôjde k overeniu, či má prihlásený používateľ vytvorený zoznam obľúbených senzorov. Ak má takýto zoznam vytvorený, bude prednostne otvorená obrazovka prehľadu obľúbených senzorov - Favourites. Ak takýto zoznam používateľ vytvorený nemá, bude otvorená obrazovka s prehľadom všetkých senzorov - Dashboard. Obe tieto obrazovky poskytnú používateľovi možnosť zobraziť detailný náhľad ľubovoľného, dostupného senzoru z prehľadu - GraphView. Postupnosť prechodu medzi obrazovkami Dashboard, Favourites a GraphView znázorňuje diagram aktivít na obrázku [[#fig:activity_diagram_after_login|1.3]].&lt;br /&gt;
&lt;br /&gt;
[[File:state_diagram_after_login.png|thumb|none|566px|alt=Diagram aktivít - práca aplikácie po úspešnom prihlásení|Diagram aktivít - práca aplikácie po úspešnom prihlásení]]&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=N%C3%A1vrh_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12778</id>
		<title>Návrh aplikácie nSoric aAurela</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=N%C3%A1vrh_aplik%C3%A1cie_nSoric_aAurela&amp;diff=12778"/>
		<updated>2020-09-03T19:51:13Z</updated>

		<summary type="html">&lt;p&gt;Matus: Vytvorená stránka „{{Praca_uvod|3|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSori…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|3|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
V tejto kapitole sú postupne opísané jednotlivé fázy návrhu aplikácie ako: špecifikácia funkčných a nefunkčných požiadaviek, definícia minimálnych požiadaviek na inštaláciu, identifikácia prípadov použitia, návrh štruktúry, funkcionality a spôsob práce jednotlivých samostatných častí aplikácie. Výsledná aplikácia nebude zahŕňať akcie spojené s administráciou systému, tie budú i naďalej dostupné len cez desktopovú aplikáciu.&lt;br /&gt;
&lt;br /&gt;
== Špecifikácia požiadaviek aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Definované požiadavky pre vývoj aplikácie boli rozdelené na dve skupiny: funkčné - popisujúce funkcie a vlastnosti, ktoré musí aplikácia poskytovať a nefunkčné požiadavky - bližšie špecifikujúce nároky na spôsob realizácie funkčných vlastností aplikácie.&lt;br /&gt;
&lt;br /&gt;
==== Funkčné požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Zoznam funkčných požiadaviek bol vytvorený na základe požadovaných funkcií, ktoré musí aplikácia zabezpečovať a poskytovať. Pri definovaní jednotlivých funkčných požiadaviek aplikácie sa vychádzalo z jej primárnej úlohy - prístup k dátam rôznych serverov systému Sensorical a ich vizuálna reprezentácia v aplikácii. Tabuľka [[#tab_funkcne_poziadavky|[tab_funkcne_poziadavky]]] zobrazuje zoznam funkčných požiadaviek.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;tab_funkcne_poziadavky&amp;quot; label=&amp;quot;tab_funkcne_poziadavky&amp;quot;&amp;gt;[tab_funkcne_poziadavky]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Nefunkčné požiadavky ====&lt;br /&gt;
&lt;br /&gt;
Zoznam nefunkčných požiadaviek bol zostavený na základe doplnkových požiadaviek a nárokov na aplikáciu. Definovanie týchto požiadaviek je spojené so špecifikáciou samotnej platformy, pre ktorú je aplikácia určená, ako aj jednotlivých nárokov na používateľské rozhranie a distribúciu aplikácie. Tabuľka [[#tab_nefunkcne_poziadavky|[tab_nefunkcne_poziadavky]]] zobrazuje zoznam nefunkčných požiadaviek.&lt;br /&gt;
&lt;br /&gt;
==== Minimálne požiadavky na inštaláciu aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Pre aplikáciu bola ako minimálna podporovaná verzia systému Android zvolená verzia 5.0 Lollipop (API 21) a ako cielená verzia, verzia 9.0 Pie (API 28). Minimálna podporovaná verzia systému bola vybraná na základe štatistík spoločnosti Google Inc tak, aby bežala na značnej väčšine zariadení. V čase vývoja aplikácie je API 21 a vyššie používané na viac ako 85% všetkých zariadení s OS Android.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;tab_nefunkcne_poziadavky&amp;quot; label=&amp;quot;tab_nefunkcne_poziadavky&amp;quot;&amp;gt;[tab_nefunkcne_poziadavky]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Funkcionality a štruktúra aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Na základe definovaných funkčných požiadaviek a nárokov na aplikáciu boli identifikované jednotlivé prípady použitia aplikácie. Táto podkapitola je venovaná bližšiemu opisu identifikovaných aktivít z prípadov použitia, ich významu resp. podstate. V tejto podkapitole je taktiež opísaná navrhnutá štruktúra aplikácie, funkcionality a princíp práce jednotlivých jej častí.&lt;br /&gt;
&lt;br /&gt;
=== Prípady použitia ===&lt;br /&gt;
&lt;br /&gt;
'''Aktéri''' - aktéri sú všetci používatelia, ktorí môžu v aplikácii vykonávať jednotlivé aktivity. V prípade aplikácie aAurela, ktorá má interné využitie, boli ako aktéri identifikovaní používatelia, ktorí sú evidovaní v databáze na vzdialenom serveri a majú tak oprávnenie systém a teda aj aplikáciu používať. '''Aktivity''' - predstavujú akcie, ktoré môžu aktéri s aplikáciou vykonávať. Jednotlivé aktivity boli navrhnuté tak, aby boli zabezpečené všetky funkčné požiadavky špecifikované v Tabuľke [[#tab_funkcne_poziadavky|[tab_funkcne_poziadavky]]]. zobrazuje vrcholový diagram prípadov použitia aplikácie aAurela.&lt;br /&gt;
&lt;br /&gt;
[[File:obrazky/vrcholovy_use_case.png|thumb|none|566px|alt=Diagram prípadov použitia aplikácie aAurela|Diagram prípadov použitia aplikácie aAurela]]&lt;br /&gt;
&lt;br /&gt;
==== Aktivity prípadov použitia ====&lt;br /&gt;
&lt;br /&gt;
* Výber adresy servera - zadanie webovej adresy vzdialeného servera, ku ktorému sa má aplikácia pripojiť.&lt;br /&gt;
* Prihlásiť sa - zadanie mena a hesla pre autentifikáciu na zvolenom serveri a prihlásenie sa do aplikácie.&lt;br /&gt;
* Zobraziť hlavný prehľad - zobrazenie a prechádzanie zoznamu všetkých dostupných senzorov kategorizovaných v rámci umiestnenia spolu so základnými údajmi naposledy nameraných hodnôt.&lt;br /&gt;
* Zobraziť prehľad obľúbených - zobrazenie a prechádzanie vytvoreného zoznamu obľúbených senzorov spolu so základnými údajmi naposledy nameraných hodnôt.&lt;br /&gt;
* Zobraziť graf - zobrazenie detailného pohľadu na históriu nameraných hodnôt vybraného senzora formou grafu a rôznych štatistík meraní.&lt;br /&gt;
* Editovať obľúbené - pridanie/odstránenie senzora do/zo zoznamu obľúbených.&lt;br /&gt;
* Aktualizovať merané hodnoty - stiahnutie najaktuálnejších nameraných hodnôt zo servera.&lt;br /&gt;
* Synchronizovať všetky údaje - synchronizácia všetkých údajov aplikácie s aktuálne dostupnými údajmi na serveri.&lt;br /&gt;
* Zmeniť zobrazovaný rozsah - zmena počtu dní, za ktoré má aplikácia zobrazovať a vyhodnocovať namerané hodnoty.&lt;br /&gt;
* Zobraziť informácie o aplikácii - zobrazenie informačnej obrazovky s bližším popisom o aplikácii.&lt;br /&gt;
* Odhlásiť sa - odhlásenie sa z aplikácie.&lt;br /&gt;
&lt;br /&gt;
=== Návrh štruktúry aplikácie ===&lt;br /&gt;
&lt;br /&gt;
Štruktúra aplikácie bola navrhnutá na základe vymedzenia hlavných aktivít z prípadov použitia. Každá z týchto aktivít predstavuje samostatnú časť (obrazovku) aplikácie, kde každá z obrazoviek slúži pre prístup do samostatnej, funkčne a logicky oddelenej časti, v ktorej je možné vykonávať rôzne ďalšie aktivity. Aplikáciu aAurela tvoria nasledujúce obrazovky:&lt;br /&gt;
&lt;br /&gt;
* ServerSelect - obrazovka pre výber adresy servera&lt;br /&gt;
* Login - obrazovka pre prihlásenie do aplikácie&lt;br /&gt;
* Dashboard - obrazovka hlavného prehľadu&lt;br /&gt;
* Favourites - obrazovka prehľadu obľúbených senzorov&lt;br /&gt;
* GraphView - obrazovka pre zobrazenie grafov a štatistík merania&lt;br /&gt;
* About - informačná obrazovka&lt;br /&gt;
&lt;br /&gt;
Takto definované funkčné časti aplikácie sú vo fáze implementácie implementované ako jednotlivé triedy Android aktivít.&lt;br /&gt;
&lt;br /&gt;
=== Funkcie a spôsob práce jednotlivých častí aplikácie ===&lt;br /&gt;
&lt;br /&gt;
==== Výber adresy servera a prihlásenie do aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Skôr, ako používateľ získa v aplikácii prístup k dátam, musí prejsť voľbou adresy servera, ku ktorému sa chce pripojiť a následne prihlásiť. Pre výber adresy servera a následné prihlásenie do aplikácie slúžia obrazovky ServerSelect a Login.&lt;br /&gt;
&lt;br /&gt;
==== ServerSelect ====&lt;br /&gt;
&lt;br /&gt;
Pri prvotnom spustení aplikácie bude používateľ vyzvaný na zadanie adresy vzdialeného Sensorical servera, ku ktorému sa chce pripojiť. Po zadaní údajov aplikácia overí správnosť a dostupnosť zadanej adresy. Ak sú zadané údaje správne, používateľ bude presmerovaný na prihlasovaciu obrazovku (Login) a zadané údaje sa uložia pre rýchle načítanie pri ďalšom spustení aplikácie. V prípade nesprávne zadaných údajov nebude používateľ pripustený k prihláseniu, ale bude vyzvaný na opravu zle zadanej adresy.&lt;br /&gt;
&lt;br /&gt;
==== Login ====&lt;br /&gt;
&lt;br /&gt;
Po otvorení prihlasovacej obrazovky sa používateľovi zobrazia polia pre zadanie prihlasovacieho mena a hesla. Po zadaní údajov aplikácia odošle na server autentifikačnú požiadavku so zadanými prihlasovacími údajmi. Ak sú zadané údaje správne, používateľ bude prihlásený. Ak zadané údaje nie sú správne, zobrazí sa oznámenie o zle zadaných prihlasovacích údajoch. Používateľ bude mať pred prihlásením možnosť voľby zapamätania prihlasovacích údajov pre automatické prihlásenie pri ďalšom spustení aplikácie.&lt;br /&gt;
&lt;br /&gt;
==== Diagram aktivít ServerSelect a Login ====&lt;br /&gt;
&lt;br /&gt;
Pri spustení aplikácie bude vždy otvorená obrazovka pre výber adresy servera - ServerSelect. Po úspešnom overení zadanej adresy sa bude pokračovať na prihlasovaciu obrazovku - Login. Prihlasovacou obrazovkou používateľ neprechádza v prípade, keď už bol do aplikácie prihlásený a zvolil možnosť zapamätania prihlásenia. Celý proces výberu adresy servera a následné prihlásenie do aplikácie znázorňuje diagram aktivít na obrázku [[#fig:activity_diagram_before_login|1.2]].&lt;br /&gt;
&lt;br /&gt;
[[File:obrazky/state_diagram_befor_login.png|thumb|none|566px|alt=Diagram aktivít - práca aplikácie pred prihlásením|Diagram aktivít - práca aplikácie pred prihlásením]]&lt;br /&gt;
&lt;br /&gt;
==== Po prihlásení do aplikácie ====&lt;br /&gt;
&lt;br /&gt;
Po zadaní správnej adresy servera a následnom úspešnom prihlásení do aplikácie získa používateľ prístup k dátam systému Sensorical. Možnosť prístupu k dátam bude mať prostredníctvom troch obrazoviek: Dashboard, Favourites a GraphView.&lt;br /&gt;
&lt;br /&gt;
==== Dashboard ====&lt;br /&gt;
&lt;br /&gt;
Obrazovka, ktorá bude štandardne zobrazená prihlásenému používateľovi. Slúži na sprostredkovanie celkového prehľadu základných dostupných dát systému. Používateľ tu uvidí zoznam všetkých jemu dostupných senzorov, kategorizovaných v rámci hierarchie prvej úrovne (oblasti) a druhej úrovne (sektoru). Obrazovka Dashboard taktiež zobrazí údaje o naposledy nameraných hodnotách jednotlivých senzorov za zvolené časové obdobie, priemernú hodnotu a trendy nameraných hodnôt jednotlivých senzorov za poslednú hodinu.&lt;br /&gt;
&lt;br /&gt;
==== Favourites ====&lt;br /&gt;
&lt;br /&gt;
Obrazovka, ktorá zobrazí prehľad používateľom vytvoreného zoznamu obľúbených senzorov. Používateľ bude mať k tejto obrazovke umožnený prístup len v prípade, ak má vytvorený vlastný zoznam obľúbených senzorov. Po prvotnom prihlásení do aplikácie nebude k dispozícii žiadny zoznam obľúbených senzorov. Ak však používateľ pridá v hlavnom prehľade (Dashboard) alebo obrazovke konkrétneho senzoru (GraphView) ľubovolný senzor do obľúbených, bude obrazovka Favourties zobrazovaná prednostne. To znamená, ak bude mať používateľ vytvorený zoznam obľúbených senzorov, zobrazí sa tento prehľad prioritne po prihlásení do aplikácie. Obrazovka Favourites taktiež zobrazí údaje o naposledy nameraných hodnotách jednotlivých senzorov za zvolené časové obdobie, priemernú hodnotu a trendy nameraných hodnôt jednotlivých senzorov za poslednú hodinu, podobne ako obrazovka Dashboard.&lt;br /&gt;
&lt;br /&gt;
==== GraphView ====&lt;br /&gt;
&lt;br /&gt;
Táto obrazovka slúži pre zobrazenie detailného náhľadu na históriu meraní konkrétneho senzora. Obrazovka GraphView bude zobrazená pri výbere ľubovoľného senzoru z prehľadu, či už na obrazovke Dashboard alebo Favourites. Podstatou obrazovky GraphView je zobraziť priebeh hodnôt meranej veličiny v závislosti od času vizuálnou formou (graf), ako aj štatistiky meraní daného senzora formou extrémov meraní.&lt;br /&gt;
&lt;br /&gt;
==== Diagram aktivít Dashboard, Favourites, GraphView ====&lt;br /&gt;
&lt;br /&gt;
Po prihlásení do aplikácie dôjde k overeniu, či má prihlásený používateľ vytvorený zoznam obľúbených senzorov. Ak má takýto zoznam vytvorený, bude prednostne otvorená obrazovka prehľadu obľúbených senzorov - Favourites. Ak takýto zoznam používateľ vytvorený nemá, bude otvorená obrazovka s prehľadom všetkých senzorov - Dashboard. Obe tieto obrazovky poskytnú používateľovi možnosť zobraziť detailný náhľad ľubovoľného, dostupného senzoru z prehľadu - GraphView. Postupnosť prechodu medzi obrazovkami Dashboard, Favourites a GraphView znázorňuje diagram aktivít na obrázku [[#fig:activity_diagram_after_login|1.3]].&lt;br /&gt;
&lt;br /&gt;
[[File:obrazky/state_diagram_after_login.png|thumb|none|566px|alt=Diagram aktivít - práca aplikácie po úspešnom prihlásení|Diagram aktivít - práca aplikácie po úspešnom prihlásení]]&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=S%C3%BAbor:Lifecycle.png&amp;diff=12777</id>
		<title>Súbor:Lifecycle.png</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=S%C3%BAbor:Lifecycle.png&amp;diff=12777"/>
		<updated>2020-09-03T19:44:23Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Platforma_Android&amp;diff=12776</id>
		<title>Platforma Android</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Platforma_Android&amp;diff=12776"/>
		<updated>2020-09-03T19:43:21Z</updated>

		<summary type="html">&lt;p&gt;Matus: /* Životný cyklus aktivity */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|2|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=  =&lt;br /&gt;
&lt;br /&gt;
Platforma Android a životný cyklus aplikácií bežiacich na tejto platforme je výrazne odlišný od životného cyklu aplikácií bežiacich na desktope. Desktopové aplikácie bežia ako relatívne samostatné procesy nezávisle od iných, paralelne bežiacich procesov.&lt;br /&gt;
&lt;br /&gt;
Na rozdiel od desktopových aplikácií, Android aplikácie prechádzajú počas svojho behu (životného cyklu) rôznymi štádiami v závislosti na rôznych systémových udalostiach resp. prerušeniach (viď [[#lifecycle|1.1.1]]). Samotná Android aplikácia môže pozostávať zo štyroch základných súčastí medzi ktoré patria: Activity (aktivita), Content providers (poskytovatelia obsahu), Broadcast recievers (prijímatelia vysielania), Services (služby). Každá aplikácia môže byť tvorená ľubovolnou kombináciou týchto súčastí . V Aplikácii aAurela sa používa len komponenta Activity, ktorá bude ďalej bližšie opísaná.&lt;br /&gt;
&lt;br /&gt;
== Komponenta Activity ==&lt;br /&gt;
&lt;br /&gt;
Komponenta Activity (ďalej len aktivita) tvorí základ používateľského rozhrania a predstavuje obdobu okna desktopovej aplikácie, prostredníctvom ktorého používateľ s aplikáciou interaguje. Jednu aplikáciu môže tvoriť niekoľko aktivít, kde každá má svoj význam a umožňuje používateľovi grafický vstup do rozdielnych častí aplikácie. Pre vývojárov reprezentuje každá aktivita samostatnú triedu.&lt;br /&gt;
&lt;br /&gt;
=== Životný cyklus aktivity ===&lt;br /&gt;
&lt;br /&gt;
Každá aktivita v rámci jednej a tej istej aplikácie má svoj vlastný životný cyklus. Životný cyklus je reprezentovaný rôznymi stavmi, ktorými aktivita počas svojho behu prechádza. Jednotlivé stavy životného cyklu Android aktivity sú nesmierne dôležité pre správne fungovanie aplikácie ako celku. Ich úlohou je zabrániť „pádu“ aplikácie pri práci s viacerými aktivitami, prípadne pri rôznych prerušeniach behu aktivity danej aplikácie.&lt;br /&gt;
&lt;br /&gt;
Zmena stavu životného cyklu Android aktivity nastáva napr. pri zmene orientácie obrazovky zariadenia, minimalizovaní aplikácie stlačením domovského tlačidla, alebo pri prerušení aplikácie prichádzajúcim hovorom. Stavy, v ktorých sa Android aktivita môže nachádzať sú: Resumed, Paused, Stopped, Destroyed.&lt;br /&gt;
&lt;br /&gt;
* '''Resumed''' - stav kedy je aktivita v popredí, v interakcii s používateľom.&lt;br /&gt;
* '''Paused''' - stav, v ktorom je aktivita pozastavená, mimo interakcie s používateľom (čiastočne viditeľná) napr. prekrytá dialógovým oknom.&lt;br /&gt;
* '''Stoped''' - stav, v ktorom sa aktivita dostala na pozadie, stratila „pozornosť“ (úplne skrytá) napr. iná aktivita sa dostala do popredia.&lt;br /&gt;
* '''Destroyed''' - stav, kedy je aktivita úplne ukončená, odstránená zo systémovej pamäte.&lt;br /&gt;
&lt;br /&gt;
Created a Started nepovažujeme za samostatné stavy, označujú sa za stavy prechodné, čo znamená, že aktivita v nich nie je schopná zotrvať po určitý čas a takmer okamžite sa z nich posúva do stavu nasledujúceho.&lt;br /&gt;
&lt;br /&gt;
* '''Created''' - je moment, kedy systém vytvorí danú aktivitu.&lt;br /&gt;
* '''Started''' - je moment, kedy sa aktivita stáva viditeľná.&lt;br /&gt;
&lt;br /&gt;
[[File:lifecycle.png|thumb|none|566px|alt=Životný cyklus Android aktivity spolu s metódami spätného volania |Životný cyklus Android aktivity spolu s metódami spätného volania ]]&lt;br /&gt;
&lt;br /&gt;
Metódy spätného volania slúžia na zachytenie zmeny stavu a na vykonanie akcie ešte pred tým, než sa aktivita dostane do stavu iného. Metódy spätného volania je možné implementovať v triede samotnej aktivity. V závislosti na zmene stavu aktivity sú volané metódy: onCreate(), onStart(), onResume(), onPause(), onRestart(), onStop(), onDestroy(). Jediná povinná metóda spätného volania, ktorá musí byť v triede aktivity implementovaná je metóda onCreate(). Metóda onCreate() je volaná vždy pri prvotnom vytvorení aktivity a štandardne sa v nej nastavuje grafické rozhranie aktivity, inicializujú sa potrebné objekty a podobne. V tejto časti bol použitý zdroj .&lt;br /&gt;
&lt;br /&gt;
== Princípy a nástroje využité pri vývoji aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Táto časť pojednáva o základných princípoch systému Android a nástrojoch, ktoré boli pri vývoji aplikácie využité. Nástroje reprezentujú dve dôležité knižnice, na ktorých je postavené jadro aplikácie: - SQLite databáza a - asynchrónna práca s vláknami. Knižnice Room a RxJava sú vzájomne kompatibilné a v spolupráci výrazne uľahčujú vývoj robustnejších aplikácií na platforme Android.&lt;br /&gt;
&lt;br /&gt;
=== SQLite databáza na platforme Android ===&lt;br /&gt;
&lt;br /&gt;
SQLite je lokálna SQL databáza (uložená ako súbor v zariadení), ktorá disponuje všetkými funkciami relačných databáz. Platforma Android umožňuje pre ukladanie väčšieho množstva štruktúrovaných dát implementovať práve databázu typu SQLite.&lt;br /&gt;
&lt;br /&gt;
Pre implementáciu SQLite databázy v aplikácii je využitá knižnica Room. Výhody, pre ktoré bola knižnica Room zvolená sú: výrazné skrátenie a sprehľadnenie kódu, validácia správnosti SQL príkazov už počas kompilácie, priama podpora knižnice RxJava.&lt;br /&gt;
&lt;br /&gt;
=== Knižnica Room ===&lt;br /&gt;
&lt;br /&gt;
Knižnica Room predstavuje abstraktnú vrstvu nad vrstvou SQLite databázy. Slúži pre vytvorenie databázy ako aj pre prístup k jej dátam.&lt;br /&gt;
&lt;br /&gt;
Knižnica Room sprostredkováva mapovanie databázových relácií na objekty v jazyku Java na základe spracovávania anotácií. Anotácie sú špeciálne príkazy, ktoré sú v prípade knižnice Room priradené k definíciám tried, metód a premenných. Pri kompilácii Room na základe použitej anotácie vygeneruje Java kód, na ktorý sa prostredníctvom anotácií odkazuje. Tento spôsob práce je označovaný aj ako ORM (Object-Relational Mapping). V tejto časti je použitý zdroj informácii .&lt;br /&gt;
&lt;br /&gt;
==== Množina tried pre vytvorenie SQLite databázy pomocou knižnice Room ====&lt;br /&gt;
&lt;br /&gt;
Pre vytvorenie a prácu s SQLite databázou pomocou knižnice Room je potrebné implementovať základnú množinu Java tried: Entita, DAO a Databáza. Pri týchto triedach je potrebné použiť anotácie @Entity, @DAO, @Database.&lt;br /&gt;
&lt;br /&gt;
''@Entity'' - anotácia triedy, ktorá reprezentuje entitu databázy. Jednotlivé premenné triedy reprezentujú atribúty danej entity. K atribútom je potrebné umožniť prístup cez metódy get a set .&lt;br /&gt;
&lt;br /&gt;
''@DAO'' - (Data accessing object) anotácia rozhrania, ktoré obsahuje metódy pre prístup do databázy. Jednotlivé metódy majú priradené anotácie na základe SQL operácie, ktorú vykonávajú:&lt;br /&gt;
&lt;br /&gt;
''@Insert'' - vkladanie záznamov do databázy,&lt;br /&gt;
&lt;br /&gt;
''@Update'' - aktualizovanie existujúcich záznamov,&lt;br /&gt;
&lt;br /&gt;
''@Delete'' - mazanie záznamov,&lt;br /&gt;
&lt;br /&gt;
''@Query'' - alternatívna možnosť definovania vlastných SQL príkazov.&lt;br /&gt;
&lt;br /&gt;
Parameterom týchto anotácií je textový reťazec reprezentujúci SQL príkaz, ktorý daná metóda vykonáva. Návratový typ metód DAO musí korešpondovať s výstupom SQL príkazu, ktorý daná metóda vykonáva .&lt;br /&gt;
&lt;br /&gt;
''@Database'' - anotácia triedy, z ktorej Room vytvorí databázu. Parameter anotácie musí obsahovať zoznam všetkých entít, resp. Java tried s anotáciou @Entity, ktoré majú byť transformované na entity databázy. Pri triede databázy je dôležité uplatnenie Singleton návrhového vzoru, ktorý zabezpečí vytvorenie a prístupnosť jedinej inštancie triedy databázy po celý čas behu aplikácie .&lt;br /&gt;
&lt;br /&gt;
==== Ďalšie anotácie knižnice Room ====&lt;br /&gt;
&lt;br /&gt;
Použitie nasledujúcich anotácií je nepovinné, avšak pri samotnej implementácii značne uľahčuje prácu s databázou. Tieto anotácie sa používajú ako anotácie premenných tried jednotlivých entít .&lt;br /&gt;
&lt;br /&gt;
''@PrimaryKey'' - anotácia premennej triedy entity, ktorá v databáze reprezentuje primárny kľúč. Voliteľný parameter tejto anotácie umožňuje explicitne zadeklarovať automatické generovanie primárneho kľúča (autoincrement).&lt;br /&gt;
&lt;br /&gt;
''@ForeignKey'' - umožňuje vytvorenie relácie medzi jednotlivými entitami pomocou cudzích kľúčov.&lt;br /&gt;
&lt;br /&gt;
''@ColumnInfo'' - ako parameter tejto anotácie je použitý textový reťazec, ktorý definuje názov atribútu, pod ktorým bude premenná triedy entity vložená do databázy.&lt;br /&gt;
&lt;br /&gt;
''@Ignore'' - anotácia, ktorú je možné použiť v prípade, ak má Room ignorovať danú premennú triedy, napr. nepoužiť premennú ako atribút entity v databáze.&lt;br /&gt;
&lt;br /&gt;
Použitie knižnice Room demonštrujú ukážky priamo z jej implementácie v aplikácii v časti [[#implementacia_sql|[implementacia_sql]]].&lt;br /&gt;
&lt;br /&gt;
=== Práca s vláknami v systéme Android ===&lt;br /&gt;
&lt;br /&gt;
Pri spustení Android aplikácie (nebežiacej na pozadí), vytvorí systém pre túto aplikáciu nový Linux proces, ktorý má pre svoj beh vyhradené jednovláknové operácie. Systémové nastavenie všetkých komponentov jednej aplikácie je také, že všetky bežia na jednom procesorovom vlákne nazývanom hlavné vlákno (main thread).&lt;br /&gt;
&lt;br /&gt;
Úlohou hlavného vlákna je zabezpečiť responzívnosť a správne fungovanie používateľského rozhrania. Hlavné vlákno zodpovedá za delegovanie udalostí na jednotlivé View komponenty (tlačidlá, textové polia…). Všetky tieto komponenty bežiace na hlavnom vlákne musia byť neustále dostupné pre interakciu s používateľom aplikácie. To znamená, ak používateľ klikne na tlačidlo, musí mať hlavné vlákno dostatok pamäťových prostriedkov na spracovanie obsluhy tejto udalosti.&lt;br /&gt;
&lt;br /&gt;
V prípade vykonávania iného, časovo náročnejšieho (blokujúceho) procesu na hlavnom vlákne, je hlavné vlákno zablokované, prestáva odpovedať a systém celý proces aplikácie ukončí. Z tohto dôvodu je potrebné časovo náročnejšie operácie vykonávať v inom, paralelnom tzv. pracovnom vlákne (worker thread) . Pre potrebu obsluhy časovo náročných operácií v paralelných vláknach je v aplikácii použitá knižnica RxJava.&lt;br /&gt;
&lt;br /&gt;
=== Knižnica RxJava ===&lt;br /&gt;
&lt;br /&gt;
RxJava je knižnica, ktorá umožňuje reaktívne resp. udalosťami riadené programovanie. Základný návrhový vzor využívaný touto knižnicou je Observer. Tento návrhový vzor funguje na princípe akcie a reakcie. Observer predstavuje objekt, ktorý sleduje stav iného objektu a v prípade zmeny stavu sledovaného objektu je Observer automaticky notifikovaný. Tento návrhový vzor je v knižnici RxJava využitý pri sledovaní priebehu asynchrónne vykonávanej práce na pracovných vláknach.&lt;br /&gt;
&lt;br /&gt;
Práve možnosť asynchrónneho vykonávania operácií predstavuje jednu z najväčších predností knižnice RxJava. V nasledujúcej časti je použitý zdroj , pričom je zachovaná terminológia oficiálnej dokumentácie knižnice RxJava.&lt;br /&gt;
&lt;br /&gt;
==== Spolupráca knižníc RxJava a Room ====&lt;br /&gt;
&lt;br /&gt;
implicitne zakazuje prácu s SQLite databázou na hlavnom aplikačnom vlákne, pretože práca s databázou predstavuje časovo náročnejšie operácie. Z tohto dôvodu je nutné operácie spojené s SQLite databázou vykonávať asynchrónne.&lt;br /&gt;
&lt;br /&gt;
* '''Observable''' reprezentuje ľubovoľný objekt, ktorý môže získavať dáta z dátového zdroja (generuje hodnoty - metódy DAO) a ktorého stav môže byť sledovaný ďalšími objektmi (observers).&lt;br /&gt;
* '''Observer''' predstavuje ľubovoľný objekt, ktorý sleduje stav Observable a má byť v prípade zmeny jeho stavu notifikovaný (prijíma hodnoty).&lt;br /&gt;
&lt;br /&gt;
Vďaka vzájomnej kompatibilite knižníc RxJava a Room je možné použiť niektorú z tried knižnice RxJava ako wrapper (obal) návratového typu metódy DAO. Použitím niektorej observable triedy knižnice RxJava ako wrapper návratového typu metódy DAO, môže byť následne celá práca tejto metódy presmerovaná na pracovné vlákno aplikovaním RxJava operátorov pre asynchrónnu prácu.&lt;br /&gt;
&lt;br /&gt;
==== Základné observable triedy knižnice RxJava ====&lt;br /&gt;
&lt;br /&gt;
* trieda '''Single''' - Observable, ktorá vracia buď jeden objekt alebo chybu.&lt;br /&gt;
* trieda '''Completable''' - Observable, vracajúca len výsledok operácie vo forme informácie, či bola úloha dokončená, alebo prišlo k chybe, samotné dáta nevracia.&lt;br /&gt;
* trieda '''Maybe''' - Observable, ktorá podobne ako Single vracia jeden objekt, ale nemusí žiaden. Na rozdiel od Single nevyhlási chybu a vráti prázdnu hodnotu.&lt;br /&gt;
&lt;br /&gt;
Príklad použitia observable triedy Maybe demonštruje [[#listing:dao|[listing:dao]]], z jej implementácie priamo v aplikácii.&lt;br /&gt;
&lt;br /&gt;
==== Operátory knižnice RxJava pre asynchrónne vykonávanie operácií ====&lt;br /&gt;
&lt;br /&gt;
Operátory knižnice RxJava slúžia nielen na zadefinovanie pracovného vlákna, na ktorom sa bude asynchrónna práca (metóda) vykonávať, ale aj na špecifikáciu vlákna, ktoré má prijímať výsledky generované týmto pracovným vláknom. Medzi tieto operátory patria: subscribeOn(), observeOn(), subscribe().&lt;br /&gt;
&lt;br /&gt;
==== Operátor subsribeOn() ====&lt;br /&gt;
&lt;br /&gt;
Tento operátor slúži na definovanie vlákna, v ktorom sa má práca metódy, na ktorú je operátor subscribeOn() volaný vykonať. Ako parameter operátora subscribeOn() môžeme použiť triedu Schedulers, ktorá disponuje metódami io(), computation(), single() a iné. Každá z týchto metód slúži pre definovanie špecifického vlákna, na ktorom bude práca metódy, na ktorú je operátor subscribeOn() aplikovaný vykonávaná . Každé z týchto vlákien má svoj špecifický účel :&lt;br /&gt;
&lt;br /&gt;
* computation() - sprístupňuje vlákno určené pre komplikovanejšiu, časovo náročnejšiu výpočtovú prácu. Maximálny počet spustených vlákien metódou computation() je limitovaný počtom procesorov.&lt;br /&gt;
* io() - sprístupňuje vlákno určené pre I/O prácu, tzn. vlákno pre asynchrónne vykonávanie inak blokujúcej I/O práce. Umožňuje vytvoriť ľubovoľný počet potrebných vlákien.&lt;br /&gt;
* single() - sprístupňuje jediné zdielané vlákno. Toto vlákno je určené pre operácie, ktoré majú byť vykonávané výhradne sekvenčne na jednom a tom istom zdielanom vlákne na pozadí.&lt;br /&gt;
&lt;br /&gt;
==== Operátor subsribe() ====&lt;br /&gt;
&lt;br /&gt;
Operátor, ktorý spája observera spolu s Observable tak, že sprostredkováva observerovi výsledky generované Observable objetkom. Aby observer mohol vidieť jednotlivé objekty generované Observable, alebo dostať informáciu o tom, či operácia skončila úspešne alebo chybou, musí byť najskôr na Observable pripojený práve použitím metódy subscribe(). Operátor subscribe() prijíma ako parameter objekt (nazývaný Observer alebo Subscriber), ktorý implementuje rozhranie obsahujúce niektorú z týchto metód :&lt;br /&gt;
&lt;br /&gt;
* onNext() - Observable volá túto metódu vždy, ak publikuje nový objekt. Parameter metódy je práve publikovaný objekt.&lt;br /&gt;
* onError() - Observable zavolá túto metódu, ak dôjde k chybe pri generovaní objektov očakávaných metódou onNext(). Pri zavolaní metódy onError(), je Observable zastavený a nepríde k ďalším volaniam metód onNext() a onComplete().&lt;br /&gt;
* onCompleted() - Observable zavolá túto metódu, ak je metóda onNext() zavolaná poslednýkrát a nenastala žiadna chyba.&lt;br /&gt;
&lt;br /&gt;
==== Operátor observeOn() ====&lt;br /&gt;
&lt;br /&gt;
Ak použijeme operátor subsribeOn(), práca Observable je presmerovaná na v ňom definované pracovné vlákno. Použitím operátora observeOn() špecifikujeme iné vlákno, v ktorom má byť po dokončení práce notifikovaný observer.&lt;br /&gt;
&lt;br /&gt;
Operátor observeOn() určuje vlákno, na ktoré má Observable prostredníctvom operátora subscribe() publikovať výsledky. Zabezpečuje presmerovanie výsledku prúdu z pracovného vlákna definovaného v operátore subscribeOn() na vlákno definované v operátore observeOn(). Ako parameter observeOn() operátora môžeme špecifikovať napríklad hlavné vlákno použitím triedy AndroidSchedulers a jej metódy mainThread() . Príklad použitia operátorov RxJava priamo v aplikácii demonštruje [[#listing:rx_operators|[listing:rx_operators]]].&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Platforma_Android&amp;diff=12774</id>
		<title>Platforma Android</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Platforma_Android&amp;diff=12774"/>
		<updated>2020-09-03T19:39:30Z</updated>

		<summary type="html">&lt;p&gt;Matus: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Praca_uvod|2|Návrh a implementácia Android aplikácie pre monitoring priemyselného procesu|Informačný systém Sensorical|Platforma Android|Návrh aplikácie nSoric aAurela|Implementácia aplikácie nSoric aAurela|Testovanie aplikácie nSoric aAurela}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
Platforma Android a životný cyklus aplikácií bežiacich na tejto platforme je výrazne odlišný od životného cyklu aplikácií bežiacich na desktope. Desktopové aplikácie bežia ako relatívne samostatné procesy nezávisle od iných, paralelne bežiacich procesov.&lt;br /&gt;
&lt;br /&gt;
Na rozdiel od desktopových aplikácií, Android aplikácie prechádzajú počas svojho behu (životného cyklu) rôznymi štádiami v závislosti na rôznych systémových udalostiach resp. prerušeniach (viď [[#lifecycle|1.1.1]]). Samotná Android aplikácia môže pozostávať zo štyroch základných súčastí medzi ktoré patria: Activity (aktivita), Content providers (poskytovatelia obsahu), Broadcast recievers (prijímatelia vysielania), Services (služby). Každá aplikácia môže byť tvorená ľubovolnou kombináciou týchto súčastí . V Aplikácii aAurela sa používa len komponenta Activity, ktorá bude ďalej bližšie opísaná.&lt;br /&gt;
&lt;br /&gt;
== Komponenta Activity ==&lt;br /&gt;
&lt;br /&gt;
Komponenta Activity (ďalej len aktivita) tvorí základ používateľského rozhrania a predstavuje obdobu okna desktopovej aplikácie, prostredníctvom ktorého používateľ s aplikáciou interaguje. Jednu aplikáciu môže tvoriť niekoľko aktivít, kde každá má svoj význam a umožňuje používateľovi grafický vstup do rozdielnych častí aplikácie. Pre vývojárov reprezentuje každá aktivita samostatnú triedu.&lt;br /&gt;
&lt;br /&gt;
=== Životný cyklus aktivity ===&lt;br /&gt;
&lt;br /&gt;
Každá aktivita v rámci jednej a tej istej aplikácie má svoj vlastný životný cyklus. Životný cyklus je reprezentovaný rôznymi stavmi, ktorými aktivita počas svojho behu prechádza. Jednotlivé stavy životného cyklu Android aktivity sú nesmierne dôležité pre správne fungovanie aplikácie ako celku. Ich úlohou je zabrániť „pádu“ aplikácie pri práci s viacerými aktivitami, prípadne pri rôznych prerušeniach behu aktivity danej aplikácie.&lt;br /&gt;
&lt;br /&gt;
Zmena stavu životného cyklu Android aktivity nastáva napr. pri zmene orientácie obrazovky zariadenia, minimalizovaní aplikácie stlačením domovského tlačidla, alebo pri prerušení aplikácie prichádzajúcim hovorom. Stavy, v ktorých sa Android aktivita môže nachádzať sú: Resumed, Paused, Stopped, Destroyed.&lt;br /&gt;
&lt;br /&gt;
* '''Resumed''' - stav kedy je aktivita v popredí, v interakcii s používateľom.&lt;br /&gt;
* '''Paused''' - stav, v ktorom je aktivita pozastavená, mimo interakcie s používateľom (čiastočne viditeľná) napr. prekrytá dialógovým oknom.&lt;br /&gt;
* '''Stoped''' - stav, v ktorom sa aktivita dostala na pozadie, stratila „pozornosť“ (úplne skrytá) napr. iná aktivita sa dostala do popredia.&lt;br /&gt;
* '''Destroyed''' - stav, kedy je aktivita úplne ukončená, odstránená zo systémovej pamäte.&lt;br /&gt;
&lt;br /&gt;
Created a Started nepovažujeme za samostatné stavy, označujú sa za stavy prechodné, čo znamená, že aktivita v nich nie je schopná zotrvať po určitý čas a takmer okamžite sa z nich posúva do stavu nasledujúceho.&lt;br /&gt;
&lt;br /&gt;
* '''Created''' - je moment, kedy systém vytvorí danú aktivitu.&lt;br /&gt;
* '''Started''' - je moment, kedy sa aktivita stáva viditeľná.&lt;br /&gt;
&lt;br /&gt;
[[File:obrazky/lifecycle.png|thumb|none|566px|alt=Životný cyklus Android aktivity spolu s metódami spätného volania |Životný cyklus Android aktivity spolu s metódami spätného volania ]]&lt;br /&gt;
&lt;br /&gt;
Metódy spätného volania slúžia na zachytenie zmeny stavu a na vykonanie akcie ešte pred tým, než sa aktivita dostane do stavu iného. Metódy spätného volania je možné implementovať v triede samotnej aktivity. V závislosti na zmene stavu aktivity sú volané metódy: onCreate(), onStart(), onResume(), onPause(), onRestart(), onStop(), onDestroy(). Jediná povinná metóda spätného volania, ktorá musí byť v triede aktivity implementovaná je metóda onCreate(). Metóda onCreate() je volaná vždy pri prvotnom vytvorení aktivity a štandardne sa v nej nastavuje grafické rozhranie aktivity, inicializujú sa potrebné objekty a podobne. V tejto časti bol použitý zdroj .&lt;br /&gt;
&lt;br /&gt;
== Princípy a nástroje využité pri vývoji aplikácie ==&lt;br /&gt;
&lt;br /&gt;
Táto časť pojednáva o základných princípoch systému Android a nástrojoch, ktoré boli pri vývoji aplikácie využité. Nástroje reprezentujú dve dôležité knižnice, na ktorých je postavené jadro aplikácie: - SQLite databáza a - asynchrónna práca s vláknami. Knižnice Room a RxJava sú vzájomne kompatibilné a v spolupráci výrazne uľahčujú vývoj robustnejších aplikácií na platforme Android.&lt;br /&gt;
&lt;br /&gt;
=== SQLite databáza na platforme Android ===&lt;br /&gt;
&lt;br /&gt;
SQLite je lokálna SQL databáza (uložená ako súbor v zariadení), ktorá disponuje všetkými funkciami relačných databáz. Platforma Android umožňuje pre ukladanie väčšieho množstva štruktúrovaných dát implementovať práve databázu typu SQLite.&lt;br /&gt;
&lt;br /&gt;
Pre implementáciu SQLite databázy v aplikácii je využitá knižnica Room. Výhody, pre ktoré bola knižnica Room zvolená sú: výrazné skrátenie a sprehľadnenie kódu, validácia správnosti SQL príkazov už počas kompilácie, priama podpora knižnice RxJava.&lt;br /&gt;
&lt;br /&gt;
=== Knižnica Room ===&lt;br /&gt;
&lt;br /&gt;
Knižnica Room predstavuje abstraktnú vrstvu nad vrstvou SQLite databázy. Slúži pre vytvorenie databázy ako aj pre prístup k jej dátam.&lt;br /&gt;
&lt;br /&gt;
Knižnica Room sprostredkováva mapovanie databázových relácií na objekty v jazyku Java na základe spracovávania anotácií. Anotácie sú špeciálne príkazy, ktoré sú v prípade knižnice Room priradené k definíciám tried, metód a premenných. Pri kompilácii Room na základe použitej anotácie vygeneruje Java kód, na ktorý sa prostredníctvom anotácií odkazuje. Tento spôsob práce je označovaný aj ako ORM (Object-Relational Mapping). V tejto časti je použitý zdroj informácii .&lt;br /&gt;
&lt;br /&gt;
==== Množina tried pre vytvorenie SQLite databázy pomocou knižnice Room ====&lt;br /&gt;
&lt;br /&gt;
Pre vytvorenie a prácu s SQLite databázou pomocou knižnice Room je potrebné implementovať základnú množinu Java tried: Entita, DAO a Databáza. Pri týchto triedach je potrebné použiť anotácie @Entity, @DAO, @Database.&lt;br /&gt;
&lt;br /&gt;
''@Entity'' - anotácia triedy, ktorá reprezentuje entitu databázy. Jednotlivé premenné triedy reprezentujú atribúty danej entity. K atribútom je potrebné umožniť prístup cez metódy get a set .&lt;br /&gt;
&lt;br /&gt;
''@DAO'' - (Data accessing object) anotácia rozhrania, ktoré obsahuje metódy pre prístup do databázy. Jednotlivé metódy majú priradené anotácie na základe SQL operácie, ktorú vykonávajú:&lt;br /&gt;
&lt;br /&gt;
''@Insert'' - vkladanie záznamov do databázy,&lt;br /&gt;
&lt;br /&gt;
''@Update'' - aktualizovanie existujúcich záznamov,&lt;br /&gt;
&lt;br /&gt;
''@Delete'' - mazanie záznamov,&lt;br /&gt;
&lt;br /&gt;
''@Query'' - alternatívna možnosť definovania vlastných SQL príkazov.&lt;br /&gt;
&lt;br /&gt;
Parameterom týchto anotácií je textový reťazec reprezentujúci SQL príkaz, ktorý daná metóda vykonáva. Návratový typ metód DAO musí korešpondovať s výstupom SQL príkazu, ktorý daná metóda vykonáva .&lt;br /&gt;
&lt;br /&gt;
''@Database'' - anotácia triedy, z ktorej Room vytvorí databázu. Parameter anotácie musí obsahovať zoznam všetkých entít, resp. Java tried s anotáciou @Entity, ktoré majú byť transformované na entity databázy. Pri triede databázy je dôležité uplatnenie Singleton návrhového vzoru, ktorý zabezpečí vytvorenie a prístupnosť jedinej inštancie triedy databázy po celý čas behu aplikácie .&lt;br /&gt;
&lt;br /&gt;
==== Ďalšie anotácie knižnice Room ====&lt;br /&gt;
&lt;br /&gt;
Použitie nasledujúcich anotácií je nepovinné, avšak pri samotnej implementácii značne uľahčuje prácu s databázou. Tieto anotácie sa používajú ako anotácie premenných tried jednotlivých entít .&lt;br /&gt;
&lt;br /&gt;
''@PrimaryKey'' - anotácia premennej triedy entity, ktorá v databáze reprezentuje primárny kľúč. Voliteľný parameter tejto anotácie umožňuje explicitne zadeklarovať automatické generovanie primárneho kľúča (autoincrement).&lt;br /&gt;
&lt;br /&gt;
''@ForeignKey'' - umožňuje vytvorenie relácie medzi jednotlivými entitami pomocou cudzích kľúčov.&lt;br /&gt;
&lt;br /&gt;
''@ColumnInfo'' - ako parameter tejto anotácie je použitý textový reťazec, ktorý definuje názov atribútu, pod ktorým bude premenná triedy entity vložená do databázy.&lt;br /&gt;
&lt;br /&gt;
''@Ignore'' - anotácia, ktorú je možné použiť v prípade, ak má Room ignorovať danú premennú triedy, napr. nepoužiť premennú ako atribút entity v databáze.&lt;br /&gt;
&lt;br /&gt;
Použitie knižnice Room demonštrujú ukážky priamo z jej implementácie v aplikácii v časti [[#implementacia_sql|[implementacia_sql]]].&lt;br /&gt;
&lt;br /&gt;
=== Práca s vláknami v systéme Android ===&lt;br /&gt;
&lt;br /&gt;
Pri spustení Android aplikácie (nebežiacej na pozadí), vytvorí systém pre túto aplikáciu nový Linux proces, ktorý má pre svoj beh vyhradené jednovláknové operácie. Systémové nastavenie všetkých komponentov jednej aplikácie je také, že všetky bežia na jednom procesorovom vlákne nazývanom hlavné vlákno (main thread).&lt;br /&gt;
&lt;br /&gt;
Úlohou hlavného vlákna je zabezpečiť responzívnosť a správne fungovanie používateľského rozhrania. Hlavné vlákno zodpovedá za delegovanie udalostí na jednotlivé View komponenty (tlačidlá, textové polia…). Všetky tieto komponenty bežiace na hlavnom vlákne musia byť neustále dostupné pre interakciu s používateľom aplikácie. To znamená, ak používateľ klikne na tlačidlo, musí mať hlavné vlákno dostatok pamäťových prostriedkov na spracovanie obsluhy tejto udalosti.&lt;br /&gt;
&lt;br /&gt;
V prípade vykonávania iného, časovo náročnejšieho (blokujúceho) procesu na hlavnom vlákne, je hlavné vlákno zablokované, prestáva odpovedať a systém celý proces aplikácie ukončí. Z tohto dôvodu je potrebné časovo náročnejšie operácie vykonávať v inom, paralelnom tzv. pracovnom vlákne (worker thread) . Pre potrebu obsluhy časovo náročných operácií v paralelných vláknach je v aplikácii použitá knižnica RxJava.&lt;br /&gt;
&lt;br /&gt;
=== Knižnica RxJava ===&lt;br /&gt;
&lt;br /&gt;
RxJava je knižnica, ktorá umožňuje reaktívne resp. udalosťami riadené programovanie. Základný návrhový vzor využívaný touto knižnicou je Observer. Tento návrhový vzor funguje na princípe akcie a reakcie. Observer predstavuje objekt, ktorý sleduje stav iného objektu a v prípade zmeny stavu sledovaného objektu je Observer automaticky notifikovaný. Tento návrhový vzor je v knižnici RxJava využitý pri sledovaní priebehu asynchrónne vykonávanej práce na pracovných vláknach.&lt;br /&gt;
&lt;br /&gt;
Práve možnosť asynchrónneho vykonávania operácií predstavuje jednu z najväčších predností knižnice RxJava. V nasledujúcej časti je použitý zdroj , pričom je zachovaná terminológia oficiálnej dokumentácie knižnice RxJava.&lt;br /&gt;
&lt;br /&gt;
==== Spolupráca knižníc RxJava a Room ====&lt;br /&gt;
&lt;br /&gt;
implicitne zakazuje prácu s SQLite databázou na hlavnom aplikačnom vlákne, pretože práca s databázou predstavuje časovo náročnejšie operácie. Z tohto dôvodu je nutné operácie spojené s SQLite databázou vykonávať asynchrónne.&lt;br /&gt;
&lt;br /&gt;
* '''Observable''' reprezentuje ľubovoľný objekt, ktorý môže získavať dáta z dátového zdroja (generuje hodnoty - metódy DAO) a ktorého stav môže byť sledovaný ďalšími objektmi (observers).&lt;br /&gt;
* '''Observer''' predstavuje ľubovoľný objekt, ktorý sleduje stav Observable a má byť v prípade zmeny jeho stavu notifikovaný (prijíma hodnoty).&lt;br /&gt;
&lt;br /&gt;
Vďaka vzájomnej kompatibilite knižníc RxJava a Room je možné použiť niektorú z tried knižnice RxJava ako wrapper (obal) návratového typu metódy DAO. Použitím niektorej observable triedy knižnice RxJava ako wrapper návratového typu metódy DAO, môže byť následne celá práca tejto metódy presmerovaná na pracovné vlákno aplikovaním RxJava operátorov pre asynchrónnu prácu.&lt;br /&gt;
&lt;br /&gt;
==== Základné observable triedy knižnice RxJava ====&lt;br /&gt;
&lt;br /&gt;
* trieda '''Single''' - Observable, ktorá vracia buď jeden objekt alebo chybu.&lt;br /&gt;
* trieda '''Completable''' - Observable, vracajúca len výsledok operácie vo forme informácie, či bola úloha dokončená, alebo prišlo k chybe, samotné dáta nevracia.&lt;br /&gt;
* trieda '''Maybe''' - Observable, ktorá podobne ako Single vracia jeden objekt, ale nemusí žiaden. Na rozdiel od Single nevyhlási chybu a vráti prázdnu hodnotu.&lt;br /&gt;
&lt;br /&gt;
Príklad použitia observable triedy Maybe demonštruje [[#listing:dao|[listing:dao]]], z jej implementácie priamo v aplikácii.&lt;br /&gt;
&lt;br /&gt;
==== Operátory knižnice RxJava pre asynchrónne vykonávanie operácií ====&lt;br /&gt;
&lt;br /&gt;
Operátory knižnice RxJava slúžia nielen na zadefinovanie pracovného vlákna, na ktorom sa bude asynchrónna práca (metóda) vykonávať, ale aj na špecifikáciu vlákna, ktoré má prijímať výsledky generované týmto pracovným vláknom. Medzi tieto operátory patria: subscribeOn(), observeOn(), subscribe().&lt;br /&gt;
&lt;br /&gt;
==== Operátor subsribeOn() ====&lt;br /&gt;
&lt;br /&gt;
Tento operátor slúži na definovanie vlákna, v ktorom sa má práca metódy, na ktorú je operátor subscribeOn() volaný vykonať. Ako parameter operátora subscribeOn() môžeme použiť triedu Schedulers, ktorá disponuje metódami io(), computation(), single() a iné. Každá z týchto metód slúži pre definovanie špecifického vlákna, na ktorom bude práca metódy, na ktorú je operátor subscribeOn() aplikovaný vykonávaná . Každé z týchto vlákien má svoj špecifický účel :&lt;br /&gt;
&lt;br /&gt;
* computation() - sprístupňuje vlákno určené pre komplikovanejšiu, časovo náročnejšiu výpočtovú prácu. Maximálny počet spustených vlákien metódou computation() je limitovaný počtom procesorov.&lt;br /&gt;
* io() - sprístupňuje vlákno určené pre I/O prácu, tzn. vlákno pre asynchrónne vykonávanie inak blokujúcej I/O práce. Umožňuje vytvoriť ľubovoľný počet potrebných vlákien.&lt;br /&gt;
* single() - sprístupňuje jediné zdielané vlákno. Toto vlákno je určené pre operácie, ktoré majú byť vykonávané výhradne sekvenčne na jednom a tom istom zdielanom vlákne na pozadí.&lt;br /&gt;
&lt;br /&gt;
==== Operátor subsribe() ====&lt;br /&gt;
&lt;br /&gt;
Operátor, ktorý spája observera spolu s Observable tak, že sprostredkováva observerovi výsledky generované Observable objetkom. Aby observer mohol vidieť jednotlivé objekty generované Observable, alebo dostať informáciu o tom, či operácia skončila úspešne alebo chybou, musí byť najskôr na Observable pripojený práve použitím metódy subscribe(). Operátor subscribe() prijíma ako parameter objekt (nazývaný Observer alebo Subscriber), ktorý implementuje rozhranie obsahujúce niektorú z týchto metód :&lt;br /&gt;
&lt;br /&gt;
* onNext() - Observable volá túto metódu vždy, ak publikuje nový objekt. Parameter metódy je práve publikovaný objekt.&lt;br /&gt;
* onError() - Observable zavolá túto metódu, ak dôjde k chybe pri generovaní objektov očakávaných metódou onNext(). Pri zavolaní metódy onError(), je Observable zastavený a nepríde k ďalším volaniam metód onNext() a onComplete().&lt;br /&gt;
* onCompleted() - Observable zavolá túto metódu, ak je metóda onNext() zavolaná poslednýkrát a nenastala žiadna chyba.&lt;br /&gt;
&lt;br /&gt;
==== Operátor observeOn() ====&lt;br /&gt;
&lt;br /&gt;
Ak použijeme operátor subsribeOn(), práca Observable je presmerovaná na v ňom definované pracovné vlákno. Použitím operátora observeOn() špecifikujeme iné vlákno, v ktorom má byť po dokončení práce notifikovaný observer.&lt;br /&gt;
&lt;br /&gt;
Operátor observeOn() určuje vlákno, na ktoré má Observable prostredníctvom operátora subscribe() publikovať výsledky. Zabezpečuje presmerovanie výsledku prúdu z pracovného vlákna definovaného v operátore subscribeOn() na vlákno definované v operátore observeOn(). Ako parameter observeOn() operátora môžeme špecifikovať napríklad hlavné vlákno použitím triedy AndroidSchedulers a jej metódy mainThread() . Príklad použitia operátorov RxJava priamo v aplikácii demonštruje [[#listing:rx_operators|[listing:rx_operators]]].&lt;/div&gt;</summary>
		<author><name>Matus</name></author>
		
	</entry>
</feed>