}w !"#$%&'()+,-./012345
M ASARYKOVA UNIVERZITA FAKULTA INFORMATIKY
Mobilní aplikace pro inventarizaci majetku ˇ B AKALÁ RSKÁ PRÁCE
Pavel Synek
Brno, Jaro 2015
Prohlášení Prohlašuji, že tato bakaláˇrská práce je mým puvodním ˚ autorským dílem, které jsem vypracoval samostatnˇe. Všechny zdroje, prameny a literaturu, které jsem pˇri vypracování používal nebo z nich cˇ erpal, v práci rˇ ádnˇe cituji s uvedením úplného odkazu na pˇríslušný zdroj.
Pavel Synek
Vedoucí práce: RNDr. Vít Rusnák ˇ ii
Podˇekování Rád bych podˇekoval Mgr. Vítu Rusnákovi, ˇ vedoucímu mojí práce, za konzultace a pomoc pˇri rˇ ešení. Také bych chtˇel podˇekovat mojí rodinˇe a pˇrátelum, ˚ kteˇrí mi byli oporou bˇehem celého studia.
iii
Shrnutí Tato bakaláˇrská práce se vˇenuje problematice inventarizace u skautské organizace Junák. V teoretické cˇ ásti je problém pˇredstaven z právního hlediska a následnˇe je rozebrán návrh aplikace, která umožní správcum ˚ majetku provádˇet offline inventarizaci pomocí zaˇrízení s operaˇcním systémem Android. V praktické cˇ ásti jsou popsány implementaˇcní detaily, použité knihovny a technologie. Výstupem této práce je mobilní aplikace Skautská Inventarizace.
iv
Abstract This Bachelor thesis deals with the problematics of inventorying at Junák scout organisation. The theoretical part introduces this issue from the legal perspective. This introduction is followed by an analysis of the application which allows the property managers to carry out offline inventorying using Android devices. The practical part consist of a description of implementation details, used libraries and technologies. The output of this work is a mobile application named Skautská Inventarizace.
v
Klíˇcová slova Android, inventarizace, mobilní inventarizace, Junák, skautIS
vi
Obsah 1 2
3
4
Úvod . . . . . . . . . . . . . . . . . . . . Návrh aplikace . . . . . . . . . . . . . . 2.1 Persony . . . . . . . . . . . . . . . . 2.1.1 Persona - Petr . . . . . . . . 2.1.2 Persona - Lukáš . . . . . . . 2.1.3 Výsledek analýzy person . 2.2 Typický prubˇ ˚ eh použití aplikace . 2.3 Návrh databáze . . . . . . . . . . . Implementace aplikace . . . . . . . . . 3.1 Komunikace se skautIS API . . . . 3.1.1 Autentizace . . . . . . . . . 3.1.2 Retrofit . . . . . . . . . . . . 3.2 Databáze . . . . . . . . . . . . . . . 3.2.1 SQLite . . . . . . . . . . . . 3.2.2 Realm . . . . . . . . . . . . 3.3 RxJava . . . . . . . . . . . . . . . . 3.3.1 Základní prvky . . . . . . . 3.3.2 Vznik Observables . . . . . 3.3.3 Životní cyklus Observables 3.3.4 Operátory . . . . . . . . . . 3.3.5 Subjekty . . . . . . . . . . . 3.4 Další použité knihovny . . . . . . . 3.4.1 Retrolambda . . . . . . . . . 3.4.2 ZBar . . . . . . . . . . . . . 3.4.3 Butter Knife . . . . . . . . . 3.5 Uživatelské rozhraní . . . . . . . . Závˇer . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
1 2 2 3 3 4 4 4 6 6 7 7 9 10 11 13 13 13 14 14 15 15 15 16 16 17 19
vii
1 Úvod ˇ Junák je nejvˇetší skautská organizace v Ceské Republice. Sdružuje více než 50000 cˇ lenu˚ ve 2000 organizacích [4]. Vˇetšina tˇechto organizací disponuje urˇcitým majetkem, který je podle zákona cˇ . 563/91 Sb. o úˇcetnictví nutno inventarizovat. Zárovenˇ jsou úˇcetní jednotky povinny prokázat provedení inventarizace u veškerého majetku a závazku˚ po dobu 5 let po jejím provedení [6]. Tento zákon definuje dva druhy inventarizace, fyzickou a dokladovou. Fyzická inventura probíhá u majetku, u kterého lze vizuálnˇe zjistit jeho existenci a dokladová inventura probíhá u závazku˚ a majetku, u kterého nelze vizuálnˇe zjistit jeho existenci, a to vˇcetnˇe jiných aktiv, jiných pasiv a skuteˇcností úˇctovaných v knize podrozvahových úˇctu˚ [6]. Dále se budu zabývat pouze fyzickou inventarizací. Stˇredisko musí evidovat veškerý majetek s poˇrizovací cenou nad 3000 Kˇc. V rámci svých pˇredpisu˚ muže ˚ evidovat i majetek s nižší poˇrizovací cenou, napˇr. pokud se jedná o majetek poˇrízený z nˇejaké úˇcelové dotace, nebo jako dar [9]. Junák má k dispozici rozsáhlý informaˇcní systém skautIS, který umožnuje ˇ mimo jiné elektronicky evidovat majetek každé jednotky. V soucˇ asnosti probíhá inventarizace ruˇcnˇe zapisováním aktuálního stavu skladu na papír a následným dohledáním odpovídajících položek ve skautISu a manuálním vložením inventury do systému. Cílem práce je navrhnout a vytvoˇrit mobilní aplikaci pro platformu Android, která umožní správcum ˚ majetku Junáka provádˇet inventarizaci elektronicky pˇrímo na místˇe skladu. Data budou uložena v lokální databázi, takže vlastní provedení inventury bude moci probíhat offline. Proces inventarizace se znaˇcnˇe urychlí díky možnosti skenování cˇ árových nebo QR (quick response) kódu˚ na vˇecech ve skladu. Aplikace také umožní vyfotit aktuální podobu vˇeci a odeslat fotku spolu s daty o provedených inventurách zpˇet do skautIsu.
1
2 Návrh aplikace Návrh zaˇcal seznámením s problémem a poté probˇehlo sestavení funkˇcních požadavku. ˚ Funkˇcní požadavky popisují služby, které má systém poskytovat, rˇ íkají jak má systém reagovat na urˇcité vstupy a jak se má systém chovat v urˇcitých situacích. V urˇcitých pˇrípadech mohou funkˇcní požadavky také stanovit, co systém nemá dˇelat [10]. ∙
Aplikace komunikuje se skautISem.
∙
Autentizace probíhá pomocí pˇrihlašovacích údaju˚ do skautISu.
∙
Sklady jsou seˇrazeny hierarchicky.
∙
U každé položky skladu mužeme ˚ vidˇet její popis, inventární cˇ íslo, poˇrizovací cenu, datum poˇrízení a datum poslední inventarizace.
∙
Položku skladu lze vyfotit.
∙
Inventarizace probíhá bud’ naˇctením QR kódu nebo manuálnˇe oznacˇ ením položky.
∙
Inventarizace probíhá bez nutnosti internetového pˇripojení.
Neménˇe duležitou ˚ cˇ ástí návrhu je stanovení nefunkˇcních požadavku. ˚ Nefunkˇcní požadavky jsou omezení služeb nebo funkcí poskytovaných systémem. Zahrnují vymezení cˇ asu, procesu vývoje a dodržovaných standardu. ˚ Nefunkˇcní požadavky jsou cˇ asto aplikovány na celý systém a ne na individuální cˇ ásti nebo služby [10]. Byly stanoveny následující nefunkˇcní požadavky: ∙
Aplikace bˇeží na operaˇcním systému Android a je naprogramovaná v Javˇe.
∙
Aplikace je zdokumentovaná a rozšiˇritelná.
Na základˇe požadavku˚ jsem vytvoˇril diagram pˇrípadu˚ užití, který je zachycen na obrázku 2.1.
2.1
Persony
Jedním z nástroju˚ použitých pˇri návrhu jsou persony. Persony jsou fiktivní osoby, které reprezentují ruzné ˚ druhy uživatelu, ˚ kteˇrí používají ur2
2. N ÁVRH APLIKACE
Obrázek 2.1: Diagram pˇrípadu˚ užití cˇ itý produkt [8]. Pomáhají s pˇresným vymˇerˇ ením cílové skupiny, pro kterou chceme aplikaci vyvíjet. Pro úˇcely aplikace Skautská Invetarizace byly vytvoˇreny dvˇe persony. 2.1.1 Persona - Petr Petrovi je 25 let a pusobí ˚ jako vedoucí stˇrediska. Je dlouhodobým cˇ lenem inventarizaˇcní komise a nedˇelá mu problém provádˇet inventuru s tužkou a papírem. Nerad si zvyká na nové vˇeci, hlavnˇe pokud by jejich použití nebylo intuitivní. 2.1.2 Persona - Lukáš Lukášovi je 17 let a je rˇ adovým cˇ lenem oddílu. Sice ho moc nezajímá samotná inventarizace, ale je fanda mobilních telefonu˚ a tak se dobrovolnˇe pˇrihlásí do inventarizaˇcní komise, aby si vyzkoušel práci s aplikací Skaut3
2. N ÁVRH APLIKACE ská Inventarizace. Nejde mu uživatelskou pˇrívˇetivost, protože si dokáže poradit i se špatnˇe navrženými aplikacemi. Baví ho využívat nejmodernˇejší technologie k rˇ ešení každodenních problému. ˚ 2.1.3 Výsledek analýzy person Vytvoˇrením dvou modelových osob vidíme, že aby byl Petruv ˚ pˇrechod z ruˇcní inventarizace na elektronickou co nejjednodušší, tak musí aplikace být velmi jednoduchá a uživatelsky pˇrívˇetivá. To naopak nezajímá Lukáše, kterého pouhá existence specializované aplikace pobídla k zapojení do procesu inventarizace Junáka. Lukáš tedy nemá žádné speciální požadavky.
2.2
Typický prubˇ ˚ eh použití aplikace
Po stažení aplikace a jejím spuštˇení uvidí uživatel pˇrihlašovací obrazovku, do které zadá své pˇrihlašovací jméno a heslo do skautISu. Po úspˇešném pˇrihlášení uživatel pˇrejde na obrazovku s výbˇerem role. To je duležité, ˚ protože každý uživatel muže ˚ mít více rolí a vybraná role ovlivnuje, ˇ s jakými sklady muže ˚ pracovat. Po výbˇeru vhodné role pˇrejde na obrazovku, která vypíše všechny sklady, se kterými muže ˚ vybraná role pracovat. Po výbˇeru jednoho ze skladu˚ dojde k naˇctení všech vˇecí ve skladech, obrázku˚ a inventur a aplikace je pˇripravená k použití offline. Uživatel muže ˚ vyrazit do terénu a výbˇerem volby inventarizovat muže ˚ bud’ skenerem nebo ruˇcnˇe vybrat pˇredmˇety, které jsou ve skladu. Po dokonˇcení inventury a obnovení pˇripojení k internetu muže ˚ volbou "synchronizovat"odeslat provedené zmˇeny na server.
2.3
Návrh databáze
Podle požadavku˚ a diagramu pˇrípadu˚ užití mužeme ˚ sestavit ER (entitnˇe relaˇcní) model databáze. ER diagram je nástroj pro sémantické modelování dat používaný k popsání dat. Abstraktnˇe popsaná data nazýváme konceptuální model. Pokud uznáme, že tento model vˇernˇe zachycuje realitu, mu˚ žeme ho nazvat schématem. Schéma znamená trvalý, fixní popis struktury dat [5]. Základní trojicí entit, které musíme v databázi uchovávat, je Warehouse, Item a Inventory. Entita Warehouse má rekurzivní vztah sama se sebou, protože každý sklad muže ˚ mít pˇriˇrazený jeden nadˇrazený sklad. Dále každý sklad muže ˚ obsahovat nula nebo více položek skladu (entita Item). Každá z položek má vazbu jak na sklad, tak na poslední provedenou inventuru. Mimo údaju˚ popisujících položku si také uchovává informaci, 4
2. N ÁVRH APLIKACE zda byla uživatelem zmˇenˇena a zda je vyžadována synchronizace. Každá inventura (entita Inventory) si také ukládá informaci o tom, zda byla zmˇenˇena. Hotové ERD schéma je na obrázku 2.2.
Obrázek 2.2: Entitnˇe relaˇcní model databáze
5
3 Implementace aplikace Aplikaci je naprogramovaná ve vývojovém prostˇredí Android Studio. Je to verze programu IntelliJ IDEA obsahující Android SDK (Software Development Kit), editor uživatelského rozhraní, Android Lint (nástroj pro statickou analýzu kódu) a sadu emulátoru˚ umožnujících ˇ vývoj i bez vlastnictví mobilního telefonu s Androidem. Minimální podporovanou verzí Androidu je 4.1.x, což odpovídá úrovni API 16. Tuto verzi používá v souˇcasnosti pˇribližnˇe 89% zaˇrízení [1] a proto je rozumným kompromisem mezi možnostmi použít nejnovˇejší cˇ ásti Android API a množstvím podporovaných zaˇrízení. Pˇri implementaci byly použity tyto open-source knihovny: ∙
Android Support Library v7
∙
Retrofit
∙
Simple XML Converter
∙
Butter Knife
∙
Timber
∙
TwoWayView
∙
Barcodescanner - ZBar
∙
Realm
∙
Material-ish Progress
∙
RxJava
∙
RxLoader
∙
Retrolambda Nˇekteré z knihoven jsou podrobnˇeji popsané v následujících kapitolách.
3.1
Komunikace se skautIS API
Hlavní funkcí aplikace je komunikace se skautIS API, které komunikuje pomocí protokolu SOAP (Simple Object Access Protocol). SOAP definuje obálkovou strukturu, která nese data v tˇele zprávy a kontrolní informace v hlaviˇcce [7]. 6
3. I MPLEMENTACE APLIKACE 3.1.1 Autentizace SkautIS nedává z bezpeˇcnostních duvod ˚ u˚ k dispozici API pro pˇrihlášení pomocí protokolu SOAP. Autentizace probíhá vždy pˇres pˇrihlašovací formuláˇr skautISu, který v pˇrípadˇe aplikací, které využívají jeho služby, uživatele po pˇrihlášení pˇresmˇeruje na stránku té aplikace. Tento pˇrístup by bylo možné použít i v mobilní aplikaci, ale bylo by nutné použít komponentu WebView, která by uživateli zobrazila stejnou pˇrihlašovací stránku skautISu, jako kdyby se pˇrihlašoval ve webovém prohlížeˇci. Lepším rˇ ešením je použít klasickou pˇrihlašovací obrazovku (obrázek 3.1) a požadavek, který by byl odeslán webovým formuláˇrem je odeslán pomocí Retrofitu. Ze stránky, kterou server vrátí je poté vyparsován pˇrihlašovací token. Tento token se spolu s unikátním ID aplikace pˇrikládá ke všem WSDL požadavkum. ˚
Obrázek 3.1: Pˇrihlašovací obrazovka 3.1.2 Retrofit Android nemá nativní podporu komunikace se SOAP API. Existuje nˇekolik knihoven jako IceSoap1 a ksoap2-android2 , které tuto podporu nabízejí, ale 1. https://github.com/AlexGilleran/IceSoap 2. https://code.google.com/p/ksoap2-android/
7
3. I MPLEMENTACE APLIKACE ani jedna nesplnuje ˇ základní požadavek, a to práci s RxJava Observables. Proto byla zvolena knihovna Retrofit, která umí vracet právˇe výsledek typu Observable
. Retrofit funguje tak, že na základˇe vytvoˇreného interface vygeneruje funkce pro volání vzdáleného API. Jako pˇríklad je uvedena funkce, která získá informace o všech skladech, se kterými má pˇrihlášená osoba právo manipulovat.
public interface SkautWarehouseApi { @POST"/Material.asmx" Observable<WarehouseAllResult> getAllWarehouses(@Body WarehouseAll body); } WarehouseAll je objekt, který v sobˇe nese informace nutné k vytvoˇrení požadavku ve správném formátu, tzn. v tomto pˇrípadˇe ID aplikace, unikátní pˇrihlašovací token a ID jednotky, pod kterou je uživatel pˇrihlášen. Tento objekt obsahuje také XPath informace nutné k vygenerování XML ve správném formátu. Na generování XML je použit Retrofit plugin Simple XML Converter. @Namespace(reference = "https://is.skaut.cz/") @Root(name = "soap:Envelope") public class WarehouseAll { @Path("soap:Body/WarehouseAll/warehouseAllInput") @Element(name = "ID_Unit") private long unitID; @Path("soap:Body/WarehouseAll/warehouseAllInput") @Element(name = "ID_Application") private String applicationID; @Path("soap:Body/WarehouseAll/warehouseAllInput") @Element(name = "ID_Login") private String loginID; public WarehouseAll() { // set all params } 8
3. I MPLEMENTACE APLIKACE
}) Objekt WarehouseAllResult slouží k deserializaci odpovˇedi a obsahuje List objektu˚ typu Warehouse.
@Namespace(reference = "https://is.skaut.cz/") @Root(name = "soap:Envelope", strict = false) public class WarehouseAllResult { @Path("soap:Body/WarehouseAllResponse") @ElementList(name = "WarehouseAllResult", entry = "WarehouseAllOutput") private List<Warehouse> warehouseList;
}
public List<Warehouse> getWarehouseList() { return warehouseList; }
Pro každý požadavek existuje dvojice tˇríd, která reprezentuje odchozí a pˇríchozí data. Každý požadavek vrací Observable, se kterým se pak dále pracuje pomocí knihovny RxJava popsané v sekci 3.3.
3.2
Databáze
Jednou z hlavních funkcí aplikace je práce s lokálními daty, tzn. jejich uložení, zobrazení a modifikace. Proto je nutné vybrat vhodný databázový systém podle následujících požadavku: ˚ Jednoduchost použití – Databázový model aplikace (na obrázku 2.2) je velmi jednoduchý a pˇri práci s ní nejsou potˇreba komplikované SQL dotazy, a proto se pˇri výbˇeru databáze mužeme ˚ zamˇerˇ it na jednoduchost integrace do aplikace. Rychlost – Rychlost databáze není zásadním kritériem, protože aplikace nepracuje s velkými objemy dat. Na druhou stranu jsou zaˇrízení s operaˇcním systémem Android cˇ asto omezené jak výkonem procesoru, tak množstvím operaˇcní pamˇeti a zárovenˇ je kratší doba nacˇ ítání a zpracování dat základem dobrého UX (User Experience). 9
3. I MPLEMENTACE APLIKACE Databázový model prošel dvˇema stupni vývoje. Nejdˇríve byl použit výchozí zpusob ˚ ukládání dat na Androidu, nativní SQLite databáze. Z du˚ vodu, ˚ které jsou popsány v následující podsekci, byla aplikace pˇrevedena na NoSQL databázové úložištˇe Realm.
3.2.1 SQLite Operaˇcní systém Android má plnou podporu SQLite bez nutnosti použít jakoukoliv knihovnu. SQLite nepoužívá, na rozdíl od napˇr. MySQL nebo PostgreSQL, klient-server architekturu, ale veškerá data ukládá v jednom multiplatformním souboru s pˇríponou .dbm. Android API poskytuje pˇrístup k databázi pomocí tˇrídy SQLiteOpenHelper. Nejprve vytvoˇríme vlastní tˇrídu, která dˇedí z tˇrídy SQLiteOpenHelper a definuje SQL dotazy pro vytvoˇrení tabulek v databázi. Pomocí instance této tˇrídy mužeme ˚ pˇristupovat k databázi. Následuje pˇríklad vložení nového skladu do databáze. Pˇríklad pˇredpokládá existenci tˇrídy WarehouseEntry, která popisuje názvy sloupcu˚ a název tabulky se sklady.
SQLiteDatabase database = myDbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(WarehouseEntry.COLUMN_ID, id); values.put(WarehouseEntry.COLUMN_PARENT_ID, parent_id); values.put(WarehouseEntry.COLUMN_NAME, name); long insertedRowId = database.insert( WarehouseEntry.TABLE_NAME, null, values); ˇ Ctení z databáze je ještˇe složitˇejší, protože je nutné vytvoˇrit projekci, která definuje, které sloupce chceme vrátit a další objekt, který popisuje rˇ azení výsledných dat. Výsledkem dotazu je instance tˇrídy Cursor, která umožnuje ˇ nad výsledkem iterovat. Ke zmˇenˇe databázového úložištˇe došlo kvuli ˚ problémum ˚ s pˇrístupem v nˇekolika vláknech najednou a také kvuli ˚ množství kódu, které bylo pro pˇripojení k databázi vytváˇret a udržovat. Protože zmˇena probˇehla v rané cˇ ásti vývoje, nezpusobila ˚ žádné problémy. 10
3. I MPLEMENTACE APLIKACE 3.2.2 Realm Realm je NoSQL úložištˇe vyvinuté v první rˇ adˇe na mobilní zaˇrízení. Jeho hlavními výhodami jsou jednoduchost a rychlost, tudíž je to vhodné databázový systém pro vyvíjenou aplikaci. Má nˇekolik nevýhod, které popíšu v další cˇ ásti. Na obrázku 3.3 je benchmark porovnávající rychlost Realmu, SQLite a dalších knihoven, které používají SQLite. Na rozdíl od ostatních
Obrázek 3.2: Porovnání rychlosti Realmu, SQLite a dalších knihoven používajících SQLite (zdroj: https://realm.io/news/introducing-realm/) NoSQL databází je u Realmu nutné pevnˇe definovat databázový model. Kvuli ˚ tomu je nutné v pˇrípadˇe zmˇeny modelu provést migraci, stejnˇe jako u SQL databází. Model se definuje tˇrídou, která dˇedí ze tˇrídy RealmObject.
public class Warehouse extends RealmObject { @PrimaryKey private long id; private String name; private Warehouse parentWarehouse;
11
3. I MPLEMENTACE APLIKACE
/* gettery a settery */ } Anotace @PrimaryKey je nepovinná a její použití o nˇeco zpomalí vkládání dat, ale dotazy budou rychlejší. Tato anotace také umožnuje ˇ použít metodu createOrUpdate, která v pˇrípadˇe, že se v již v databázi nachází objekt se shodným primárním klíˇcem, pˇrepíše stávající objekt novým. Realm nepodporuje složené klíˇce a primární klíˇc musí být bud’ rˇ etˇezec nebo cˇ íslo (datový typ short, int nebo long) [3]. Je nutné, aby všechny promˇenné mˇely getter a setter, protože Realm pˇri kompilaci vygeneruje tˇrídu WarehouseRealmProxy, která je potomkem tˇrídy Warehouse a má pˇrepsané gettery a settery. Získávání dat z Realmu probíhá následujícím zpusobem: ˚
RealmQuery<Warehouse> query = realm.where(Warehouse.class); RealmResults<Warehouse> allWarehouses = query.findAll(); Warehouse firstWarehouse = query.findFirst(); Tˇrída RealmResults implementuje rozhraní List, tudíž je v ní možné vyhledávat, rˇ adit její prvky a pˇredávat ji všude, kde se oˇcekává typ List. Vkládání dat do Realmu probíhá následujícím zpusobem: ˚
Warehouse warehouse = new Warehouse(); warehouse.setId(5); warehouse.setName("Test"); warehouse.setParentWarehouse(null); realm.beginTransaction(); Warehouse realmWarehouse = realm.copyToRealm(warehouse); realm.commitTransaction(); Veškerý zápis musí probíhat v transakcích. Pokud by tˇrída Warehouse nemˇela primární klíˇc, bylo by na vložení možné použít realm.createObject(Warehouse.class); a až poté nastavit hodnoty promˇenných. Protože primární klíˇc má, tento zpusob ˚ není vhodný, protože by pˇri vkládání mohlo dojít ke kolizi s existujícím objektem, který má nastavené výchozí id a celá transakce by selhala. Velkou nevýhodou Realmu je skuteˇcnost, že objekty jsou vázané na instanci Realmu, která je vázaná na vlákno, ve kterém byla vytvoˇrena. To znamená, že nelze objekty používat v jiném vláknˇe, než v kterém byly vytvorˇ eny. To má na platformˇe Android velký dopad, protože by se mˇely všechny 12
3. I MPLEMENTACE APLIKACE nároˇcnˇejší operace provádˇet mimo hlavní vlákno, aby nebrzdily uživatelské rozhraní. Tento problém se mi nepodaˇrilo vyˇrešit, ale protože se Realm neustále vyvíjí, tak v budoucnu bude možné objekty mezi vlákny pˇredávat. Znamená to, že všechny výbˇery z databáze bˇeží na hlavním vláknˇe a mírnˇe tak celou aplikaci zpomalují.
3.3
RxJava
RxJava vychází z Reactive Extensions pro C#, což je knihovna vytvoˇrená Microsoftem, která umožnuje ˇ vytváˇret asynchronní programy použitím Observables a operátoru. ˚ 3.3.1 Základní prvky Základní prvky knihovny RxJava jsou Observable a Subscriber. Observable produkuje data a lze ho transformovat pomocí operátoru. ˚ Subscriber se pˇrihlásí k odbˇeru Observable a dostává data, která Observable produkuje. 3.3.2 Vznik Observables Observable lze vytvoˇrit z existujících objektu, ˚ Listu˚ nebo polí pomocí Observable.just nebo Observable.from. Následující pˇríklad ukazuje rozdíl mezi tˇemito funkcemi.
List<String> items = new ArrayList<>(); items.add("a"); items.add("b"); items.add("c"); Observable> allItems = Observable.just(items); Observable<String> singleItems = Observable.from(items); Observable.just zavolá jednou onNext, ve kterém pˇredá celý List a poté skonˇcí voláním onCompleted. Observable.from zavolá tˇrikrát onNext, jednou pro každé písmeno, a až poté skonˇcí voláním onCompleted. V aplikaci Skautská Inventarizace se vˇetšina Observables generuje knihovnou Retrofit z odpovˇedí vzdáleného serveru. 13
3. I MPLEMENTACE APLIKACE 3.3.3 Životní cyklus Observables Kontrakt každého Observable je 0 až nekoneˇcno volání onNext, následované bud’ voláním onCompleted nebo onError. Na tento proud událostí se aplikují operátory, které umožnují ˇ Observables mˇenit, rozdˇelovat, kombinovat, filtrovat nebo aplikovat vlastní operátory.
3.3.4 Operátory Základním operátorem pro práci s Observables je flatMap. Tento operátor pro každou pˇríchozí událost vyšle dál nula až nekoneˇcno nových událostí podle funkce, kterou mu pˇredáme. Díky tomuto operátoru a Retrofitu mu˚ žeme také rˇ etˇezit sít’ová volání. Jako pˇríklad je uvedena funkce na pˇrihlášení uživatele a vrácení Listu, který obsahuje jeho dostupné role.
public Observable> login(final String username, final String password) { return loginApi.login(username, password) .flatMap(loginData -> { return userApi.getUserDetail(loginData.getName()); }) .flatMap(userDetail -> { return userApi.getRoles(userDetail.getName()); }) .flatMap(roles -> { return Observable.from(roles); }) .filter(role -> MATERIAL_ROLES.contains(role.getRoleID())) .toList(); } Funkce je díky lambda výrazum ˚ velmi jednoduchá a snadno cˇ itelná. Mu˚ žeme vidˇet nˇekolikanásobné použití operátoru flatMap na zˇretˇezení sít’ových volání, poté je použit operátor filter, který ze seznamu rolí vybere pouze ty, které mají pro správu majetku smysl. Výsledky nakonec agreguje do Listu. 14
3. I MPLEMENTACE APLIKACE 3.3.5 Subjekty Další duležitou ˚ cˇ ásti knihovny RxJava jsou subjekty. Subjekty implementují jak rozhraní Observable, tak Observer. Znamená to, že mužou ˚ odebírat proud událostí urˇcitého Observable a zárovenˇ tyto události posílat dál Observerům, kteˇrí odebírají události od nˇej. V aplikaci Skautská Inventarizace jsem využil PublishSubject, který posílá dál všechny události vzniklé od doby, kdy ho zaˇcne Subscriber odebírat. Tˇrída ZBarScannerView má funkci public Observable<String> getBarcodes(), která vrací právˇe PublishSubject. Ve smyˇcce, která zpracovává naskenované kódy jsou výsledky zaslané do PublishSubjectu pomocí publishSubject.onNext(scannedCode). Je zde vidˇet, že subjekty se hodí hlavnˇe k propojení API, které nativnˇe nepracuje s Observables, a Subscribera.
3.4
Další použité knihovny
3.4.1 Retrolambda Operaˇcní systém Android využívá virtuální stroj Dalvik, který je uzpuso˚ bený k bˇehu na zaˇrízeních s omezeným množstvím pamˇeti. Kvuli ˚ použití alternativního virtuálního stroje ale nemá Android k dispozici všechny vlastnosti nejnovˇejších verzi Javy. Android nyní podporuje nˇekteré vlastnosti Javy verze 7, jako je diamantový operátor, multi-catch klauzule a rˇ etˇezce v konstrukci switch. Pokud projekt cílí na úrovenˇ API 19 nebo vyšší (odpovídá Androidu 4.4 KitKat), je možné využít ještˇe try-with-resources [2]. Abychom mohli na Androidu využít cˇ ást novinek z Javy 7 a 8, je nutné použít nástroj Retrolambda 3 . Ten umožnuje ˇ použít konstrukci try-withresources a hlavnˇe lambda výrazy a reference na metody. Následující pˇríklad ukazuje rozdíl mezi kódem bez použití lambda výrazu˚ a s ním.
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // do something } });
3. https://github.com/orfjackal/retrolambda
15
3. I MPLEMENTACE APLIKACE
button.setOnClickListener((View v) -> { // do something }); Výhody lambda výrazu˚ jsou nejvíc zˇrejmé pˇri použití v kombinaci s knihovnou RxJava, která je popsána v sekci 3.3. Retrolambda funguje tak, že zmˇení Java 8 bajtkód tak, že je ho možné spustit i na starší verzi Javy. Znamená to, že rychlost programu bude stejná jako bez použití lambda výrazu, ˚ ale zdrojový kód je pˇrehlednˇejší. Pro použití na Androidu je vhodné nástroj Retrolambda doplnit pluginem Gradle Retrolambda, který výraznˇe zjednodušuje konfiguraci a použití Retrolambdy v prostˇredí, které používá na sestavení programu Gradle. 3.4.2 ZBar Android API nativnˇe nepodporuje skenování cˇ árových a QR kódu. ˚ Proto je nutné využít jedno z dostupných open-source rˇ ešení, mezi které patˇrí zejméne Google ZXing4 a Zbar5 . Obˇe knihovny nabízejí možnost jednoduché integrace do aplikace pomocí Intentu. Hlavní nevýhodou je nutnost nainstalovat odpovídající aplikaci, která obstará vyfocení a pˇreˇctení kódu a odešle data zpátky do aplikace, která skenování iniciovala. Zárovenˇ je to ale výhoda, protože se skenovací aplikace muže ˚ aktualizovat bez ohledu na ostatní aplikace, které ji využívají. Pro použití v aplikaci Skautská Inventarizace se ovšem toto rˇ ešení nehodí, protože je nutné mít výˇrez skeneru na stejné obrazovce jako seznam položek ve skladu, u kterého právˇe provádíme inventuru. Proto bylo nutné najít knihovnu, která umožnuje ˇ skenování kódu˚ bez nutnosti instalovat další aplikace. Vhodnou knihovnou je barcodescanner6 , který do aplikace pˇridává vlastní View obsahující výˇrez fotoaparátu a obstarávající parsování kódu. Zdrojový kód bylo ale nutné upravit, aby se View dal vložit do Fragmentu. Byla také nahrazena puvodní ˚ implementace odeslání výsledku callbackem za PublishSubject, který je blíže popsaný v sekci 3.3.5. 3.4.3 Butter Knife Jedním z problému˚ Android API je nutnost psát opakující se kód jako View view = findViewById(R.id.view_id); 4. https://github.com/zxing/zxing 5. http://zbar.sourceforge.net 6. https://github.com/dm77/barcodescanner
16
3. I MPLEMENTACE APLIKACE pokaždé, když používáme View, který je definovaný v layout XML souboru. Mezi nejˇcastˇeji používané Views patˇrí Button, TextView nebo EditText. Knihovna Butter Knife rˇ eší tento problém pomocí Annotation Processingu. Button button1; ... button1 = (Button) findViewById(R.id.button1);
@InjectView(R.id.button2) Button button2; Druhá cˇ ást kódu demonstruje použití knihovny Butter Knife, kdy pomocí anotace InjectView pˇriˇradíme tlaˇcítko definované v XML k objektu typu Button. Další vlastností je možnost definovat listenery (napˇr. OnClickListener u tlaˇcítek) pomocí anotace @OnClick( R.id.button_id). Pokud s tlaˇcítkem nepotˇrebujeme dále manipulovat, nemusíme vytváˇret jeho instanci a inicializovat ji pomocí InjectView, ale staˇcí použít právˇe anotaci OnClick.
@OnClick(R.id.button) void buttonClicked() { // handle click }
3.5
Uživatelské rozhraní
Duležitou ˚ stránkou každé aplikace je uživatelské rozhraní. Jeho nová verze pˇrichází s každou velkou aktualizací Androidu. S Androidem 4.0 "Ice Cream Sandwitch" pˇrišlo uživatelské rozhraní Holo a s nejnovˇejším Androidem 5.0 "Lollipop"zase Material. Rozhraním Holo se nebudu dále zabývat, protože je nahrazeno rozhraním Material. Material design se snaží, aby se objekty uživatelského rozhraní chovaly jako objekty v reálném svˇetˇe. To znamená, že vrhají stíny, pˇri dotyku se rozpohybují a jejich animace nejsou lineární, protože se chovají, jako kdyby mˇely urˇcitou váhu. V aplikaci Skautská Inventarizace jsou prozatím implementované pouze základní prvky Material Designu. Je definována základní barevná paleta - primární barva a její odstíny a k tomu doplnková ˇ barva, která slouží k tónování urˇcitých prvku˚ jako je EditText nebo Checkbox, pokud je s nimi manipulováno. Dále jsou implementovány animace položek seznamu. ˚
17
3. I MPLEMENTACE APLIKACE
Obrázek 3.3: Vzhled aplikace Skautská Invetarizace
18
4 Závˇer V mé bakaláˇrské práci se zamˇerˇ uji na problém inventarizace u skautské organizace Junák. Na zaˇcátku je pˇredstaven problém z právního a formálního hlediska. V druhé kapitole popisuji návrh aplikace, tzn. funkˇcní a nefunkˇcní požadavky, persony definující typické uživatele aplikace, prubˇ ˚ eh použití aplikace koncovým uživatelem a ER model databáze. Výstupem mé práce je mobilní aplikace pro platformu Android s názvem Skautská Inventarizace. Jejím úkolem je umožnit správcum ˚ majetku Junáka provádˇet inventarizaci majetku elektronicky bez nutnosti internetového pˇripojení. Aplikace dále umožnuje ˇ zobrazit podrobné informace o položkách skladu a poˇrízení jeho fotografie. Podrobný popis fungování aplikace a použitých knihoven je v kapitole 3. Zvláštní pozornost jsem vˇenoval knihovnám Realm a RxJava, které v souˇcasnosti nepatˇrí mezi bˇežnˇe používaná rˇ ešení. Zdrojové kódy aplikace jsou zdokumentovány a celý projekt je nahraný na serveru GitHub1 . Pˇredpokládá se další vývoj aplikace s ohledem na vyvíjející se potˇreby správcu˚ majetku Junáka.
1. https://github.com/PavelSynek/skaut-inventarizace
19
Literatura [1] Dashboards - Platform Versions, Kvˇeten 2015. Dostupné z: https:// developer.android.com/about/dashboards/index.html. [2] Gradle Plugin User Guide, Kvˇeten 2015. Dostupné z: http://tools. android.com/tech-docs/new-build-system/user-guide. [3] Realm Java documentation, Kvˇeten 2015. Dostupné z: https://realm. io/docs/java/latest/. [4] Zajímavá fakta a cˇ ísla, Kvˇeten 2015. Dostupné z: http://www.skaut. cz/skauting/o-skautingu/fakta-cisla. [5] BAGUI, Sikha a EARP, Richard. Database Design Using EntityRelationship Diagrams, Second Edition (Foundations of Database Design). Auerbach Publications, 2011. ISBN 1439861765. ˇ [6] CESKO. Zákon cˇ . 563 ze dne 12. prosince 1991 o úˇcetnictví. 1999. ˇ Sbírka zákonu˚ Ceské republiky. [7] HIRSCH, Frederick, KEMP, John a ILKKA, Jani. Mobile Web Services: Architecture and Implementation. Wiley, 2006. ISBN 0470015969. [8] LIDWELL, William, HOLDEN, Kritina a BUTLER, Jill. Universal Principles of Design. Rockport Publishers, 2003. ISBN 1592530079. [9] PETERA, Jan. Operace velké I, Listopad 2014. cˇ asopis Skauting. [10] SOMMERVILLE, Ian. Software Engineering (9th Edition). Pearson, 2010. ISBN 0137035152.
20
Pˇríloha Odkazy na použité knihovny Android Support Library v7 – https://developer.android.com/tools/ support-library/index.html Retrofit – https://github.com/square/retrofit Simple XML Converter – https://github.com/square/retrofit/tree/ master/retrofit-converters/simplexml Butter Knife – https://github.com/JakeWharton/butterknife Timber – https://github.com/JakeWharton/timber TwoWayView – https://github.com/lucasr/twoway-view Barcodescanner - ZBar – https://github.com/dm77/barcodescanner Realm – https://github.com/realm/realm-java Material-ish Progress – https://github.com/pnikosis/materialish-progress RxJava – https://github.com/ReactiveX/RxJava RxLoader – https://github.com/evant/rxloader Retrolambda – https://github.com/evant/gradle-retrolambda
Pˇrihlašovací údaje do aplikace Uživatelské jméno - stredisko.koprivnice Heslo - koprivnice.Web5
Elektronické pˇrílohy skautskaInventarizace.apk Aplikace v binární formˇe thesis.zip Archiv obsahující zdrojový kód
21