Professional Documents
Culture Documents
PROGRAMIRANJA
By android@Vidi
SADRZAJ:
Android kola programiranja Pisanje i pokretanje prvog programa.........3
Trei nastavak serijala o Google Android programiranju Interakcija sa
korisnikom................................................................................................. 8
Android programiranje #4: Uvod u pisanje programskoga koda..............12
Android programiranje #5: Koritenje rasporeda kontrola u sloenim
aplikacijama............................................................................................ 18
Android programiranje #6: Koritenje osnovnih Android kontrola............24
Android programiranje #7.......................................................................31
Android programiranje #8: Android kontrole u akciji IV...........................35
Android programiranje #9: Koritenje datotenog 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 sloenijih aplikacija..........................78
Android programiranje #16: Koritenje kartografskih servisa..................82
Android programiranje #17: to je novo u 3.x izdanjima.........................86
android:layout_height=fill_parent
android:background=@color/BijelaBoja>
<TextView
android:layout_width=fill_parent
android:layout_height=wrap_content
android:text=@string/hello
/>
<EditText android:text=@+id/EditText01 android:id=@+id/EditText01
android:layout_height=wrap_content
android:layout_width=fill_parent></EditText>
<Button android:id=@+id/Button01
android:layout_height=wrap_content
android:onClick=myClickHandler android:layout_width=wrap_content
android:text=Prihvati></Button>
<Button android:id=@+id/Button02
android:layout_width=wrap_content
android:layout_height=wrap_content
android:onClick=myClickHandler android:text=Odbaci></Button>
</LinearLayout>
Sve ono to smo ranije dobili grafikim oblikovanjem
suelja u nekoliko prozora razvojne okoline, ovdje je
prikazano u obinom XML formatu zapisa. Iskusniji
programeri mogu na ovom mjestu izravno izvoditi
promjene, pa ak i dodavanje novih objekata na suelje.
Na primjer, probajte jednostavno umnoiti dio teksta
namijenjen definiranju gumba Button02 pa ete dobiti
jo jedan identian gumb na korisnikom suelju.
Primijetimo na kraju dananjeg nastavka da u XML opisu oba gumba
postoji veza prema programskom kodu za obradu dogaaja onClick, jer je
autor teksta to ve pripremio u primjeru, ali zbog zadane veliine svakog
pojedinog nastavka serijala, o tome e neto vie rijei biti u sljedeem
broju.
<Button android:id=@+id/Button01
android:layout_height=wrap_contentandroid:onClick=myClickHand
ler android:layout_width=wrap_content
android:text=Prihvati></Button>
<Button android:id=@+id/Button02
android:layout_width=wrap_content
android:layout_height=wrap_content android:onClick=myClickHan
dler android:text=Odbaci></Button>
Na koji nain u vlastite projekte moete dodati dio koji nedostaje? Jedan
od naina izravni je upis prije oznaenoga teksta u prozoru zaduenom za
tekstualni prikaz sadraja datoteke main.xml. Drugi nain koritenje je
prozora Properties, nakon to eljeni objekt postane aktivan objekt (vidi
priloenu sliku uz tekst). U naem primjeru oba objekta povezana su s
istim dijelom programskog koda, jer se u njemu na jedinstven nain prvo
provjerava objekt na koji je korisnik programa napravio pritisak. Mogue
je napraviti i drugaije rjeenje. Svaki gumb moe biti povezan s
posebnom funkcijom za obradu dogaaja. Na autoru programa je odluiti
to je najbolje izabrati u odreenoj situaciji.
Pripadajui programski kod primjera u ovom trenutku ima sljedei 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;
}
}
}
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);
}
}
Poetni izgled prozora: Nakon pokretanja programa
pojavljuje se poetna poruka.
Budui da zajednika funkcija za obradu dogaaja
nakon pritiska na gumb vie ne postoji, nego je
zamijenjena s dvije pojedinane funkcije, treba korigirati
veze izmeu oba gumba i pripadajuega programskoga koda. To se
ponovno moe napraviti izmjenom svojstva On click u
prozoruProperties te upisivanjem
vrijednosti myClickButton1, odnosnomyClickButton2. Klikom na gumb
na krajnjoj desnoj strani toga reda moe se prikazati i dijaloki okvir za
odabir postojeih dijelova programskoga koda. Alternativni nain za
izvoenje iste operacije (neto bri, ali zahtijeva veu preciznost u
pisanju) izravna je izmjena tekstualnog sadraja datotekemain.xml. U
konanici, bez obzira na uporabljeni nain izmjene vrijednosti, u toj
datoteci treba biti sljedei sadraj.
<?xml version=1.0 encoding=utf-8?>
<Button android:id=@+id/Button01
android:layout_height=wrap_content
android:layout_width=wrap_content
android:text=Prihvati android:onClick=myClickButton1android:scr
ollHorizontally=false></Button>
<Button android:id=@+id/Button02
android:layout_width=wrap_content
android:layout_height=wrap_content
android:text=Odbaci android:onClick=myClickButton2></Button
>
LinearLayout
AbsoluteLayout
TableLayout
RelativeLayout
FrameLayout
ScrollView
Poetni raspored osnovnih kontrola: Koristi se
podrazumijevani raspored osnovnih kontrola
LinearLayout.
android:layout_height=fill_parent android:background=@color/BijelaB
oja>
<TextView
android:layout_width=fill_parent
android:layout_height=wrap_content
android:text=@string/hello
/>
<EditText android:text=@+id/EditText01 android:id=@+id/EditText01
android:layout_height=wrap_content android:layout_width=fill_parent
>
</EditText>
<Button
android:id=@+id/Button01 android:layout_height=wrap_content
android:layout_width=wrap_content android:text=Prihvati
android:onClick=myClickButton1 android:scrollHorizontally=false>
</Button>
<Button
android:id=@+id/Button02 android:layout_width=wrap_content
android:layout_height=wrap_content android:text=Odbaci android:on
Click=myClickButton2>
</Button>
</LinearLayout>
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. Budui da to jo uvijek nismo napravili, uzete su
podrazumijevene vrijednosti 0, to je izazvalo spomenuto skupljanje
kontrola.
Navoenjem apsolutnih vrijednosti za poziciju i veliinu kontrola dolazi
do njihovog eljenog formatiranja, kao to to pokazuje pratea slika uz
tekst.
<?xml version=1.0 encoding=utf-8?>
<AbsoluteLayout
xmlns:android=http://schemas.android.com/apk/res/android
android:orientation=vertical
android:layout_width=fill_parent
android:layout_height=fill_parent android:background=@color/BijelaB
oja>
<TextView
android:layout_width=fill_parent
android:layout_height=wrap_content
android:text=@string/hello
/>
<EditText android:text=@+id/EditText01 android:id=@+id/EditText01
android:layout_x=40px
android:layout_y=50px
android:layout_width=400px
android:layout_height=50px>
</EditText>
<Button android:id=@+id/Button01
android:text=Prihvati
android:onClick=myClickButton1
android:layout_x=40px
android:layout_y=100px
android:layout_width=100px
android:layout_height=50px>
</Button>
<Button android:id=@+id/Button02
android:text=Odbaci
android:onClick=myClickButton2
android:layout_x=340px
android:layout_y=100px
android:layout_width=100px
android:layout_height=50px>
</Button>
</AbsoluteLayout>
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_PAR
ENT, 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);
}
}
}
Rezultat klika na web adresu u kontroli TextView: Prikaz
sadraja zadane adrese u pregledniku.
Posebnu vrstu kontrola za upis teksta predstavljaju
kontroleAutoCompleteTextView te MultiAutoComple
teTextView. Njihova najvanija znaajka je da tijekom
upisa/ispravljanja teksta omoguavaju automatsko
dovravanje upisanog teksta. Evo i primjera odgovarajueg programskog
koda nadopisanog na kraj postojeeg 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 koritenja 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 koritenja kontrole EditText */
Primjer koritenja kontrole EditText: Kontrola se koristi za
upis i izmjenu teksta.
Android programiranje #7
<LinearLayout
xmlns:android=http://schemas.android.com/apk/res/android
android:orientation=vertical android:layout_width=fill_parent
CHAPTER 4: Building User Interfaces and Using Controls 137
android:layout_height=fill_parent>
<RadioGroup android:id=@+id/rBtnGrp
android:layout_width=wrap_content
android:layout_height=wrap_content
android:orientation=vertical >
<RadioButton android:id=@+id/pRBtn android:text=Piletina
android:layout_width=wrap_content
android:layout_height=wrap_content/>
<RadioButton android:id=@+id/sRBtn android:text=Svinjetina
android:layout_width=wrap_content
android:layout_height=wrap_content/>
<RadioButton android:id=@+id/gRBtn android:text=Govedina
android:layout_width=wrap_content
android:layout_height=wrap_content/>
</RadioGroup>
</LinearLayout>
U izmiljenoj aplikaciji za naruivanje u restoranu u prvom sluaju
korisnik aplikacije moe oznaiti razliite dijelove obroka neovisno jedan o
drugome, a u drugom sluaju za glavni obrok moe izabrati samo jednu
od vrsta glavnog jela (mesa).
Vrlo vaan dio gotovo svake aplikacije (osim onih krajnje trivijalnih, ili
onih koje su potpuno optimizirane za neko specijalizirano podruje) je
upravljanje vremenom. ak i razliite igre, kao kategorija aplikacija kakve
se vrlo esto piu za mobilne ureaje ukljuujui i Android platformu,
esto spremaju razliite podatke o igrau ili statusu igre povezane s
datumom i vremenom. Naravno, za prikaz ili izmjenu datuma i vremena
programer uvijek moe izmisliti svoje vlastite kontrole, ali nije loe kad je i
osnovni razvojni sustav opremljen odgovarajuim kontrolama. To posebno
vrijedi kod aplikacija s naglaskom na funkcionalnosti, a ne na vizualnoj
raskoi.
Android platforma opremljena je s dvije meusobno prilino razliite vrste
kontrola za tu namjenu. Prva grupa kontrola moe samo prikazati podatke
o vremenu, dok ih druga vrsta moe 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 odreen ve prije
spomenutom namjenom (prikazom podataka), pa se u praksi koriste
neto rjee, osim ako je dovoljno da kontrola zaista samo prikazuje datum
ili vrijeme. Zato se s navedene dvije kontrole vie neemo baviti. Ako
njihova ogranienja zadovoljavaju vae planove u izradi aplikacija,
jednostavno ih postavite na neki od standardnih rasporeda kontrola i
zaboravite na njih.
android:layout_width=fill_parent
android:layout_height=fill_parent>
<DatePicker android:id=@+id/datePicker
android:layout_width=wrap_content android:layout_height=wrap_cont
ent />
<TimePicker android:id=@+id/timePicker
android:layout_width=wrap_content android:layout_height=wrap_cont
ent />
</LinearLayout>
Prva (gornja) kontrola zaduena je za prikaz, odnosno odabir datuma, a
donja to isto radi s vremenom, kao to se to moe provjeriti na priloenoj
slici uz tekst. Kad se tome pridoda programski kod naveden u nastavku
zaduen za podeavanje poetnih vrijednosti kontrola, dobije se sasvim
funkcionalno korisniko suelje. Najvei nedostatak ove grupe kontrola je
njihova relativna nezgrapnost. Drugim rijeima jednostavno su prevelike
za intenzivno koritenje, naroito ako koristite ureaj s relativno
skromnom rezolucijom zaslona. Ako to predstavlja nepremostivu prepreku
moete se snai 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));
}
}
Koritenje izbornika
Osim sasvim jednostavnih uradaka veina aplikacija podrava neki oblik
sustava izbornika namijenjen izboru svih operacija koje nudi aplikacija. Ni
Android platforma po tome nije nikakav izuzetak. Zapravo mogli bi rei da
vrijedi ak suprotno programeru je na raspolaganju nekoliko razliitih
sustava izbornika, a na njemu je odlui koji od njih najvie odgovara
potrebama konkretne aplikacije. Dok ste neke od dostupnih sustava
izbornika ve susretali na drugim operativnim sustavima u vrlo slinom
obliku, Android nudi i neke novosti na ovom podruju, zbog ega emo se
izbornicima pozabaviti u dva broja asopisa.
Po obiaju kreemo od najjednostavnijeg oblika izbornika, za iju pojavu
u aplikaciji je zaduen iskljuivo 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 odgovarajuom 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 izvoenja dodatnog programskog koda su tri opcije izbornika,
koje se pojavljuju na samom dnu zaslona). Kao to to pokazuje prethodni
{
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();
Istaknimo vrlo vanu injenicu koju svakako treba uzeti u obzir kod rada
s datotenim sustavom, a to je mogunost pojave greke. Osnovni niz
naredbi za zapis podataka u datoteku:
fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
moe ponekad dovesti do pojave greke, ako ni zbog ega drugog onda
zbog nedostatka prostora na mediju na kojem se nalazi datoteni sustav.
Kako se aplikacija u tom sluaju ne bi poela nekontrolirano ponaati,
treba ugraditi bar osnovni mehanizam obrade pogreke u vlastitom kodu,
to je ovdje i napravljeno koritenjem standardne try .. catch strukture.
Pogledajmo sada kako se koristi suprotni tijek podataka namijenjen
itanju spremljenih podataka.
private void VratiPodatkeCritical2() throws IOException
{
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 pogreaka
(throws IOException), jer se moe dogoditi da u datotenom sustavu iz
ovog ili onog razloga ne postoji, ili je oteena datoteka s podacima.
Budui 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 takoer
odraditi u jednom koraku, te ujedno razbiti podatke u odgovarajue
polje podataka pomou naredbe:
String[] list = TextUtils.split(string1, ###);
Preostalo je jo samo to da se na koritenom rasporedu kontrola unutar
aplikacije pronae odgovarajua kontrola te da joj se dodijeli tono
odreena vrijednost proitana iz datoteke. Za taj postupak koristi se
niz findViewById naredbi.
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 koliine
prikupljenih podataka o korisniku aplikacije neprikladne za prikaz na samo
jednom zaslonu ograniene rezolucije (uobiajene kod mobilnih telefona
opremljenih Android sustavom), koristi se vie meusobno povezanih
rasporeda kontrola, a na svakom od rasporeda upotrijebljene su razliite
kontrole kako bi se to jednostavnije i preglednije unijeli relevantni
podaci. Kako to zaista izgleda na zaslonu Android ureaja moete
provjeriti na temelju priloenih slika uz tekst, a dijelovi odgovarajueg
XML koda navedeni su u nastavku.
<AbsoluteLayout android:id=@+id/AbsoluteLayout01
android:layout_width=fill_parent android:layout_height=fill_parent
xmlns:android=http://schemas.android.com/apk/res/android>
<Button android:layout_width=wrap_content
android:layout_height=wrap_content android:layout_x=0px
android:layout_y=0px android:id=@+id/btn2VratiSe
android:onClick=btn2VratiSeClick android:text=<<
Natrag></Button>
<Button android:layout_width=wrap_content
android:layout_height=wrap_content android:layout_y=0px
android:text=Poniti nezgodu android:minWidth=150px
android:layout_x=90px android:onClick=btn2PonistiNezgoduClick
android:id=@+id/btn2PonistiNezgodu></Button>
<TextView android:layout_height=wrap_content
android:layout_width=wrap_content
android:text=Prezime i ime: android:id=@+id/txtvPrezimeIme
android:layout_y=50px android:layout_x=2px></TextView>
<EditText android:saveEnabled=false
android:layout_height=wrap_content android:layout_width=fill_parent
android:layout_x=0px android:id=@+id/txtPrezimeIme
android:singleLine=true android:layout_y=65px></EditText>
<AbsoluteLayout android:id=@+id/AbsoluteLayout01
android:layout_width=fill_parent android:layout_height=fill_parent
xmlns:android=http://schemas.android.com/apk/res/android>
<EditText android:saveEnabled=false
android:layout_height=wrap_content
android:layout_width=wrap_content android:singleLine=true
android:layout_y=65px android:id=@+id/txtKrvnaGrupa
android:maxLength=2 android:text=__ android:layout_x=170px
android:maxWidth=50px android:minWidth=50px>
<CheckBox android:layout_height=wrap_content
android:layout_width=wrap_content android:id=@+id/chkSida
android:layout_x=0px android:text=Sida
android:layout_y=120px></CheckBox>
<CheckBox android:layout_height=wrap_content
android:layout_width=wrap_content android:layout_x=85px
android:layout_y=120px android:text=Hepatitis C
android:id=@+id/chkHepatitisC></CheckBox>
<CheckBox android:layout_height=wrap_content
android:layout_width=wrap_content android:id=@+id/chkDonator
android:text=Donator android:layout_x=210px
android:layout_y=120px></CheckBox>
U trenutku prelaska s jednog rasporeda kontrola na drugi postojei
sadraj kontrola iz starog rasporeda kontrola sprema se za kasnije
koritenje, a novi raspored kontrola se popunjava prethodno spremljenim
sadrajem (ako takav postoji zbog ranijeg koritenja aplikacije). Obje
operacije objanjene su u prethodnom nastavku serijala. Pokaimo sada
kako se programskim kodom prelazi s jednog rasporeda kontrola na drugi.
Na svakom osnovnom rasporedu postoje dva gumba za kretanje na
slijedeu odnosno prethodnu stranicu (razumljivo osim na prvom i
zadnjem). Slijedi primjer koritenja na drugom rasporedu kontrola na
njemu postoji gumb za prelazak na prvi, odnosno na trei 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 pogreke prilikom kretanja kroz osnovne rasporede
kontrola ne bi izazvale ruenje programa, prijenos prikaza s jednog
rasproeda kontrola na drugi zamotan je u odgovarajuu strukturu za
obradu pogreke.
Osim prikaza podataka na standardnim rasporedima kontrola, vrlo esto
je u programu potrebno prikazati i odgovarajue dijaloke okvire o
statusnim informacijama, grekama u radu i slino. U nastavku je
naveden primjer programskog koda za prikaz dijalokog okvira s
podacima o autorima programa (ako za to ne namjeravate koristiti
poseban raspored kontrola zbog vee vizualne dojmljivosti takvog dijela
aplikacije).
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(),Greka);
e.printStackTrace();
}
AlertDialog ad = new AlertDialog.Builder(prvaPomoc.this).create();
CharSequence poruka = Zabiljeeno 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();
}
}
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 tona geografska lokacija s koje je
poruka poslana, kako bi se to bre i jednostavnije dolo do unesreenog
korisnika aplikacije. Ako mobilni telefon (ili neki drugi ureaj koji se temelji
na Android platformi) u sebi sadri odgovarajui hardverski dio za
dobijanje takvog podatka, onda slijedei 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 sadre 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 obino, bitno je da takv dio
aplikacije podloan pogrekama bude obuhvaen u strukturu za obradu
pogreaka. Zahtijevani podatak moe u nekom trenutku jednostavno biti
nedostupan. Na primjer, izvor GPS podataka je uniten solarnom bakljom.
Dobro malo se alimo, mnogo je vjerojatniji neki drugi uzrok problema,
iako prema najavama nekih strunjaka 2012 godine to moda uope vie
nee biti samo ala.
LocationManager je vrlo sloen objekt na Android platformi pa njegovo
detaljno opisivanje prelazi okvire ovog teksta. Osnovni primjer prikazan u
prethodnom dijelu programskog koda, trebao bi vam posluiti kao vodi
za dodatno istraivanje prateih 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
sluaju da navedena dva podatka nisu pripremljena, onda se korisniku
aplikacije javlja odgovarajua poruka kako bi se rijeio problem. Za to se
koristi funkcija o ijoj smo namjeni i djelovanju raspravljali u jednom od
prethodnih nastavaka serijala.
Sasvim je jasno da kritina situacija, u kojoj se moe nai korisnik
aplikacije, nije ba idealan trenutak da aplikacija javi kako smo u fazi
njezinog punjenja poetnim podacima zaboravili navesti neki detalj (fiksni
dio SMS poruke ili odredini broj). Otprilike se radi o istoj situaciji kao kad
bi va najnoviji automobil (dostupan uz mjesenu ratu od svega 500 kn,
ali uz uee 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 koenja javio nekakvu poruku da to ne moe ili
ne eli napraviti. Rjeenje problema je vrlo jednostavno. Nakon upisivanja
svih potrebnih podataka u aplikaciju na samom poetku njezina
koritenja, treba poslati probnu poruku te provjeriti je li zaista sve u redu.
try
{
final EditText tmp = (EditText) findViewById(R.id.txtSMSPoruka);
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 tono vrijeme slanja poruke. Ne
treba posebno ni napominjati da se svi podaci iz prethodne operacije
spremaju u odgovarajua spremita 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 mogunosti sami izraivati relativno sloene
Android aplikacije. Meutim, jo uvijek nismo zavrili serijal, jer nam je
preostala demonstracija koritenja nekoliko bitnih tehnika kao to je dobro
poznati Google Maps, preuzimanje podataka s ugraenih senzora,
koritenje dodatnih grafikih i zvunih mogunosti te jo poneka
zanimljivih sitnica. Ostalo je jo dosta zanimljivog materijala za slijedeih
nekoliko nastavaka, posebno ako sve te dijelove uz dodatak ve
obraenih elimo kreativno povezati u prave aplikacije.
(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.
GetValue(oznaka)
ita vrijednost sa zadanim nazivom iz spremita. U sluaju da traena
oznaka ne postoji u spremitu (npr. kod prvog pokuaja itanja vrijednosti
na novom ureaju), onda metoda vraa prazan niz znakova.
U sluaju da treba obrisati spremite 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 slijedeih
naziva: Camera, ImagePicker, Player, Sound i VideoPlayer. Svaka od
kontrola zaduena je za upravljanje odgovarajuim 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
razliite vrste pokretanja grafikih objekata (dakle najee igre). Na
priloenoj slici uz tekst vidi se da je preduvjet za koritenje kontroli iz ove
grupe upravo postojanje kontrole Canvas. Pomou svojstava kontrola
poputInterval, Speed ili Rotates upravlja se uestalou, brzinom i
rotacijom sliica ili loptica u vlastitoj aplikaciji. Budui da u jednoj
aplikaciji moe biti vie Canvas kontrola, nema nikakvog razloga da
njihovim inteligentnim paljenjem i gaenjem na jednom jedinom zaslonu
(prije istaknuto ogranienje trenutne verzije razvojnog alata) napravite
prilino kompleksnu igru.
Sensors komponente
Danas je sasvim uobiajeno da pametni telefoni i drugi ureaji temeljeni
na Androidu imaju ugraen manji ili vei broj senzora, koji se mogu vrlo
djelotvorno iskoristiti u razliitim vrstama aplikacija (najee igrama).
Zbog toga je razvijeno nekoliko posebnih komponenti za relativno
jednostavnu podrku takvoj vrsti hardvera. Sve komponente su nevidljive
tijekom izvoenja, ali moraju biti ukljuene u aplikaciju da bi se mogle
iskoristiti njihove mogunosti.
Komponenta AccelerometerSensor zaduena je za interakciju softvera
sa senzorom za mjerenje pomicanja ureaja po sve tri osi koordinatnog
sustava. Od tuda dolaze nazivi najvanijih svojstava: XAccel, YAccel,
Zaccel. Pomou svojstva Available programer moe provjeriti jesu li
Vrijednost
Action android.intent.action.VIEW
ActivityClass com.google.android.maps.MapsActivity
ActivityPackage com.google.android.apps.maps
&ie=UTF8&t=h&radius=0.12&split=1&filter=0&rq=1&ev=zi&hq=french
+landmarks&hnear=&ll=48.853252,2.349111&spn=0,0.004415
&z=18&layer=c&cbll=48.853046,2.348861&panoid=74fLTqeYdgkPYj6KKL
lqgQ&cbp=12,63.75,,0,-35.58
U sluaju da elite provjeriti sami kako sve to skupa lijepo djeluje u praksi,
a nemaze ni vremena ni volje da ispoetka razvijate cijelu aplikaciju,
moete krenuti linijom manjeg otpora te usmjeriti svoj preglednik na
adresu http://appinventor.googlelabs.com/learn/tutorials/maptour/maptou
r.html
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;