Android Skola Programiranja Android@Vidi Skola

March 14, 2017 | Author: rgostecn | Category: N/A
Share Embed Donate


Short Description

Android Skola Programiranja Android@Vidi Skola...

Description

ANDROID SKOLA PROGRAMIRANJA By android@Vidi Kopija teksta Android@Vidi skole programiranja za android sisteme Robert 12/3/2014

SADRZAJ: Android škola programiranja – Pisanje i pokretanje prvog programa .................................... 3 Treći nastavak serijala o Google Android programiranju – Interakcija sa korisnikom ............. 8 Android programiranje #4: Uvod u pisanje programskoga koda. ......................................... 12 Android programiranje #5: Korištenje rasporeda kontrola u složenim aplikacijama ............ 18 Android programiranje #6: Korištenje osnovnih Android kontrola ....................................... 24 Android programiranje #7.................................................................................................... 31 Android programiranje #8: Android kontrole u akciji IV ....................................................... 35 Android programiranje #9: Korištenje datotečnog sustava .................................................. 40 Android programiranje #10: Nekoliko standardnih dijelova aplikacije ................................. 48 Android programiranje #11: Standardni dijelovi aplikacije................................................... 59 Android programiranje #12: Alternativni pristup razvoju aplikacija ..................................... 65 Android programiranje #13: Alternativni pristup razvoju aplikacija II .................................. 69 Android programiranje #14: Alternativni pristup razvoju aplikacija III ................................. 73 Android programiranje #15: Izrada složenijih aplikacija ....................................................... 78 Android programiranje #16: Korištenje kartografskih servisa .............................................. 82 Android programiranje #17: Što je novo u 3.x izdanjima ..................................................... 86

Android škola programiranja – Pisanje i pokretanje prvog programa Prošli put smo u malo poduţem početnom tekstu objasnili zašto pokrećemo novu školu programiranja i koji su nam sve alati potrebni za nju, odnosno kako ih treba instalirati na računalo da bi sve proradilo na odgovarajući način. Budući da je za razvoj Google Android aplikacija potrebno instalirati nekoliko alata različitih proizvođača, takva instalacija nikad ne prolazi tako glatko kao kad je riječ o instalaciji pojedinačnoga razvojnog alata samo jednog proizvođača. Ok, ako ste napravili sve što smo napisali u prošlom nastavku, sad biste trebali imati računalo spremno za pisanje prvog Google Android programa, što ćemo doista i napraviti u nastavku teksta. Usput ćemo malo „zagrepsti“ po glavnim dijelovima razvojne okoline potrebnim za razvoj takve vrste aplikacija, kao i samom emulatoru odgovarajućeg hardverskog uređaja, jer na kraju krajeva, tek u njemu moţemo vidjeti rezultate rada našeg programa na smisleni način. Nakon toga se u sljedećim brojevima moţemo pozabaviti samim programiranjem i naprednijim programskim tehnikama. Stvaranje projekta HelloWorld: Ovako izgleda početni dijaloški okvir kod stvaranja projekta

Kako rezervirani prostor za ovaj serijal u nekoliko brojeva časopisa jednostavno nije dovoljan za detaljnije bavljenje razvojnom okolinom, tog segmenta razvoja aplikacije dotaknut ćemo se samo kad nešto postane zaista neophodno. Ipak, ako ste do sad već koristili neku od modenijih razvojnih okolina za razvoj aplikacija (a napomenuli smo da praćenje serijala zahtijeva određeno predznanje), onda ne biste trebali imati previše problema ni sa snalaţenjem u razvojnoj okolini Eclipse. Kao što to dobra programerska tradicija nalaţe, priču o programiranju u Google Androidu započet ćemo od trivijalnog HelloWorld primjera. Njegova namjena jest pokazati kako se u novom razvojnom okruţenju prikazuje jednostavna poruka korisniku programa. Za mlađe (ili starije) čitatelje koji moţda upravo sada prvi put započinju avanturu programiranja u nekom programskom jeziku, treba napisati samo kratko objašnjenje zašto se u gotovo svakoj školi programiranja započinje s tako trivijalnim primjerom budući da on sam za sebe zapravo ne radi ništa korisno. Ideja u pripremi tako jednostavnog primjera jest u tome da se programer što brţe upozna s novim programskim jezikom, ali i njegovim razvojnim okruţenjem, kako bi se nakon toga što brţe moglo prijeći na sloţenije probleme.

Za pisanje novog programa potrebno je u razvojnoj okolini Eclipse izabrati naredbu File > New > Project te u dijaloškom okviru prikazanom u nastavku odabrati odgovarajuću vrstu projekta. U ovom slučaju to je Android Project. Kao rezultat izvođenja prethodne operacije, pojavljuje se dijaloški okvir New Android Project gdje se od programera očekuje upisivanje nekoliko polaznih podataka o vlastitom projektu. Project Name predstavlja naziv projekta na kojem trenutno radimo. U ovom slučaju, to će biti HelloWorld. Osim naziva projekta, potrebno je izabrati mjesto na disku za spremanje njegovih sastavnih dijelova. To moţe biti podrazumijevana radna površina definirana prilikom prvog pokretanja radne okoline, neko točno određeno mjesto na disku, ili se u razvoj projekta moţe krenuti od već postojećeg projekta – recimo nekog od pratećih primjera Google Android projekata. Za sada na ovom mjestu moţemo ostaviti podrazumijevane vrijednosti, dakle – uključene opcije Create New Project in Workspace te Use default location. Projekt HelloWorld nakon stvaranja: Automatski je generiran čitav niz datoteka koje se mogu pregledati u razvojnoj okolini Eclipse.

Projekt HelloWorld nakon stvaranja: Automatski je generiran čitav niz datoteka koje se mogu pregledati u razvojnoj okolini Eclipse. U slučaju da je na računalo instalirano više inačica razvojnih paketa Google Android SDK, potrebno je izabrati jedan od njih, nakog čega će se odgovarajuća oznaka inačice pojaviti u okviru Min SDK Version na dnu dijaloškog okvira. Da bi se moglo nastaviti s radom na projektu, potrebno je navesti još nekoliko podataka. U okvir Application Name treba upisati naziv aplikacije, što moţe biti bilo kakav niz znakova, dakle i onaj jednak nazivu projekta. U Package Name treba upisati naziv Java paketa. Ovaj naziv treba biti sastavljen od najmanje dva dijela međusobno odvojena točkom – na primjer helloWorld.java (prema uobičajenim konvencijama prvo slovo treba biti malo). U okvir Create Activity treba upisati naziv prve aktivnosti u Google Android projektu – na primjer helloWorld. Sada je moguće kliknuti na gumb Next te tako prijeći na sljedeći dijaloški okvir namijenjen za stvaranje odgovarajućega pomoćnog projekta za testiranje. Projekti za testiranje namijenjeni su za pojednostavljeno ponavljanje testiranja vrlo sloţenih Google Android projekta (kakav HelloWorld zasigurno nije), ali ćemo na ipak kreirati takav projekt kako bismo se upoznali i s tom mogućnošću razvojnog alata. Na ovom mjestu mogu se ostaviti sve predloţene vrijednosti što za posljedicu ima stvaranje projekta HelloWorldTest. Nakon izvođenja svih prethodno nabrojenih operacija, u

radnoj površini na disku stvara se čitava „hrpa“ datoteka, a sadrţaj svake od njih moţe se vidjeti u odgovarajućem prozoru radne okoline. Za jednostavnije snalaţenje najbolje je koristi hijerarhijski prikaz dijelova projekta u posebnom prozoru na lijevom dijelu razvojne okoline (Navigator). Upravljanje virtualnim uređajima: Omogućuje testiranje projekta na različitim emulacijama hardverskih karakteristika.

Budući da je razvojna okolina automatski pripremila čitav niz datoteka, prva ideja koja nam svakako mora pasti na pamet isprobavanje je nastale situacije. Najjednostavniji način za to jest odabir naredbe Run As > Android Application iz padajućeg izbornika povezanog s projektom HelloWorld. Podrazumijeva se da se ista naredba moţe izvesti na bar još nekoliko načina kao u svim modernim razvojnim okolinama – na primjer odabirom istoimene naredbe iz glavnog izbornika ili odgovarajuće ikone na alatnoj traci prozora. Na taj detalj više se nećemo vraćati ni u ovom ni u budućim tekstovima, nego istraţivanje alternativnih mogućnosti ostavljamo samim čitateljima. Budući da je cijeli Android sustav namijenjen razvoju aplikacija za prijenosne mobilne uređaje, razumljivo je da se aplikacija ne moţe izvesti „u zraku“, nego nam je za to potreban nekakav uređaj za njezino izvođenje – ako ništa drugo, onda bar u obliku softverske emulacije. Takav softverski „stroj“ naziva se Android Virtual Device ili skraćeno AWD. Ako nekakva konfiguracija emulatora već ne postoji od prije, treba je pripremiti prema konkretnim potrebama za testiranje vlastite aplikacije. Za upravljanje virtualnim uređajima koristi se dijaloški okvir Android SDK and AVD Manager, što uključuje operacije poput stvaranja uređaja, njegovog brisanja, ispravljanja te moţda najvaţnije, pokretanja uređaja. Ključni hardverski parametri koji se mogu definirati kod stvaranja novoga virtualnog stroja jesu količina raspoloţive radne memorije te rezolucija zaslona. Nakon stvaranja novoga virtualnog uređaja, u njega je moguće učitati, a nakon toga i isprobati vlastitu aplikaciju. Budući da za sada naša aplikacija predstavlja samo goli kostur aplikacije te kao takva zapravo ne radi ništa pametno, ni u virtualnom uređaju nema se mnogo toga za vidjeti osim osnovne poruke korisniku programa. U slučaju da se tekst iz aplikacije ne prikaţe automatski u virtualnom uređaju, kliknite na gumb Menu prikazan na prozoru virtualnog uređaja. Trenutno stanje programskoga koda ima oblik prikazan u nastavku, ali ne treba smetnuti s uma da to nije jedini dio aplikacije. Tako, na primjer, za pregled i izmjenu prikazane poruke treba otvoriti datoteku strings.xml, hijerarhijski smještenu u mapi res/values.

package helloWorld.java;import android.app.Activity; import android.os.Bundle;public class helloWorld extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } Na sličan način, otvaranjem datoteke main.xls smještene u mapi res/layout, moţe se oblikovati grafičko sučelje aplikacije na način vrlo sličan izvođenju odgovarajućih postupaka u drugim modernim razvojnim okolinama – na primjer Microsoft Visual Studio. Kao osnovnu vjeţbu u korištenju razvojne okoline, probajte u vlastitu aplikaciju dodati jedan gumb te mu eventualno podesiti neka od svojstava za određivanje izgleda u prozoru Properties. Virtualni uređaj u akciji: Stvarni izgled ovisi o parametrima definiranim prilikom njegovog stvaranja.

Vizualna priprema sučelja aplikacije: Izvodi se u posebnom prozoru radne okoline.

Spomenimo na ovom mjestu kako se čitava operacija prevođenja izvornoga koda, pokretanja virtualnog uređaja te učitavanja prevedenog programa u uređaj moţe opisati svakako, ali sigurno ne pojmom „brza operacija“, bez obzira na snagu računala. Ako ste već ranije probali slične kombinacije razvojnih alata i emulatora drugih proizvođača, onda sigurno niste iznenađeni prethodnom tvrdnjom, jer ste na to već jednostavno navikli. Dobra vijest je da je vrijeme učitavanja nove inačice aplikacije u već pokrenuti virtualni uređaj bitno kraće, što znači da je isprobavanje vlastite aplikacije nakon manjih promjena izvornoga koda ipak prilično bezbolan proces.

Spomenimo na kraju današnjeg predstavljanja početnih koraka u razvoju Android aplikacija, jer se dovršena i testirana Android aplikacija moţe pripremiti za distribuciju u obliku datoteke s nastavkom .apk. Riječ je o komprimiranoj datoteci sastavljenoj od većeg broja datoteka koje sadrţe sve potrebne informacije za izvođenje aplikacije na uređaju s ugrađenom podrškom za Google Android. Kad završite ovu školu i napišete prve kvalitetne aplikacije, prruţa vam se mogućnost da ponešto i zaradite putem online trgovine Google Android aplikacija, koja svakodnevno dobiva sve veći broj naslova od programera širom svijeta.

Treći nastavak serijala o Google Android programiranju – Interakcija sa korisnikom Drugi nastavak nove škole programiranja u razvojnom alatu Google Android bio je namijenjen izradi „klasične aplikacije“ u svim školama programiranja – općepoznatog primjera HelloWorld. Cilj projekta bio je brzo upoznavanje dijelova razvojne okoline potrebnih za izradu vlastitih aplikacija, dok o samom programiranju nije bilo rečeno baš mnogo. U biti, u prošlom tekstu samo smo isprobali ono što je automatski pripremila razvojna okolina. Ovaj put idemo korak dalje pa počinjemo u početnu aplikaciju dodavati prve objekte, a nakon toga i programski kod za njihovu reakciju na događaje u okolini, to jest na operacije korisnika programa. Usput ćemo se malo pozabaviti i posebnom terminologijom koja se koristi tijekom rada na Google Android projektima. Prije nego počnemo „zaozbiljno“, dopustite da se osvrnemo na bitan tehnički detalj. Moderna razvojna okolina kao što je Eclipse ima čitav niz prozora za definiranje različitih dijelova projekta, pa se početniku nije baš uvijek lako snaći sa svim tim dijelovima, posebno ako je neki od bitnih prozora zatvoren ili premješten s podrazumijevanog mjesta slučajno ili namjerno. Kako bi olakšao praćenje teksta, autor se trudi da priloţene slike uz tekst uvijek pokazuju bitne dijelove. Problem nastaje kad se zbog ovog ili onog razloga (najčešće nedostatka prostora u časopisu), neka od slika mora izostaviti, ili se smanji tako da je teško razaznati neke dijelove. Zato ćemo (bar u početku) stalno navoditi ne samo što treba napraviti da bi se dovršila neka operacija nego i kako se zapravo stiţe do tog mjesta. Navedimo prvo što ţelimo postići u današnjem i sljedećem nastavku. U osnovni projekt, HelloWorld, iz prošlog nastavka ţelimo dodati tri nova objekta – jedan okvir za prikaz i unos teksta od strane korisnika te dva dodatna gumba za upravljanje tim okvirom. Odmah pri pokretanju programa okvir za tekst se programski puni početnom vrijednošću, a pritisak mišem na bilo koji od dodatna dva gumba izaziva zamjenu početnog sadrţaja drugačijim tekstom. Dakle, ništa spektakularno u smislu izvođenja programa, ali i tako jednostavan primjer demonstrira različite načine korištenja Google Android sustava u razvoju aplikacija za mobilne uređaje. Rad na proširenju početnog HelloWorld projekta započinjemo otvaranjem datoteke main.xml u prozoru radne okoline, pod nazivom Android Layout Editor, jer je on namijenjen grafičkom uređivanju izgleda vlastite aplikacije. Naravno, budući da je u osnovi riječ o običnoj .xml datoteci, moţemo je otvoriti i u nekom od tekstualno orijentiranih prozora, ali se to baš ne preporučuje početniku. Na ovom mjestu postoji velik stupanj analogije sa stvaranjem

HTML dokumenata (što je vjerojatno poznato bar dijelu čitatelja). HTML dokument moţemo stvoriti izravnim upisivanjem sastavnih dijelova u tekstualnom obliku (teţi način), ili njihovim „crtanjem“ u odgovarajućem grafički orijentiranom alatu (lakši način). Za sada ćemo i u razvojnoj okolini Eclipse izabrati lakši način izrade korisničkog sučelja, a kad postanete iskusniji, moţete koristiti oba načina. Spomenimo na ovom mjestu namjenu prozora Outline, koji zapravo predstavlja „nešto između“. U njemu je vidljiv samo popis osnovnih dijelova od kojih se sastoji korisničko sučelje aplikacije, kao i njihov međusobni odnos, ali ne i drugi detalji za određivanje izgleda. Korisničko sučelje aplikacije iz prošlog nastavka bilo je sastavljeno od svega dva dijela: LinearLayout i TextView. Prvi dio pripada grupi objekata namijenjenih određivanju međusobnog rasporeda osnovnih objekata koji čine korisničko sučelje (u terminologiji Google Androida to su layouts objekti). U današnjem nastavku nećemo se detaljnije baviti ovim dijelom oblikovanja korisničkog sučelja, nego to ostavljano za buduće nastavke serijala. Za sada spomenimo samo da je tijekom inicijalne pripreme projekta uporabljen prilično jednostavan raspored objekta pod prije spomenutim nazivom LinearLayout, a mi ćemo ga zasad koristiti bez ikakvih izmjena. U projekt HelloWorld automatski je dodan još jedan objekt namijenjen osnovnoj interakciji s korisnikom programa, što se zapravo svodilo na običan prikaz pozdravne poruke. U terminologiji Google Androida, takvi objekti s vlastitim vizualnim izgledom, namijenjeni izgradnji različitih dijelova korisničkog sučelja za interakciju s korisnikom aplikacije – nazivaju se widgets. Već smo spomenuli da ćemo u korisničko sučelje dodati još tri dijela pa sad prelazimo na izvođenje odgovarajućih operacija. Iz prozora Views treba redom povući tri objekta na dio koji prikazuje grafičku reprezentaciju aplikacije (objekt LinearLayout). Jednom to treba napraviti s objektom tipa EditText, a dva puta s objektom tipa Button. O samom mjestu „ispuštanja“ objekta ne treba voditi previše računa, jer se pozicioniranje nacrtanih objekata ionako izvodi automatski zbog korištenja vrlo jednostavnog načina raspoređivanja objekata. Primijetimo na ovom mjestu da je razvojna okolina nacrtanim objektima automatski dodijelila nazive (EditText01, Button01 i Button02), baš kao i dio drugih vrijednosti svojstava. Ako ste već ranije koristili neku inačicu Microsoftove razvojne okoline, bit će vam potpuno jasno što se je dogodilo u prethodnom koraku. Isto tako, prepoznat ćete način za pregled i izmjenu podrazumijevanih vrijednosti svojstava aktivnog objekta. Za to se koristi prozor Properties, a u njemu treba jednostavno pronaći svojstvo čiji sadrţaj namjeravamo izmijeniti te upisati (ili izabrati što ovisi o vrsti svojstva) novu vrijednost. Na primjer, ako ţelimo boju cjelokupne pozadine izmijeniti s crne na bijelu, kao aktivan objekt treba označiti LinearLayout, a

