Hello Android – czyli szkielet aplikacji

Na prośbę mciek piszę tutorial nie do końca programistyczny… Większość zadań przy tworzeniu szkieletu aplikacji na platformę Android pomoże nam stworzyć Eclipse.

Podstawy

Nie chcę powtarzać rzeczy które są dobrze i przystępnie napisane w Dev Guide, więc temat instalacji Android Developer Tools i tworzenie nowego projektu w Eclipse pozostawię oryginalnemu artykułowi http://developer.android.com/guide/developing/eclipse-adt.html. Kody „wyjściowe” użyte w tym artykule są automatycznie tworzone przez Eclipse przy stworzeniu nowego projektu.

Spróbuje pokrótce omówić podstawowe elementy aplikacji i opisać metody wbudowanych klas które mozna (a często trzeba) przeciążać.

Podstawową „jednostką” w aplikacji jest Activity, czyli aktywność z którą użytkownik ma do czynienia, pojedyncza „strona” aplikacji. Nazwanie Activity „podstawową jednostką aplikacji” może wydawać się nielogiczne – przecież aplikacja składa się zwykle z więcej niż jednej „strony”, czyli musi byc coś bardziej podstawowego – ale jedne Activities, są uruchamiane z innych i od strony programisty nie jest szczególnie ważne to co jest poniżej (na razie trzeba w to uwierzyć ;-)

Klasa Activity posiada między innymi metodę onCreate, którą musimy przeciażyć, żeby nasze Activity robiło cokolwiek sensownego.

public class HelloAndroid extends Activity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }
}

Do metody onCreate przekazywany jest stan Activity z poprzedniego uruchomienia (informacje na temat zapisywania stanu być może pojawią się w innym artykule, na razie nie będzie nam to do niczego potrzebne).

Na początku musimy wywołać metodę onCreate klasy Activity po której dziedziczymy (super.onCreate – żeby pojawiło się chociaż czrne okienko, które będziemy mogli wypełnić)

Kolejnym krokiem jest ustawienie widoku na podstawie pliku XML za pomocą metody setContentView (na początku może się to wydawać strasznie zagmatwane, ale naprawdę dobrze się spisuje – pozwala na zupełne oddzielenie layoutu od kodu aplikacji).

Tak więc nasz plik res/layout/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
  <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"/>
</LinearLayout>

Tak więc main.xml opisuje nam wygląd pierwszej strony naszej aplikacji. LinearLayout to kontener na elementy, który automatycznie ustawia je obok siebie w ustalonej orientacji (android:orientation=”vertical”/”horizontal”), wypadałoby, żeby główny kontener zajmował całą dostępną przestrzeń ekranu, więc mamy android:layout_width=”fill_parent” android:layout_height=”fill_parent”. TextView to normalny element tekstowy (takij jak JLabel, albo normalny tekst w HTML) jako wartość parametru android:text podajemy otwartym tekstem to co ma nam się „napisać” lub referencję do wartości podanej w pliku res/values/strings.xml

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <string name="app_name">Hello Android</string>
 <string name="hello">Hello World, HelloAndroid!>/string>
</resources>

Po uruchomieniu aplikacji na emulatorze lub telefonie (Run=>Run configurations…->dwuklik na android application->Project, Browse->Wybieramy nasz projekt->Run) pojawi nam się czarne okienko z jasnym napisem (uwaga! uruchomienie emulatora może potrwać kilka minut, najlepiej spokojnie czekać i nic nie robić z okienkiem emulatora).

Aplikacja nie jest zbyt użyteczna i nie jest do końca jasne jak się zabrać do przerobienia jej na taką… Ale DO ROBOTY!

Przerabiamy

Dodamy do istniejącego szkieletu kilka elementów które pozwolą nam na interakcję z użytkownikiem i pokażą jakygląda tworzenie aplikacji na Androida. Aplikacja wyswietli pole TextView,edytowalne pole tekstowe (EditText) i przycisk (Button). Po kliknięciu na przycisk treść EditText zostanie wpisana do TextView.

1. XML’e

W androidzie każdy element widoku do którego chcemy się odwołać z kodu programu musi mieć swoje id (android:id), przerabiamy więc nasz plik main.xml żeby wyglądał następująco:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"/>
  <EditText android:hint="@string/typeSomething" android:id="@+id/field" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
  <Button android:text="@string/change" android:id="@+id/change" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
</LinearLayout>

i strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">Hello Android</string>
  <string name="hello">Witaj, Wpisz coś w pole in naciśnij "Zmień"</string>
  <string name="typeSomething">Wpisz coś</string>
  <string name="change">Zmień</string>
</resources>

Mamy więc pole tekstowe (TextView) o id „text” w którym wyświetli się napis hello z pliku strings.xml, EditText o id „field” i tekstem podpowiedzi (bardzo fajna sprawa w formularzach, tekst jest widoczny tylko wtedy gdy pole jest puste) @strings/typeSomething i przycisk o id „change” z napisem @strings/change.

Wszystko wygląda tak jak powinno teraz czas na przeróbki kodu Java.

2. Java

