Vývoj pro Android – II

Mnozí čtenáři jistě vlastní telefon nebo jiné zařízení s Androidem a běžně s ním pracují, používají aplikace, stahují je z Android marketu a instalují. Ovšem jak taková aplikace vypadá uvnitř? Minule jsme si řekli, v čem se aplikace pro Androida vyvíjí, dnes si ukážeme, jak jsou uvnitř uspořádané.

Architektura uvnitř aplikací

Na rozdíl od konceptu vývoje pro iPhone, kde stavíme aplikaci poměrně striktně jako MVC architekturu, v Androidu si vrstvení aplikace určujeme sami. Leckdy je ale vhodné se u MVC alespoň inspirovat, aby zůstala aplikace čitelná.

Aplikace v Androidu sestávají ze čtyř základních typů komponent.

  • Activities – komponenty UI odpovídající jednomu formuláři / obrazovce
  • Services – služba bez UI běžící dlouhodobě na pozadí (stahování, přehrávání, výpočet)
  • Content providers – cesta, jak sdílet data ven z aplikace (např. sms, kontakty, bookmarky)
  • Broadcast Intent Receivers – naslouchadlo vzkazů z vnějšku (i zevnitř aplikace)

Existence každé komponenty je deklarovaná v souboru AndroidManifes­t.xml a na základě deklarací systém ví, co lze jak volat a jakým způsobem může komponenta spolupracovat s okolím. Na úrovni kódu vznikají komponenty děděním od jednoho ze čtyř předků:

Stejně jako v Javě, i na Androidu za nás správu paměti řeší VM. Paměti není mnoho, podle základní specifikace máme k dispozici 16MB haldu na aplikaci (na lepších telefonech i více), nicméně architektura aplikací na Androidu je stavěná tak, že nepoužité části aplikace jsou odklízeny, a uvolňují tím paměť. K tomu, aby probíhalo odklízení korektně, potřebujeme ve svých komponentách patřičně reagovat na změny v životním cyklu aplikace, tzn. ve správný okamžik uložit rozpracovaný uživatelův formulář, uvolnit hook na GPS či uvolnit zámek na podsvícení obrazovky. Více ke stavům životního cyklu aktivit a služeb nalezneme v dokumentaci Activity resp. v dokumentaci Service.

Stejně jako v Javě, tak i v Dalviku jsou třídy sdružovány do balíčků – packages. Viditelnost mezi třídami (public, protected, default, private) je zde zachovaná jako v Javě. U aplikace pak označujeme jeden package jako kořenový. Tento package je deklarovaný spolu s komponentami v descriptoru AndroidManifest.xml a v Androidu je použit jako unikátní identifikátor naší aplikace. Přestože je package označen jako kořenový, neznamená to, že bychom nesměli v jeho rodičích hierarchii větvit. Můžeme tak např. vyvíjet aplikaci s kořenovým package

eu.inmite.prj.test1

a přesto do ní zahrnout i třídy v package

eu.inmite.libs.

Intenty a rovnost aplikací

Vstupních bodů do aplikace může být hned několik. Za hlavní vstupy považujeme aktivity označené jako launcher. Launcherů může být v aplikací více než jeden, a seznam všech Launcherů v telefonu de facto odpovídá seznamu aplikací na uživatelské domovské obrazovce.

Další cesta jak se dostat do aplikace je reakce na tzv. Intent (přibližně přeloženo jako „událost“). Může jít např. o Intent obsahující kombinaci webové url a akce “ android.intent.action.VIEW”, nebo při odeslání obrázku o kombinaci interního URI vedoucí na obrázek v galerii spolu s akcí “ android.intent.action.SEND”. Obecně je Intent definován jako abstrakce operace, kterou je třeba provést. Obsahuje URI a textový identifikátor akce, která se má na daném URI provést. V prvním příkladu uvedeném výše bude umět na Intent reagovat pravděpodobně jen Browser, v druhém případě pak typicky umí reagovat mailer, sms aplikace, Twitter či facebook klient, a nejen ti. Druhý případ je také ukázkou, kdy aktivita není přímo launcherem aplikace, a přesto ji správně formulovaným Intentem můžeme vyvolat. Intenty vychází jak ze systému (přišla sms, telefon změnil polohu, …), tak z aplikací (otevři webovou url, vyfoť mi fotku, …).

