Java » Java ME

Absolutne początki - część 2

Kontynuacja artykułu J2ME - Absolutne początki

Z poprzedniej części kojarzysz pewnie kod:
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.*;
 
public class PierwszyProgram extends MIDlet
{
 public PierwszyProgram()
 {
   Form forma = new Form ("Pierwszy program");
   forma.append ("To jest pierwszy program :-]");
 
   Display ekran = Display.getDisplay (this);
   ekran.setCurrent (forma);
 }
 public void startApp()
 {
  // kod wykonywany przy starcie oraz przy wznowieniu
 }
 public void pauseApp()
 {
  // kod wykonywany przy wstrzymaniu
 }
 public void destroyApp (boolean unconditional)
 {
  // kod wykonywany przy zamykaniu
 }
}

Kod niby działa w emulatorze, ale po wysłaniu pliku .jar na telefon okazuje się, że nie wszystko jest tak, jak powinno być. Spróbuj zamknąć tą aplikację. Niestety, jedyny sposób na jej zakończenie to przytrzymać klawisz Esc (ewentualnie za pomocą menu czynności) i brutalnie "zabić" program. Taki sposób zamykania oczywiście nas nie satysfakcjonuje. Przydałaby się możliwość zamknięcia aplikacji w bardziej cywilizowany sposób, i to będzie właśnie przedmiotem niniejszego artykułu.

CommandListener i spółka


Prawie wszystkie telefony posiadają przynajmniej dwa klawisze wielofunkcyjne, z angielska zwane softkeyami. Mogą one przyjmować dowolne funkcje, zależnie od kontekstu. W menu jeden z nich zwykle posiada opis Wybierz, drugi jeszcze coś innego. Za pomocą Javy możemy zagospodarować te klawisze w obrębie aplikacji w dowolny sposób.

Pierwszy krok - zmieniamy nieco definicję klasy. Mamy coś takiego:
public class PierwszyProgram extends MIDlet

Dopisujemy do tej definicji dołączenie interfejsu CommandListener. Zatem linijka ta wygląda następująco:
public class PierwszyProgram extends MIDlet implements CommandListener


Deklaracja interfejsu CommandListener wymusza na nas zdefiniowanie pewnej funkcji. W interfejsie tym zadeklarowana jest abstrakcyjna metoda commandAction. Wypełnienie jej treścią należy do zadań programisty. Dodajemy zatem jej definicję w którymkolwiek miejscu (oczywiście nie w środku jakiejś innej metody):
 public void commandAction (Command c, Displayable s)
 {
 }

Po tej operacji kod znów jest poprawny, ale program niczego nowego nie robi. Zatem piszemy dalej...

Krok drugi - definiujemy polecenie i od razu dołączamy je do formatki. Do konstruktora dopisujemy:
Command komenda_wyjscie = new Command ("Zakończ",Command.EXIT,0);
forma.addCommand (komenda_wyjscie);


Program jeszcze musi wiedzieć, która klasa ma obsługiwać polecenia. W naszym przypadku klasą tą jest klasa główna MIDletu - to do niej dołączyliśmy interfejs CommandAction. Dlatego dopisujemy jeszcze jedną instrukcję:
forma.setCommandListener (this);


Krok trzeci - definiujemy zachowanie naszego MIDletu po odebraniu polecenia. Wcześniej dołożyliśmy metodę commandAction, teraz czas na jej zagospodarowanie. W ciele metody wpisujemy:
if (c.getCommandType() == Command.EXIT) notifyDestroyed();


Zapisujemy program, uruchamiamy go i testujemy. Teraz możemy już zamknąć program w cywilizowany sposób, nawet po wrzuceniu go na telefon.

Oto pełny kod naszego programu:
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.*;
 
public class PierwszyProgram extends MIDlet implements CommandListener
{
 public PierwszyProgram()
 {
   Form forma = new Form ("Pierwszy program");
   forma.append ("To jest pierwszy program :-]");
 
   Display ekran = Display.getDisplay (this);
   ekran.setCurrent (forma);
 
   Command komenda_wyjscie = new Command ("Zakończ",Command.EXIT,0);
   forma.addCommand (komenda_wyjscie);
   forma.setCommandListener (this);
 
 }
 public void startApp()
 {
  // kod wykonywany przy starcie oraz przy wznowieniu
 }
 public void pauseApp()
 {
  // kod wykonywany przy wstrzymaniu
 }
 public void destroyApp (boolean unconditional)
 {
  // kod wykonywany przy zamykaniu
 }
 
 public void commandAction (Command c, Displayable s)
 {
  if (c.getCommandType() == Command.EXIT) notifyDestroyed();
 }


O formatowaniu słów kilka


Powyższy kod jest napisany w taki sposób, aby każdy widział, o co w nim chodzi. Warto jednak wiedzieć, że mamy pełną dowolność stosowania znaków nowej linii. W zasadzie wszędzie, gdzie możemy wstawić spację, możemy postawić również łamanie linii. Zatem zapisy
public class PierwszyProgram extends MIDlet implements CommandListener

oraz
public 
  class PierwszyProgram 
  extends MIDlet 
  implements CommandListener

są sobie równoważne. Podobnie trzy definicje:
 public void startApp()
 {
 }
 public void pauseApp()
 {
 }
 public void destroyApp (boolean unconditional)
 {
 }

możemy bez bólu odchudzić do postaci:
public void startApp() { }
public void pauseApp() { }
public void destroyApp (boolean unconditional) { }


Jeszcze o poleceniach


Konstruktor klasy Command przyjmuje trzy parametry:
Command (String podpis, int typ, int priorytet)
Pierwsza zmienna nie wymaga żadnych wyjaśnień - jest to napis, jakim dane polecenie się legitymuje. Zmienna typ służy do określenia, jaki typ polecenia definiujemy. Pozwala to urządzeniu wyświetlić komendę w specjalny sposób. My użyliśmy stałej Command.EXIT, w tym wypadku jest najbardziej pasująca. Warto jednak wiedzieć, że są inne:
  • Command.OK
  • Command.BACK
  • Command.ITEM
  • Command.CANCEL
  • Command.EXIT
  • Command.HELP
  • Command.SCREEN
  • Command.STOP
Trzecie polecenie - priorytet, służy do określenia kolejności poleceń. Jeżeli liczba poleceń przewyższa ilość przycisków funkcyjnych, reszta poleceń pojawi się jako menu dostępne pod jednym z przycisków. Parametr priorytet pozwala ustalić kolejność elementów na tak stworzonej liście. Polecenie o wyższym priorytecie jest tym, który ma wpisaną tutaj mniejszą liczbę. Liczby te oczywiście nie muszą iść po kolei.

W metodzie commandAction pobieramy typ i priorytet polecenia za pomocą odpowiednio metod getCommandType() i getPriority() obiektu klasy Command (możemy go w deklaracji metody nazwać dowolnie, byle był klasy Command). Pozwoli nam to odróżnić odebrane polecenia.

Polecenia dodajemy do obiektu dziedziczącego po klasie Displayable (a więc Form, ale także np. Canvas czy TextBox) za pomocą metody addCommand (Command c). Analogicznie możemy go stamtąd usunąć za pomocą metody removeCommand (Command c).

W naszym przypadku umieściliśmy obsługę poleceń wewnątrz bieżącej klasy. Nic nie stoi na przeszkodzie by stworzyć do tego celu osobną klasę. Jedynym wymaganiem jest zaimplementowanie w niej interfejsu CommandListener. W prostych zastosowaniach wystarczy jednak umieścić obsługę poleceń w klasie głównej - tak też zrobiliśmy w naszym kodzie.

2 komentarze

Crackers 2008-11-08 09:32

nie wiem czego ale mi ten kod nie działa a mam wszystko poprawni tak jak tu autor powyżej napisał

Bru2s 2008-02-19 00:15

Super mam nadzieje, że wyjdzie z tego cała seria artów...fatalbomb czekam na więcej ;)