setContentView(R.layout.main) spowodowało przypisanie naszemu Activity layoutu z pliku main.xml, teraz na pomocą metody findViewById(int id) możemy dobierać się do poszczególnych elementów layoutu.

W tym miejscu musi się pojawić krotka dygresja ;) Czym jest „int id”? Wtyczka ADT do Eclipse przy każdym zapisaniu pliku xml aktualizuje na jego podstawie plik gen/PACKAGENAME/R.java, którego nie powinniśmy w żadnym wypadku edytować ręcznie. w tym pliku edytowane są id wszystkich elementów layoutu, stringów, obrazków itd. (wszystkiego co znajduje się w katalogu res). Nie chcę zagłębiać się w szczegóły, bo mogę powiedzieć coś głupiego, ale twórcy androida zrobili coś takiego w celu ogólnego przyspieszenia działana apikacji (czytanie plików XML byłoby zbyt wolne).

Chcemy spowodować, żeby po kliknięciu na przycisk wywoływana była odpowiednia akcja. Filozofia obsługi elementów GUI w Androidzie jest taka sama jak w zwykłej Javie, więc nasz przycisk mus mieć dodany ActionListener, a w naszym przypadku dokładnie OnClickListener.

Dodajemy więc w pliku HelloAndroid.java (za setContentView):

((Button)findViewById(R.id.change)).setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View arg0) {
    // Tu musimy przeczytać zawartość pola @id/field i wpisać do @id/hello
  }
});

Po kliknięciu na przycisk program wykona to co będzie w przeciążonej metodzie onClick naszego OnCLickListenera.

Weby dostać się do pola EditText i TextView tak samo musimy uzyc findViewById i użyć odpowiednich metod.

String tekst = ((EditText)findViewById(R.id.field)).getText().toString();
((TextView)findViewById(R.id.text)).setText(tekst);

Kod kompletnego HelloAndroid.java:

package pl.skyman.tutorial.helloandroid;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
public class HelloAndroid extends Activity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ((Button)findViewById(R.id.change)).setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View arg0) {
        String tekst = ((EditText)findViewById(R.id.field)).getText().toString();
        ((TextView)findViewById(R.id.text)).setText(tekst);
      }
    });
  }
}

Źródła kompletnego projektu Eclipse HelloAndroid.zip

  • Wykop
  • Facebook
  • Twitter

7 Komentarzy

  1. bebe on Wrzesień 12th, 2009

    Świetny pomysł na artykuł, dzięki! :) Niestety, WP Syntax zjadł XMLe. ;)

  2. skyman on Wrzesień 12th, 2009

    A tyle się z nim męczyłem… Swoją drogą zna ktos jakiś wygodny sposób na wrzucanie kodów no wpisów w WP?

  3. bebe on Wrzesień 13th, 2009

    Ja używam CodeColorer. Jest mało wygodny i trochę przekombinowany, ale efekt jest ok. Szczegóły tu: http://kpumuk.info/projects/wordpress-plugins/codecolorer/

  4. skyman on Wrzesień 13th, 2009

    Instalując CodeCororer’a znalazłem WP-Syntax Button i wygląda na to, że załatwia większość problemów… (This plugin also corrects a disagreement when switching editor mode.)

  5. justyn on Wrzesień 23rd, 2009

    Ciekawy przykład.Super dal poczatkującego.
    Przeczytałem z wielka satysfakcją.
    Dobra robota.

  6. Keph on Styczeń 4th, 2010

    Takie pytanie, bo mnie to gryzło odkąd zacząłem się bawić w programowanie Androida: co oznacza ten plusik w XMLu, około „@ id/cośtam”?

    Czy to jest po prostu oznaczenie? Jeśli tak, czemu np. „@string” czegoś takiego nie ma?

    Czy to oznacza dopięcie jakichś wewnętrznych, androidowych elementów? Jeśli tak, jakich? Da się z tym coś fajnego zrobić?

    Coś jeszcze innego? Tylko co?

    Ech, zagadki ;)

  7. skyman on Styczeń 4th, 2010

    Ciężkie pytanie…
    Szczerze mówiąc dopiero po Twoim pytaniu dokładnie sprawdziłem o co chodzi i wygląda na to, że jest to kolejna mała androidowa głupota (może trochę za ciężkie słowo).

    Plusa „+” trzeba użyć wtedy gdy dane id nie było nigdy wcześniej zdefiniowane. Ciężko określić co to znaczy „wcześniej”. Na pewno wcześniej zdefiniowanymi id są te z bazowych layoutów androida @android:id/text, @android:id/list, @android:id/empty (używane na przykład w layoutach których „klasa obsługująca” dziedziczy po TextView albo ListView). Nie wiem czy jeśli mamy to samo „własne” (nie z @android) id w kilku layoutach to trzeba używać plusa czy nie (dla pewności zawsze używam, ale być może powoduje to zbędne tworzenie dodatkowych haszy dla id). Nie do końca rozumiem dlaczego np. ADP parsując pliki layoutów samo nie rozstrzyga czy traktować id jako nowe czy nie.

    Dokładne źródło: http://developer.android.com/guide/topics/ui/declaring-layout.html#id

Twój komentarz

Tagi

android autobuser cron google java linux python sieć sms test

linki