Díky Intentům získáváme do jisté míry rovnost aplikací. Můžeme si tak naprogramovat nejen vlastní mailer či aplikaci pro práci se sms a nahradit tak předinstalované aplikace, ale můžeme nahradit i samotnou homescreen, což je rozcestník pro jakoukoliv uživatelskou činnost s telefonem. Kromě toho můžeme naši aplikaci postavit jako nového rovnocenného partnera dalších aplikací při obsluze standardních Intentů, jako třeba v případě zmiňovaného maileru či sms aplikace.

Pokud reakce na Intent neznamená žádnou přímou reakci vůči uživateli, např. pouhé uložení do DB při přijetí SMS, můžeme si vystačit pouze s BroadcastRe­ceiverem, zmíněným výše, a není třeba reagovat samostatnou aktivitou.

V některých případech (odeslání sms, vytočení hovoru, použití GPS, přístup na Internet, …) je reakce na Intent podmíněna také oprávněním. Toto oprávnění deklarujeme v deskriptoru AndroidManifest.xml a uživatel schvaluje oprávnění naší aplikaci v okamžiku instalace aplikace do telefonu. Tento krok dává smysl především proto, aby měl uživatel jasno o tom, co ta či ona aplikace může provádět a pokud je to v rozporu s tím, co by měla aplikace dělat, buďto ji vůbec neinstaluje, nebo se aplikace včas zbaví. Úplný přehled standardních oprávnění je k nahlédnutí v dokumentaci.

UI a Resources

Při vývoji pro Android přicházíme do styku s resource soubory. Souhrnně se jedná o všechny soubory umístěné v projektovém podadresáři res. Adresář res má pevně danou strukturu a v jednotlivých podadresářích nalezneme definice uživatelských obrazovek, obrázkové soubory, konfiguračních XML soubory, definice jazykových hlášek, binární soubory, či deklarace stylů a témat.

Pro všechny resource soubory nám ADT plugin automaticky vytváří index v podobě statických klíčů (ve třídě R v kořenovém package), které jménem a umístěním přesně odpovídají danému souboru. Můžeme tak např. v kódu pracovat s obrázkem či UI layoutem, aniž bychom složitě parsovali vstupní soubory. Tato vymoženost je možná právě díky pevné struktuře res adresáře a konvenci, kde klíč resource souboru vychází z jeho názvu. Kromě indexování souborů jsou do indexu zahrnuty také jednotlivé kousky informací ze souborů – v případě definice jazykových hlášek jsou to přímo jednotlivé textové hodnoty (R.string.*) a z UI definice jde pak o ID jednotlivých komponent (R.id.*). Každá změna v res adresáři vyvolá automatickou obnovu indexu.

K definici jednotlivých uživatelských obrazovek můžeme přistupovat více způsoby. V naprosté většině případů použijeme deklarativní cestu, kdy je obrazovka popsána v XML souboru umístěném v res/layout. Protože se jedná o resource, máme pro něj k dispozici klíč (R.layout.*) a načtení uživatelské obrazovky v aktivitě je tak záležitostí jednoho volání:

Pokud ale potřebujeme, můžeme strom komponent inicializovat i v kódu instanciací jednotlivých View prvků.

Většina nastavení a definic v Android aplikacích stojí na XML. XML obsahuje spoustu textového balastu a jeho parsování zabírá zbytečně výkon. Proto jsou všechna XML v aplikace přeložena při buildu do binarizované XML podoby. Pokud chceme v konvertovaném formátu číst, stačí nám stáhnout AXMLPrinter2 nástroj (spustíme “java -jar AXMLPrinter2.jar SOUBOR”)

Zajímavým konceptem jsou 9patch obrázky, díky kterým můžeme definovat natahování či smršťování svých obrázků, ať už jde o pozadí formuláře či skin tlačítka. Jedná se o png soubor pouze s příponou .9.png, ve kterém je jednopixelový okraj určen pro definování roztahování (levý a horní okraj) a paddingu (pravý a dolní okraj). Snadno tak zachováme rovnoměrný gradient či kulaté rohy, i když obrázek zvětšujeme / zmenšujeme bez zachování poměru stran.

