28 września 2011

Układ w Androidzie - jedno słowo, dwa znaczenia

3 komentarzy
Trafiłem na pokaźne źródło wiedzy nt. Androida - serwis mobiletuts+, a tam trzy serie artykułów - Android User Interface Design, Android Fundamentals oraz Android Essentials. Poza tym wiele dodatkowych artykułów spoza tych serii, a wszystkie wydają się być pisane zrozumiale i przede wszystkim zwięźle. Wszystko jedynie za koszt Twojego czasu.

Czytając Android User Interface Design: Layout Basics zrozumiałem, a właściwie napisano, że layout (układ, rozkład) może oznaczać dwie rzeczy w Androidzie - plik XML z rozkładem elementów wizualnych w katalogu res/layout lub klasę, która odpowiada za pożądany rozkład, odpowiadającej elementowi we wspomnianym pliku XML. Dzięki temu możemy wszystko oprogramować, albo obsłużyć deklaratywnie, wynosząc do pliku XML.

Weźmy na przykład układ formatki, z której korzystam do wprowadzenia lokaty w Lokatniku - res/layout/deposit.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <TextView
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/deposit_name"></TextView>
  <EditText
    android:id="@+id/editText1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <requestfocus></requestFocus>
  </EditText>
  <TextView
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/bank_name"></TextView>
  <EditText
    android:id="@+id/editText2"
    android:layout_height="wrap_content"
    android:layout_width="161dp"></EditText>
  <TextView
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:id="@+id/textView3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/procent_text"></TextView>
  <EditText
    android:id="@+id/editText3"
    android:layout_height="wrap_content"
    android:inputType="number"
    android:layout_width="160dp"></EditText>
  <TextView
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:id="@+id/textView4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/amount_text"></TextView>
  <EditText
    android:id="@+id/editText4"
    android:layout_height="wrap_content"
    android:inputType="number"
    android:layout_width="158dp"></EditText>
  <LinearLayout
    android:id="@+id/linearLayout1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <Button
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:text="@string/save_label"
      android:id="@+id/save"></Button>
    <Button
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:text="@string/discard_label"
      android:id="@+id/discard"></Button>
  </LinearLayout>
</LinearLayout>
Plik układu deposit.xml korzysta z elementu LinearLayout, którego javowym odpowiednikiem jest klasa android.widget.LinearLayout. I tak dla każdego elementu.

Podczas uruchomienia mamy taki oto efekt:


Budowanie układu może być bardzo zajmującym zajęciem, więc warto wesprzeć swoje wysiłki korzystając z dedykowanego edytora w Eclipse ADT - Eclipse layout resource designer (aczkolwiek dochodzą mnie słuchy, że nie jest to najbardziej wyrafinowane, a przez to i pomocne, narzędzie). Dla mnie, do tej pory, narzędzie spełnia pokładane w nim nadzieje i choćby dla celów poznawczych zwykle od niego zaczynam budowanie układu. Poniżej graficzna reprezentacja powyższego pliku XML w edytorze Eclipse.


Z ostatnimi zmianami w aplikacji Lokatnik (dostępna w repo na githubie) przygotowałem sobie przyczułek do zapisu lokat do lokalnej bazy danych, a to oznacza, że nadeszła pora popróbować się z SQLite. Już nie mogę się doczekać!

27 września 2011

Zapiski z trzeciej części "Hello, Android" - "Beyond the Basics"

0 komentarzy
W Zapiski z pierwszej części "Hello, Android" oraz Zapiski z drugiej części "Hello, Android" przedstawiłem swoje spojrzenie na zawartość dwóch pierwszych części "Hello, Android", wydanie 3. Dzisiaj skończyłem trzecią część "Beyond the Basics".