kao vrijednost svojstva Background upisati vrijednost #FFFFFF. Na sličan način moţemo gumbima Button01 i Button02 izmijeniti početni tekst na vrijednost Prihvati odnosno Odbaci, tako da za svaki gumb izvedemo korekciju vrijednosti svojstva Text. Objektu EditText01 također izmijenimo vrijednost svojstva Layout width na unaprijed definiranu vrijednost fill_parent, kako bi se objekt proširio na punu širinu. Za vjeţbu, moţete promijeniti početnu vrijednost prikazanog teksta na objektu EditText01, iako ćemo to kasnije napraviti programski, kako bismo demonstrirali izmjenu vrijednosti svojstava u programskom jeziku. Nestrpljivi čitatelji mogu probati sami otkrivati čemu sluţe druga dostupna svojstva tako da im izmijene početnu vrijednosti, a mi ćemo u sljedećim nastavcima serijala objašnjavati neka od njih kad nam zatrebaju. Objasnimo na ovom mjestu nešto zaobilazniji način za izmjenu vrijednosti svojstava. Vrijednost #FFFFFF na prvi, drugi pa čak i treći pogled početniku ne odaje da je riječ o bijeloj boji, a priznat ćete da ni iskusnijima nije baš lako pamtiti slične vrijednosti, ako ih ne koriste svakodnevno. Postoji li način da se takve vrijednosti koriste na „humaniji“ način? Srećom, da, a odgovarajući postupak opisujemo u nastavku teksta. U hijerarhijskom pregledu dijelova projekta (prozor Navigator) treba pronaći i otvoriti datoteku res \ values \ strings.xml. U ovoj datoteci nalaze se definicije resursa uporabljenih na različitim mjestima u programu. Na ovo mjesto treba jednostavno dodati novi resurs pod nazivom BijelaBoja. Za to se koristi klik na gumb Add.., nakon čega se otvara dijaloški okvir za odabir kategorije resursa. U njemu sasvim logično treba izabrati kategoriju Color, iako se potpuno sličan postupak primjenjuje za druge vrste resursa. Preostaje još samo da se kao naziv resursa (Name) upiše vrijednost BijelaBoja, a kao njegova vrijednost (Value) #FFFFFF. Naravno, nemojte zaboraviti ni na spremanje nove vrijednosti resursa pomoću ikone diskete na alatnoj traci razvojne okoline. Ako sada zatvorimo datoteku strings.xml, vraćamo se ponovno na grafičku reprezentaciju korisničkog sučelja. Ponovno kao aktivni objekt izaberimo LinearLayout te pronađimo svojstvo Background. Nakon klika na gumb s tri točke na samom desnom kraju reda, otvara se dijaloški okvir Reference Chooser. U njemu moţemo pronaći vrijednost BijelaBoja u okviru kategorije Color te je izabrati kao novu vrijednost svojstva, potvrdom na gumb OK. Kao nova vrijednost svojstva sada će biti prikazana vrijednost @color/BijelaBoja, što i dalje predstavlja bijelu boju, ali sada napisanu na mnogo čitljiviji način od upisa heksadecimalnoga koda iste boje. Na sličan način moţemo definirati druge vrijednosti koje namjeravamo uporabiti u različitim dijelovima programa.

Za kraj ovoga poglavlja, otvorimo ponovno datoteku main.xml, ali sada u običnome tekstualnom editoru. Dobit ćemo nešto poput: Sve ono što smo ranije dobili grafičkim oblikovanjem sučelja u nekoliko prozora razvojne okoline, ovdje je prikazano u običnom XML formatu zapisa. Iskusniji programeri mogu na ovom mjestu izravno izvoditi promjene, pa čak i dodavanje novih objekata na sučelje. Na primjer, probajte jednostavno umnoţiti dio teksta namijenjen definiranju gumba Button02 pa ćete dobiti još jedan identičan gumb na korisničkom sučelju. Primijetimo na kraju današnjeg nastavka da u XML opisu oba gumba postoji veza prema programskom kodu za obradu događaja onClick, jer je autor teksta to već pripremio u primjeru, ali zbog zadane veličine svakog pojedinog nastavka serijala, o tome će nešto više riječi biti u sljedećem broju.

Android programiranje #4: Uvod u pisanje programskoga koda. U prošlom, trećem poglavlju Google Android programiranja, u početnu inačicu aplikacije HelloWorld dodali smo nekoliko osnovnih grafičkih objekata, te usput objasnili više bitnih dijelova razvojne okoline Eclipse, povezanih s postavljanjem i pregledom grafičkih objekata korištenih u aplikaciji, odnosno pripremom i izmjenom njihovih svojstava. Međutim, tako dugo dok nacrtanim objektima ne dodamo nekakav programski kod, oni u aplikaciji sluţe manje-više samo kao ukras, pa kao takvi ne rade ništa pametno. Tek kada se objektima pridruţe odgovarajuće funkcije za reakciju objekta na „podraţaj“ iz okoline (recimo pritisak na objekt od strane korisnika aplikacije na zaslonu uređaja), počinje se doista nešto događati. Vratimo se na trenutak ponovno na tekstualni prikaz dijela datoteke main.xml, zaduţene za definiranje izgleda objekata u aplikaciji, ali istovremeno i za povezivanje nacrtanih objekata s dijelovima programskoga koda. Usredotočimo se u nastavku na sljedeće dijelove datoteke: … … Povezivanje objekata s programskim kodom: Izvedivo je izravnim uređivanjem tekstualnog sadrţaja datoteke Main.xml. Dijelovi označeni istaknutim pismom zaduţeni su za povezivanje oba „nacrtana“ gumba u sučelju s odgovarajućom funkcijom u programskom kodu – u ovom slučaju ona je zaduţena za obradu događaja izazvanog pritiskom korisnika na kontrolu. Da odmah razjasnimo jednu vrlo bitnu stvar (kako se čitatelji ne bi našli u svojevrsnoj konfuziji pri praćenju teksta), iako smo je već spomenuli na kraju prethodnog nastavka. Ako se pozorno pratili tekst iz prošlog broja te pokušali ponoviti sve opisane operacije, onda u vašem projektu trenutno nema navedenih dijelova. U projektu autora teksta ti dijelovi postoje, jer je primjer prvo napravljen do kraja, a tek onda je započeto pisanje teksta. Odatle dolazi

do istaknute razlike između projekata, ali ćemo odmah poduzeti sve potrebne operacije da ih uklonimo. Na koji način u vlastite projekte moţete dodati dio koji nedostaje? Jedan od načina izravni je upis prije označenoga teksta u prozoru zaduţenom za tekstualni prikaz sadrţaja datoteke main.xml. Drugi način korištenje je prozora Properties, nakon što ţeljeni objekt postane aktivan objekt (vidi priloţenu sliku uz tekst). U našem primjeru oba objekta povezana su s istim dijelom programskog koda, jer se u njemu na jedinstven način prvo provjerava objekt na koji je korisnik programa napravio pritisak. Moguće je napraviti i drugačije rješenje. Svaki gumb moţe biti povezan s posebnom funkcijom za obradu događaja. Na autoru programa je odlučiti što je najbolje izabrati u određenoj situaciji. Pripadajući programski kod primjera u ovom trenutku ima sljedeći oblik (datoteka HelloWorld.java): package helloWorld.java; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.os.Bundle; public class helloWorld extends Activity { private EditText text; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (EditText) findViewById(R.id.EditText01); text.setText(“No button pressed”); } // Will be connected with the buttons via XML public void myClickHandler(View view) { switch (view.getId()) { case R.id.Button01: text.setText(“Button 1 was clicked”); break; case R.id.Button02: text.setText(“Button 2 was clicked”);

break; } } } U prethodnom primjeru mogu se uočiti tri glavna dijela. Prvo je naveden čitav niz import naredaba kako bi se u vlastiti program uključili svi potrebni dijelovi za izvođenje aplikacije. Pomoću dijela: public void onCreate(Bundle savedInstanceState) { započinje drugi dio, odnosno izvođenje glavnog dijela programa. U njemu se, osim inicijalizacije same aplikacije, postavlja početna vrijednost tekstualnog sadrţaja za trenutno jedini objekt u aplikaciji zaduţen za prikaz odnosno unos teksta (EditText01). Za to su zaduţene naredbe za njegovo „pronalaţenje“ među postojećim objektima, a nakon toga za postavljanje početne vrijednosti. setContentView(R.layout.main); text = (EditText) findViewById(R.id.EditText01); text.setText(“No button pressed”); Kao što smo to već spomenuli, u ovom primjeru oba gumba u aplikaciji povezana su na zajednički dio programskoga koda za obradu događaja. Alternativni način povezivanja: Korištenje prozora Properties u razvojnoj okolini Eclipse. Pomoću naredbe switch provjerava se o kojem je gumbu doista riječ, a onda se izvodi jedan od dva moguća nastavka. Svaki od njih izaziva prikaz drugačije poruke u prije spomenutomu tekstualnom okviru. Ako je sve napravljeno precizno, prema uputama iz ovog i prethodnog nastavka serijala, tijekom izvođenja programa trebali biste dobiti identično ponašanje programa kao na slikama uz tekst. Pokupajmo sada u svrhu svojevrsne vjeţbe opisati sve potrebne izmjene kako bi u programskom kodu primjera svaki gumb imao vlastitu proceduru za obradu događaja. U praksi je to zapravo češće rješenje zbog velike razlike između namjene pojedinih gumba u aplikaciji. Postojeći programski kod primjera helloWorld.java u tom slučaju treba izmijeniti u sljedeći oblik.

package helloWorld.java; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.os.Bundle; public class helloWorld extends Activity { private EditText text; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (EditText) findViewById(R.id.EditText01); text.setText(“No button pressed”); } // first Button public void myClickButton1(View view) { text.setText(“Button 1 was clicked”); } // second Button public void myClickButton2(View view) { text.setText(“Button 2 was clicked”); } } Početni izgled prozora: Nakon pokretanja programa pojavljuje se početna poruka. Budući da zajednička funkcija za obradu događaja nakon pritiska na gumb više ne postoji, nego je zamijenjena s dvije pojedinačne funkcije, treba korigirati veze između oba gumba i pripadajućega programskoga koda. To se ponovno moţe napraviti izmjenom svojstva On click u prozoruProperties te upisivanjem vrijednosti myClickButton1, odnosnomyClickButton2. Klikom na gumb na krajnjoj

desnoj strani toga reda moţe se prikazati i dijaloški okvir za odabir postojećih dijelova programskoga koda. Alternativni način za izvođenje iste operacije (nešto brţi, ali zahtijeva veću preciznost u pisanju) izravna je izmjena tekstualnog sadrţaja datotekemain.xml. U konačnici, bez obzira na uporabljeni način izmjene vrijednosti, u toj datoteci treba biti sljedeći sadrţaj. … … Ovime je dovršen početni niz tekstova o razvoju aplikacija pomoću Google Android platforme. Ako ste pozorno pratili sve što je do sada napisano o ovoj temi, sada biste na vlastitom računalu trebali imati pravilno instaliran razvojni sustav, a ujedno biste ga trebali poznavati do razine korištenja koja omogućuje praćenje i upis primjera iz sljedećih nastavaka serijala. Kao i obično u školama programiranja, praćenje tekstova olakšat ćemo izdavanjem pratećih primjera na digitalnomu mediju uz časopis. Što ćemo raditi u budućim nastavcima? Zbog relativne ograničenosti prostora za ovaj serijal u časopisu, škola programiranja u razvojnom alatu Google Izgled prozora nakon klika na prvi gumb: Početna poruka zamjenjuje se novom porukom.

Android dalje će izgledati nešto drugačije nego što je to bio slučaj s prethodnim sličnim materijalima istog autora. To znači da nećemo obrađivati segment po segment programskoga jezika ni pratećih biblioteka funkcija, a onda izmišljati odgovarajući primjer za njihovu demonstraciju, nego ćemo raditi upravo obrnutim redoslijedom. Prvo ćemo napraviti jedan ili više sloţenijih primjera namijenjenih demonstraciji različitih mogućnosti Google Android platforme, a onda objasniti što rade ključni dijelovi primjera. Kao što smo istaknuli na samom početku serijala, za praćenje tako koncipiranih nastavaka očekuje se određeno predznanje u smislu poznavanja osnovnih pojmova uobičajenih u programerskom ţargonu, poput varijable, petlje ili procedure. Drugim riječima, to bi

trebalo značiti da već posjedujete osnovno praktično znanje programiranja u nekom drugom razvojnom alatu. U međuvremenu, dok čekate sljedeći bitno kompliciraniji nastavak serijala, moţete sami pokušati dodati u projekt nekoliko novih gumba ili drugačijih vrsta kontrola, a onda ih povezati s osnovnim događajem na korisničkom sučelju (On click).

Android programiranje #5: Korištenje rasporeda kontrola u složenim aplikacijama Nakon što smo prošli put „dotjerali do kraja“ s nešto sloţenijim Android projektom u kojem je bilo i malo više programskog koda, došao je trenutak da se detaljnije pozabavimo najvaţnijim dijelovima razvojnog alata, kako bi u slijedećim nastavcima mogli izrađivati ozbiljnije aplikacije. Jedna od tipičnih karakteristika svake sloţenije aplikacije, bez obzira na softversku platformu na kojoj se izvodi, je postojanje većeg broja prozora, formi ili zaslona (već prema terminologiji uobičajenoj za tu razvojnu platformu) u okviru iste aplikacije. Ni Android aplikacije po tom pitanju nisu nikakav izuzetak. U dosadašnja dva jednostavna primjera aplikacija iz prethodnih nastavaka serijala koristili smo isti pogled (odnosno istu vrstu rasporeda osnovnih objekata) pod nazivom LinearLayout. U tim primjerima zapravo se nismo previše obazirali na karakteristike korištenog rasporeda kontrola, nego smo jednostavno po njemu postavili ostale objekte korištene u aplikaciji (dva gumba i jedan okvir za unos teksta). Glavna tema današnjeg teksta posvećena je upravo različitim vrstama rasporeda osnovnih kontrola dostupnim u okviru Android platforme, što uključuje opisivanje njihovih mogućnosti i načina korištenja. U okviru Google Android platforme dostupne su slijedeće vrste rasporeda osnovnih objekata: 1. 2. 3. 4. 5. 6.

LinearLayout AbsoluteLayout TableLayout RelativeLayout FrameLayout ScrollView

Početni raspored osnovnih kontrola: Koristi se podrazumijevani raspored osnovnih kontrola LinearLayout. Prije nego što malo detaljnije objasnimo svaki od rasporeda, posvetimo riječ, dvije izvornoj terminologiji te hrvatskim pojmovima korištenim u tekstu. U originalnoj terminologiji osnovni objekti (npr. gumb, okvir za tekst i slično) nazivaju se Widget, a kad su vidljivi na zaslonu View. PojmomViewGroup (u osnovi također posebnoj vrsti pogleda) označava se skupina osnovnih „Viewa“ razmještena po zaslonu u određenom rasporedu – to je ovih 6 rasporeda spomenutih u prethodnom nabrajanju. Sad kad smo nabrojili temeljne

engleske pojmove navedimo i to koje ćemo prijevode koristi u nastavku teksta da ne stvaramo nepotrebnu zabunu. Umjesto pojmova Widget i View koristit ćemo riječi objekt ili kontrola, dok će ViewGroup biti zamijenjen s pogled ili raspored kontrola. To moţda nije najbolje moguće rješenje prijevoda, ali s druge strane predstavlja vrlo čestu terminologiju korištenu u opisu drugih razvojnih alata. Ako ste već koristili neki od njih, bez problema ćete pratiti rečenice u tekstu kojeg upravo čitate. Vratimo se sada na glavnu temu današnjeg teksta – korištenje različitih rasporeda osnovnih kontrola u vlastitim aplikacijama. Obavimo to istim redom kao u ranijem nabrajanju. LinearLayout predstavlja osnovni raspored kontrola gdje su sve osnovne kontrole raspoređene u samo jednom redu ili samo jednom stupcu. Tijekom rada na osnovna dva projekta u prethodnim nastavcima, nove kontrole su se uvijek pojavljivale jedna ispod druge, jer smo koristili upravo taj osnovni raspored kontrola automatski predloţen od strane razvojne okoline tijekom stvaranja projekta. Iako za sloţenije aplikacije ovakav raspored osnovnih kontrola nije uvijek i najpogodnije rješenje, kod početnih koraka u novom razvojnom alatu zapravo nema nekih prevelikih zamjerki na njegovo korištenje. Kod drugog od spomenutih rasporeda kontrola AbsoluteLayout programer nije ograničen na neki od podrazumijevanih oblika „redanja“ osnovnih kontrola po pozadini, nego ima potpunu slobodu u njihovom postavljanju na dostupnom području. O samim svojstvima potrebnim za pozicioniranje svake pojedine kontrole na ovakvoj vrsti pogleda odnosno rasporeda, bit će više riječi slijedeći put. Raspored kontrola pod nazivom TableLayout, kao što to sam naziv govori, koristi se kod razvrstavanja osnovnih kontrola u više redova ili stupaca tablice, odnosno u čelije tablice. Na taj način mogu se dobiti „lijepi“ pravilni rasporedi osnovnih kontrola na pogledu, što se vrlo često koristi kod različitih vrsta unosa podataka u aplikacijama. U RelativeLayout rasporedu kontrole se mogu postaviti na različita mjesta na dostupnom prostoru za njihovo prikazivanje, ali točno mjesto svake kontrole nije određeno njezinim apsolutnim koordinatama kao kod rasporeda pod nazivom AbsoluteLayout, nego je pozicija osnovne kontrole definirana relativnim koordinatama prema drugoj osnovnoj kontroli. FrameLayout se u aplikacijama koristi za rezerviranje mjesta za naknadno postavljanje drugih kontrola tako da se one uvijek „sidre“ prema gornjem lijevom uglu FrameLayout rasporeda kontrola. Sve će biti jasnije kad se to prikaţe slikom u nekoj od budućih aplikacija. Zadnja vrsta rasporeda osnovnih kontrola pod nazivom ScrollView koristi se u slučajevima kad na fizičkim dimenzijama zaslona jednostavno nije moguće prikazati sve potrebne osnovne kontrole na smislen i pregledan način (bez međusobnog preklapanja i jasnog razdvajanja). Pogled ScrollView zapravo predstavlja posebnu

vrstu rasporeda FrameLayout na koju se u praksi obično postavlja dodatna vrsta osnovnog rasporeda kontrola (RelativeLayout). U okviru jedne sloţene aplikacije moţe se koristiti veći broj istih ili različitih vrsta rasporeda kontrola, između kojih se prebacivanje, to jest aktiviranje nekog drugog rasporeda, izvodi pomoću programskog koda. Pogledajmo sada kako korištenja različitih rasporeda izgleda na nekoliko primjera. Osnovni raspored kontrola iz dovršenog primjera u prethodnom nastavku, koji je koristio podrazumijevani raspored LinearLayout imao je slijedeći XML oblika zapisa. Raspored kontrola AbsoluteLayout: Sve kontrole se preklapaju jer još nisu upisane njihove apsolutne koordinate. Ako u prethodnom XML kodu izmijenimo samo naziv rasporeda LinearLayout u AbsoluteLayout, sve kontrole „skupit“ će se u gornjem lijevom uglu prikaza, jer bi u ovakvom

rasporedu trebalo obavezno navesti apsolutne vrijednosti pozicija kontrola. Budući da to još uvijek nismo napravili, uzete su podrazumijevene vrijednosti 0, što je izazvalo spomenuto skupljanje kontrola. Navođenjem apsolutnih vrijednosti za poziciju i veličinu kontrola dolazi do njihovog ţeljenog formatiranja, kao što to pokazuje prateća slika uz tekst.



Raspored kontrola AbsoluteLayout: Za svaku kontrolu su navedene apsolutne vrijednosti za određivanje izgleda.

Zamjenom apsolutnog rasporeda kontrola relativnim u okviru XML definicije više nije potrebno navoditi apsolutne vrijednosti pozicija kontrola, nego samo njihovu relativnu poziciju u odnosu na neku drugu kontrolu. Apsolutne vrijednosti zaduţene za definiranje veličine kontrole mogu se koristiti i dalje na isti način. Na temelju slijedećeg XML sadrţaja, pomoću relativnog rasporeda kontrola oponašan je početni raspored kontrola LinearLayout.

U prethodna tri primjera korišteno je nekoliko dodatnih elemenata za definiranje rasporeda osnovnih kontrola u okviru osvnovne XML datoteke za

Raspored kontrola RelativeLayout: U ovom slučaju je oponašan osnovni raspored LinearLayout. definiranje izgleda zaslona. Nešto više riječi o njihovoj namjeni moţete pročitati u slijedećem poglavlju

Android programiranje #6: Korištenje osnovnih Android kontrola Nakon što smo raspravili što su to zapravo rasporedi osnovnih kontrola, u današnjem nastavku uvoda u Android programiranje moţemo prijeći na drugi bitan preduvjet izrade korisničkog sučelja, a to je upoznavanje osnovnih kontrola namijenjenih za postavljenje na takve rasporede. No, prije toga evo jednog primjera programskog koda (za kojeg nije bilo mjesta u prošlom nastavku), gdje se korisničko sučelje u potpunosti stvara programskim kodom. Drugim riječima, ako je programeru iz nekog razloga tako zgodnije, ne mora prvo „crtati“ korisničko sučelje u odgovarajućem prozoru razvojne okoline, a onda dodavati programski kod da „oţivi“ nacrtane kontrole, nego sve to moţe napraviti u jednom prolazu isključivo programskim kodom. Ako ste već u prošlosti koristili Microsoft Visual Studio, onda će vam sve biti mnogo jasnije kad napišemo da je riječ o postupku analognom dinamičkom dodavanju kontrola na formu tijekom izvođenja programa. package Hello.Android; import android.app.Activity; import android.os.Bundle; import android.view.ViewGroup.LayoutParams; import android.widget.LinearLayout; import android.widget.TextView; public class HelloActivity extends Activity { private LinearLayout prezimeime; private LinearLayout adresa; private LinearLayout podloga; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); createPrezimeIme(); createAdresa(); createPodloga();

setContentView(podloga); } private void createPodloga() { podloga = new LinearLayout(this); podloga.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); podloga.setOrientation(LinearLayout.VERTICAL); podloga.addView(prezimeime); podloga.addView(adresa); } private void createPrezimeIme() { prezimeime = new LinearLayout(this); prezimeime.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); prezimeime.setOrientation(LinearLayout.HORIZONTAL); TextView prezimeLbl = new TextView(this); prezimeLbl.setText(“Prezime ime: “); TextView prezime2Lbl = new TextView(this); prezime2Lbl.setText(“Android Vid”); prezimeime.addView(prezimeLbl); prezimeime.addView(prezime2Lbl); } private void createAdresa() { adresa = new LinearLayout(this); adresa.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); adresa.setOrientation(LinearLayout.VERTICAL); TextView adresaLbl = new TextView(this); adresaLbl.setText(“Adresa:”); TextView adresa2Lbl = new TextView(this); adresa2Lbl.setText(“Redacija VIDI”);