U resource souborů nesmíme zapomenout zmínit definování alternativ těchto souborů pro různé konfigurace telefonu (např. čeština, landscape s VGA rozlišením displaye). Vlastnostmi, které se podílejí na konfiguraci, jsou zvolený jazyk telefonu, rozlišení displaye, orientace displaye, přítomnost hardwarové klávesnice a několik dalších. Vybrané vlastnosti jednoduše přidáme jako suffixy názvu adresáře oddělené pomlčkami a Android framework nám sám poskytne nejvhodnější resource soubor, příp. defaultní variantu bez suffixu, pokud žádná alternativa aktuální konfiguraci neodpovídá. Navíc, v základním stavu aplikace, pokud dojde ke změně platné konfigurace (např. při změně orientace displaye), restartuje se automaticky aktivita s novou sadou resource souborů.

(obrázky ukazují příklad landscape alternativy pro main.xml formulář)

Release, Android market a kompatibilita

V okamžiku, kdy buildujeme výslednou aplikaci, zabalí se veškerý přeložený kód (.dex soubor) spolu s resource soubory (definice UI, obrázky, styly, texty či konfiguračních soubory) a descriptorem aplikace AndroidManifest.xml do podepsaného zip souboru s příponou .apk. Apk soubor je připraven pro spuštění jak v emulátoru, tak v reálném telefonu. Pokud nespouštíme aplikaci z Eclipse ( Run as > Android application), kdy je build i spuštění provedeno automaticky, můžeme z příkazové řádky instalovat aplikaci “adb install moje_aplikace.apk”. Nástroj ADB nelezneme v adresáři SDK/tools.

Rozhodneme-li se svou aplikaci distribuovat prostřednictvím Android marketu, potřebujeme pouze vývojářský účet, za který zaplatíme $25. Jakmile vložíme aplikaci do marketu, je dostupná ke stažení prakticky okamžitě. Aplikace neprochází žádným schvalovacím procesem jako v případě AppStore u iPhone. U Androida předpokládá provozovatel marketu, že kvalitní aplikace si sami uživatelé vytřídí pozitivním hodnocením a komentáři.

Dříve než aplikaci definitivně vložíme do marketu, musíme si připravit produkční release. Ten – na rozdíl od vývoje, kde za nás aplikaci podepisuje ADT plugin předgenerovaným vývojovým klíčem – podepíšeme vlastním klíčem, který bude také svázaný s naším vývojářským účtem v Android marketu. Touto cestou je zajištěno nejen to, že aplikace v marketu pochází opravdu od nás, ale ani mimo market není možné aplikaci aktualizovat falešným updatem, který by způsobil paseku. Postup přípravy produkčního buildu nalezneme v dokumentaci.

Android market je také cesta, jak distrubovat updaty své aplikace. Jakmile aktualizujeme APK soubor novější vezí (rozhodující je android:versi­onCode v AndroidMani­fest.xml), uživatelům se při automatické kontrole updatů aplikace označí i naše aplikace. V tento okamžik (Android 2.1 a dříve) není možné v Androidu nastavit něco jako automatický update aplikace, čili bychom měli veřejné updaty dobře rozmýšlet, abychom uživatele nutností neustálých aktualizací neotrávili. Přestože informace není ještě potvrzena, očekává se, že nejbližší verze Androida (v. 2.2 – codename Froyo) již bude disponovat možností povolit pro vybrané aplikace jejich automatický update.

Na závěr jen poznámka k různým verzím Android frameworku. Svou aplikaci, např. kvůli přítomnosti novějších API, můžeme omezit na minimální požadovanou verzi frameworku (v AndroidMani­fest.xml definujeme <uses-sdk />). Android market podle této deklarace aplikaci nenabízí uživatelům starších telefonů. V opačném směru pak obecné pravidlo říká, že aplikace jsou zpětně kompatibilní, tzn. aplikaci napsanou pro Android 1.1 spustíme i na telefonu s Androidem 2.1, nicméně jak už tomu bývá, toto pravidlo neplatí na sto procent, ale to už je téma pro jiný článek.

Informace v tomto článku jsou velmi hrubým shrnutím základních informací o vývoji pro Android. Pokud se do vývoje budete chtít ponořit hlouběji, mohu jen doporučit prokousat se DevGuide.

Hodně štěstí při vašem prvním “ File > New > Android project ... Run as > Android application”.

Autor vyvíjí pro Android ve společnosti Inmite, která se specializuje na vývoj pro smartphony (kromě Androidu i Blackberry či iPhone). O Androidu i přednáší.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 6

Přehled komentářů

blizzboz Re: Vývoj pro Android - II
Richard Market
Murdej Re: Market
dc Re: Vývoj pro Android - II
Franta Prodej v Marketu z CR
grexos nejdu
Zdroj: https://www.zdrojak.cz/?p=3231