PUM
Transkrypt
PUM
Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i Podstawy tworzenia aplikacji z wykorzystaniem języka Java ME ćwiczenia 3 Wykorzystanie klasy List do tworzenie menu • • Klasa List - tworzenie list wyboru (EXCLUSIVE, MULTIPLE, IMPLICIT) Dodatkowe możliwości (dodatkowe komendy, pliki graficzne itp.) Przykładowa aplikacja import javax.microedition.midlet.MIDlet; import javax.microedition.lcdui.*; import java.io.*; public class MenuLista extends MIDlet implements CommandListener { private Display dp; // wykorzystanie klasy List (3 listy: menu główne + listy wyboru) private List mainMenu, samochodyLista, plytyLista; // wykorzystanie klasy Form (formularz w ustawieniach) private Form formularz; // wykorzystanie klasy TextField (pole tekstowe w formularzu) private TextField tf; 1 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i // wykorzystanie klasy Alert (informacje o programie) private Alert info; // wykorzystanie klasy Command (polecenie OK na ekranach) private Command oKCommand; // wykorzystanie klasy Image (obrazki w menu głównym i na listach); private Image samochod, plyta, konfiguracja, informacja, wyjscie; public MenuLista() { // utworzenie menu głównego aplikacji (wykorzystanie listy typu IMPLICIT) mainMenu = new List("Menu aplikacji", List.IMPLICIT); // utworzenie obrazków z plików znajdujących się w katalogu res try { samochod = Image.createImage("/car.png"); plyta = Image.createImage("/cd.png"); konfiguracja = Image.createImage("/settings.png"); informacja = Image.createImage("/info.png"); wyjscie = Image.createImage("/exit.png"); } catch (IOException e) { System.out.println("Brak obrazka!"); } // dodanie kolejnych pozycji menu (drugi parametr obiekt klasy Image) mainMenu.append("Samochody", samochod); mainMenu.append("Płyty CD", plyta); mainMenu.append("Konfiguracja", konfiguracja); mainMenu.append("Informacja o programie", informacja); mainMenu.append("Wyjście", wyjscie); // ustawienie nasłuchiwacza (bieżąca klasa) mainMenu.setCommandListener(this); // utworzenie polecenia OK oKCommand = new Command("OK", Command.OK, 0); // utworzenie listy samochodów (wykorzystanie listy typu EXCLUSIVE) i dodanie // pozycji samochodyLista = new List("Wybierz samochód", List.EXCLUSIVE); samochodyLista.append("Fiat Panda", samochod); samochodyLista.append("Ford Mondeo", samochod); samochodyLista.append("Seat Leon", samochod); samochodyLista.append("Skoda Fabia", samochod); // dodanie do listy samochodów polecenia OK samochodyLista.addCommand(oKCommand); // ustawienie nasłuchiwacza (bieżąca klasa) samochodyLista.setCommandListener(this); // utworzenie listy płyt CD (wykorzystanie listy typu MULTIPLE) i dodanie pozycji plytyLista = new List("Zaznacz płyty", List.MULTIPLE); plytyLista.append("Dire Straits - Brothers in Arms", plyta); plytyLista.append("Pink Floyd - Dark Side of The Moon", plyta); plytyLista.append("Guns n' Roses - Use your Illusion", plyta); plytyLista.append("Queen - Innuendo", plyta); plytyLista.append("Led Zeppelin - IV", plyta); // dodanie do listy płyt CD polecenia OK 2 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i plytyLista.addCommand(oKCommand); // ustawienie nasłuchiwacza (bieżąca klasa) plytyLista.setCommandListener(this); // utworzenie formularza formularz = new Form("Konfiguracja"); // utworzenie pola tekstowego tf = new TextField("Załóż hasło", null, 20, TextField.ANY); // dodanie pola tekstowego formularz.append(tf); // dodanie do formularza polecenia OK formularz.addCommand(oKCommand); // ustawienie nasłuchiwacza (bieżąca klasa) formularz.setCommandListener(this); // pobranie referencji do obiektu Display dp = Display.getDisplay(this); } public void startApp() { // ustawienie ekranu głównego (menu główne) dp.setCurrent(mainMenu); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } public void commandAction(Command c, Displayable d) { // sprawdzenie czy wystąpiło polecenie wyboru z listy i jesteśmy w głównym menu if (c == List.SELECT_COMMAND && d == mainMenu) { // pobranie indeksu wybranej pozycji int indeks = mainMenu.getSelectedIndex(); // pobranie tekstu związanego z wybraną pozycją String akcja = mainMenu.getString(indeks); // obsługa pozycji menu (sprawdzanie akcji ze Stringiem) if (akcja.equals("Wyjście")) { // zakończenie pracy midletu destroyApp(true); notifyDestroyed(); } else if (akcja.equals("Samochody")) { // ustawienie głównego ekranu na listę samochodów dp.setCurrent(samochodyLista); } else if (akcja.equals("Płyty CD")) { // ustawienie głównego ekranu na listę płyt CD dp.setCurrent(plytyLista); } else if (akcja.equals("Konfiguracja")) { // ustawienie głównego ekranu na formularz dp.setCurrent(formularz); } else if (akcja.equals("Informacja o programie")) { 3 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i // utworzenie obiektu klasy Alert Alert al = new Alert("Informacje","Autor: Jan Kowalski\nWersja: 0.666alfa\n", informacja, AlertType.INFO); // czas na jaki ma się wyświetlić okno alertu (milisekundy) al.setTimeout(3000); // ustawienie głównego ekranu na nasz alert, a po upływie czasu na menu // główne dp.setCurrent(al, mainMenu); } } // obsługa polecenia OK (powrót do menu głównego) else if (c == oKCommand) { dp.setCurrent(mainMenu); } } } Zapis danych w pamięci urządzeń mobilnych • • Wykorzystanie RMS (Record Management System) o pakiet javax.microedition.rms o klasa RecordStore (zarządzanie zbiorami i rekordami) utworzenie obiektu klasy RecordStore RecordStore rs = RecordStore.openRecordStore("baza", true); • • operacje na zbiorze (dodawanie rekordów, modyfikacja, usuwanie) zamknięcie otwartego zbioru rs.closeRecordStore(); Przykładowa aplikacja Zadaniem aplikacji ma być tworzenie i przechowywanie notatek tekstowych. import import import import javax.microedition.midlet.MIDlet; javax.microedition.lcdui.*; javax.microedition.rms.*; java.io.*; public class Kajet extends MIDlet implements CommandListener { // wykorzystanie klasy Display private Display dp; // wykorzystanie klasy List (menu główne, menu z notatkami) private List mainMenu, listaNotek; // wykorzystanie klasy TextBox (dodawanie i wyświetlanie notatek) private TextBox tb, tbf; // wykorzystujemy klasę RecordStore do zapisu danych w pamięci urządzenia private RecordStore rs; // wykorzystanie klasy Command (polecenie powrotu i zapisywania) 4 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i private Command backCommand, saveCommand, backListCommand; // tablica przechowująca notki String[] notki; // konstruktor public Kajet() { try { // otwieramy zbiór z rekordami (jeśli nie istnieje zostanie utworzony) rs = RecordStore.openRecordStore("Notatki", true); } catch (RecordStoreException e) { System.out.println ("Problem z RMS"); } mainMenu = new List("Kajet", List.IMPLICIT); mainMenu.append("Nowa notka", null); mainMenu.append("Lista notek", null); mainMenu.append("Wyjście",null); mainMenu.setCommandListener(this); backCommand = new Command("Wróć", Command.BACK, 0); backListCommand = new Command("Wróć", Command.BACK, 0); saveCommand = new Command("Dodaj", Command.SCREEN, 1); tb = new TextBox("Nowy wpis", null, 320, TextField.ANY); tb.addCommand(backCommand); tb.addCommand(saveCommand); tb.setCommandListener(this); dp = Display.getDisplay(this); } public void startApp() { dp.setCurrent(mainMenu); } public void pauseApp() { } public void destroyApp(boolean unconditional) { try { // zamknięcie zbioru z danymi rs.closeRecordStore(); } catch (RecordStoreException e) { System.out.println ("Nie można zamknąć RMS"); } } 5 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i public void commandAction(Command c, Displayable d) { // sprawdzenie czy wystąpiło polecenie wyboru z listy i jesteśmy w głównym menu if (c == List.SELECT_COMMAND && d == mainMenu) { // pobranie indeksu wybranej pozycji int indeks = mainMenu.getSelectedIndex(); // pobranie tekstu związanego z wybraną pozycją String akcja = mainMenu.getString(indeks); // obsługa pozycji menu (sprawdzanie akcji ze Stringiem) if (akcja.equals("Wyjście")) { // zakończenie pracy midletu destroyApp(true); notifyDestroyed(); } else if (akcja.equals("Nowa notka")) { // wyczyszczenie zawartości pola tekstowego tb.setString(null); // ustawienie głównego ekranu na nowy wpis dp.setCurrent(tb); } else if (akcja.equals("Lista notek")) { // utworzenie listy notek listaNotek = new List("Lista notek", List.IMPLICIT); try { // wyliczenie wszystkich rekordów RecordEnumeration re = rs.enumerateRecords(null, null, false); // zmienna pomocnicza int i = 0; // tworzymy tablicę Stringów z notkami o rozmiarze takim jak // liczba rekordów notki = new String[re.numRecords()]; // przechodzimy przez wszystkie rekordy w naszym zbiorze while(re.hasNextElement()){ // odczytujemy rekord byte[] record = re.nextRecord(); // tworzymy strumien danych wejściowych ByteArrayInputStream raw = new ByteArrayInputStream(record); DataInputStream in = new DataInputStream(raw); // odczytujemy notkę String notka = in.readUTF(); // wpisujemy notkę do tablicy notki[i] = notka; i++; // tworzymy krótką wersję notki do pokazania na liście notka = notka.substring(0, (notka.length()) > 40 ? 40 : notka.length()) + "..."; listaNotek.append(notka, null); 6 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i // zamykamy strumień danych wejściowych in.close(); } } catch (IOException e) { System.out.println ("Bład wejścia/wyjścia"); } catch (RecordStoreException e) { System.out.println ("Błąd zapisu RMS"); } // dodajemy polecenie powrotu do głównego menu listaNotek.addCommand(backCommand); // ustawiamy nasłuchiwacza na bieżącą klasę listaNotek.setCommandListener(this); // ustawienie głównego ekranu na listę notek dp.setCurrent(listaNotek); } } // obsługa listy notek, po wybraniu notki pokazujemy jej całą treść else if (c == List.SELECT_COMMAND && d == listaNotek) { // tworzymy pole tekstowe z zawartością odpowiedniej notki pobranej z tablicy // notek tbf = new TextBox("Pełny tekst", notki[listaNotek.getSelectedIndex()], 320, TextField.UNEDITABLE); // dodajemy polecenie powrotu na listę notek tbf.addCommand(backListCommand); // ustawiamy nasłuchiwacz tbf.setCommandListener(this); // ustawiamy bieżący ekran na nasze pole z pełną treścią notki dp.setCurrent(tbf); } // obsługa polecenia BACK (powrót do menu głównego) else if (c == backCommand) { dp.setCurrent(mainMenu); } // obsługa polecenia BACK (powrót do menu z listą notek) else if (c == backListCommand) { dp.setCurrent(listaNotek); } // obsługa polecenia zapisz else if (c == saveCommand) { // tworzymy strumień danych wyjściowych ByteArrayOutputStream arrayStream = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(arrayStream); try { // wpisujemy dane pobrane z pola tekstowego do strumienia out.writeUTF(tb.getString()); // tworzymy tablice bajtów byte[] data = arrayStream.toByteArray(); // dodajemy rekord rs.addRecord(data, 0, data.length); 7 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i // zamykamy strumień out.close(); } catch (IOException e) { System.out.println ("Bład wejścia/wyjścia"); } catch (RecordStoreException e) { System.out.println ("Błąd zapisu RMS"); } // ustawiamy bieżący ekran na główne menu dp.setCurrent(mainMenu); } } } Połączenie z internetem Wszystkie aplikacje mobilne umożliwiają obsługę połączeń sieciowych za pomocą prostego API będącego składową GFC (Generic Connection Framework). Obsługiwane protokoły to http oraz https. Pakiet javax.microedition.io zawiera większość klas związanych z GFC. Nawiązanie połączenia to wykorzystanie jednej z metod open dostępnych w klasie Connector. Dostęp do danych z sieci jest możliwy w następujący sposób: String url = "http://strona.pl/index.html"; HttpConnection c = (HttpConnection) Connector.open(url); InputStream in = c.openInputStream(); // in.read() ...odczyt danych 8 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i Przykładowa aplikacja (pobieranie kursu USD z witryny NBP) import import import import javax.microedition.lcdui.*; javax.microedition.midlet.MIDlet; javax.microedition.io.*; java.io.*; public class PobieranieDanych extends MIDlet implements CommandListener { // wykorzystanie klasy TextBox (okno tekstowe) private TextBox tb; // wykorzystanie klasy Command (obsługa komend) private Command exitCommand; // wykorzystanie klas HttpConnection (połączenie po http) oraz InputStream (obsługa // strumienia wejściowego) private HttpConnection c; private InputStream is; // wykorzystanie klasy StringBuffer (dynamiczny łańcuch tekstowy) private StringBuffer sb; public PobieranieDanych () { // tworzymy obiekt klasy StringBuffer sb = new StringBuffer(); try { // łączymy się ze stroną NBP c = (HttpConnection) Connector.open("http://nbp.pl/Kursy/KursyA.html", Connector.READ, true); // otwieramy strumień danych wejściowych is = c.openInputStream(); int ch=0; // odczytujemy wszystkie dane (-1 koniec danych) oraz dodajemy je do // łańcucha tekstowego while ((ch = is.read()) != -1) { sb.append((char) ch); } } catch (IOException x){ System.out.println ("Błąd wejścia wyjścia"); } finally { try { is.close(); c.close(); } catch (IOException x) { System.out.println ("Błąd wejścia wyjścia"); } } 9 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i // zamieniamy obiekt klasy StringBuffer na String (potrzebujemy kilku metod) String wyn = sb.toString(); // wyszukujemy ciągu znaków USD int i = wyn.indexOf("USD"); // szukamy aktualnegoo kursu USD i = i + 26; // wycinamy kurs (ciągle będzie to łańcuch tekstowy) String wartosc = wyn.substring(i, i + 6); // zamieniamy , na . wartosc = wartosc.replace(',','.'); // konwertujemy String z kursem na zmienną typu float float kurs = Float.parseFloat(wartosc); // tworzymy nowy obiekt klasy TextBox wraz z aktualnym kursem tb = new TextBox("Aktualny kurs USD", "USD: " + kurs, 100, TextField.ANY); // tworzymy nowe polecenie exitCommand = new Command("Zakończ", Command.EXIT, 0); // dodajemy polecenie do pola tekstowego tb.addCommand(exitCommand); // wskazujemy obiekt obslugujacy zdarzenia tb.setCommandListener(this); } public void startApp() { // ustawiamy ekran poczatkowy Display.getDisplay(this).setCurrent(tb); } public void pauseApp() { } public void destroyApp(boolean u) { } // ciało metody z interfejsu CommandListener public void commandAction(Command c, Displayable d) { // obsluga polecenia exitCommand (kończymy działanie aplikacji) if (c == exitCommand) { destroyApp(true); notifyDestroyed(); } } } Wysyłanie tekstu Java ME udostępnia prostą komunikację tekstową i multimedialną za pomocą Wireless Messaging API (WMA). WMA bazuje na GFC (Generic Connection Framework). Pakiet javax.wireless.messaging zawiera większość klas i metod potrzebnych do takiej 10 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i komunikacji. Wysłanie bądź też odebranie połączenia to utworzenie obiektu klasy MessageConnection oraz wypełnienie treści wiadomości i jej wysłanie. Poniżej prosty przykład wysyłania wiadomości tekstowej (SMS): import import import import import javax.microedition.lcdui.*; javax.microedition.midlet.MIDlet; javax.microedition.io.*; java.io.*; javax.wireless.messaging.*; /** * MIDlet: WysylanieSMS * Klasy główne: TextBox, Alert (dziedziczące z klasy Screen) */ public class WysylanieSMS extends MIDlet implements CommandListener, Runnable { // wykorzystanie klasy TextBox (okno tekstowe) private TextBox tb; // wykorzystanie klasy Command (obsługa komend) private Command exitCommand, sendCommand; // wykorzystanie klasy Display private Display dp; public WysylanieSMS() { tb = new TextBox("Wpisz tekst", null, 160, TextField.ANY); // tworzymy nowe polecenia (polecenia związane z aplikacją mają typ // Command.SCREEN) exitCommand = new Command("Zakończ", Command.EXIT, 0); sendCommand = new Command("Wyślij SMS", Command.SCREEN, 1); // dodajemy polecenia do pola tekstowego tb.addCommand(exitCommand); tb.addCommand(sendCommand); // wskazujemy obiekt obslugujacy zdarzenia tb.setCommandListener(this); dp = Display.getDisplay(this); } public void startApp() { dp.setCurrent(tb); } public void pauseApp() { } public void destroyApp(boolean u) { } // ciało metody z interfejsu CommandListener public void commandAction(Command c, Displayable d) { // obsluga polecenia exitCommand (kończymy działanie aplikacji) if (c == exitCommand) { destroyApp(true); notifyDestroyed(); 11 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i } // obsluga polecenia infoCommand (wyświetlenie informacji użytkownikowi) if (c == sendCommand) { // tworzymy nowy wątek Thread t = new Thread(this); // startujemy wątek t.start(); // tworzymy obiekt klasy Alert wraz z odpowiednimi danymi Alert al = new Alert("Informacja", "Wysłałeś SMS", null, AlertType.INFO); // ustawiamy czas (podany w ms) przez jaki Alert ma być // wyświetlany al.setTimeout(2000); // wyświetlamy Alert oraz wskazujemy na ekran, który ma zostać // wyświetlony po zamknięciu Alerta dp.setCurrent(al, tb); } } public void run() { MessageConnection mc = null; // Inbox telefonu komórkowego nie podajemy portu String cs = "sms://+5550001"; try { // tworzymy połączenie mc = (MessageConnection) Connector.open(cs); // tworzymy nową wiadomość tekstową TextMessage tm = (TextMessage) mc.newMessage(MessageConnection.TEXT_MESSAGE); // ustawiamy treść wiadomości tm.setPayloadText(tb.getString()); // wysyłamy mc.send(tm); } catch (IOException ioe) { System.out.println ("Bład wejścia/wyjścia"); } // sprawdzamy czy połączenie zostało otwarte if (mc != null) { try { // zamykamy połaczenie mc.close(); } catch (IOException ioe) { System.out.println ("Błąd wejścia/wyjścia"); } } } } 12 Programowanie urządzeń mobilnych Podst a wy t wo rzen ia a pl ik acj i Zadania 1. Uruchom MIDlet z listą jako menu. Zmień pliki graficzne, dodaj nowe pozycje w poszczególnych listach. 2. Zapoznaj się z działaniem MIDletu Kajet. Dodaj ikony do poszczególnych pozycji menu. Zastanów się jak rozbudować funkcjonalność aplikacji (usuwanie notek, aktualizacja). Wprowadź modyfikacje. 3. Uzupełnij MIDlet PobieranieDanych o nowe waluty (EUR, GPB itd.). Zastanów się jak przechowywać dane w pamięci urządzenia. Zaprojektuj MIDlet przechowujący kursy kilku walut wraz z ich datami. 4. Napisz aplikację umożliwiającą wysyłanie SMS'ów, ich archiwizację (folder wysłane). Program ma mieć możliwość tworzenia SMS'ów przeznaczonych do wysłania później (folder wersje robocze/do wysłania). 13