adresa.addView(adresaLbl); adresa.addView(adresa2Lbl); } }

Stvaranje rasporeda kontrola i samih kontrola pomoću programskog koda: Ne treba uvijek prvo nacrtati kontrole u razvojnoj okolini. Prethodni programski primjer tijekom svojeg izvođenja stvara osnovni raspored kontrola pod nazivom podloga, a onda na njega dodaje tekstualne kontrole za prikaz imena i adrese. Sličan postupak se moţe primijeniti za sve vrste kontrola. Ako ne volite prekucavati primjere, moţete ga pronaći na pratećem digitalnom mediju uz časopis. Vratimo se sada glavnom dijelu teksta – kontrolama namijenjenim postavljanju na neki od osnovnih rasporeda kontrola te njihovim najbitnijim svojstvima. Ako ste već koristili neki od modernijih razvojnih alata, ponovo ćete pronaći dosta sličnosti, a ako niste, onda svakako pogledajte tekst u nastavku te sami pokušajte napraviti nekoliko vlastitih primjera s takvim kontrolama. Kontrole ćemo u nastavku prikazati prema učestalosti u aplikacijama – dakle prvo one koje se najčešće koriste. TextView Kontrola tipa TextView namijenjena je prikazu različitih vrsta tekstova na zaslonu, ali bez mogućnosti njihove izmjene odnosno uređivanja. Zato se ova vrsta kontrole u vlastitim aplikacijama najčešće koristi za prikaz informacija korisniku poput dodatnih opisa uz glavne kontrole koje omogućavaju uređivanje teksta. Međutim, ako dio prikazanog teksta predstavlja web adresa, onda se kontrola moţe upotrijebiti znatno kreativnije, tako da klik mišem na web adresu otvara preglednik te prikazuje njezin sadrţaj (vidi primjer slike uz tekst). Da bi demonstrirali takvo ponašanje kontrole TextView u prethodnom programskom primjeru treba napraviti dvije izmjene. Prvo, treba u aplikaciju uključiti posebnu klasu za pronalaţenje veze prema veb adresi u tekstualnom nizu znakova (klasa Linkify): import android.widget.LinearLayout; import android.widget.TextView; import android.text.util.Linkify;

a onda dodati novu kontrolu nazvanu txtWeb čiji tekstualni sadrţaj uključuje web adresu: private void createPodloga() { podloga = new LinearLayout(this); podloga.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); podloga.setOrientation(LinearLayout.VERTICAL); podloga.addView(prezimeime); podloga.addView(adresa); TextView txtWeb = new TextView(this); txtWeb.setText(“Dodatne informacije o Android programiranju na http://www.vidilab.com/”); Linkify.addLinks(txtWeb, Linkify.ALL); podloga.addView(txtWeb); } Nakon pokretanja programa, kao što to demonstrira prateća slika uz tekst, u sadrţaju kontrole pojavljuje se posebno istaknuta web adresa, a klik na adresu otvara njezin sadrţaj u podrazumijevanom pregledniku. EditText Ako je korisniku potrebno omogućiti da u programu upiše odnosno da uredi postojeći tekstualni sadrţaj, onda umjesto kontrole tipa TextView treba

Korištenje kontrole TextView: Omogućava i otvaranje sadrţaja zadane web adrese. koristiti kontrolu tipa EditText. Treba istaknuti kako ni ova vrsta kontrole nije zamišljena za upis velikih tekstova, nego prije svega kraćih podataka kakvi se obično zapisuju u pojedine stupce baze podataka. Kontrola EditText posjeduje brojna dodatna svojstva čijom promjenom vrijednosti se moţe bitno izmijeniti ponašanje kontrole, prije svega način prikaza teksta. Na primjer: Auto text – automatski ispravlja moguće pogreške tijekom upisa teksta Capitalize – pretvara upisana slova u velika slova Numeric – postavlja brojčani unos podataka Password – postavlja upis lozinke (ne vide se znakovi kod upisa)

Phone number - postavlja unos telefonskog broja Single line - definira unos teksta u jednom redu Slijedeći primjer pokazuje dinamičko dodavanje tekstualne kontrole na osnovni raspored kontrola uz korištenje dvije dopunske metode za prikaz dodatnih informacija uz kontrolu. private void createPodloga() { podloga = new LinearLayout(this); podloga.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); podloga.setOrientation(LinearLayout.VERTICAL); podloga.addView(prezimeime); podloga.addView(adresa); /* dodatak 1 – primjer korištenja kontrole TextView */ TextView txtWeb = new TextView(this); txtWeb.setText(“Dodatne informacije o Android programiranju na http://www.vidilab.com/”); Linkify.addLinks(txtWeb, Linkify.ALL); podloga.addView(txtWeb); /* dodatak 2 – primjer korištenja kontrole EditText */ EditText txtKorisnik = new EditText(this); txtKorisnik.setText (“Upišite korisničko ime”); txtKorisnik.setHint(“Pazite na upis malih i velikih slova”); txtKorisnik.setError(“Pazite na veličinu slova”); podloga.addView(txtKorisnik); } Rezultat klika na web adresu u kontroli TextView: Prikaz sadrţaja zadane adrese u pregledniku. Posebnu vrstu kontrola za upis teksta predstavljaju kontroleAutoCompleteTextView te MultiAutoCompleteTextVi ew. Njihova najvaţnija značajka je da tijekom upisa/ispravljanja teksta omogućavaju automatsko dovršavanje upisanog teksta. Evo i primjera

odgovarajućeg programskog koda nadopisanog na kraj postojećeg programskog koda u funkciji createPodloga. private void createPodloga() { podloga = new LinearLayout(this); podloga.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); podloga.setOrientation(LinearLayout.VERTICAL); podloga.addView(prezimeime); podloga.addView(adresa); /* dodatak 1 – primjer korištenja kontrole TextView */ TextView txtWeb = new TextView(this); txtWeb.setText(“Dodatne informacije o Android programiranju na http://www.vidilab.com/”); Linkify.addLinks(txtWeb, Linkify.ALL); podloga.addView(txtWeb); /* dodatak 2 – primjer korištenja kontrole EditText */

Primjer korištenja kontrole EditText: Kontrola se koristi za upis i izmjenu teksta.

EditText txtKorisnik = new EditText(this); txtKorisnik.setText (“Upišite korisničko ime”); txtKorisnik.setHint(“Pazite na upis malih i velikih slova”); txtKorisnik.setError(“Pazite na veličinu slova”); podloga.addView(txtKorisnik); /* dodatak 3 – primjer korištenja kontrole AutoCompleteTextView */ AutoCompleteTextView actv = new AutoCompleteTextView(this); ArrayAdapter aa = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, new String[] {“English”, “Hebrew”, “Hindi”, “Spanish”, “German”, “Greek” });

actv.setAdapter(aa); podloga.addView(actv); } Nakon upisa početnih slova (npr. en) automatski se predlaţe podudarajuća potpuna tekstualna vrijednost, pa se ona nakon toga moţe jednostavno izabrati umjesto da se upisuje u cijelosti. Buttons Android platforma omogućava korištenje tri različita tipa gumbi – osnovni gumb (Button Control), gumb sa slikom (ImageButton Control) te gumb s mogućnošću prikaza dva različita stanja gumba (ToggleButton Control). Osnovni tip gumba već smo koristili u primjerima iz prethodnih nastavaka serijala, a detaljne mogućnosti korištenja sva tri tipa gumbi predstavit ćemo u slijedećem nastavku serijala zajedno s ostatkom osnovnih kontrola.

Android programiranje #7 S predstavljanjem osnovnih Android kontrola prošli put smo zastali na dobro poznatim gumbima (Buttons). Kao i u drugim modernim operativnim sustavima ovaj tip kontrole koristi se u aplikacijama za izvođenje različitih operacija, a (ponovo kao i u drugim operativnim sustavima) moţe imati nekoliko pojavnih oblika. Osnovni oblik gumba (Button) na sebi sadrţi samo običan tekst koji označava kakvu će operaciju u okviru određene aplikacije izazvati pritisak na gumb. Ako zadnjih nekoliko desetljeća niste proveli izolirani u samici nekog zaostalog nedemokratskog reţima bez ikakvog kontakta s modernim računalima, onda je prethodna rečenica sasvim dovoljna da shvatite o čemu je ovdje riječ. Budući da smo ovaj gumb već nekoliko puta koristili u primjerima iz prethodnih nastavaka serijala, kako u pogledu izmjene osnovnih svojstava, tako i u pogledu dodavanja programskog koda, nećemo se više ni baviti njime. Budući da se moderna korisnička sučelja sve više temelje na slici nego na riječi, razumljivo da je običan gumb doţivio svojevrsnu vizualnu nadogradnju, postavši tako u Android terminologiji kontrola pod nazivom ImageButton. Namjena unaprijeđene kontrole je potpuno jednaka kao i u njezinom osnovnom obliku, jedino što takav gumb moţe izgledati bitno ljepše (što izravno ovisi o slici postavljenoj na njegovu površinu). Upravo je zamjena osnovnih vrsta gumbi slikovnim jedan od najvaţnijih, ali ujedno i najjednostavnijih načina da vlastitu aplikaciju učinite atraktivnijom te u konačnici privlačnijom potencijalnim korisnicima. Slikovna verzija gumba povezuje se s odgovarajućom datotekom s grafičkim sadrţajem pomoću svojstva src, što se moţe napraviti u za to namijenjenom prozoru razvojne okoline, izravno u XML datoteci, ili programskim kodom. U priloţenoj segmentu XML datoteke prikazan je primjer korištenja drugog od nabrojenih načina, dok se za istu namjenu u programskom kodu treba koristiti metoda setImageResource(). Treća vrsta gumba pod nazivom ToggleButton omogućava prikaz više stanja iste pojave unutar aplikacije. Na primjer, jednim stanjem gumba moţe se pokazati da je uključen nekakav parametar odnosno izvođenje nekakve operacije, a drugim stanjem da je parametar isključen odnosno da je prekinuto izvođenje operacije. U praksi se takva vrsta gumbi najčešće koristi za prilagođavanje različitih dijelova aplikacije ţeljama i potrebama korisnika aplikacije. Kao što to ponovo prikazuje priloţena XML datoteka sa definicijama sve tri vrste opisanih gumbi, pomoću dva dodatna svojstva gumba android:textOn=”Pokrenuto” android:textOff=”Zaustavljeno”> moguće je definirati dva različita tekstualna sadrţaja za prikazivanje na samom gumbu ovisno o njegovom trenutnom stanju (uključeno / isključeno).

Kako izgleda korisničko sučelje nastalo na temelju prethodne XML datoteke moţete vidjeti na priloţenoj slici uz današnji tekst. Zadnjoj od prije opisanih kontrola prilično slične su još dvije vrste kontrola. To su CheckBox i RadioButton. Riječ je o kontrolama koje su zapravo i poznatije korisnicima aplikacija, jer su osim na Android platformi prisutne u praktično svim modernim grafičkim sučeljima današnjice. Obje od navedenih kontrola omogućavaju uključivanje/isključivanje različitih opcija, ali se međusobno razlikuju u situacijama kad u korisničkom sučelju aplikacije postoji više kontrola istog tipa. CheckBox kontrole su u pogledu međusobnog stanja neovisne jedne od druge, što znači da uključivanje ili isključivanje jedne od kontrola ne utječe na stanje druge kontrole. Osim promjene trenutnog stanja od strane krajnjeg korisnika aplikacije, vrijednosti se

mogu postavljati programskim kodom korištenjem metode setChecked() dok se trenutno stanje moţe dobiti pomoću isChecked(). Trenutno stanje neke RadioButton kontrole ovisi o stanju drugih kontrola iste vrste, što drugim riječima znači da u jednom trenutku samo jedna od takvih kontrola moţe biti uključena, dok sve druge kontrole automatski poprimaju vrijednost isključeno. Zato se ova vrsta kontrola koristi za rad s vrijednosti koje se međusobno isključuju. Sa stanovišta programskog koda uključivanje/isključivanje stanja kontrole provodi se na sličan način kao i kod CheckBox kontrola. Spomenimo na ovom mjestu i to da se pojam međusobnog isključivanja RadioButton kontrola odnosi na kontrole u istom „spremniku“ kontrola. Ako u aplikaciji trebaju postojati dvije neovisne grupe takvih kontrola, onda treba pripremiti i dva spremnika (npr. rasporeda kontrola). Evo kratkog segmenta XML datoteke namijenjenog definiranju obiju vrsta kontrola. CheckBox kontrole: : Building User Interfaces and Using Controls RadioButton kontrole:

Korištenje gumbi: Programeru su na raspolaganju tri različite vrste gumbi.

U izmišljenoj aplikaciji za naručivanje u restoranu u prvom slučaju korisnik aplikacije moţe označiti različite dijelove obroka neovisno jedan o drugome, a u drugom slučaju za glavni obrok moţe izabrati samo jednu od vrsta glavnog jela (mesa).

Android programiranje #8: Android kontrole u akciji IV Vrlo vaţan dio gotovo svake aplikacije (osim onih krajnje trivijalnih, ili onih koje su potpuno optimizirane za neko specijalizirano područje) je upravljanje vremenom. Čak i različite igre, kao kategorija aplikacija kakve se vrlo često pišu za mobilne uređaje uključujući i Android platformu, često spremaju različite podatke o igraču ili statusu igre povezane s datumom i vremenom. Naravno, za prikaz ili izmjenu datuma i vremena programer uvijek moţe izmisliti svoje vlastite kontrole, ali nije loše kad je i osnovni razvojni sustav opremljen odgovarajućim kontrolama. To posebno vrijedi kod aplikacija s naglaskom na funkcionalnosti, a ne na vizualnoj raskoši. Android platforma opremljena je s dvije međusobno prilično različite vrste kontrola za tu namjenu. Prva grupa kontrola moţe samo prikazati podatke o vremenu, dok ih druga vrsta moţe prikazati, ali i dozvoliti izmjenu vrijednosti od strane krajnjeg korisnika aplikacije. U prvu grupu kontrola pripadaju kontroleAnalogClock i DigitalClock (sam naziv u potpunosti govori o čemu je riječ). Glavni nedostatak im je određen već prije spomenutom namjenom (prikazom podataka), pa se u praksi koriste nešto rjeđe, osim ako je dovoljno da kontrola zaista samo prikazuje datum ili vrijeme. Zato se s navedene dvije kontrole više nećemo baviti. Ako njihova ograničenja zadovoljavaju vaše planove u izradi aplikacija, jednostavno ih postavite na neki od standardnih rasporeda kontrola i zaboravite na njih.

U slučaju da je potrebno omogućiti nekakav oblik interakcije korisnika aplikacije u pogledu odabira datuma i/ili vremena, onda je bolje upotrijebiti kontrole pod nazivom DatePicker i TimePicker. Njihovo postavljanje na osnovni raspored kontrola moţe se napraviti prema slijedećem primjeru.

Prva (gornja) kontrola zaduţena je za prikaz, odnosno odabir datuma, a donja to isto radi s vremenom, kao što se to moţe provjeriti na priloţenoj slici uz tekst. Kad se tome pridoda programski kod naveden u nastavku zaduţen za podešavanje početnih vrijednosti kontrola, dobije se sasvim funkcionalno korisničko sučelje. Najveći nedostatak ove grupe kontrola je njihova relativna nezgrapnost. Drugim riječima jednostavno su prevelike za intenzivno korištenje, naročito ako koristite uređaj s relativno skromnom rezolucijom zaslona. Ako to predstavlja nepremostivu prepreku moţete se snaći i sami te napraviti vlastite i bitno manje kontrole. package Hello.Android; import android.app.Activity; import android.os.Bundle; import android.widget.DatePicker; import android.widget.TimePicker; public class HelloActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); DatePicker dp = (DatePicker)this.findViewById(R.id.datePicker); dp.init(2010, 11, 13, null); TimePicker tp = (TimePicker)this.findViewById(R.id.timePicker); tp.setIs24HourView(true); tp.setCurrentHour(new Integer(10)); tp.setCurrentMinute(new Integer(10)); } } Korištenje izbornika Osim sasvim jednostavnih uradaka većina aplikacija podrţava neki oblik sustava izbornika namijenjen izboru svih operacija koje nudi aplikacija. Ni Android platforma po tome nije nikakav izuzetak. Zapravo mogli bi reći da vrijedi čak suprotno – programeru je na raspolaganju nekoliko različitih sustava izbornika, a na njemu je odluči koji od njih najviše odgovara potrebama konkretne aplikacije. Dok ste neke od dostupnih sustava izbornika već susretali na drugim operativnim sustavima u vrlo sličnom obliku, Android nudi i neke novosti na ovom području, zbog čega ćemo se izbornicima pozabaviti u dva broja časopisa.