Już wspominałem, że książka wręcz przykuwa do siebie swoją prostotą i nie zagłębia się w sztuczki i kruczki związane z danym tematem. Książka jest wprowadzeniem we wszystko, co możemy znaleźć na platformie Android bez zagłębiania się w niuanse posługiwania się daną cechą. "Poszukiwacze skarbów", czyli osoby, które co najmniej wertują książki w poszukiwaniu czegoś odkrywczego, mogą się zawieść jej zawartością, ale to może równie dobrze świadczyć, że są to osoby, które już spędziły trochę czasu z Androidem i być może jeszcze nie wiedzą dokładnie, jak on działa, ale wiedzą wystarczająco wiele o każdej z cech. Porównałbym to do mojego rozumienia roli architekta i specjalisty w IBM (pewnie w każdej innej firmie sprzedającej oprogramowanie wspomagające budowanie rozwiązań końcowych jest podobnie). Architekt posiada szeroką wiedzę, która jest stosunkowo płytka patrząc na każdy z produktów, ale wystarczająca, aby zaproponować architekturę systemu. W przeciwieństwie do architekta, specjalista wie dużo na temat wybranego produktu lub produktów, ale z pewnością będzie to podzbiór produktów, o których cokolwiek może powiedzieć architekt. Zwykłem to porównywać do wiedzy poziomej, w poprzek wielu produktów u architekta, a wiedzy pionowej w bardzo niewielu produktach, w szczególności jednego, u specjalisty. Książka "Hello, Android" jest bardzo dobrym kompedium wiedzy na temat platformy Androida dla architekta, ale zdecydowanie na niewiele się zda dla osób, które potrzebują wiedzy specjalistycznej, tej pionowej, np. podczas rozwiązywania problemu lub poszukiwaniu wiedzy tajemnej. To nie jest ten typ książki.

Już z samego tytułu można wnosić, że jej celem jest jedynie wprowadzenie, ale takie szersze, do wielu, jeśli nie wszystkich, głównych funkcjonalności oferowanych przez platformę Android. Uważam, że książka jest doskonałym wprowadzeniem dla początkujących i jeszcze przed częścią 4. "The Next Generation" śmiało mogę ją polecić wszystkim, którym marzy się zrozumienie istoty programowania w Javie na platformę Android lub samodzielnym spróbowaniem się z tematem tworzenia aplikacji androidowej.

Śmiem również twierdzić, że nie dane mi było jeszcze czytać książki, która swym rozmiarem nie przerażałaby mnie, lub nastawiała na dłuższą lekturę, a jednocześnie była na tyle bogata w treść, aby stanowić doskonały przyczułek do dalszych badań. Mógłbym nawet posunąć się do stwierdzenia, że często była zbyt przewidywalna w swojej prostocie i kiedykolwiek można byłoby spodziewać się czegoś bardziej trudnego, autor po prostu kończył rozdział proponując odnośniki do powszechnie dostępnej dokumentacji, np. tej na Android Developers.

W części trzeciej dowiadujemy się o możliwości komunikacji poza urządzenie, np. komunikacji z zewnętrznymi stronami, zabawą z JavaScript oraz użyciem usług RESTowych. Jest też dostatecznie wiele na temat SQLite i OpenGL, więc śmiało możnaby stwierdzić, że dla każdego coś dobrego. Uważam, że ta przekrojowa wiedza w książce zadowoli nawet najbardziej wybrednego czytelnika, bo choćby sam styl pisarski autora gwarantuje dobrą zabawę, nawet przy czytaniu o czymś, co już znamy. W naszym przypadku, czytanie angielskojęzycznych książek pisanych przez rodowitych anglojęzycznych już samo w sobie daje zysk, więc trudno mówić o stracie, jeśli poświęcimy tej książce trochę swojej uwagi. Ja nie mogę narzekać.

Moje nieśmiałe trudy związane z pisaniem aplikacji androidowej Lokatnik można znaleźć w repozytorium android-examples. I tu mam pytanie do znawców tematu posługiwania się gitem na GitHubie. Chciałbym stworzyć jedno repozytorium, np. android-examples z wieloma aplikacjami, np. Lokatnik czy Powitanie (czyli tak, jak jest teraz), ale nie chciałbym podczas git commit w Eclipse dla Lokatnik być informowanym o zmianach w drugim projekcie - Powitanie i vice versa. Czy jest na to rozwiązanie inne niż stworzenie dwóch oddzielnych repo?

24 września 2011

ListView w res/layout czy android.app.ListActivity?

5 komentarzy
To chyba jedno z tych pytań dotyczących zalet definiowania widoku (rozkładu elementów graficznych na ekranie) deklaratywnie jako zasób w res/layout w porównaniu z oprogramowywaniem go jako podklasa android.app.Activity.

W przykładzie Hello, Views > List View użyto tego drugiego podejścia, w którym widok w większości budowany jest w ramach podklasy android.app.ListActivity z rozkładem R.layout.list_item.

Przeglądając android.widget.ListView trafiłem na możliwość definiowania wielu elementów deklaratywnie, tak że ostatecznie moja wersja prezentuje się nieznacznie inaczej. Chciałoby się wręcz napisać lepiej, ale tutaj moja skromność bierze górę, więc pozostanę przy skromniej.
package pl.japila.android;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class ContactsActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.main);

        ListView lv = (ListView) findViewById(R.id.listView1);
        lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(getApplicationContext(), ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}
Użyty widok R.id.listView1 wygląda następująco:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/listView1"
     android:layout_height="fill_parent""
     android:layout_width="fill_parent""
     android:entries="@array/names_array"
     android:textFilterEnabled="true"
     android:clickable="true">
</ListView>
Rozumiem, że jeśli pozycje na liście są statyczne (jak w przykładzie) to android:entries (linia 6) w znaczniku ListView wystarczy. Zastanawia mnie, czy istnieje jakakolwiek przewaga użycia klasy android.app.ListActivity. Na chwilę obecną nie widzę żadnej. W końcu zawsze mogę dostać się do odpowiedniego elementu widoku przez View.findViewById() lub Activity.findViewById(), więc mogę równie wiele w obu przypadkach. Czy ktoś mógłby uchylić rąbka tajemnicy, dlaczego/kiedy powinienem stosować jedno nad drugie?

21 września 2011

Zapiski z drugiej części "Hello, Android"

1 komentarzy
Jak już pisałem w Zapiski z pierwszej części "Hello, Android", Pragmatic Programmers udostępnił mi darmową wersję "Hello, Android", wydanie 3, którą powoli acz nieprzerwanie czytam w wolnych chwilach - podczas dojazdów do/od klienta, a zwykle wieczorem. Nie sądzę, aby dane mi było całkowicie poświęcić się Androidowi, czy osiągnąć szczyty tworząc aplikacje mobilne na niego, ale frajdy jest z nim co niemiara (właśnie uzmysłowiłem sobie, że jest to mój pierwszy raz, kiedy napisałem "co niemiara" i to początkowo z błędem!). Twierdzę, że nauka Androida pomaga zrozumieć tworzenie aplikacji graficznych w ogólności, więc może przydać się również poza obszarem tworzenia aplikacji mobilnych. Poznawanie nowego, jeśli jeszcze dodatkowo podparte stosunkowo gładkim wejściem w temat, najwyraźniej sprawia mi dużo zadowolenia.

Dzisiaj skończyłem czytać 2. część zatytułowaną "Android Basics" i przyznam, że, ku mojemu ogromnemu zdumieniu, czytanie jej na S2ce bardzo przypadło mi do gustu. Obawiałem się, że będzie mi brakowało możliwości oznaczania sekcji, do których warto wrócić, podczas dalszej nauki, ale od kiedy znalazłem tę funkcję w czytniku Amazon Kindle for Android i mam dodatkowo możliwość umieszczania notatek - "zapisków na marginesie", jestem w pełni usatysfakcjonowany. Drukowanie odeszło do lamusa. Dodatkowo jest funkcja tłumaczenia słówek, co tym bardziej uzasadnia moją inwestycję (warto przypomnieć, że jest to bodaj pierwsza moja inwestycja stricte "naukowa" powyżej 1000 PLN i krążyłem koło niej przez miesiące rozważając iPhone, iPad, Kindle i właśnie smartfona z Androidem - HTC Sensation lub Samsung Galaxy S2). Chciałbym, aby dalsze inwestycje były tak udane.

Dzięki lekturze oswoiłem się z tworzeniem interfejsu użytkownika, opanowałem rozumienie znaczenia aktywności (android.app.Activity), widoków (android.view.View) i poznałem klasy android.content.Intent oraz android.widget.Toast. Poznałem AndroidManifest.xml i generowaną klasę R. Bardzo proste (żeby nie napisać prostackie) aplikacje są już w moim zasięgu. Kiedykolwiek widzę to niewielkie okienko w czytniku Google Reader, które informuje o oznaczeniu wpisu gwiazdką, już wiem, że użyto Toast. Zacząłem przyglądać się aplikacjom, które używam na S2ce, pod kątem użytych klas i jak rozwiązano komunikację pomiędzy aktywnościami (wciąż zastanawia mnie, jak napisano górną belkę w Google Reader, ale rozumiem, że wszystko w swoim czasie). W rozdziale mogłem zapoznać się z LogCat - widokiem Eclipse ADT do przeglądania zapisów w dzienniku Androida i co mnie niezwykle zaskoczyło, są tam również zapisy z fizycznego urządzenia, kiedy podłączone jest do komputera po USB. Trzeba było widzieć moją minę, kiedy poszukując wpisów z klasy android.util.Log, zobaczyłem zdarzenia o wygaszaniu ekranu, ładowaniu baterii i w ogóle niskopoziomowych zdarzeń, które fruwają po "magistrali" androidowej. Aż do rozdziału 5. "Multimedia" bawiłem się przednio.

Od rozdziału 5. "Multimedia" zacząłem się lekko nudzić. Może dlatego, że oswoiłem się trochę ze środowiskiem i gdyby narysować krzywą ilości wiedzy, jaką musiałem przyswoić względem rozdziałów, to naturalnie na początku było jej więcej i chyba była bardziej przydatna. Mimo, że daleko mi do tytułu znawcy tematu, to zdążyłem już nabrać pewności, że tytuł jest na wyciągnięcie ręki i nie jest to szczególnym wyzwaniem (czyżbym był zbyt pewny siebie?!). Ot, programowanie w Javie z nowym API. Tego doświadczyłem już wielokrotnie, więc kolejne ślęczenie nad dokumentacją, wcale mnie nie przeraża. Oczywiście, wymaga to wielu godzin spędzonych nad dokumentacją i ciągłego konfrontowania jej w praktyce, ale obawiałem się, że całe środowisko będzie wymagało całkowitej zmiany myślenia, przyzwyczajeń, czy czegoś w ten deseń. Nic bardziej mylnego. Uważam, że wybór S2ki był strzałem w dziesiątkę, bo swoimi możliwościami - ekran, procesor, pamięć - zdejmuje ze mnie karby zestawiania właściwego środowiska wykonawczego, co niejednokrotnie wpływa na ogólny pogląd sprawy i dalszej nauki. Dodatkowo, wejście w temat Androida z książką "Hello, Android" jest dopasowane na miarę. Dziękuję Bartek za pomoc! (patrz jego komentarz do wpisu Wrześniowy Android).

Rozdział 5. to omówienie sposobów na odgrywanie muzyki w tle, czy podczas wciśnięcia przycisków w aplikacji, wyświetlanie filmów i na zakończenie wprowadzenie do przechowywania stanu aplikacji w przestrzeni zarezerwowanej dla niej bezpośrednio na urządzeniu lub karcie SD. Na szczęście jest tego tyle, aby dać ogólny pogląd, bez wnikania w szczegóły. I dobrze, bo na tym etapie nie jest mi to potrzebne. Nie mogę doczekać się przedstawienia SQLite, ale to już wiem, że wcześniej zapoczątkuję wieczorną lekturą artykułu Understanding Android local data store APIs, na który dzisiaj trafiłem. Więcej na moim kanale @jaceklaskowski na twitterze. Zapraszam do nasłuchiwania.

Przy okazji, coraz częściej dochodzą do mnie głosy, że wstrzeliłem się z tym moim androidowym wrześniem w plany wielu osób, które również rozważały wejście w Androida. Super móc zamienić słowo z innymi - na blogu, Google Buzz, czy GTalku, rozumiejąc, o czym się do mnie mówi. Niesamowite uczucie wszechobecnego wsparcia i wspólnego badania tematu. Cudownie, że dzięki Androidowi mam również okazję poznać nowe osoby. Bezcenne! Pojawiła się wręcz oferta przeprowadzenia przeze mnie autorskiego szkolenia z Androida. Wszystko to sprawia, że aż się chce zintensyfikować wysiłki. Chyba złapałem falę! :)

20 września 2011

Znikające okienka z android.widget.Toast

3 komentarzy
Przykłady dostępne w zestawie Technical Resources (oznaczone Tutorial) z łatwością spełniają większość potrzeb nowicjusza w temacie tworzenia aplikacji androidowych. Pisane są przystępnym językiem, tak że bez względu na znajomość Javy, czytelnik powinien odnaleźć się w nawale informacji. Polecam!

Mam już za sobą przestudiowanie Hello World i zabrałem się za Hello Views.

Analizując przykłady trafiłem na klasę android.widget.Toast:

"A toast is a view containing a quick little message for the user."

Ku mojemu zdziwieniu klasa nie dziedziczy po android.view.View czy android.app.Activity, ale zakładam, że tworzy rodzaj Activity na potrzeby wyświetlenia komunikatu użytkownikowi. Komunikat może pochodzić z "resource" (a już miałem napisać "zasób", ale dla dobra sprawy pohamowałem się) lub podany jest jawnie (niezalecane ze względu na lokalizację aplikacji). Wywołujemy metodę statyczną Toast.makeText(Context context, CharSequence text, int duration) i pojawia się okienko z wybranym tekstem. Przypomina mi to w zastosowaniu javax.swing.JOptionPane, ale Toast znika samo (po zadanym czasie, np. przez stałą Toast.LENGTH_SHORT lub Toast.LENGTH_LONG).

W repo android-examples/Powitanie jest już wersja aplikacji z użyciem Toast.makeText() - wyświetla imię podane przez użytkownika w polu tekstowym. Wciąż nic imponującego, ale utrzymuje mnie w ciągłym kontakcie z nowym środowiskiem, a to bardzo ważne na początku.

19 września 2011

Początkowy ekran aplikacji androidowej - o intent-filter

6 komentarzy
Nie tak dawno temu zastanawiałem się nad sposobem, w jaki Android wybiera główny ekran aplikacji, co wiedziałem, że jest reprezentowane przez aktywność (ang. activity) - podklasę android.app.Activity. Każda "odsłona" widoku to kolejna aktywność na stosie wyświetlanych ekranów. Chcesz coś wyświetlić użytkownikowi, stwórz odpowiednią aktywność.

Pamiętaj: Aktywność musi być zarejestrowana w pliku konfiguracyjnym aplikacji androidowej AndroidManifest.xml przez znacznik <activity> (z jedynym wymaganym elementem android:name).

Wyświetlenie widoku odbywa się przez metodę android.content.Context.startActivity(Intent intent). Aktywność (widok, ekran) jest podklasą Context.

Aplikacja androidowa może posiadać wiele ekranów (aktywności), a wybór tego jednego, początkowego odbywa się przez znacznik <intent-filter> w ramach aktywności, w pliku AndroidManifest.xml:
<activity android:name="...">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
</activity>
Podczas tworzenia aplikacji w Eclipse ADT czy z linii poleceń z android, jesteśmy pytani o nazwę głównej aktywności, która staje się właśnie początkowym ekranem użytkownika przez określenie go z <intent-filter> w AndroidManifest.xml.

Teraz wszystko jasne. Nie mam więcej pytań. A Ty?

18 września 2011

Czym jest android.content.Intent oraz android.app.Activity?

1 komentarzy
Kiedy analizowałem aplikację na Androida, spotykałem się zwykle z klasą android.content.Intent. Wszędzie było jej pełno. Na tyle dużo, aby zwróciła moją uwagę i postanowiłem doczytać, jaka jest jej właściwie rola. Śmiem twierdzić, że jest jedną z bardziej ważnych (jeśli nie najważniejszych) klas w Androidzie.

Już pierwsze zdanie w dokumentacji javadoc dla android.content.Intent wyjaśniło znaczenie klasy:
"An intent is an abstract description of an operation to be performed."
Śmiało możemy przetłumaczyć Intent na jego najbliższy odpowiednik w polskim - zamiar, bo każdorazowe utworzenie Intent będzie wyrażało zamiar wykonania pewnej operacji. W takiej formie widziałem ją w "Hello, Android", kiedy to zamiar wyświetlenia (uruchomienia) android.app.Activity był związany ze stworzeniem obiektu Intent.

Pewnie zastanawiasz się, po co chciałbym wyświetlić Activity? I ponownie wystarczy zajrzeć do dokumentacji, aby dowiedzieć się o jej roli:
"An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View)."
Jeśli dodać, że obie klasy są częścią platformy od wersji 1.0, to staje się jasne, skąd tego tyle w aplikacjach androidowych, z którymi miałem do czynienia do tej pory (przede wszystkim podczas lektury "Hello, Android"). Najczęściej moje spotkanie z obiema klasami miało postać:
Intent i = new Intent(this, A.class);
startActivity(i);
gdzie this wskazuje na klasę dziedziczącą po android.app.Activity, a A.class nową Activity, która zostanie umieszczona na stosie ekranów prezentowanych użytkownikowi.

Pamiętajmy, że każda aktywność uruchomiona przez metodę android.content.Context.startActivity(Intent intent) musi być zarejestrowana przez w AndroidManifest.xml.

I krótka aplikacja do odpalenia na własnym smartfonie - wystarczy podać własne imię, aby pojawiło się przywitanie. Jest to ten typ aplikacji, którą moglibyśmy śmiało nazwać "Hello World". Kompletny projekt, gotowy do importu do Eclipse, znajduje się w repozytorium android-examples/Powitanie. Proszę o uwagi, które mógłyby pomóc mi w udoskonaleniu aplikacji.

A może masz pytania o Androidzie, na które mógłbym odpowiedzieć? Może sugestie, w jakim kierunku powinienem zmierzać z moim rozpoznawaniem Androida? Ten typ nauki najbardziej mi odpowiada - czytelnicy pytania, a ja odpowiedzi, albo wersja bardziej interaktywna - uczestnicy spotkania pytania, a ja w roli prelegenta z odpowiedziami. Już mnie kręci na zaprezentowanie swojej dotychczasowej wiedzy na spotkaniu Warszawa JUG. To mogłoby zachęcić przyszłych i aktualnych androidowiczów do spotkania i podzielenia się doświadczeniami. Tego mi trzeba. Niedługo (tydzień, dwa) rodzi się kolejny Laskowski i muszę zintensyfikować naukę, póki "wolny czas" to nie coś wirtualnego :-)