Po običaju krećemo od najjednostavnijeg oblika izbornika, za čiju pojavu u aplikaciji je zaduţen isključivo programski kod nalik na onaj pridodan na kraj prethodnog projekta za prikaz datumski i vremenski orijentiranih kontrola (funkcija onCreateOptionsMenu). Navedeni naziv funkcije je obavezan i ujedno povezan s odgovarajućom aktivnosti u programu. package Hello.Android; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.DatePicker; import android.widget.TimePicker; public class HelloActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); DatePicker dp = (DatePicker)this.findViewById(R.id.datePicker); dp.init(2010, 11, 13, null); TimePicker tp = (TimePicker)this.findViewById(R.id.timePicker); tp.setIs24HourView(true); tp.setCurrentHour(new Integer(10)); tp.setCurrentMinute(new Integer(10)); } public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0 // Group ,1 // item id ,0 //order ,”append”); // title menu.add(0,2,1,”edit”); menu.add(0,3,2,”clear”); return true;

} } Rezultat izvođenja dodatnog programskog koda su tri opcije izbornika, koje se pojavljuju na samom dnu zaslona). Kao što to pokazuje prethodni primjer dodavanje svake od opcija izbornika zahtijeva navođenje četiri parametra.To su redom oznaka grupe, oznaka opcije izbornika, redoslijed opcije u okviru izbornika, te tekst koji se prikazuje na samoj opciji izbornika. Prve tri opcije su brojčane, a četvrta je iz sasvim razumljivih razloga tekstualna. Zadnja od nabrojenih opcija moţe se u programskom kodu za generiranje izbornika zadati izravno, kao što je to slučaj u prethodnom primjeru, ili se odgovarajuća vrijednost moţe unaprijed pripremiti u resursnoj datoteci. Istaknimo kako nije uvijek potrebno navoditi baš sve brojčane vrijednosti, nego se umjesto njih moţe upotrijebiti vrijednost Menu.None. Ako je potrebno opcije izbornika u aplikaciji grupirati u više od jedne grupe, onda se to rješava navođenjem različitih oznaka grupe prilikom zadavanja naredbi za stvaranje opcija izbornika. Takva podjela izbornika na dvije grupe prikazana je u slijedećem segmentu programskog koda, kojeg treba umetnuti u program umjesto istoimene funkcije iz prethodnog kompletnog primjera koda. Kako će izgledati dobijeni rezultat moţe se vidjeti na priloţenoj slici uz tekst. public boolean onCreateOptionsMenu(Menu menu) { //Group1 int group1 = 1; menu.add(group1,1,1,”g1.item1″); menu.add(group1,2,2,”g1.item2″); //Group2 int group2 = 2; menu.add(group2,3,3,”g2.item1″); menu.add(group2,4,4,”g2.item2″); return true; } Kao što smo to već objasnili ranije, prethodne naredbe izazivaju samo prikaz izbornika na zaslonu uređaja, ali pritisak na te izbornike trenutno ne izaziva baš nikakvu reakciju, jer jednostavno nedostaje odgovarajućeg programskog koda za tu namjenu. To je tema kojom ćemo se pozabaviti u slijedećem broju, baš kao i

dodavanjem slika na opcije izbornika, kako bi se postigao što bolji vizualni dojam u vlastitoj aplikaciji. U ostatku današnjeg teksta navest ćemo karakteristike preostalih vrsta izbornika dostupnih na Android platformi. Prva vrsta su takozvani prošireni izbornici. Ova vrsta izbornika nastaje automatski, ako programer „pretjera“ s brojem opcija osnovnog izbornika. U tom slučaju se kao opcija izbornika automatski prikazuje vrijednost More, a njezinim odabirom korisnik aplikacije moţe stići do početno skrivenih opcija izbornika. Jedno od ograničenja proširenih izbornika je u tome što ne dozvoljavaju prikaz slike, pa zato prilikom pripreme izbornika treba paziti da se na istom mjestu u aplikaciji ne pojave i trešnje i višnje, to jest opcije izbornika sa slikama i one bez slika. Kod dodavanja ikona na opcije izbornika u igri je još nekoliko dodatnih ograničenja osim onog spomenutog u prethodnom odjeljku. Na opciji izbornika s ikonom ne moţe biti prikazana oznaka njezinog izbora (kvačica), a ako je tekst opcije izbornika nešto duţi, onda će biti prikazan samo početni dio. To i nije nelogično – ako odaberete ikonu koja vrlo reprezentativno označava neku operaciju, zašto bi je onda naširoko i opisivali. Prednosti takvog pristupa kod stvaranja višejezičnog sučelja ne trebamo posebno ni isticati.

U slučaju vrlo širokog raspona mogućih operacija u aplikaciji, neke (ili sve) opcije izbornika mogu imati svoje podizbornike. Opcije podizbornika dodaju se programski odgovarajućim metodama što ćemo prikazati u slijedećem nastavku. Za sada istaknimo kako i ova kategorija izbornika ne podrţava prikaz ikona, iako se formalno ne javljaju nikakve greška kod takvog pokušaja. Izbornici ovisni o kontekstu predstavljaju posebnu vrstu izbornika čiji izgled se mijenja ovisno o smislu izvođenja pojedinog dijela aplikacije, a aktiviraju se takozvanim dugim pritiskom na neki element korisničkog sučelja. Programer moţe u vlastitu aplikaciju dodati i standardne sistemske izbornike. Kako se to radi, također ćemo demonstrirati slijedeći put.

Android programiranje #9: Korištenje datotečnog sustava Nakon što smo u prošlom nastavku pokazali kako se stvara osnovna vrsta izbornika, danas ćemo objasniti kako program na najednostavniji mogući način putem izbornika odgovara na akcije korisnika. Ujedno ćemo od ovomjesečnog nastavka napraviti malo „ubrzanje“ u izlaganju kako bi u planiranom broju preostalih nastavaka mogli doista i napraviti nekakvu malo sloţeniju aplikaciju. Ideja je da izloţenu materiju prikaţemo na međusobno povezani način, kako nakon prolaska kroz čitav serijal ne bi imali niz nepovezanih segmenata znanja o pojedinim dijelovima Android SDK sustava, ali bez mogućnosti njihovog slaganja u smislenu cjelinu. S druge strane, na temelju dosadašnjih nastavaka više ne bi trebali imati previše problema s tim da pronađete gdje se umeću pojedini dijelovi programskog koda. Zato na ovom mjestu nećemo izloţiti sve moguće načine stvaranja izbornika i „hvatanja“ operacija korisnika, jer ih ima zbilja podosta, pa bi se izlaganje htjeli mi to ili ne, lako pretvorilo u „prepisivanje“ originalnih uputa. Umjesto toga ćemo u sloţenijoj aplikaciji koju smo maloprije najavili pokazati brojne dodatne mogućnosti u korištenju. Osnovni oblik reakcije izbornika na djelovanje korisnika priprema se u dva koraka prema slijedećem obrascu. U prvom koraku treba Implementirati OnMenuClickListener sučelje. U drugom koraku, koji se izvodi nakon izbora neke od opcija od strane korisnika, poziva se metoda onMenuItemClick(). To je ujedno mjesto gdje se izvodi stvarna obrada događaja – pritiska na neku od opcija izbornika. //korak1 public class MyResponse implements OnMenuClickListener { //… @override boolean onMenuItemClick(MenuItem item) { //izvođenje operacije return true; } }

//korak 2 MyResponse myResponse = new MyResponse(…); menuItem.setOnMenuItemClickListener(myResponse); … Osim osnovnog načina reakcije izbornika na događaje postoji još nekoliko varijanti koje ćemo demonstrirati na sloţenijoj aplikaciji. U njoj ćemo ujedno pokazati kako se izvornici mogu stvoriti preko odgovarajuće resursne XML datoteke, a ne samo programskim kodom. Rad s datotekama Svaka malo sloţenija aplikacija, koja rukuje s korisnim podacima, mora imati mogućnost spremanja podataka iz aplikacije u neko spremište te njihovo vraćanje kad se za tim ukaţe potreba. U današnjem nastavku pokazat ćemo kako se navedene dvije operacije izvode pomoću datotečnog sustava ugrađenog u Android SDK. Za to ćemo koristiti dva specijalizirana tijeka podataka – FileOutputStream iFileInputStream. Prvi se koristi za prijenos podataka na relaciji program – datoteka, a drugi u obrnutom smjeru. Ujedno ćemo pokazati dvije dodatne nuţne operacije kod takvog postupka. Prva je „skupljanje“ trenutnih vrijednosti različitih Android kontrola upisanih od strane korisnika aplikacije kako bi se imalo što upisati u datoteku, a druga je njihovo ponovno vraćanje iz datoteke i postavljanje na odgovarajuću kontrolu. Pogledajmo prvo kako se izvodi spremanje podataka u datoteku na segmentu programskog koda „izvađenog“ iz jedne manje medicinski orijentirane aplikacije. U ovom trenutku zapravo i nije previše bitno o kakvim se podacima radi. Primijetimo samo da se podaci ne skupljaju isključivo iz tekstualnih nego i iz drugih oblika kontrola, a prije samog spremanja u datoteku se grupiraju u jedan sloţeniji niz znakova. U njemu su podaci međusobno odvojeni posebnim nizom znakova za odvajanje, kako bi se olakšalo njihovo obnavljanje kod suprotne operacije čitanja iz datoteke.

Spremanje podataka iz aplikacije: Prethodni primjeri koda odnose se na jednostavnu medicinski orijentiranu aplikaciju.

private void SpremiPodatkeCritical2() throws IOException { String FILENAME = “PrvaPomocCritical2″; String string = “”; FileOutputStream fos; try { final EditText tmp = (EditText) findViewById(R.id.txtSpol); String tmps = tmp.getText().toString(); if (tmps.length() == 0) tmps = “!!!”; final EditText tmp2 = (EditText) findViewById(R.id.txtTezina); String tmps2 = tmp2.getText().toString(); if (tmps2.length() == 0) tmps2 = “!!!”; final EditText tmp3 = (EditText) findViewById(R.id.txtKrvnaGrupa); String tmps3 = tmp3.getText().toString(); if (tmps3.length() == 0) tmps3 = “!!!”; final EditText tmp4 = (EditText) findViewById(R.id.txtRhFaktor); String tmps4 = tmp4.getText().toString(); if (tmps4.length() == 0) tmps4 = “!!!”; final CheckBox tmp5 = (CheckBox) findViewById(R.id.chkSida); String tmps5 = “N”; if (tmp5.isChecked()) tmps5 = “D”; final CheckBox tmp6 = (CheckBox) findViewById(R.id.chkHepatitisC); String tmps6 = “N”; if (tmp6.isChecked()) tmps6 = “D”; final CheckBox tmp7 = (CheckBox) findViewById(R.id.chkDonator); String tmps7 = “N”;

if (tmp7.isChecked()) tmps7 = “D”; final EditText tmp8 = (EditText) findViewById(R.id.txtAlergija); String tmps8 = tmp8.getText().toString(); if (tmps8.length() == 0) tmps8 = “!!!”; final EditText tmp9 = (EditText) findViewById(R.id.txtDijagnoza); String tmps9 = tmp9.getText().toString(); if (tmps9.length() == 0) tmps9 = “!!!”; final EditText tmp10 = (EditText) findViewById(R.id.txtTerapija); String tmps10 = tmp10.getText().toString(); if (tmps10.length() == 0) tmps10 = “!!!”; final EditText tmp11 = (EditText) findViewById(R.id.txtNapomena); String tmps11 = tmp11.getText().toString(); if (tmps11.length() == 0) tmps11 = “!!!”; string = tmps + “###” + tmps2 + “###” + tmps3 + “###” + tmps4 + “###” + tmps5 + “###” + tmps6 + “###” + tmps7 + “###” + tmps8 + “###” + tmps9 + “###” + tmps10 + “###” + tmps11; fos = openFileOutput(FILENAME, Context.MODE_PRIVATE); fos.write(string.getBytes()); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } }

Istaknimo vrlo vaţnu činjenicu koju svakako treba uzeti u obzir kod rada s datotečnim sustavom, a to je mogućnost pojave greške. Osnovni niz naredbi za zapis podataka u datoteku: fos = openFileOutput(FILENAME, Context.MODE_PRIVATE); fos.write(string.getBytes()); fos.close(); moţe ponekad dovesti do pojave greške, ako ni zbog čega drugog onda zbog nedostatka prostora na mediju na kojem se nalazi datotečni sustav. Kako se aplikacija u tom slučaju ne bi počela nekontrolirano ponašati, treba ugraditi bar osnovni mehanizam obrade pogreške u vlastitom kodu, što je ovdje i napravljeno korištenjem standardne try .. catch strukture. Pogledajmo sada kako se koristi suprotni tijek podataka namijenjen čitanju spremljenih podataka. private void VratiPodatkeCritical2() throws IOException { String FILENAME = “PrvaPomocCritical2″; String string1 = “”; setContentView(R.layout.critical2); FileInputStream fis; try { fis = openFileInput(FILENAME); BufferedReader buf = new BufferedReader(new InputStreamReader(fis)); string1 = buf.readLine(); String[] list = TextUtils.split(string1, “###”); final EditText tmp = (EditText) findViewById(R.id.txtSpol); if (list[0].matches(“!!!”)) list[0] = “”; tmp.setText(list[0]); final EditText tmp2 = (EditText) findViewById(R.id.txtTezina); if (list[1].matches(“!!!”)) list[1] = “”;

tmp2.setText(list[1]); final EditText tmp3 = (EditText) findViewById(R.id.txtKrvnaGrupa); if (list[2].matches(“!!!”)) list[2] = “”; tmp3.setText(list[2]); final EditText tmp4 = (EditText) findViewById(R.id.txtRhFaktor); if (list[3].matches(“!!!”)) list[3] = “”; tmp4.setText(list[3]); final CheckBox tmp5 = (CheckBox) findViewById(R.id.chkSida); tmp5.setChecked(false); if (list[4].matches(“D”)) tmp5.setChecked(true); final CheckBox tmp6 = (CheckBox) findViewById(R.id.chkHepatitisC); tmp6.setChecked(false); if (list[5].matches(“D”)) tmp6.setChecked(true); final CheckBox tmp7 = (CheckBox) findViewById(R.id.chkDonator); tmp7.setChecked(false); if (list[6].matches(“D”)) tmp7.setChecked(true); final EditText tmp8 = (EditText) findViewById(R.id.txtAlergija); if (list[7].matches(“!!!”)) list[7] = “”; tmp8.setText(list[7]); final EditText tmp9 = (EditText) findViewById(R.id.txtDijagnoza); if (list[8].matches(“!!!”)) list[8] = “”; tmp9.setText(list[8]); final EditText tmp10 = (EditText) findViewById(R.id.txtTerapija); if (list[9].matches(“!!!”)) list[9] = “”; tmp10.setText(list[9]); final EditText tmp11 = (EditText) findViewById(R.id.txtNapomena); if (list[10].matches(“!!!”)) list[10] = “”;

tmp11.setText(list[10]); fis.close(); } catch (FileNotFoundException e) { final EditText tmp = (EditText) findViewById(R.id.txtSpol); tmp.setText(“$_”); final EditText tmp2 = (EditText) findViewById(R.id.txtTezina); tmp2.setText(“___”); final EditText tmp3 = (EditText) findViewById(R.id.txtKrvnaGrupa); tmp3.setText(“__”); final EditText tmp4 = (EditText) findViewById(R.id.txtRhFaktor); tmp4.setText(“_”); final CheckBox tmp5 = (CheckBox) findViewById(R.id.chkSida); tmp5.setChecked(false); final CheckBox tmp6 = (CheckBox) findViewById(R.id.chkHepatitisC); tmp6.setChecked(false); final CheckBox tmp7 = (CheckBox) findViewById(R.id.chkDonator); tmp7.setChecked(true); final EditText tmp8 = (EditText) findViewById(R.id.txtAlergija); tmp8.setText(“$Alergija”); final EditText tmp9 = (EditText) findViewById(R.id.txtDijagnoza); tmp9.setText(“$Dijagnoza”); final EditText tmp10 = (EditText) findViewById(R.id.txtTerapija); tmp10.setText(“$Terapija”); final EditText tmp11 = (EditText) findViewById(R.id.txtNapomena); tmp11.setText(“$Napomena”);

e.printStackTrace(); } } Ponovno, potrebna je standardna procedura za obradu pogrešaka (throws IOException), jer se moţe dogoditi da u datotečnom sustavu iz ovog ili onog razloga ne postoji, ili je oštećena datoteka s podacima. Budući da smo prilikom spremanja podatke formatirali tako da se čitava operacija njihovog spremanja izvodi u jednom koraku (što nije obavezno te ovisi o karakteristikama vlastite aplikacije), sada ćemo čitanje također „odraditi“ u jednom koraku, te ujedno razbiti podatke u odgovarajuće polje podataka pomoću naredbe: String[] list = TextUtils.split(string1, “###”); Preostalo je još samo to da se na korištenom rasporedu kontrola unutar aplikacije pronađe odgovarajuća kontrola te da joj se dodijeli točno određena vrijednost pročitana iz datoteke. Za taj postupak koristi se niz findViewById naredbi.

Android programiranje #10: Nekoliko standardnih dijelova aplikacije Prošli put smo iz nešto sloţenije medicinski orijentirane Android aplikacije „izvukli“ dio programskog koda zaduţen za spremanje podataka te za njihovo ponovno čitanje kad se za tim ukaţe potreba. U današnjem nastavku pokazat ćemo još nekoliko karakterističnih dijelova programskog koda, koje uz manje ili veće promjene moţete upotrijebiti u vlastitim projektima. Prvo jedan sasvim logičan, ali vaţan savjet. Svaka sloţenija Android aplikacija, a naročito ako ona koristi različite sistemske module (kao što je to slučaj u ovom primjeru), zahtijeva uključivanje odgovarajućih biblioteka. Ovisno o načinu oblikovanja korisničkog sučelja i pisanju programskog koda, taj je postupak u najvećoj mogućoj mjeri automatiziran. Međutim, ako se tijekom razvoja u aplikaciji odjednom pojavi čitav niz pogrešaka, postoji dosta velika vjerojatnost da nedostaje (zbog izostanka ili slučajnog brisanja) odgovarajuća import naredba. U nastavku slijedi prikaz kako to prilično komplicirano izgleda u ovom slučaju:

Primjer rasporeda kontrola: Jedan od standardnih dijelova aplikacije za prikupljanje podataka o korisniku.

import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.sql.Date; import java.text.DateFormat;

import java.util.Calendar; import android.R.bool; import android.R.integer; import android.R.string; import android.app.Activity; import android.app.AlertDialog; import android.app.PendingIntent; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.ColorStateList; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.os.Message; import android.os.Messenger; import android.telephony.SmsManager; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.Button; import android.widget.CheckBox; import android.widget.CheckedTextView; import android.widget.EditText; U medicinski orijentiranoj aplikaciji čije dijelove koristimo za demonstraciju programskog koda, zbog relativno velike količine prikupljenih podataka o korisniku aplikacije neprikladne za prikaz na samo jednom zaslonu ograničene rezolucije

(uobičajene kod mobilnih telefona opremljenih Android sustavom), koristi se više međusobno povezanih rasporeda kontrola, a na svakom od rasporeda upotrijebljene su različite kontrole kako bi se što jednostavnije i preglednije unijeli relevantni podaci. Kako to zaista izgleda na zaslonu Android uređaja moţete provjeriti na temelju priloţenih slika uz tekst, a dijelovi odgovarajućeg XML koda navedeni su u nastavku. … … … … U trenutku prelaska s jednog rasporeda kontrola na drugi postojeći sadrţaj kontrola iz starog rasporeda kontrola sprema se za kasnije korištenje, a novi raspored kontrola se popunjava prethodno spremljenim sadrţajem (ako takav postoji zbog ranijeg korištenja aplikacije). Obje operacije objašnjene su u prethodnom nastavku serijala. Pokaţimo sada kako se programskim kodom prelazi s jednog rasporeda kontrola na drugi. Na svakom osnovnom rasporedu postoje dva gumba za kretanje na slijedeću odnosno prethodnu stranicu (razumljivo osim na prvom i zadnjem). Slijedi primjer korištenja na drugom rasporedu kontrola – na njemu postoji gumb za prelazak na prvi, odnosno na treći raspored kontrola. public void btn3VratiSeClick(View view) { try { SpremiPodatkeCritical2(); } catch (IOException e1) { e1.printStackTrace(); } setContentView(R.layout.critical); try {

VratiPodatkeCritical(); } catch (IOException e) { e.printStackTrace(); } } public void btn3DaljeClick(View view) { try { SpremiPodatkeCritical2(); } catch (IOException e1) { e1.printStackTrace(); } setContentView(R.layout.critical3); try { VratiPodatkeCritical3(); } catch (IOException e) { e.printStackTrace(); } } Kako eventualne pogreške prilikom kretanja kroz osnovne rasporede kontrola ne bi izazvale rušenje programa, prijenos prikaza s jednog rasproeda kontrola na drugi „zamotan“ je u odgovarajuću strukturu za obradu pogreške. Osim prikaza podataka na standardnim rasporedima kontrola, vrlo često je u programu potrebno prikazati i odgovarajuće dijaloške okvire o statusnim informacijama, greškama u radu i slično. U nastavku je naveden primjer programskog koda za prikaz dijaloškog okvira s podacima o autorima programa (ako za to ne namjeravate koristiti poseban raspored kontrola zbog veće vizualne dojmljivosti takvog dijela aplikacije).

Primjer rasporeda kontrola: Drugi standardni dio aplikacije.

public void btnPrvaPomocClick(View view) { AlertDialog ad = new AlertDialog.Builder(prvaPomoc.this).create(); CharSequence poruka = “Autor programa \n” ; poruka = poruka + “Crnko Nenad\n\n”; poruka = poruka + “Stručni medicinski suradnik\n”; poruka = poruka + “Fusić Snjeţana\n\n”; poruka = poruka + “Verzija programa\n”; poruka = poruka + “25.06.2010 23:00:00″; ad.setTitle(“O programu…”); ad.setMessage(poruka); ad.setButton(“Zatvori”, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { } }); ad.show(); }

U slučaju da vam to negdje zatreba, evo i opće funkcije za otvaranje osnovnog oblika dijaloškog okvira koju uz veće ili manje preinake moţete upotrijebiti u vlastitim aplikacija. Ulazni parametri funkcije su poruka koja se prikazuje u okviru dijaloškog okvira te njegovo zaglavlje. private void MsgBox(String Poruka, String VrstaPoruke) { AlertDialog ad = new AlertDialog.Builder(prvaPomoc.this).create(); ad.setTitle(VrstaPoruke); ad.setMessage(Poruka); ad.setButton(“Zatvori”, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { } }); ad.show(); } Navedimo na kraju današnjeg nastavka najsloţeniji „komad“ programskog koda zaduţen za pripremu i slanje SMS poruke s podacima iz programa u slučaju nezgode. Zbog ograničenja prostora u časopisu ovim dijelom ćemo se nešto detaljnije pozabaviti u slijedećem nastavku serijala. public void btnPosaljiSMSClick(View view) { final Button btnPosaljiSMS = (Button) findViewById(R.id.btnPosaljiSMS); Calendar Kalendar = Calendar.getInstance (); CharSequence mTrenutnoVrijeme = Kalendar.getTime().toString(); mGodina = Kalendar.get(Calendar.YEAR); mMjesec = Kalendar.get(Calendar.MONTH);

mDan = Kalendar.get(Calendar.DAY_OF_MONTH); mSati = Kalendar.get(Calendar.HOUR_OF_DAY); mMinute = Kalendar.get(Calendar.MINUTE); mSekunde = Kalendar.get(Calendar.SECOND ); mTrenutnoVrijeme = Integer.toString(mDan) + “.” + Integer.toString(mMjesec) + “.” + Integer.toString(mGodina) + ” ” + Integer.toString(mSati) + “:” + Integer.toString(mMinute) + “:” + Integer.toString(mSekunde); setContentView(R.layout.critical3); try { VratiPodatkeCritical3(); } catch (IOException e1) { e1.printStackTrace(); } final CheckBox tp = (CheckBox) findViewById(R.id.chkGPSPozicija); String pozicija = “”; if (tp.isChecked()) { try { LocationManager locationManager; String context = Context.LOCATION_SERVICE; locationManager = (LocationManager)getSystemService(context); String provider = LocationManager.GPS_PROVIDER; Location location = locationManager.getLastKnownLocation(provider);

double lat = location.getLatitude(); double lng = location.getLongitude(); pozicija = ” ” + Double.toString(lat) + ” / ” + Double.toString(lat); } catch (Exception e) { e.printStackTrace(); } } try { final EditText tmp = (EditText) findViewById(R.id.txtSMSPoruka); String tmps = tmp.getText().toString(); if (tmps.length() == 0) { setContentView(R.layout.main); MsgBox(“Nije definiran tekst SMS poruke!”, “Upozorenje”); return; } final EditText tmpbr = (EditText) findViewById(R.id.txtSMSBroj); String tmpsbr = tmpbr.getText().toString(); if (tmpsbr.length() == 0) { setContentView(R.layout.main); MsgBox(“Nije definiran broj za slanje SMS poruke!”, “Upozorenje”); return; }

setContentView(R.layout.main); VratiPodatkeMain(); tmps = tmps + pozicija; SmsManager sm = SmsManager.getDefault(); sm.sendTextMessage(tmpsbr, null, tmps + pozicija, null, null); } catch (Exception e) { MsgBox(e.getMessage(),”Greška”); e.printStackTrace(); } AlertDialog ad = new AlertDialog.Builder(prvaPomoc.this).create(); CharSequence poruka = “Zabiljeţeno vrijeme slanja SMS poruke za pomoć\n\n” ; poruka = poruka + mTrenutnoVrijeme.toString(); ad.setTitle(“Potvrda operacije”); ad.setMessage(poruka); ad.setButton(“Zatvori”, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { } }); ad.show(); btnPosaljiSMS.setText(“SMS poruka: ” + mTrenutnoVrijeme); try { SpremiPodatkeMain();

} catch (IOException e) { e.printStackTrace(); } }

Android programiranje #11: Standardni dijelovi aplikacije Na kraju teksta u prethodnom broju časopisa naveden je malo veći segment programskog koda za izvođenje nekoliko bitnih stvari u programu, ali jednostavno nije bilo dovoljno mjesta za njegovo detaljnije objašnjenje. Zato u današnjem nastavku slijedi malo detaljnija rasprava o korištenim objektima i metodama u tom dijelu aplikacije. Razjasnimo prvo namjenu izdvojenog dijela programskog koda s kraja prethodnog nastavka, kako bi lakše mogli pratiti detalje u nastavku. Ideja je da korisnik aplikacije u trenutku kad doţivi nekakvu nezgodu (koja bitno utječe na njegovo zdravstveno stanje) moţe što jednostavnije i brţe poslati SMS poruku na unaprijed definirani broj, kako bi izabranu osobu ili ustanovu obavijestio o svojoj nezgodi. Pretpostavka za izvođenje takvog postupka je da nakon nezgode ostane u svjesnom stanju, kako bi zaista mogao pokrenuti aplikaciju te pritisnuti gumb za slanje SMS poruke. Ako moţe napraviti tu operaciju, onda moţe pritisnuti i drugi gumb kako bi zabiljeţio vrijeme nezgode, jer se tako kod pruţanja prve pomoći lako moţe ustanoviti koliko je vremena doista prošlo od nezgode. To moţe biti vrlo bitan faktor za poduzimanje različitih operacija nad unesrećenim. Čak i ako korisnik aplikacije u trenutku kad stigne prva pomoć bude u nesvijesti, moţe se pročitati podatak o trenutku nezgode, kao i drugim bitnim karakteristikama unesrećenog (krvna grupa, kronične bolesti i slično). Te informacije su dostupne i u situaciji kad SMS poruka nije poslana, a nije zabiljeţen ni trenutak nezgode – bitno je samo da spasitelji malo „pročeprkaju“ po Android mobitelu, jer je on najverojatnije negdje pri ruci. Ostaje još samo odgovor na pitanje zašto su operacije slanja SMS poruke i biljeţenja trenutka nezgode razdvojene. Postoje situacije kad SMS poruku, a pogotovo neke njezine dijelove (vidi nastavak teksta) nije moguće ni pripremiti ni poslati, pa se u tom slučaju moţe zabiljeţiti samo trenutak nezgode. LocationManager: Vrlo sloţen objekt na Android platformi zaduţen za dobijanje točne geografske lokacije.

Prvi dio programskog koda je najjednostavniji za objašnjavanje jer sluţi za obično određivanje točnog vremena nakon pritiska korisnika na odgovarajući gumb aplikacije. To vrijeme se trajno pamti kako bi ga spasitelji mogli naknadno očitati. Ovaj segment programskog koda „zamotan“ je u standardnu rutinu za obradu pogreške, u slučaju da se dogodi nekakav problem tijekom izvođenja aplikacije. public void btnPosaljiSMSClick(View view) { final Button btnPosaljiSMS = (Button) findViewById(R.id.btnPosaljiSMS); Calendar Kalendar = Calendar.getInstance (); CharSequence mTrenutnoVrijeme = Kalendar.getTime().toString(); mGodina = Kalendar.get(Calendar.YEAR); mMjesec = Kalendar.get(Calendar.MONTH); mDan = Kalendar.get(Calendar.DAY_OF_MONTH); mSati = Kalendar.get(Calendar.HOUR_OF_DAY); mMinute = Kalendar.get(Calendar.MINUTE); mSekunde = Kalendar.get(Calendar.SECOND ); mTrenutnoVrijeme = Integer.toString(mDan) + “.” + Integer.toString(mMjesec) + “.” + Integer.toString(mGodina) + ” ” + Integer.toString(mSati) + “:” + Integer.toString(mMinute) + “:” + Integer.toString(mSekunde); setContentView(R.layout.critical3); try { VratiPodatkeCritical3(); } catch (IOException e1) { e1.printStackTrace(); }

final CheckBox tp = (CheckBox) findViewById(R.id.chkGPSPozicija); Da bi SMS poruka koja se šalje na unaprijed definirani telefonski broj bila što korisnija, ideja je da njezin dio bude točna geografska lokacija s koje je poruka poslana, kako bi se što brţe i jednostavnije došlo do unesrećenog korisnika aplikacije. Ako mobilni telefon (ili neki drugi uređaj koji se temelji na Android platformi) u sebi sadrţi odgovarajući hardverski dio za dobijanje takvog podatka, onda slijedeći dio programskog koda koristi Android objekt LocationManager za dobijanje potrebnog geolokacijskog podatka. String pozicija = “”; if (tp.isChecked()) { try { LocationManager locationManager; String context = Context.LOCATION_SERVICE; locationManager = (LocationManager)getSystemService(context); String provider = LocationManager.GPS_PROVIDER; Location location = locationManager.getLastKnownLocation(provider); double lat = location.getLatitude(); double lng = location.getLongitude(); pozicija = ” ” + Double.toString(lat) + ” / ” + Double.toString(lat); } catch (Exception e) { e.printStackTrace(); } } Prethodne naredbe sadrţe još nekoliko naredbi za formatiranje podataka o geografskoj lokaciji, kako bi podaci u okviru poruke bili prikazani na što čitljiviji podaci razumljiv spasiteljima. Kao i obično, bitno je da takv dio aplikacije podloţan pogreškama bude obuhvaćen u strukturu za obradu pogrešaka. Zahtijevani podatak

moţe u nekom trenutku jednostavno biti nedostupan. Na primjer, izvor GPS podataka je uništen solarnom bakljom. Dobro – malo se šalimo, mnogo je vjerojatniji neki drugi uzrok problema, iako prema najavama nekih stručnjaka 2012 godine to moţda uopće više neće biti samo šala. LocationManager je vrlo sloţen objekt na Android platformi pa njegovo detaljno opisivanje prelazi okvire ovog teksta. Osnovni primjer prikazan u prethodnom dijelu programskog koda, trebao bi vam posluţiti kao vodič za dodatno istraţivanje pratećih uputa o Android SDK sustavu. Nakon što su pripremljeni svi potrebni podaci o geografskoj lokaciji, preostaje još samo njihovo spajanje s unaprijed definiranim fiksnim dijelom SMS poruke, te slanje poruke na prije upisani mobilni broj. U slučaju da navedena dva podatka nisu pripremljena, onda se korisniku aplikacije javlja odgovarajuća poruka kako bi se riješio problem. Za to se koristi funkcija o čijoj smo namjeni i djelovanju raspravljali u jednom od prethodnih nastavaka serijala. Sasvim je jasno da kritična situacija, u kojoj se moţe naći korisnik aplikacije, nije baš idealan trenutak da aplikacija javi kako smo u fazi njezinog punjenja početnim podacima zaboravili navesti neki detalj (fiksni dio SMS poruke ili odredišni broj). Otprilike se radi o istoj situaciji kao kad bi vaš najnoviji automobil (dostupan uz mjesečnu ratu od svega 500 kn, ali uz učešće od 30 posto i ostatak vrijednosti od 30 posto – kako to danas nude sitnim slovima neki oglasi na koje se skoro navukao i autor ovih redova), u trenutku hitnog kočenja javio nekakvu poruku da to ne moţe ili ne ţeli napraviti. Rješenje problema je vrlo jednostavno. Nakon upisivanja svih potrebnih podataka u aplikaciju na samom početku njezina korištenja, treba poslati probnu poruku te provjeriti je li zaista sve u redu. try { final EditText tmp = (EditText) findViewById(R.id.txtSMSPoruka); String tmps = tmp.getText().toString(); if (tmps.length() == 0) { setContentView(R.layout.main); MsgBox(“Nije definiran tekst SMS poruke!”, “Upozorenje”); return; }

final EditText tmpbr = (EditText) findViewById(R.id.txtSMSBroj); String tmpsbr = tmpbr.getText().toString(); if (tmpsbr.length() == 0) { setContentView(R.layout.main); MsgBox(“Nije definiran broj za slanje SMS poruke!”, “Upozorenje”); return; } setContentView(R.layout.main); VratiPodatkeMain(); tmps = tmps + pozicija; SmsManager sm = SmsManager.getDefault(); sm.sendTextMessage(tmpsbr, null, tmps + pozicija, null, null); } catch (Exception e) { MsgBox(e.getMessage(),”Greška”); e.printStackTrace(); } AlertDialog ad = new AlertDialog.Builder(prvaPomoc.this).create(); CharSequence poruka = “Zabiljeţeno vrijeme slanja SMS poruke za pomoć\n\n” ; poruka = poruka + mTrenutnoVrijeme.toString(); ad.setTitle(“Potvrda operacije”); ad.setMessage(poruka); ad.setButton(“Zatvori”, new DialogInterface.OnClickListener() { @Override

public void onClick(DialogInterface arg0, int arg1) { } }); ad.show(); Na kraju cijelog postupka prikazuje se točno vrijeme slanja poruke. Ne treba posebno ni napominjati da se svi podaci iz prethodne operacije spremaju u odgovarajuća „spremišta“ u mobilnom telefonu, kako bi i kasnije bili dostupni prema potrebi. btnPosaljiSMS.setText(“SMS poruka: ” + mTrenutnoVrijeme); try { SpremiPodatkeMain(); } catch (IOException e) { e.printStackTrace(); } } Na temelju svega dosad napisanog u ovom te u prethodnih nekoliko brojeva, već bi trebali biti u mogućnosti sami izrađivati relativno sloţene Android aplikacije. Međutim, još uvijek nismo završili serijal, jer nam je preostala demonstracija korištenja nekoliko bitnih tehnika kao što je dobro poznati Google Maps, preuzimanje podataka s ugrađenih senzora, korištenje dodatnih grafičkih i zvučnih mogućnosti te još poneka zanimljivih sitnica. Ostalo je još dosta zanimljivog materijala za slijedećih nekoliko nastavaka, posebno ako sve te dijelove uz dodatak već obrađenih ţelimo kreativno povezati u prave aplikacije. LocationManager: Vrlo sloţen objekt na Android platformi zaduţen za dobijanje točne geografske lokacije.

Android programiranje #12: Alternativni pristup razvoju aplikacija U prethodnih desetak (i još malo više) nastavaka serijala o Android programiranju pokazali smo dosta toga što vam moţe pomoći kod razvoja vlastitih aplikacija – počevši od instalacije svih potrebnih alata na vlastito računalo pa sve do razvoja standardnih dijelova sloţenijih aplikacija. U međuvremenu se uređaji bazirani na Androidu (telefoni, ali i „tabletići“ te drugi mobilni uređaji) sve bolje prodaju širom svijeta, tako da razvoj aplikacija za ovu platformu sigurno neće biti uzaludan napor. Iako ćemo se u slijedećih nekoliko nastavaka serijala pozabaviti s još nekoliko naprednijih programerskih tehnika, ovaj put ćemo se malo detaljnije osvrnuti na alernativni (čitaj bitno jednostavniji) način za razvoj aplikacija, također nastao u radionicama istog proizvođača. Na kraju krajeva među čitateljima časopisa sigurno ima onih s vrlo dobrim idejama za razvoj novih aplikacija, ali im se korištenje Google SDK alata ipak čini malo prekompliciranim. Srećom, Googleovi inţenjeri intenzivno rade na nešto drugačijem pristupu čitavoj stvari, pa ćemo vas u današnjem nastavku upoznati s njihovim najnovim uradkom za tu namjenu. App Inventor for Android je naziv za alat namijenjen malo manje spretnim programerima dizajniranim tako da omogućava vizualno orijentirani razvoj različitih Android aplikacija izravno u pregledniku. Zbog toga je pisanje programskog koda gotovo u potpunosti izbačeno iz alata te zamijenjeno nečim genijalno preglednim. Ako ste ipak zainteresirani za programiranje, onda vam ovaj alat zapravo i ne treba, jer već imate dobro poznati Android SDK. Iako u trenutku pisanja teksta (prema tvrdnjama iz samog Googlea) alat još uvijek ne podrţava sve što je zamišljeno (još uvijek se nalazi u beta fazi razvoja) već sada se pomoću njega mogu napraviti zanimljive i korisne aplikacije. Googleovi inţenjeri naglašavaju kako se trenutni problemi prije svega odnose na područja instalacije upravljačkih uređaja, prijenosa dijelova razvojnog alata Java na računalo te distribuciju same aplikacije na odredišni mobilni uređaj, odnosno postavljanje različitih postavki korištenja aplikacije na tom uređaju. Zato se u trenutnoj fazi razvoja alata od zainteresiranih korisnika traţi da pripreme što detaljnije povratne informacije o korištenju alata, kako bi se što prije prevladali svi uočeni problemi.

Priprema računala za razvoj: Mogu se koristiti različite kombinacije operativnih sustava i preglednika.

Razvoj vlastitih aplikacija u alatu App Inventor for Android započinje pripremom vlastitog računala za takav zadatak. Za razliku od Microsofta ili Applea poznatih po ograničavaju razvoja na vlastiti hardver i/ili softver, Googleov razvojni tim kontinuirano podrţava sve najpopularnije platforme (Windows, Mac i Linux). Zato nije ni čudo da se Android polako, ali sigurno, probija prema samom vrhu popularnosti na području mobilnih platformi. Nastavak teksta, te prije svega prateće slike) podrazumijevaju razvoj vlastitih aplikacija u Google Chrome pregledniku na Windows računalu, ali iz prije navedenih razloga ne bi trebali imati previše problema ni u razvoju aplikacija na nekoj drugoj konfiguraciji. Prvi korak u pripremi računala je preuzimanje odgovarajućeg programa za upravljanje pripremom razvojne konfiguracije. Ovaj program moţe se slobodno preuzeti usmjeravanjem preglednika na web adresuhttp://appinventor.googlelabs.com/learn/setup/setupwindows.html Nakon preuzimanja instalacijskog programa treba ga instalirati na računalo te podesiti parametre ciljnog mobilnog uređaja. U trenutnoj fazi razvoja alata podrţano je izravno svega nekoliko uređaja poput T-Mobile G1 ili T-Mobile myTouch, dok se za ostalo „očvrsje“ treba pomučiti malo više te napraviti manja ili veća podešavanja na samom telefonu. Budući da je ovaj postupak ovisan o samom telefonu, kao takav prelazi okvire napisanog teksta. Sve potrebne informacije moţete pronaći slijedeći odgovarajuće linkove na prije navedenoj web adresi.

Početak rada na aplikaciji: Započinje stvaranjem projekta – u ovom slučaju HelloPurr.

Izrada prve aplikacije U nastavku teksta opisat ćemo izradu prve aplikacije prema Googlevoj pratećoj dokumentaciji. Za razliku od uobičajenog Hello World primjera koji samo prikazuje dvije riječi na zaslonu, Googleov početni primjer odmah koristi i audio/video podatke, to jest prikazuje sliku te reproducira zvuk. Zato kao početni korak u izradi aplikacije treba skinuti jednu sliku u .pngformatu, odnosno jednu zvučnu datoteku u .mp3 formatu. Umjesto onih koje nudi Google za testiranje razvojnog alata, moţete upotrijebiti svoje vlastite, ali za sada ćemo se drţati priloţene „kuharice“. Razvojni alat pokrećete postavljanjem preglednika na adresuhttp://appinventor.googlelabs.com. Da bi se moglo prijeći na razvoj same aplikacije potrebno je da korisnik ima odgovarajući google email korisnički račun.

Ako ga još nemate, ovo je prilika da ga stvorite. Kad obavite tu formalnost, pojavljuje se stranica namijenjena pripremi novih aplikacija, odnosno administriranju postojećih. Budući da pripremate svoj prvi projekt, izaberite opciju New na vrhu stranice te upišite naziv aplikacije HelloPur.

Razvojna okolina: Vrlo je jednostavna i namijenjena korisnicima koji nisu profesionalni programeri.

Kao rezultat izvođenja prethodne operacije pojavljuje se glavna stranica razvojnog alata namijenjena izradi aplikacije (vidi prateće slike uz tekst). Sve izgleda vrlo jednostavno, ali je sasvim dovoljno za korisnike kojima je namijenjena – neprofesionalnim programerima s dobrim idejama za vlastite aplikacije. U lijevom dijelu stranice nalaze se različite grupe kontrola namijenjene iskorištavanju brojnih mogućnosti Android sustava. Tijekom razvoja prve aplikacije bit će nam potrebne svega dvije kontrole: Button i Label. Jednostavnom operacijom povlačenja postavite in na središnji dio stranice namijenjen simuliranju zaslona mobilnog uređaja. Kontrole postavite jednu ispod druge, a onda je preostalo da im izmijenite nekoliko svojstva, kako bi dobili izgled sučelja prikazan na jednoj od pratećih slika uz tekst. KontroliButton potrebno je obrisati početni tekst prikazan na kontroli (svojstvoText) te učitati prije spomenutu sliku kitty.png (svojstvo Image). KontroliLabel potrebno je postaviti boju pozadine na plavu (svojstvo BackgroundColor), povećati veličinu pisma na 30 (svojstvo FontSize), te upisati novi tekst „Pet the Kitty“. Svojstvo koje se koristi za zadnju operaciju već znate s prve kontrole. Sve to se izvodi u prozoru Properties na desnoj strani osnovne stranice.

Postavljanje prve kontrole: Izvodi se običnim povlačenjem kontrole na centralni dio koji predstavlja zaslon mobilnog uređaja.

Na ovom stupnju razvoja aplikacije u nju je dodana slika, ali još uvijek ne i zvučni zapis. Zato je potrebno u aplikaciju povući još jednu kontrolu (Sound iz grupe Media), a onda pomoću gumba na dnu stranice dodati prije spomenutu mp3 datoteku (meow.mp3). Ovim potezom sučelje je u potpunosti dovršeno s dizajnerske strane, ali je za kompletiranje aplikacije potrebno napraviti još nešto. Da bi se tijekom izvođenja aplikacije pritiskom na sliku umiljate mačkice izazvalo njezino glasanje, to jest reprodukcija mpr datoteke, potrebno je ipak „napisati mali program“. Prethodnu tvrdnju smo stavili u znake navoda, jer je za razliku od drugih vizualno orijentiranih sučelja, koja u konačnici ipak zahtijevaju prilično znanje programiranja, Google ovdje stvarno napravio korak naprijed. Na vrhu osnovne stranice potrebno je kliknuti na opciju Open the Block Eidtor, a ako ste to napravili prvi put, pričekati određeno vrijema kako bi se na vaše računalo instalirala dodatna komponenta za „pisanje programskog koda“. Evo ponovno navodnika, a konačno i objašnjenja zašto. Kad se otvori popis svih dostupnih događaja, oni su prikazati u obliku svojevrsne slagalice. Potrebni događaj u kontekstu nekog dijela aplikacije potrebno je jednostavno „spariti“ s pravom operacijom, što se izvodi običnom operacijom povlačenja. U konkretnom slučaju potrebno je događaj Button1.Click povezati s operacijom Sound1.Play i to je to. Koliko to efektno izgleda moţete provjeriti na priloţenoj slici ili isprobati sami. Bravo Google!

Prozor Properties: Koristi se za izmjenu različitih svojstava označene kontrole.

Preostalo je još samo da isprobate aplikaciju na stvarnom hardverskom uređaju tijekom instalacije povezanim s razvojnim alatom, ili na odgovarajućem softverskom emulatoru. Na kraju je pomoću operacijePackage for Phone moguće napraviti i distribucijski oblik aplikacije. Priznajte da nije bilo komplicirano, iako nismo baš detaljno opisivali način promjene svojstava. Ipak bi ovaj tekst trebali pratiti čitatelji s bar početnim poznavanjem programiranja, tako da ne bi trebao biti problem izvesti tako elementarne operacije u dizajnu aplikacije. Pomoću alata App Inventor for Android (iako je još uvijek u fazi beta verzije) mogu se napraviti znatno sloţenije aplikacije u što se moţete uvjeriti i sami nakon malo vjeţbe.

Android programiranje #13: Alternativni pristup razvoju aplikacija II Prošli put smo demonstrirali osnove korištenja Googleovog alternativnog alata za razvoj Android aplikacija namijenjenog neprogramerima i „malo manje spretnim programerima“. App Inventor for Android, kako je njegov naziv, pokazao se sasvim prikladnim za stvaranje elementarne Android aplikacije (nešto slično klasičnom Hello World primjeru), a danas ćemo probati prikazati da je upotrebljiv za bitno sloţenije projekte. Odgovorimo prvo na nekoliko najvaţnijih pitanja povezanih s korištenjem alata na razvoju sloţenijih projekata. Najvaţnije pitanje koje se nameće samo po sebi je potencijalna sloţenost dovršene aplikacije. Tu odmah treba biti izravan te reći da se pomoću alata App Inventor for Android ne moţe napraviti baš sve što i s sluţbenim razvojnim alatom, ali da se moţe puno toga – moţe se. Osim brojnih komponenti za razvoj različitih dijelova sučelja (što smo djelomice pokazali u u prošlom uvodnom tekstu o alatu), na raspolaganju su najvaţnije programske strukture poput foreach, while, if-else (iako u nešto slikovitijem obliku nego je to uobičajeno u programskim jezicima), a moguća je i komunikacija s web servisima te svojevrsnim spremištem podataka. Od vaţnijih tehnologija karakterističnih za mobilne uređaje današnjice, trenutno nije podrţan samo Bluetooth, ali se prema tvrdnjama proizvođača intenzivno radi i na tom segmentu.

Basic komponente: Predstavljaju osnovne grafičke elemente aplikacije.

Ako vam slučajno ni sve nabrojano nije dovoljno za izradu vlastite aplikacije, onda alat skoro neograničeno moţete nadopunjavati izradom vlastitih komponenti u Javi. To znači da morate ipak biti nešto vještiji u programiranju, a onda se neminovno postavlja pitanje zašto ne bi sve skupa ipak programirali u standardnom SDK razvojnom sustavu. Ako pomoću alata App Inventor for Android moţete sami odraditi veći dio projekta, onda ima smisla da za manji nedostajući segment vlastite aplikacije angaţirate Java programera da vam pomogne. Trenutno dva najveća nedostatka alata odnose se na nemogućnost izravne objave aplikacije na globalnom trţištu Android aplikacija (Android Market), te ograničenost aplikacije na samo jedan prikaz (raspored kontrola). Google obećava kako će prvi problem biti uskoro riješen pa se zato njime nećemo previše baviti. Napišimo zato

nekoliko riječi o drugom problemu. Na trenutnom stupnja razvoja alata ne moţe se izvoditi prebacivanje između više različitih vrsta prikaza ili rasporeda kontrola. To na prvi, drugi i treći pogled predstavlja zbilja veliko ograničenje u razvoju aplikacija, ali ga je ipak moguće prevazići jednim od slijedeća dva trika. 1. Naizmjeničnim „paljenjem i gašenjem“ kontrola, to jest izmjenom vidljivosti različitih komponenti postavljenih na jedini dostupni prikaz kontrola. 2. Međusobnim višestrukim povezivanjem više App Inventor for Android aplikacija, od kojih svaka moţe imati različite rasporede kontrola na osnovnom zaslonu. Kad su prije koje desetljeće nešto slično mogli raditi autori sloţenih igara na strojevima poput ZX Spectruma ili Commodorea 64 te kasetofonom kao uređajem vanjske memorije, nema nikakvog razloga zašto se to ne bi moglo napraviti i danas sa znatno modernijim hardverom.

Media komponente: Komponente za upravljanje različitim multimedijalnim dijelovima mobilnog uređaja.

Iako slijedeća vijest nema nikakve veze s prethodnom točkom, današnjim tekstom, pa čak ni cijelim serijalom u cjelini, ipak ću je spomenuti na ovom mjestu, ako je do sada već niste sami negdje pročitali. Kultni Commodore 64 je prije kratkog vremena doţivio svoju inkarnaciju s istim izgledom izvana, ali ultramodernim hardverom i softverom iznutra. Narudţbe se mogu napraviti već sada, a isporuka se očekuje u petom mjesecu. Morao sam to jednostavno spomenuti – prve ljubavi se teško zaboravljaju, makar to bila i računala. Vratimo se sada ponovo današnjoj temi. Ključne dijelove aplikacije moţemo podijeliti u dvije velike skupine: 1. Komponente ili kontrole 2. Blokove Komponente su osnovni grafički dijelovi aplikacije, a međusobno se osim po izgledu razlikuju prije svega po svojoj namjeni. Osnovna grupa komponenti pod nazivom Basic obuhvaća zbilja osnovne komponente karakteristične za moderna korisnička sučelja poput gumbi, oznaka i slika. Ako ste ikad probali napisati bilo kakvu aplikaciju u nekom modernijem razvojnom alatu, trebali bi znati o čemu je riječ, pa se zato i nećemo previše baviti njihovim karakteristika. U istoj grupi kontrola nalaze se još dvije sloţenije kontrole, a one ipak zahtijevaju poneku dodatnu riječ. To su Canvas i TinyDB.

Animation komponente: Preduvjet za njihovo korištenje je postojanje komponente Canvas.

Kontrola Canvas zamišljena je kao dvodimenzionalno područje za crtanje likova pomoću programskog koda, odnosno za pomicanje sličica („sprites“). Budući da je to isto područje osjetljivo na dodir, sasvim je razumljivo da predstavlja temeljni dio većine različitih igara razvijenih u ovom alatu. Svaka od lokacija na komponenti Canvas označava se uobičajenim matematičkim zapisom za dvodimenzionalne površine – kao koordinate x i y. O vaţnosti navedene kontrole u razvoju aplikacija najbolje govori činjenica da je u zadnjoj reviziji alata od strane Googlea s kraja trećeg mjeseca, veliki dio poboljšanja dodan upravo u Canvas kontrolu. Neka od tipičnih svojstava i metoda Canvas kontrole, čija imena govore sama za sebe su: BackgroundImage, LineWidth, Touched(number x, number y, boolean touchedSprite), Clear(), DrawLine(number x1, number y1, number x2, number y2), DrawCircle(number x, number y, number r). Tijekom pisanja igara kontrola Canvas se vrlo često upotrebljava u kombinaciji s kontrolom Clock kako bi se osiguralo odvijanje operacija u zadanim vremenskim intervalima. Spomenimo na ovom mjestu kako kontrola Clock ujedno pripada grupi „nevidljivih“ kontrola, što znači da se ne vidi tijekom izvođenja aplikacije, ali mora biti nacrtana na osnovnoj formi kako bi se mogle koristiti njezine mogućnosti. Kontrola TinyDB namijenjena je trajnom spremanju podataka iz aplikacije u mobilni uređaj. Prilikom svakog prekida izvršavanja aplikacije gubi se sadrţaj svih korištenih kontrola te se ponovo puni inicijalnim vrijednostima kod slijedećeg pokretanja aplikacije. Ako prilikom novog pokretanja aplikacije treba krenuti od njezinog zadnjeg stanja, onda treba postojati nekakav mehanizam za spremanje vrijednosti iz aplikacije u Android uređaj, te njihovo ponovno čitanje (na primjer, postavke aplikacije, stanje bodova u privremeno prekinutoj igri i slično). Upravo za takvu namjenu zamišljena je kontrola TinyDB, odnosno njezine dvije jedine dostupne metode: StoreValue(oznaka, vrijednost) Sprema vrijednost (niz znakova ili popis) pod određenim nazivom u spremište na mobilnom uređaju.

GetValue(oznaka) Čita vrijednost sa zadanim nazivom iz spremišta. U slučaju da traţena oznaka ne postoji u spremištu (npr. kod prvog pokušaja čitanja vrijednosti na novom uređaju), onda metoda vraća prazan niz znakova. U slučaju da treba obrisati spremište od starih vrijednosti, onda se to izvodi na telefonu standardnom naredbom Settings → Applications → Manage Applications. U grupi kontrola pod nazivom Media nalazi se 5 komponenti slijedećih naziva: Camera, ImagePicker, Player, Sound i VideoPlayer. Svaka od kontrola zaduţena je za upravljanje odgovarajućim hardverskim ili softverskim resursom, pa su u skladu s tim i dodijeljeni nazivi svojstava odnosno metoda (npr.TakePicture ili AfterPicture za kontrolu Camera, odnosno Start, Stop ili Pause za kontrolu Player). Grupa kontrola Animation te njezine dvije jedine komponente Ball odnosno ImageSprite, koriste se u kombinaciji s prije spomenutom kontrolom Canvas za aplikacije u kojima je potrebno izvoditi različite vrste pokretanja grafičkih objekata (dakle najčešće igre). Na priloţenoj slici uz tekst vidi se da je preduvjet za korištenje kontroli iz ove grupe upravo postojanje kontrole Canvas. Pomoću svojstava kontrola poputInterval, Speed ili Rotates upravlja se učestalošću, brzinom i rotacijom „sličica ili loptica“ u vlastitoj aplikaciji. Budući da u jednoj aplikaciji moţe biti više Canvas kontrola, nema nikakvog razloga da njihovim inteligentnim paljenjem i gašenjem na jednom jedinom zaslonu (prije istaknuto ograničenje trenutne verzije razvojnog alata) napravite prilično kompleksnu igru.

Social komponente: Zaduţene su za pristup i korištenje različitih socijalnih podataka iz mobilnog uređaja.

Posljednja grupa kontrola koju ćemo spomenuti u današnjem nastavku su kontrole iz grupe Social zaduţene za pristup i korištenje različitih socijalnih podataka iz mobilnog uređaja (ContactPicker, EmailPicker, PhoneCall, PhoneNumberPicker, Texting i Twitter). Pomoću ovih kontrola moguće je postići da vlastite aplikacije upravljaju telefonskim pozivima, slanjem sms i/ili email porukama, odnosno korištenjem usluga Twittera (npr. korištenjem metoda poput DirectMessage, RequestDirectMessage iliRequestFriendTimeLine). U slijedećem nastavku napravit ćemo pregled preostalih dostupnih kontrola, a onda napraviti nekoliko sloţenijih primjera, koji bi trebali prikazati kako ovim alatom doista nije problem brzo napraviti i znatno sloţenije aplikacije.

Android programiranje #14: Alternativni pristup razvoju aplikacija III Danas ćemo se pozabaviti preostalim komponentama dostupnim u Googleovom alatu App Inventor for Android namijenjenom brzom razvoju Android aplikacija. Komponente su razvrstane u nekoliko grupa slijedećih naziva: Sensors, Screen Arrangement, LEGO MINDSTORMS, Other stuff i Not ready for prime time. Krenimo redom.

Sensors komponente: Zaduţene su za upravljanje različitim senzorima u mobilnom uređaju.

Sensors komponente Danas je sasvim uobičajeno da pametni telefoni i drugi uređaji temeljeni na Androidu imaju ugrađen manji ili veći broj senzora, koji se mogu vrlo djelotvorno iskoristiti u različitim vrstama aplikacija (najčešće igrama). Zbog toga je razvijeno nekoliko posebnih komponenti za relativno jednostavnu podršku takvoj vrsti hardvera. Sve komponente su nevidljive tijekom izvođenja, ali moraju biti uključene u aplikaciju da bi se mogle iskoristiti njihove mogućnosti. Komponenta AccelerometerSensor zaduţena je za interakciju softvera sa senzorom za mjerenje pomicanja uređaja po sve tri osi koordinatnog sustava. Od tuda dolaze nazivi najvaţnijih svojstava: XAccel, YAccel, Zaccel. Pomoću svojstva Available programer moţe provjeriti jesu li navedeni senzor uopće dostupni u uređaju, a svojstvom Enabled upravljati dozvolom korištenja senzora. Događajem AccelerationChanged moţe se precizno reagirati na pomicanje uređaja po bilo kojoj od navedene tri osi (parametara događaja), dok je nešto „grublji događaj“ Shaking namijenjen mnogo jednostavnijem zadatku – običnoj provjeri „drmanja“ uređajem. Drugi događaj se najčešće moţe upotrijebiti za efektan prekid izvođenja različitih operacija u aktivnoj aplikaciji. Druga nevidljiva kontrola iz iste skupine je LocationSensor, a namijenjena je dobijanju geografske pozicije mobilnog uređaja, ako je u njega ugrađen odgovarajući GPS prijemnik (svojstvo HasLongitudeLatitude). Softverski je podrţano mjerenje nadmorske visine (svojstvo HasAltitude), ako i takva mogućnost postoji u hardveru. Ostalim dostupnim svojstvima moţe se dobiti vrijednost svake od navedenih tri dimenzija, dok su događaji LocationChanged te StatusChanged zaduţeni za reakciju aplikacije na promjene pozicije uređaja u prostoru, odnosno na

promjene načina mjerenja pozicije (izravno dobijeni GPS podaci ili podaci dobijeni od mreţnog operatora). Zadnja komponenta iz grupe OrientationSensor zaduţena je za provjeru orijentacije uređaja u prostoru (svojstva Roll, Pitch i Yaw te događaj OrientationChanged). Ova sofverska komponenta se u kombinaciji s pripadajućim senzorom koristi u različitim aplikacijama za promjenu načina prikaza podataka ovisno o promjeni orijentacije uređaja (vodoravni ili vertikalni prikaz podataka). Screen Arrangement komponente

Screen Arrangement komponente: Koriste se kao „podloga“ za raspored drugih kontrola.

Sve tri komponente iz ove grupe (HorizontalArrangement, TableArrangement i HorizontalArrangement) zaduţene su za jednostavnije raspoređivanje ostalih komponenti po zaslonu uređaja. Kao što im i nazivi govore, svaka od komponenti je zaduţena za jednu vrstu rasporeda osnovnih kontrola. Osim za početno raspoređivanje kontrola sve tri komponente mogu se također iskoristiti za njihovo jednostavnije premještanje ili skrivanje. Dostupna svojstva kontrola su vrlo jednostavna te razumljiva sama po sebi (Visible, Height, Width, Rows i Columns). LEGO MINDSTORMS komponente Sedam komponenti iz grupe LEGO MINDSTORMS predviđene su za upravljanje različitih dijelovima poznatog Lego kompleta za učenje robotike pomoću nekog od Android uređaja. Iskreno, nismo imali priliku ni zadovoljstvo isprobati kako sve to skupa djeluje u praksi, pa se zato za sada nećemo previše ni baviti ovim dijelom razvojnog alata. Nadamo se da ćemo u ne tako dalekoj budućnosti ipak biti u prilici isprobati simbozu Lego i Google proizvoda. Other stuff komponente

LEGO MINDSTORMS komponente: Zaduţene su za povezivanje s Lego „očvrsjem“.

Šaroliko društvo softverskih komponenti iz ove grupe nikako se po svojoj namjeni ne moţe dovesti u izravnu vezu, zbog čega je cijela grupa dobila naziv koji označava takvu raznolikost. Jedna od najvaţnijih komponenti iz grupe je komponenta ActivityStater. Zaduţena je za pokretanje nekoliko različitih aktivnosti na uređaju: drugih aplikacija napravljenih u istom alatu ako takve postoje u uređaju (čime se moţe izbjeći dosta ozbiljno ograničenje o korištenju jednog zaslona ekrana po aplikaciji), aplikacije zaduţene za upravljanje kamerom (ako je kamera ugrađena u mobilni uređaj), pretraţivanje web sadrţaja, postavljanje preglednika na točno određenu web adresu, odnosno postavljenje točno određene lokacije na karti. Zbog toga komponenta podrţava različite načine vlastitog pozivanja. Evo primjera iz prateće dokumentacije zaduţenog za pretraţivanje weba u „potrazi za vampirima“. Action: android.intent.action.WEB_SEARCH ExtraKey: query ExtraValue: vampire ActivityPackage: com.google.android.providers.enhancedgooglesearch ActivityClass: com.google.android.providers.enhancedgooglesearch.Launcher Komponenta BarcodeScanner zaduţena je za jednostavno čitanje običnih jednodimenzionalnih, ali i sve popularnijih dvodimenzionalnih bar kodova (korištenjem metode DoScan, svojstva Result i događaj AfterScan). Da je takva komponenta jednostavno neizostavna u modernim softverskim rješenjima, autor teksta moţe posvjedočiti iz prve ruke. Na nedavno završenoj Microsoftovoj konferenciji Windays 11 u Rovinju, osim očekivanih mjesta za takvu vrstu označavanja, dvodimenzionalni bar kodovi su se mogli primijetiti i na majicama nekih sudionika. Naoruţani Android uređajem te odgovarajućom aplikacijom više ne morate gubiti vrijeme da bi saznali osnovne informacije o vlasniku majice. Umjesto toga u njegovom smjeru jednostavno uperite kameru i pogledate na zaslonu sve što vam ţeli odati o sebi.

Other stuff komponente: Ostale komponente koje se koriste u razvoju.

Dvije komponente sličnog naziva BluetoothServer i BluetoothClientzaduţene su za podršku obiju strana koje sudjeluju u Bluetooth komunikaciji (servera i klijenta). Popis dostupnih metoda, svojstava i događaja je zbilja impresivan (bar u usporedni s drugim komponentama iz istog alata), a potrebno je poznavati još poneki detalj Bluetooth tehnologije, tako da se u ovom tekstu jednostavno ne moţemo detaljnije pozabaviti njihovim korištenjem. Kako je potpisnik ovih redova u bliskoj prošlosti imao prilike raditi na Bluetooth orijentiranom projektu namijenjenom starim dobrim Java MIDP uređajima, osobno moţe potvrditi da je korištenje Google tehnologije na istom području bitno jednostavnije. Budući da sami razvojni inţenjeri tvrde da se na ovom segmentu razvojnog alata još uvijek intenzivno radi, ipak treba malo sačekati sa završnom ocjenom. Komponenta Notifier omogućava prikaz različitih vrsti obavijesti korisniku aplikacije odnosno trajno biljeţenje takvih informacija u svrhu kasnije analize. Za to je pripremljeno nekoliko metoda (ShowMessageDialog, ShowChooseDialog, ShowTextDialog, ShowAlert i LogError) čije korištenje rezultira različitim načinom prikaza informacija korisniku odnosno njihovom biljeţenju. Na raspolaganju su također dva događaja: AfterChoosing i ShowChooseDialog, kako bi se moglo ustanoviti što je poduzeo korisnik kao reakciju na prikazane informacije od strane aplikacije. Zadnje dvije komponente iz grupe (SpeechRecognizer i TextToSpeech) zamišljene su kao podrška za izradu govorno orijentiranog korisničkog sučelja u vlastitim Android aplikacijama. Prva kontrola namijenjena je razumijevanju izgovorenog, dok je druga zaduţena za suprotan proces – izgovaranje napisanog teksta. Koliko to sve skupa radi ili ne radi dobro s različitim govornim jezicima moţete isprobati sami. Obje komponente su vrlo jednostavne za korištenje, jer se primjena svodi na upotrebu jednostavnih metoda poput GetText, Speek, Country i Language. Spomenimo na ovom mjestu kako se za izgovor napisanog teksta koristi ista Google tehnologija koja je korištena u serijalu o naprednom programiranju Windows aplikacija, objavljenom u više prethodnih brojeva vašeg omiljenog časopisa. Not ready for prime time komponente Not ready for prime time komponente: Eksperimentalne komponente u intenzivnoj fazi razvoja.

U posljednoj grupi komponenti navedene su komponente na čijem razvoju još uvijek intenzivno rade Googleovi razvojni inţenjeri, pa su kao takve podloţne različitim promjenama dok ne stignu u fazu dovršenog proizvoda. Trenutno su u tu grupu svrstane slijedeće komponente: FusionTablesControl – korištenje kartografskih prikaza u kombinaciji s FusionTables tehologijom. GameClient – povezivanje aplikacija (najčešće igara) s odgovarajućim serverima za „udruţene NEzločinačke poduhvate“. SoundRecorder – biljeţenje i pohranjivanje zvučnih zapisa. TinyWebDB – komunikacija s web servisima zbog dvosmjerne razmjene podataka. Voting – osnova za buduće glasačke listiće u „Android demokraciji budućnosti“. Kako su sve nabrojane komponente iz ove grupe u razvoju, za sada se nećemo previše ni baviti njima. Ipak moramo priznati da nas strašno zanima vrlo novi svijet u kojem ćemo praktično trenutno moći odlučivati o bitnim stvarima u zemlji, a ne čekati da to radimo od izbora do izbora. Naţalost, ipak bi se mogli okladiti na prilično velike iznose kako će takvu tehnologiju prije prihvatiti različiti „reality“ spektakli nego drţavna uprava. Ţivi bili pa vidjeli. Ovime je završeno predstavljanje najvaţnijih segmenata Googleovog razvojnog alata za neprogramere. Preostalo je da pomoću njega probamo napraviti jednu sloţeniju aplikaciju kao demonstraciju kako različite komponente surađuju u praksi.

Android programiranje #15: Izrada složenijih aplikacija Nakon što smo u prošlih nekoliko nastavaka predstavili najvaţnije dijelove Googleovog alata za razvoj aplikacija namijenjenog korisnicima neprogramerima, odnosno malo manje vještim programerima, došao je trenutak da pokaţemo kako se ti dijelovi zaista koriste u vlastitim aplikacijama. Za razliku od prve demo aplikacije, kad smo vrlo detaljno riječju i slikom opisivali kako se izvode sve operacije potrebne da se dobije dovršena aplikacija, u današnjem nastavku ćemo samo naznačiti glavne smjernice u pripremi aplikacije, a na vama je da probate sami dovesti projekt u funkcionalno stanje. Tako ćemo odmah pripremiti i svojevrsnu vjeţbanju u korištenju alata. Iako se danas mobilni uređaji koriste za izvođenje više desetaka različitih operacija – od planiranja vlastitog vremena, preko slušanja muzike i gledanja filmova pa sve do igranja različitih vrsta igara, mogućnost izvođenja starog, dobrog telefonskog poziva (ili bar odgovaranja na njega) još uvijek ostaje jedna od najbitnijih namjena većine mobilnih telefona. Zato ćemo u prvom primjeru nešto sloţenije aplikacije demonstrirati što moţemo napraviti u Googlevom razvojnom alatu po tom pitanju, ako ne ţelimo koristiti već ugrađene mogućnosti u sam uređaj. Pretpostavka za uspješno izvođenje slijedeće aplikacije na konkretnom Android uređaju je da taj uređaj podrţava izvođenje telefonskih poziva, a ne samo različite internet orijentirane načine vlastitog korištenja (pregled web stranica, razmjena email poruka i slično). Također, u spremište kontakata u uređaju trebalo bi biti upisano bar nekoliko telefonskih brojeva, a nekima od brojeva trebale bi biti dodijeljenje slike njihovih vlasnika. Čak i ako svi nabrojeni zahtjevi budu zadovoljeni, moţe se dogoditi da na nekim uređajima primjer ipak ne djeluje kako se očekuje. Razloge treba traţiti u tome što u trenutnoj fazi razvoja alat App Inventor for Android još uvijek nije ni testiran ni optimiziran za sve dostupne uređaje na trţištu. Googleovi razvojni inţenjeri obećavaju kako će takve „porođajne muke“ biti riješene u bliskoj budućnosti kad razvojni alat više ne bude u fazi svojevrsnog testiranja. Za uspostavu telefonskog poziva iz Android uređaja, kao što to već znate, treba kreirati novi prazan projekt te mu dodijeliti nekakav naziv koji simbolizira namjenu projekta. U pripremi primjera povezanog s ovim tekstom korišten je naziv VidiPhoneCall, ali nema apsolutno nikakvog razloga da ne odaberete neki drugi mnogo „razumljiviji“ naziv (npr. APC 4MM – Android PhoneCall System for Modern Manager). Od dostupnih Android komponeti u projektu su nam na samom početku potrebne samo dvije: komponenta PhoneCall iz grupe Social te komponenta Button iz grupe Basic. U nastavku teksta ćemo slične konstrukcije skraćeno pisati Social -> PhoneCall, odnosno Basic -> Button.

Social -> Phone Call: Temeljna komponenta za izvođenje telefonskog poziva iz vlastite Android aplikacije.

Svakoj komponenti postavljenoj na osnovni zaslon razvojni alat automatski dodjeljuju naziv sastavljen od naziva komponente te rednog broja takve vrste komponente unutar projekta. U slučaju jednostavnijih projekta takvi nazivi se mogu izravno koristiti za dovršetak projekta, ali dobra praksa iskusnijih programera predlaţe njihovo preimenovanje u daleko razumljivije nazive, kako bi se kasnije olakšalo snalaţenje u projektu. Što se u nekom projektu koristi više različitih komponenti (to vrijedi i za sve druge razvojne alate), to je vaţnije imati smislenije nazive, da bi se programer što brţe i jednostavnije mogao snaći u naknadnoj analizi i izmjeni programskog koda. Dobro, kod alata App Inventor zapravo ni ne moţemo govoriti baš o „pisanju programskog koda“, jer je prije riječ o nećemu nalik slaganju komada slagalice sastavljene od dostupnih događaja i metoda korištenih komponeti, ali nema nikakvog razloga da ignoriramo pravilo o imenovanju komponenti. Preimenovanje komponente postavljene na osnovni zaslon projekta izvodi se njezinim označavanjem, te klikom na gumb u razvojnoj okolini alata. Za potrebe ovog projekta komponentu PhoneCall1 preimenovali smo u TelefonskiPoziv, a komponetu Button1 uUspostaviPoziv. Još jednom ponavljamo – budući da bi rad na ovom projektu trebao ujedno biti vaša samostalna vjeţba korištenja Googleovog razvojnog alata, nazive komponenti moţete izabrati prema vlastitim sklonostima. Za komponentu TelefonskiPoziv moţe se izmijeniti i početna vrijednost svojstva PhoneNumber na ţeljeni broj pozivatelja (ako se pozivi najčešće upućuju na taj broj), dok komponenti UspostaviPoziv treba izmijeniti svojstvo Text, kako bi zamjena za podrazumijevanu vrijednost Text for Button1 preciznije pokazivala namjenu gumba. U ovom trenutku je dovršeno „crtanje“ korisničkog sučelja, a sad preostaje još samo to da se „napiše odgovarajući programski kod“, odnosno dovrši slagalica u inovativnom Googleovom sučelju za tu namjenu (o čijem korištenju je bilo više riječi u prvom nastavku serijala). Sasvim konkretno – u ovom slučaju potrebno je napraviti povezivanje bloka Click iz kontrole UpostaviPoziv s blokomMakePhoneCall iz kontrole TelefonskiPoziv. Na taj način dovršena je prva verzija aplikacije koja omogućava uspostavu telefonskog poziva iz Android uređaja s upisanim odredišnim brojem nakon što korisnik pritisne kontrolu (gumb) UspostaviPoziv. Djelovanje programa moţete (ili ipak ne moţete) provjeriti sami na vlastitom komadu Android hardvera, već prema tome kako je on trenutno podrţan od strane Googleovih razvojnih inţenjera.

Na trenutnom stupnju razvoja naše nove aplikacije trebalo bi biti moguće uspostaviti telefonski poziv, ali aplikacija još uvijek „nema pojma“ o podacima zapisanim u bazu kontakata u okviru samog uređaja, nego se svi telefonski brojevi moraju upisivati u cijelosti. Budite iskreni pa priznajte sami sebi koliko često u praksi zaista izvodite operaciju upisivanja broja pozivatelja u odnosu na učestalost biranja dostupnih brojeva iz baze kontakata. Zato aplikaciju treba dodatno proširiti tako da postane „svjesna“ ranije pripremljenih telefonskih brojeva.

Dovršeno sučelje aplikacije za telefoniranje: Omogućava korištenje podataka iz spremišta kontakata u samom uređaju.

U drugoj verziji aplikacije ćemo na osnovni zaslon aplikacije dodati još jednu novu kontrolu: Social -> PhoneNumberPicker, a onda joj izmijeniti predloţeni naziv u IzaberiBroj, odnosno tekst koji se prikazuje na kontroli s početne vrijednosti Text for PhoneNumberPicker1 za hrvatsku verziju aplikacije primjereniji oblik Izaberi broj. Kontrola tipa PhoneNumberPicker predstavlja svojevrsnu verziju običnog gumba, s tom razlikom da pritisak na kontrolu automatski izaziva prikaz podataka iz postojeće baze kontakata u uređaju. Kad smo napisali „prikaz podataka“, onda smo zaista mislili samo na to, jer odabir telefonskog broja iz prikazanih podataka još uvijek nije moguć, bar ne tako dugo dok se ponovo ne pripremi odgovarajuća „slagalica“ za upravljanje izvođenjem programa. Da bi se na temelju izabranog podatka iz popisa kontakata zaista ostvario telefonski poziv, potrebno je spojiti blok AfterPicking kontrole IzaberiBroj s blokom MakePhoneCall iz kontrole TelefonskiPoziv. Potrebno je napraviti još prijenos odgovarajućeg parametra (izabranog telefonskog broja) između te dvije kontrole, što se izvodi dodatnim vezanjem blokaPhoneNumber kontrole IzaberiBroj s prije navedenim blokom MakePhoneCall. Ovim korakom, ako je sve pravilno izvedeno, trebala bi biti dovršena druga faza u razvoju aplikacije. Sada je aplikacija spremna za izvođenje telefonskih poziva na temelju prije spremljenih podataka u bazu kontakata. U smislu poboljšanja grafičkog izgleda aplikacije moguće je u aplikaciju dodati još poneki detalj. Premda se u trenutnoj verziji broj iz baze kontakata zaista moţe izabrati kao temelj za telefonski poziv, korisnik aplikacije još uvijek ne moţe vidjeti o kojem je telefonskom broju riječ. Da ne spominjemo nemogućnost prikaza slike vlasnika telefonskog broja, ako takva postoji u uređaju. Unapređenje korisničkog sučelja aplikacije moţe se postići tako da se u okviru istog

bloka AfterPicking kontrole IzaberiBroj, naprave dva dodatna povezivanja. Blok PhoneNumber iz kontrole IzaberiBroj treba povezati s blokom Text ranije opisanog gumba UspostaviPoziv, a blok Picture iz kontrole IzaberiBroj spojiti s blokom Image, također svojstvom gumba UspostaviPoziv. Navedenim operacijama je aplikacija poboljšana u vizualnom smislu pa osim zahtijevane funkcionalnosti sada posjeduje i odgovarajuće korisničko sučelje. Trenutna verzija aplikacija se i dalje moţe nadograđivati, pa evo nekoliko ideja koje moţete probati napraviti sami: 1. Osim prijenosa broja koji se poziva iz baze spremljenih kontakata, probajte prenijeti još neke podatke na osnovni zaslon aplikacije (prije svega prezime i ime korisnika). Razmislite prvo trebaju li vam kakve dodatne kontrole na sučelju, da bi to zaista mogli napraviti. Ova točka ne bi trebala biti prezahtijevna za realizaciju. 2. Podaci o uspostavljenim pozivima mogli bi se sačuvati za kasniju analizu. Kako je u ovom slučaju riječ o malo zahtijevnijem postupku, o njemu će više riječi biti neki drugi put. Na kraju, ambiciozniji čitatelji mogu probati sami napraviti sličan projekt ispočetka tako da se umjesto uspostave telefonskog poziva izvodi slanje dobre, stare SMS poruke. U tom slučaju temeljnu kontrolu za rad aplikacije (Social -> PhoneCall), treba zamijeniti nečim drugim, ali vam to sada nećemo otkriti, nego vam ostavljamo da na temelju prethodnih nastavaka serijala i vlastitog eksperimentiranja sami pronađe o čemu je riječ. U svakom slučaju preporučamo vam da sami probate „odraditi“ cijeli posao oko današnje aplikacije, kako bi mogli lakše pratiti slijedeći projekt, gdje ćemo još manje detaljizirati oko biranja kontrola i njihovog korištenja nego što je to bi slučaj danas. Budući da ćemo raditi na mnogo sloţenijem projektu jednostavno moramo pretpostaviti da su vam dobro poznate osnovne stvari oko korištenja Googleovog alata za neprogramere.

Android programiranje #16: Korištenje kartografskih servisa U današnjem završnom nastavku svojevrsnog podserijala o korištenju Googleovog alata za brzo prototipiranje aplikacija, pokazat ćemo kako se u okviru tog alata koriste kartografske mogućnosti Googleovih servisa, jedne od najčešće korištenih tehnologija u aplikacijama na mobilnim uređajima.Dodatna vrlo zanimljiva razvojna tehnika demonstrirana u istom primjeru je pozivanje jedne Android aplikacije iz druge Android aplikacije. Već smo nekoliko puta spomenuli kako je trenutno jedno od najvećih ograničenja Googleovog razvojnog alata za neprogramere u tome što se unutar jedne aplikacije moţe koristiti samo jedan raspored kontrola. Upravo sposobnošću pozivanja jedne aplikacije iz druge moţe se zaobići spomenuto ograničenje. Način korištenja kartografskih servisa na kojem se temelji današnji tekst prikazan je u Googeovom primjeru pripremljenom od strane profesora Davida Wolbera sa sveučilišta u San Franciscu. Prije nego što nastavimo s detaljnijim objašnjavanjem primjera istaknimo na ovom mjestu još jednu bitnu mogućnost operativnog sustava Android u pogledu izrade rješenja koje se sastoji od većeg broja sastavnih dijelova. Dok za pozivanje drugog dijela aplikacije iz početnog dijela treba koristiti komponentu ActivityStarter, povratak unatrag se izvodi potpuno automatski. Dovoljno je samo izabrati standardnu operaciju operativnog sustava za tu namjenu, to jest odgovarajuću tipku na samom uređaju.

Prvi dio aplikacije (sučelje): Sastoji se od tri osnovne kontrole: Image1, ListPicker1 i ActivityStater1.

U prvom dijelu aplikacije na osnovni zaslon projekta postavljene su svega tri kontrole: Image1, ListPicker1 i ActivityStater1. Kontrole su redom namijenjene za prikaz početne slike programa, izbor triju različitih odredišta za prikaz na karti, te na kraju komponente za pokretanje dodatne kartografski orijetirane aplikacije. Prve dvije kontrole ne bi trebale biti posebno teške za korištenje, tako da ih nećemo ni posebno opisivati. Uostalom, kontrolu za prikaz slika koristili smo već u prvom, najtrivijalnijem primjeru korištenja alata. Nešto više vremena posvetit ćemo korištenju komponente ActivityStarter, zato što ona zahtijeva oblik znanja kakav je uobičajen u krugovima pravih Android

programera, ali nije baš uobičajen za korisnike neprogramere. Drugim riječima, druga komponenta cjelokupnog rješenja mora se pozvati iz prve prema točnom definiranom protokolu, što bi u ovom slučaju imalo otprilike slijedeći oblik: ActivityStarter svojstvo

Vrijednost

Action android.intent.action.VIEW ActivityClass com.google.android.maps.MapsActivity ActivityPackage com.google.android.apps.maps

Prvi dio aplikacije (programski blokovi): Najvaţniji dio povezan je aktivnostima kontrole ActivityStarter.

Programski blokovi povezani s aplikacijom podijeljeni su u dva dijela. Prvi dio je zajedno s pratećim deklaracijama vrijednostima zaduţen za pripremu početnog izgleda aplikacije (vidi prateću sliku uz tekst), dok se drugi izvodi nakon odabira neke od zadanih lokacija: “Tour Eiffel”, „Musee du Louvre“ i „Cathedrale Notre Dame“. Nakon odabira jednog od navedena tri mjesta iz popisa prelazi se na izvođenje programskog blokaListPicker1.AfterPicking. Na ovom mjestu dolazimo do male dodatne komplikacija pa je treba objasniti nešto detaljnije. Da bi se pomoću komponente ActivityStarter mogla uspješno pokrenuti druga komponenta za prikaz nekog mjesta na mapi, potrebno je komponenti prenijeti adresu u točno propisanom formatu, a to u ovom slučaju znači popunjavanje svojstvaActivityStater.DataUri. U spomenuto svojstvo mora se postaviti kombinacija vrijednosti „geo:0,0?q=“ te konkretne vrijednosti za izabranu lokaciju iz popisa dostupnih mjesta (ListPicker1.Selection). Za to se koristi posebni programski blok zaduţen za rukovanje nizovima znakova (make text). U slučaju odabira druge od dostupnih vrijednosti dobije se konačna vrijednost: geo:0,0?q=’Musee du Louvre’. Izvođenje aplikacije: Osnovni oblik izvođenja aplikacije u Android emulatoru.

Sad je konačno sve spremno za pozivanje drugog dijela aplikacije, pa prvi dio aplikacije zaista predaje kontrolu izvođenja drugom dijelu na ranije opisani način. Po ţelji se (to smo isto već spomenuli) moţete vratiti na prvi dio korištenjem standardne operacije u operativnom sustavu Android. „Sirovi“ oblik kartografskog prikaza kakav je u ovom trenutku prisutan u aplikaciji moţe se dalje nadograđivati tako da se modulu zaduţenom za prikaz objekta mnogo preciznije zada način prikaza nekog mjesta prema sintaksi propisanoj od strane Googlea. Na primjer, za znatno atraktivniji način prikaza svih triju lokacija mogla bi se navesti „malo sloţenije odrednice“: Eiffel Tower http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=eiffel+towe r&sll=37.0625,-95.677068 &sspn=48.909425,72.333984&ie=UTF8&hq=Tour+Eiffel&hnear=Tour+Eiffel,+Quai+ Branly,+75007+Paris,+Ile-deFrance,+France&ll=48.857942,2.294748&spn=0.001249,0.002207&t=h&z=19 Musee Louvre http://maps.google.com/maps?f=q&source=s_q&hl=en&q=louvre&sll=48.86096,2. 335421&sspn=0.002499,0.004415&ie=UTF8&t=h&split=1 &filter=0&rq=1&ev=zi&radius=0.12&hq=louvre&hnear=&ll=48.86096,2.335421&s pn=0.002499,0.004415&z=18 Notre Dame, Street View ttp://maps.google.com/maps?f=q&source=s_q&hl=en&q=french+landmarks&sll=4 8.853252,2.349111&sspn=0.002411,0.004415 &ie=UTF8&t=h&radius=0.12&split=1&filter=0&rq=1&ev=zi&hq=french+landmark s&hnear=&ll=48.853252,2.349111&spn=0,0.004415 &z=18&layer=c&cbll=48.853046,2.348861&panoid=74fLTqeYdgkPYj6KKLlqgQ&cbp =12,63.75,,0,-35.58 U slučaju da ţelite provjeriti sami kako sve to skupa lijepo djeluje u praksi, a nemaze ni vremena ni volje da ispočetka razvijate cijelu aplikaciju, moţete krenuti linijom manjeg otpora te usmjeriti svoj preglednik na adresu http://appinventor.googlelabs.com/learn/tutorials/maptour/maptour.html

Kontinuirani razvoj alata

Napredno izvođenje aplikacije: U prikaz su uključene dodatne opcije za prikaz slika na zadanoj lokaciji.

U razdoblju od prvog spominjanja razvojnog alata App Inventor for Android u ovom serijalu, pa do današnjeg nastavka, Googleovi razvojni inţenjeri marljivo su radili na njegovim unapređenjima (a rade i dalje). Budući da se razvoj aplikacija izvodi izravno u nekom od preglednika nije potrebno preuzimati nikakve nove verzije alata da bi se iskoristile te novosti, nego su one odmah dostupne čim se alat slijedeći put pokrene nakon njegovog aţuriranja na Googleovom serveru. Osim ispravke uočenih pogrešaka prijavljenih od strane korisnika, izgleda da se najintenzivnije radi na daljnjim doradama komponenti u okviru kolekcije Other Stuff. Komponenta Web zamišljena je tako da osigurava dodatne mogućnosti u izravnom preuzimanju podataka s web servera, za što se do sada morao koristiti poseban Java kod (ili programski kod u nekom drugom programskom jeziku) distribuiran na server. Sada je postalo moguće pozivati određene skupine API funkcija izravno preko Web komponente. Na primjer, korištenjem poziva funkcija iz Yahoo Finance API biblioteke prilično je jednostavno u Android aplikaciju dodati prikaz različitih poslovnih informacija o čijoj pripremi i pouzdanosti brine Yahoo. Iako to nema izravne veze s temom današnjeg teksta, za eventualno zainteresirane ipak spomenimo kako se sve potrebne informacije o korištenju Yahoo Finance API tehnologije nalaze na adresi:http://www.gummy-stuff.org/Yahoo-data.htm

Web komponenta u akciji: Izravno korištenje Yahoo Finance API tehnologije. Za sada toliko o ovoj temi. Nadamo se da vas je sve do sada napisano potaklo da počnete razmišljati o razvoju vlastitih Android aplikacija, čak i ako niste programer, ili ako to nikada niste ni mislili postati. Kad savladate razvojni alat za neprogramere moţda ćete poţeljeti da se u budućnosti počnete baviti i „pravim“ Google Android programiranjem. Na njega ćemo se ponovo vratiti u slijedećem nastavku, kako bi pokazali još nekoliko naprednijih tehnika korištenja osnovnog SDK alata.

Android programiranje #17: Što je novo u 3.x izdanjima Da čovjek jednostavno ne povjeruje kako vrijeme brzo leti – od početka serijala o programiranju korištenjem Googleovog razvojnog alata Android SDK, već je prošlo više od godinu dana, a u međuvremenu se je mnogo toga dobrog dogodilo sa samim alatom u smislu proširenja njegovih mogućnosti. Za to je prije svega zasluţna prava eksplozija pojave novih modela tablet računala, jer je upravo ona dovela do potrebe optimiziranja Android sustava za takvu vrstu hardvera. Novosti u alatu App Inventor for Android Prije nego se pozabavimo osnovnim Android SDK razvojnim sustavom namijenjenom „pravim programerima“, napišimo nekoliko dodatnih riječi o najnovijim vijestima povezanim s Googleovim alternativnim alatom za brzo prototipiranje aplikacija (App Inventor for Android), jer smo se upravo njime bavili zadnjih nekoliko brojeva. Ako vam se alat dopao, pa zato planirate njegovo dugoročnije korištenje, vaţno je znati što vam očekuje u budućnosti. Prvo, i trenutno najvaţnije, kao novu web adresa za online korištenje alata App Inventor for Android trebati će ubuduće koristiti www.appinventorbeta.com umjesto dosadašnje adrese appinventor.googlelabs.com. U duhu vođenja brige za postojeće korisnike vlastitih proizvoda, uobičajenom kod velikih IT poduzeća, sve postojeće aplikacije registriranih korisnika sačuvane su i dostupne na novoj adresi, tako da nema potreba za nekakvim „prepisivanjem“ aplikacija s jedne adrese na drugo.

Android 3.x: Donosi brojne promjene u korisničkom sučelju optimizirane za moderne tablet uređaje.

Drugo, te jednako vaţno za buduće korištenje alata, Google prestaje s izravnim radom na odrţavanju i razvoju alata App Inventor for Android. To na sreću ne znači da će alat nestati, nego da on prelazi u „open source“ kategoriju. Za budući status alata brigu će voditi novoosnovani Center for Mobile Learning u okviru MIT Media Laba, te biti pod stalnim nadzorom tri profesora s istog sveučilišta: Hal Abelson, Eric Klopfer i Mitchel Resnik. Prva osoba iz nabrojene trojke zasluţna je za predlaganje i pokretanje čitavog projekta 2008 godine zajedno s poduzećem Google, iz laboratorija drugog profesora potekla je prva verzija razvojnog alata, i to upravo na temelju ideje zadnjeg imena s popisa. Dovršetak cijelog postupka očekuje

se do kraja godine, a postojeći korisnici alata će redovito dobijati informacije o svim promjenama. Novosti u „osnovnom“ Android sustavu Nakon razjašnjavanja trenutne i buduće situacije s alatom za brzo prototipiranje Android aplikacija, vratimo se sada na osnovni razvojni alat Android SDK. Od trenutka početka pisanja serijala, kojeg upravo čitate, razvojni alat je promijenio svoju prvu brojčanu oznaku verzije s 2 na 3, što uvijek znači da je došlo do bitnih promjena u nekom softverskom paketu. Kao što smo to već spomenuli na samom početku ovog teksta, ključni okidač za takve promjene je sveopća „zaluđenost“ tablet računalima, kako od strane proizvođača, tako i od strane korisnika mobilnih uređaja. Budući da se po dijelu svojih hardverskih karakteristika takvi uređaji razlikuju od mobilnih telefona, Android sustav doţivio je bitne promjene što simbolizira nova početna oznaka verzije. Pogledajmo prvo što se najvaţnijeg dogodilo sa stanovišta krajnjeg korisnika. Najvaţnije su, naravno, promjene na dimenzijama i rezoluciji zaslona, jer su ove vrijednosti u pravilu dosta veće nego kod mobilnih telefona. Povećanje zaslona pretpostavka je za dodatnu zabavu u korisničkom sučelju, kako u pogledu redizajna postojećih dijelova, tako i u pogledu dodavanja potpuno novih dijelova sučelja poput sistemske ili akcijske trake. Kad govorimo o promjenama u korisničkom sučelju onda se to odnosi na dio vidljiv na zaslonu, ali i na sistemske, grafički orijentirane module u pozadin,i koji su također morali doţivjeti brojne promjene. Na većem zaslonu uređaja mogla se između ostalog redizajnirati softverska tipkovnica namijenjena unosu znakova. Tipkovnica je jednostavno postala udobnija te brţa za korištenje nego prije, jer se do dijela tipki više ne mora dolaziti zaobilazno. Još jedna bitna stvar povezana s korisničkim sučeljem je poboljšana mogućnost upravljanja operacijama označavanja, isijecanja, kopiranja i umetanja teksta. Sada se za tu operaciju koriste dodatne strelice prikazane na zaslonu.

Promjene u poznatim aplikacijama: Na primjer, aplikacija za upravljanje ugrađenom kamerom.

Prva od prije spomenutih traka, smještena na samom dnu zaslona, namijenjena je za brzi pristup obavijestima, statusnim pokazateljima sustava te navigacijskim gumbima postavljenim na sam zaslon. U pravilu sistemska traka dostupna je stalno, iako se ako je to baš potrebno moţe sakriti u slučaju da neka aplikacija treba

iskoristiti cijeli dostupni prostor zaslona. Još jedan vaţan zadatak sistemske trake je upravljanje višezadatkovnim radom preko popisa nedavno korištenih aplikacija (Recent Apps). Druga traka (akcijska) nalazi se na vrhu zaslona, a izgled i djelovanje ovise joj o kontekstu izvođenja aplikacije, što znači da promjenom njezinog izgleda upravlja aplikacija, a ne sam Android sustav. Od ostalih novosti svakako treba spomenuti nove mogućnosti povezivanja tablet računala s vanjskim uređajima pomoću Media/Picture Transfer Protocola, odnosno povezivanje prave tipkovnice s uređajem kako bi se još više olakšalo upisivanje teksta. Na kraju tu je i nekoliko poboljšanja standardnih aplikacija – preglednik, elektronička pošta, kamera, galerija i imenik. U još novijim verzijama nasljednicama s oznaka 3.1 i 3.2 uvedena su dodatna unapređenja u korisničkom sučelju te povezivanju s vanjskim uređajima (npr. različiti dodaci za igru) i Wi-Fi, dok je sam Android sustav optimiziran za brojne tablet uređaje, koji su se na trţištu pojavili u međuvremenu. U ovom nabrajanju ne smijemo nikako zaboraviti na još jednu promjenu, budući da ona nije vidljiva na prvi pogled, ali pridonosi ukupnom zadovoljstvu korištenja Android platforme. Osim što u verziji 3.x Android podrţava istovremeno korištenje većeg broja aplikacija, sada se te aplikacije mogu izvoditi i na većem broju procesora odnosno jezgri, ako je takva hardverska konfiguracija ugrađena u mobilni uređaj. Android uređaji tako će uskoro moći rješavati najsloţenije probleme, a da ne spominjemo kako će dobro na njima izgledati različite igre. U međuvremenu su se na trţištu zaista pojavili višejezgreni uređaji, tako da ovo više nije samo teoretska mogućnost sustava. Sad kad smo ukratko naveli što je sve novo u sustavu sa stanovišta krajnjeg korisnika, pogledajmo što to zapravo znači za programere, ako ţele pisati optimizirane aplikacije za nove verzije Andrioda s početnom verzijom 3. Svaka nova verzija Androida sa sobom donosi izmijenjeno programsko sučelje s određenim brojem novih poziva API funkcija, odnosno izmjene u načinu korištenja postojećih funkcija. Budući da su se u verziji 3.0 (i novijima) pojavili potpuno novi dijelovi korisničkog sučelja, kao što je akcijska traka ili sistemska traka, najvaţnije API promjene povezane su upravo s tim dijelovima. Drugim riječima, dobili smo sasvim dovoljno građe za još nekoliko nastavaka serijala u kojima bi se demonstrirale najnovije mogućnosti platforme. Navedimo sada primjer dijela programskog koda namijenje korištenju akcijske trake u vlastitim aplikacijama, tek toliko da steknete dojam kako to izgleda Detaljnije djelovanje programskog koda koji upravlja alatnom trakom, ali i drugim novostima verzije 3.x objasnit ćemo na sloţenijem primjeru kojeg počinjemo izrađivati slijedeći put.

package com.example.android.apis.app; import com.example.android.apis.R; import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; public class ActionBarTabs extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.action_bar_tabs); } public void onAddTab(View v) { final ActionBar bar = getActionBar(); final int tabCount = bar.getTabCount(); final String text = “Tab ” + tabCount; bar.addTab(bar.newTab() .setText(text) .setTabListener(new TabListener(new TabContentFragment(text)))); }

public void onRemoveTab(View v) { final ActionBar bar = getActionBar(); bar.removeTabAt(bar.getTabCount() – 1); } public void onToggleTabs(View v) { final ActionBar bar = getActionBar(); if (bar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) { bar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); bar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE); } else { bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE); } } public void onRemoveAllTabs(View v) { getActionBar().removeAllTabs(); } private class TabListener implements ActionBar.TabListener { private TabContentFragment mFragment; public TabListener(TabContentFragment fragment) { mFragment = fragment; } public void onTabSelected(Tab tab, FragmentTransaction ft) { ft.add(R.id.fragment_content, mFragment, mFragment.getText()); } public void onTabUnselected(Tab tab, FragmentTransaction ft) {

ft.remove(mFragment); } public void onTabReselected(Tab tab, FragmentTransaction ft) { Toast.makeText(ActionBarTabs.this, “Reselected!”, Toast.LENGTH_SHORT).show(); } } private class TabContentFragment extends Fragment { private String mText; public TabContentFragment(String text) { mText = text; } public String getText() { return mText; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View fragView = inflater.inflate(R.layout.action_bar_tab_content, container, false); TextView text = (TextView) fragView.findViewById(R.id.text); text.setText(mText); return fragView; } } }

View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF