Prezentacja programu PowerPoint

Download Report

Transcript Prezentacja programu PowerPoint

Programowanie urządzeń mobilnych
Wykład 1
Wprowadzenie
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Układ zajęć :
Wykład:
15 godzin wykładu zorganizowane w postaci 15
jednogodzinnych wykładów
Zaliczenie/egzamin w formie pisemnej
Środa 1315-1400 Sala E2 ( WEIE )
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Układ zajęć :
Laboratorium:
15 godzin laboratoriów zoogranizowanych po dwie godziny
,co dwa tygodnie
Zaliczenie w postaci projektu
Środa 11:15 - 13:00 Sala 110 ( WEIE )
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Wykład – wykaz zagadnień:
1.
Podstawy budowy i programowania urządzeń mobilnych
(telefon komórkowy, PDA - Personal Digital Assistant)
2. Wprowadzenie do Javy MicroEdition (J2ME)
3. Grafika 2D i 3D w J2ME (API niskiego poziomu)
4. GUI w J2ME
5. Połączenia sieciowe w J2ME
6. Składowanie danych w urządzeniach mobilnych przy wykorzystaniu J2ME
7. Dystrybucja programów w J2ME
8. Programowanie i testowanie w Microsoft Mobile ASP.NET
9. Programowanie i testowanie w Symbian OS
10. Programowanie i testowanie w Adroid OS
11. Podstawy i rola Objective C w rozwiązaniach mobilnych
Laboratorium:
1.
Tworzenie oprogramowanie na telefony komórkowe w
środowisku J2ME
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Literatura:
Literatura podstawowa:
1 J2ME. Java dla urządzeń mobilnych. Ćwiczenia Krzysztof Rychlicki-Kicior
ISBN: 83- 246-0393-X Helion 2006
2 Krzysztof Rychlicki Kicior "J2ME. Praktyczne projekty"
Helion ISBN: 83-246-0597-5
3 Marek Wierzbicki "Java. Programowanie obiektowe"
Helion 2006 ISBN: 83-246- 0290-9
4 Kim Topley "J2ME. Almanach" O'Reilly ISBN: 83-7361-118-5
Literatura uzupełniająca:
1.Miller B.M., Bisdikian Ch.: Bluetooth, Helion, Gliwice, 2003.
2.White, James i Hemphill, Davies (2002) "Java 2 Micro Edition. Java in Small Things.", Manning
Publications Co., Greenwich, 2002
3. Internet
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Podstawy budowy i programowania
urządzeń mobilnych
(telefon komórkowy, PDA - Personal
Digital Assistant)
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
1.
Podstawy budowy i programowania urządzeń mobilnych (telefon komórkowy, PDA Personal Digital Assistant)
CDC(Connected Device Configuration)
Konfiguracja CDC (ang. Connected Device Configuration) jest konfiguracją środowiska Java ME
zdefiniowanych przez Java Community Process.
Konfiguracja CDC przeznaczona jest dla urządzeń wyposażonych w ok. 2048 kB pamięci i pracujących
z 32-bitowymi procesorami, czyli np. dla wideotelefonów konsol gier, zestawów audio-wideo,
PDA.
Specyfikacja znajduje się w dokumentacji JSR-36 i JSR-218. Jest ona przeznaczona dla urządzeń
posiadających:
•
stałe połączenie z siecią,
•
32 bitowy procesor,
•
minimum 512KB dostępnej pamięci ROM,
•
minimum 256KB pamięci operacyjnej RAM,
•
graficzny interfejs użytkownika.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Konfiguracja CLDC (ang. Connected Limited Device Configuration) jest bardziej ograniczoną wersją CDC
i jest zdefiniowany przez Java Community Process.
Konfiguracja CLDC jest przeznaczona dla urządzeń wyposażonych w około 512 kB pamięci i pracujących z
16- lub 32-bitowymi procesorami, czyli np. dla telefonów komórkowych, notesów elektronicznych czy
pagerów.
W stosunku do CDC , CLDC brakuje między innymi:
•obsługę działań na liczbach zmiennoprzecinkowych,
•uruchamianie kodu natywnego dzięki JNI (ang. Java Native Interface),
•obsługę słabych referencji,
•serializację obiektów,
•definiowanie przez użytkownika loaderów klas,
•obsługę mechanizmu debugowania.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
J2ME - Mobile Information Device Profile (MIDP)
MIDP jest uzupełnienie konfiguracji CLDC o odpowiednie klasy języka Java przeznaczone dla urządzeń mobilnych jak np. telefony
komórkowe. Specyfikacja MIDP jest rozwijana przez Java Community Process (JCP).
W 2000 r. udostępniono wersję 1.0.
W 2002 roku wersję 2.0 MIDP.
Programy napisane z wykorzystaniem MIDP noszą nazwę MIDletów (szerzej o MIDletach będzie mowa w dalszej części
wykładu oraz na laboratorium). Uruchamiane są w środowisku K virtual machine.
Profil MIDP zawiera bardziej rozbudowaną obsługę platformy Java niż sama konfiguracja CLDC . MIDP wymagają zatem
więcej pamięci. Specyfikacja CLDC wymaga przynajmniej 120 kB pamięci RAM (Random Accesss Memory) na przechowywanie
specyfikacji MIDP, oraz co najmniej 32 kB na stos. Oprócz tego wymaga minimum 8 kB pamięci nieulotnej,jest ona potrzebna, aby MIDlety
mogły zapisywać dane – np.. Adresy i nr telefony w przypadku MIDletu pracującego jako książka adresowa.
Urządzenia korzystające z MIDP powinny być wyposażone w ekrany umożliwiające wyświetlenie co najmniej dwóch kolorów
w rozdzielczości minimum 96 na 54 pikseli.
Oprócz tego , do komunikacji z użytkownikiem posiadać powinny jedno lub więcej następujących mechanizmów: klawiatura
telefonu, klawiatura QWERTY, ekran dotykowy.
Ich wyposażenie musi także zapewniać obsługę protokołu HTTP 1.1.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Wymagania programowe
Minimalne założenia:
•Minimalne jądro do zarządzania sprzętem (np. obsługa przerwań, wyjątków, minimalne szeregowanie). Jądro musi
zapewnić co najmniej jeden szeregowalny wątek, by uruchomić Virtualną Maszynę Javy.
•Mechanizm czytania i pisania z nieulotnej pamięci aby utrzymać API
•dostęp do czytania i pisania w bezprzewodowej sieci urzadzenia aby utrzymać API
•mechanizm zapewniający zapisywanie znaczników czasowych w rekordach zapisanych w zasobach pamięci trwałej
•minimalna zdolność do zapisywania w mapie bitowej graficznego wyświetlacza
•mechanizm przechwytujący dane z wejścia z jednego (lub więcej) z trzech urządzeń
•machanizm zarządzający cyklem życia aplikacji urządzenia
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Architektura MIDP
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Najniższy blok (MID) przedstawia poziom sprzętu urządzenia przenośnego. Jego część stanowi native system software, który zawiera system
operacyjny i biblioteki użyte przez konkretne urządzenie. Powyżej jest warstwa oprogramowania, czyli CLDC. Tutaj także znajduje się
K-Virtual Machine (KVM) oraz skojarzone biblioteki zdefiniowane przez specyfikację CLDC.
CLDC posiada dwa rodzaje API:
1. MIDP: Zbiór API zdefiniowanych przez MIDP.
2. OEM-specific: Klasy, które mają dostęp do specyficznych funkcjonalności konkretnego urządzenia. Nie zapewniają zatem przenośności
aplikacji, które z nich korzystają. Spowodowane jest to dużą różnorodnością urządzeń mobilnych, dostępnych na rynku.
Na samym szczycie znajdują się
•MIDP: Aplikacja MIDP lub MIDlet, używa tylko API zdefiniowane przez specyfikację MIDP i CLDC. Używana najczęściej, zapewnia
przenośność aplikacji.
•OEM-Specific: Aplikacje wykorzystujące specyficzne możliwości danych urządzeń. Aplikacje nie są przenośne.
•Native: rodzima aplikacja, która nie jest napisana w Javie.
Pakiety i klasy
Pakiety i klasy wchodzące w skład J2ME - MIDP:
•java.util.Timer - ułatwienie dla wątków w szeregowaniu zadań
•java.util.TimerTask - zadanie które może być szeregowane przez Timer
•javax.microedition.rms - mechanizm obsługi zasobu pamięci trwałej
•javax.microedition.midlet - definicja aplikacji MIDP, interkacji między nimi oraz środowiska w którym aplikacja działa
•javax.microedition.io - obsługa sieci oparta na CLDC
•javax.microedition.lcdui - interfejs użytkownika dla aplikacji
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Zmiany w MIDP 2.0, w stosunku do MIDP 1.0
•Rozszerzony interfejs użytkownika
Modyfikacja elementów takich jak : Popup ChoiceGroup czy Alert ekranu .
•Media Support Media Support
Dodana obsługa dźwięku w formacie .wav, oraz możliwość wykorzystania mediów strumieniowych
•Game Support
Game API to rozszerzenie zapewniające nowe możliwości twórcom gier w zakresie wykorzystania grafiki np. poprzez długo
oczekiwane sprite'y i warstwy.
•Expanded Connectivity(Rozszerzona Łączność)
Wsparcie dla standardów HTTP, HTTPS, datagramów, gniazd oraz komunikacji wykorzystującej port szeregowy.
Oprócz tego oferuje wsparcie szyfrowania transmisji za pomocą protokołów SSL, WTLS czy podpisywania midletów
certyfikatami X.509.
•Push Architecture
Model push, umożliwia przesyłanie danych z serwera do aplikacji, np aktywacje zainstalowanych na urządzeniu midletów,
przesyłanie komunikatów i powiadomień wprost do aplikacji.
•Over-the-air (OTA) Provisioning
Ttechnika instalowania, uruchamiania i aktualizacji midletów over-the-air (OTA), stała się oficjalnie częścią specyfikacji.
•End-to-end Security
Wsparcie dla technologii takich jak : HTTPS i wykorzystuje istniejące standardy, takie jak SSL, WTLS, czy
podpisu elektronicznego.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
J2ME – MIDlet, budowa i przykład
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Szkielet MIDletu
import javax.microedition.midlet.MIDlet;
public class PierwszyMIDlet extends MIDlet {
public void startApp(){
}
public void pauseApp(){
}
public void destroyApp(boolean){
}
/** Opcjonalny konstruktor:**/
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
MIDlet musi mieć również publiczny bezargumentowy konstruktor :
public NazwaKlasy() {}
W przypadku zwykłej aplikacji, napisanej w języku JAVA, metoda wywoływania inicjalizacji obiektów była
statyczną metodą main(), w przypadku MIDletu jest to
public void startApp() {}
MIDlet może ulec zawieszeniu, w tym celu wywołać można metodę
public void pauseApp() {}
W tym momnecie MIDlet zwalnia swoje zasoby, zawieszone jest działanie "timerów". Ekran wówczas może być
przekazany np. innemu MIDletowi.
W stan zawieszenia może również dobrowolnie wprowadzić siebie aplikacja. Dokonuje tego wywołując metodę
Public notifyPaused() {}
W przypadku wywołania metody notifyPaused() platforma nie wywołuje już metody pauseApp().
Zakłada, że MIDlet wywołując metodę notifyPaused() jest już gotowy do przejścia w stan zawieszenia.
Dlatego metoda pauseApp() często poprzedza wywołanie metody notifyPaused().
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Aby powrócić ze stanu zawieszenia w stan aktywny, MIDlet wywołuje bezargumentową metodę
resumeRequest() {}
Informuje ona informuje maszynę wirtualną, że MIDlet jest gotowy do działania. Uruchomiony zostanie, gdy tylko
przydzielone mu będą odpowiednie zasoby, co nastąpi, gdy takie będą (np.. Zwolni je inny MIDlet). W przypadku powrotu
ze stanu zawieszenia w stan aktywny, ponownie wywoływana jest metoda
Public startApp() {}
Oczywiście rodzi to niebezpieczeństwo podwójnego alokowania pamięci podczas inicjacji obiektów w tej metodzie.
Trzeba więc albo inicjować obiekty w konstruktorze lub wprowadzić inne metody zabezpieczeń przed dublowaniem się
obiektów.
Zakończyć działanie MIDletu można za pomocą metody :
public void destroyApp(boolean) {}
Tutaj usuwanie są obiekty, ewentualne dane zapisywane są w pamięci trwałej.
MIDlet można również zakończyć wywołując metodę
notifyDestroyed()
Platforma nie wywołuje wówczas metody destroyApp().
Przyjmuje, iż aplikacja została już przygotowana do zamknięcia.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Grafika 2D i 3D w J2ME (API niskiego poziomu)
Źródło : O'reilly - j2me in a nutshell, str. 397
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Klasa Canvas jest klasą dziedziczącą po klasie Displayable. Udostępnia ona powierzchnię ekranu do
dowolnych operacji graficznych. Nie można dodać do niej komponentów, pozwala jedynie na
niskopoziomowe operacje graficzne.
Klasa Canvas nie udostępnia żadnych możliwości graficznych. Jest to zadanie klasy Graphics. Natomiast
klasa Canvas przenosi obraz z obiektu klasy Graphics na ekran.
Zatem klasa Canvas pozwala na dostęp do pojedynczych pikseli wyświetlanych na
ekranie urządzenia. Zawiera metody pozwalające np. na rysowanie figur geometrycznych,
definiowania ich koloru, czy wyświetlanie tekstu
(z uwzględnieniem wielkości, czcionki, czy pozycji na ekranie.)
Nie definiuje natomiast elementów interfejsu użytkownika, takich jak przycisku czy pola tekstowe.
Te elementy udostępniają inne klasy, i są to elementu należące do API wysokiego poziomu.
Klasy Canvas oraz Graphics zawarte są w pakiecie javax.microedition.lcdui, zatem wymagane jest użycie
Dodatkowej paczki:
import javax.microedition.lcdui.*;
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Klasa Canvas zawiera metody, dzięki którym możemy sprawdzić cechy urządzenia (ekranu). Poniższe
metody pozwalają pozyskać wymiary ekranu (w pikselach) i sprawdzić, czy urządzenie dostarcza podwójne
buforowanie:
public int getHeight()
public int getWidth()
public boolean isDoubleBuffered()
Podwójne buforowanie polega na tym, iż zmiany w wyglądzie nie są widoczne od razu dla użytkownika, a
przygotowywane są w buforze poza ekranem, a następnie wyświetlanie na nim. Pomaga to uniknąć migotania
ekranu.
Z kolei informację o liczbie wyświetlanych przez urządzenie kolorów możemy poznać dzięki metodom z
klasy Display:
public boolean isColor()
public int numColors()
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Klasa Canvas wywiedziona z Displayable. A już Displayable daje możliwość dołączenia do niej komend.
Można zatem dołączać je do obiektów klas rozszerzających klasę Canvas. Metoda korzystania z klasy
Canvas : będziemy definiowanie klasy wywodzące się z niej, wypełniając jedyną abstrakcyjną w niej
metodę:
protected abstract void paint(Graphics g)
Korzystając z podanego nam jako argument (przez maszynę wirtualną) argumentu typu Graphics, będziemy
w tej metodzie definiować wygląd naszego obiektu.
Oprócz tego Canvas posiada także wiele zdefiniowanych metod, pozwalających na np. Ponowne narysowanie
obiektu (metoda repaint()), reagować na naciśnięcie lub zwolnienie przycisku klawiatury, czy zdarzenie
wygenerowane przez inne urządzenie wejściowe (np. Dotkniecie ekranu dotykowego czy przesunięcie
rysika). Do tego dochdzą metody pozwalające sprawdzić właściwości ekranu.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykład użycia dla Canvas
private class Ekran extends Canvas{
String tekst =” ”;
int szerokosc,wysokosc;
public Ekran(String napis){
tekst = napis;
szerokosc = getWidth();
wysokosc = getHeight();
}
public paint(Graphics g){
g.setColor(0xffffff); //zmiana aktualnego koloru
// Rysowanie prostokąta o rozmiarze ekranu
g.fillRect(0, 0, ScreenWidth, ScreenHeight);
g.setColor(255,0,0); //zmiana aktualnego koloru
// Wyświetlenie tekstu na środku ekranu
g.drawString(label, ScreenWidth/2, ScreenHeight/2, g.HCENTER|g.TOP);
repaint(); //Narysowanie ekranu od nowa.
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykład użycia dla Canvas c.d.
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.*;
public class PierwszyMIDlet extends MIDlet {
private Display display;
private class Ekran extends Canvas{
String tekst =” ”;
int szerokosc,wysokosc;
public Ekran(String napis){
tekst = napis;
szerokosc = getWidth();
wysokosc = getHeight();
}
public paint(Graphics g){
g.setColor(0xffffff); //zmiana aktualnego koloru
// Rysowanie prostokąta o rozmiarze ekranu
g.fillRect(0, 0, ScreenWidth, ScreenHeight);
g.setColor(255,0,0); //zmiana aktualnego koloru
// Wyświetlenie tekstu na środku ekranu
g.drawString(label, ScreenWidth/2, ScreenHeight/2, g.HCENTER|g.TOP);
}
}
public void startApp(){
display = Display.getDisplay(this);
display.setCurrent(new Ekran(„Pierwszy MIDlet"));
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykład klasy pozwalającej na wyświetlanie obrazów
na ekranie urządzenia
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
class ImageInCanvas extends Canvas {
Image image;
public ImageDemoCanvas () {
try {
image = Image.createImage (/logo.png);
}
catch (IOException e) {
throw new RuntimeException („Unable to load Image ”+e);
}
}
public void paint (Graphics g) {
g.setGrayScale (255);
g.fillRect (0, 0, getWidth (), getHeight ());
g.drawImage (image, 0, 0, Graphics.TOP | Graphics.LEFT);
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Ciekawsze metody klasy Graphics
public int getColor();
public void setColor( int RGB);
public void drawRect(int x, int y, int width, int height); // native
public void drawRoundRect(int x, int y, int width, // native
public void setColor( int red, int green, int blue);
int height, int arcWidth, int arcHeight);
public Font getFont();
public void drawString(String str, int x, int y, // native
public void setFont( Font font);
int anchor);
public int getTranslateX();
public void drawSubstring(String str, int offset, int len, // native
public int getTranslateY();
int x, int y, int anchor);
public void clipRect(int x, int y, int width, int height);
public void fillArc(int x, int y, int width, int height, // native
public void drawArc(int x, int y, int width, int height, // nativeint startAngle, int arcAngle);
public void fillRect(int x, int y, int width, int height); // native
int startAngle, int arcAngle);
public void drawChar(char character, int x, int y, // native public void fillRoundRect(int x, int y, int width, // native
int height, int arcWidth, int arcHeight);
int anchor);
public void drawChars(char[] data, int offset, // native
public void setClip( int x, int y, int width, int height);
int length, int x, int y, int anchor);
public void translate( int x, int y);
public void drawImage(Image img, int x, int y, // native
int anchor);
public void drawLine( int x1, int y1, int x2, int y2); // native
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Oprócz operacji związanych z ekranem urządzenia, klasa Canvas zawiera także metody obsługi zdarzeń
z urządzeń wejściowych, takich jak klawiatura, czy ekran dotykowy, czy np. Rysik (w przypadku
urządzeń typu PDA).
W przypadku klawiatury mamy do dyspozycji następujące metody :
protected void keyPressed(int keyCode)
-Klawisz naciśniety
protected void keyReleased(int keyCode)
-Klawisz puszczony
protected void keyRepeated(int keyCode)
-Klawisz przytrzymamy
Niektóre klawisze zdefiniowane są na stałe:
•KEY_NUMn - gdzie n, to oznaczenie kolejnych przycisków (od 0 do 9),
•KEY_STAR - klawisz oznaczający klawisz ze znaczkiem gwiazdki,
•KEY_POUND - klawisz ze znaczkiem hash.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykład użycia dla Canvas (obsługa zdarzeń)
private class Ekran extends Canvas {
public konstruktor() {
String s = "";
}
//-------Pozostałe instrukcje---------//
public void paint(Graphics g){
g.setColor(0,255,0);
g.fillRect(ScreenWidth/2, ScreenHeight/2, ScreenWidth, ScreenHeight);
g.setColor(0,0,0);
g.drawString(s, ScreenWidth/2, ScreenHeight/2, g.HCENTER|g.TOP);
}
public void Klawisz(){
public void keyPressed (int key) {
s = "Naciśnięty klawisz: "+key; repaint();
repaint();
}
public void keyReleased (int key) {
s = "Puszczony klawisz: "+key; repaint();
repaint();
}
public void keyRepeated (int key) {
s = "Przytrzymany klawisz: "+key; repaint();
repaint();
}
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
GUI
w
J2ME
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
GUI J2ME (API wysokiego poziomu)
Źródło : O'reilly - j2me in a nutshell, str. 397
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Komponenty wysoko-poziomowego GUI:
Alert – Służy do wyświetlania wiadomości o nagłym zdarzeniu.
Może zawierać zarówno tekst jak i grafikę.
Alert testAlert = new Alert(„Belkla gorna", „Tresc alertu.", null, AlertType.INFO);
testAlert.setTimeout(Alert.FOREVER);
Typ alertu
Opis
ALARM
Informowanie użytkownika o
nagłych zdarzeniach
CONFIRMATION
Prośba do użytkownika o
potwierdzenia akcji
ERROR
Informacja o błędzie
INFO
Informacja dla użytkownika
WARNING
Ostrzeżenie o niebezpiecznych
operacjach
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Komponenty wysoko-poziomowego GUI:
ChoiceGroup – element dający możliwość wyboru z listy opcji. Może zawierać tekst jak i grafikę.
Obrazek jest połozy obok tekstu i traktowany jako jeden obiekt.
private ChoiceGroup cg_kierunek, cg_przystanek, cg_typ
cg_typ = new ChoiceGroup("Typ srodka komunikacji : ", Choice.EXCLUSIVE);
cg_typ.append("Tramwaj", null);
cg_typ.append("Autobus", null);
TextBox – kontrolka umożliwiająca użytkownikowi na wpisanie i edycje tekstu.
Ma ustaloną maksymalną ilość tekstu. Maksymalny rozmiar tekstu
może być większy od ekranu, na którym ma zostać wyświetlony, wtedy automatycznie pojawiają się
paski przewijania.
private TextBox tekst;
tekst = new TextBox(„Belka górna",„Tekst domyślny",20,0);
Trzeci parametr oznacza maksymalny rozmiar tekstu, czwarty parametr pozwala na włączenie ograniczeń co
Do edycji tekstu.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Komponenty wysoko-poziomowego GUI:
TekstField – podobnie jak TextBox słuzy do wprowadzania tekstu, z ta różnica, ze pozwana na
Wprowadzenie masek ,np. w przypadku wpisywania nr telefonu klawiatura automatycznie przełączy
Na tryb wprowadzania liczb.
private TextField tekst;
tekst = new TextField(„Belka górna",„Tekst domyślny",20,0);
Trzeci parametr oznacza maksymalny rozmiar tekstu, czwarty parametr pozwala na włączenie ograniczeń co
Do edycji tekstu.
Ticker – pasek znajdujący się na górze ekranu, w którym przejawia się przewijający się tekst.
Parametry takie jak szybkość czy kierunek przesuwania się tekstu są zdefiniowanie przez urządzenie
I nie ma możliwości ich zmiany.
Ticker aTicker = new Ticker („Ticker J2ME!");
Forma.setTicker(aTicker);
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Gauge – Element odpowiadający za działanie wszelkiego rodzaje paski postępu, może tez
Służyć jako regulator poziomu jakiejś wartości.
private Gauge glosnosc;
glosnosc = new Gauge(„Glosnosc",true,10,1);
Pierwszy parametr określa etykietę regulatora
Drugi parametr określa, czy można zmieniać jego ustawienia
Trzeci parametr określa wartość maksymalną
Czwarty parametr oznacza wartość, jaka suwak przymnie po zainicjowaniu.
Na ekranie wyświetlany na raz może być tylko jeden obiekt z wyżej wymienionych, ponieważ na raz
wyświetlany może być tylko jeden obiekt dziedziczący po klasie „Screen”. A co jeśli chcemy Wyświetlić na
raz kilka obiektów, np. TextBox z podpisem ?
Private TexBox teskt;
/-----------reszta instrukcji-----------/
Public startApp(){
display = Display.getDisplay(this);
tekst = new TextBox("Belka górna","Tekst domyślny",20,0);
display.setCurrent(tekst);
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
W przypadku, gdy chcemy wyświetlić na ekranie na raz kilka elementów, trzeba je umieścić w jakimś kontenerze.
W tym celu można zastosować element „Form”. „Form” zajmuje się wyświetlaniem i pozycjonowaniem elelmentów
Znajdujących się wewnątrz.
public void startApp(){
display = Display.getDisplay(this);
txt = new TextField("Belka górna","Tekst domyślny",20,0);
cg_typ = new ChoiceGroup("Typ srodka komunikacji : ", Choice.EXCLUSIVE);
forma1 = new Form("Demo Form");
cg_typ.append("Tramwaj", null);
cg_typ.append("Autobus", null);
forma1.append(cg_typ);
forma1.append(txt);
display.setCurrent(forma1);
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Oprócz „Form” istnieje jeszcze inny komponent, pozwalający na grupowanie wewnątrz innych elementów
graficznych. Jest to komponent „List”, który działa nieco podobnie do elementu „choice”.
Użytkownik może przeglądać elementy tej listy, a dopiero wybranie któregoś elementu powoduje jakaś akcje
Dla aplikacji. Dokonuje się tego za pomocą komponentu „Command”.
CommandListener
Jeśli klasa implementuje interfejs CommandListener to można tworzyc w niej interaktywne przyciski typu Button.
Jest to dość popularne rozwiązanie do obsługi komend. W J2ME niestety nie mamy żadnych buttonów itp. więc interakcja
odbywa się poprzez klawisze na telefonie. Aby ją obsłużyć należy dodać obiekt typu Command do obiektu tworzącego
formę w aplikacji. Konstruktor obiektu Command wygląda następująco:
publi Command(String tekst, int typ, int priorytet)
tekst - nazwa wyświetlana
typ - typ komendy (Ok, Exit, Cancel, Help)
priorytet - służy do układania kolejności. Można też wg niego rozróżniać komendy
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
public class PierwszyMIDlet extends MIDlet implements CommandListener {
private Display display;
private TextBox tekst;
private TextField txt;
public Form forma1;
private ChoiceGroup cg_typ;
public void startApp(){
display = Display.getDisplay(this);
txt = new TextField("Belka górna","Tekst domyślny",20,0);
cg_typ = new ChoiceGroup("Typ srodka komunikacji : ", Choice.EXCLUSIVE);
forma1 = new Form("Demo Form");
cg_typ.append("Tramwaj", null);
cg_typ.append("Autobus", null);
forma1.append(cg_typ);
forma1.append(txt);
forma1.addCommand(new Command("Exit",Command.EXIT,0));
forma1.setCommandListener(this);
display.setCurrent(forma1);
display.setCurrent(forma1);
}
public void commandAction(Command c, Displayable d) {
if (c.getCommandType()==Command.EXIT)
notifyDestroyed();
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
public class PierwszyMIDlet extends MIDlet implements CommandListener {
private Display display;
private TextField a,b,Wynik;
public Form forma1;
private Command exitCommand;
private Command calculateCommand;
private ChoiceGroup dzial_typ;
public void startApp(){
display = Display.getDisplay(this);
a = new TextField(„Liczba 1: ",„0",20,0);
b = new TextField(„Liczba 2: ",„0",20,0);
Wynik = new TextField(„Wynik: ",„0",20,0);
dzial_typ = new ChoiceGroup(„Wybierz dzialanie : ", Choice.EXCLUSIVE);
forma1 = new Form("Demo Form");
dzial_typ.append(„dodaj", null);
dzial_typ.append(„odejmnij", null);
forma1.append(dzial_typ);
forma1.append(a);
forma1.append(b);
forma1.append(Wynik);
exitCommand = new Command("Wyjście", Command.SCREEN,
2);
calculateCommand = new Command("Oblicz",
Command.SCREEN, 1);
forma1.addCommand(exitCommand );
forma1.addCommand(calculateCommand);
forma1.setCommandListener(this);
display.setCurrent(forma1);
}©
2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
public void commandAction(Command c, Displayable s) {
if (c == exitCommand) {
destroyApp(false);
notifyDestroyed();
}
if (c == calculateCommand) {
float A,B,wynik;
try {
A = Float.parseFloat(a.getString().equals("")?"0":a.getString());
B = Float.parseFloat(b.getString().equals("")?"0":b.getString());
}
catch (Exception e) {
A=B=0;
}
wynik = A + B;
wynik.setString(„”+wynik);
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Połączenia sieciowe w J2ME
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Źródło: http://developers.sun.com/mobility/midp/articles/genericframework/
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Źródło : O'reilly - j2me in a nutshell, str. 326
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Urządzenia mobilne prawie zawsze posiadają na możliwość komunikacji z innym urządzeniami
tego typu oraz często także z Internetem. W przypadku J2ME problem ten rozwiązano tworząc Interfejs
Connection, który reprezentuje dowolne połączenie (np. za pomocą protokołu http czy też innego). Z
interfejsu tego wywodzą się interfejsy realizujące różne rodzaje połączenia. Jest on klasą bazową dla wielu
metod przesyłania danych zarówno w sieci jak i w obrębie urządzenia. Interfejs Connection ma tylko jedną
metodę:
public abstract void close() throws IOException
interfejs reprezentujący dowolne połączenie nie ma metody otwierającej takie połączenie. Zestawienie
połączenia jest możliwe za pomocą odpowiednich metod klasy Connector. Klasa Connector zawiera tylko
statyczne metody i są to metody pozwalające utworzenie referencji do interfejsu Connection i realizacji
połączenia danego typu. Metody te wyglądają następująco :
public static Connection open(String nazwa) throws IOException
public static Connection open(String nazwa,int tryb_dostepu ) throws IOException
public static Connection open(String nazwa,int tryb_dostepu,boolean czas) throws IOException
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Metody przedstawione powyżej zwracają referencję do interfejsu Connection oraz pozwalają na
nawiązanie połączenia z innym urządzeniem. Urządzenie jest określane w pierwszym
argumencie. Połączenie może zachodzić w trybie czytania, pisania, lub obydwu jednocześnie, przy czym
tryb połączenia w obie strony jest przyjmowany domyślnie. Oprócz tego czas oczekiwania na połączenie
może być ograniczany.
Każda z metod open zwraca referencję do obiektu utworzonego na podstawie klasy
implementującej Connection. Mogą to być referencje klasu HttpConnection (dla protokołu http),
StreamConnection (dla gniazd), DatagramConnection (dla datagramów). Postać nazwy urządzenia, z
którym chcemy nawiązać polaczenie wygląda następująco :
{protokół}:[{adres_sieciowy}][{parametry}]
Poniżej przekłady nazw dla różnych urządzeń :
http://www.wp.pl:80/
http://www.strona.com/strona?page=index
socket://www.kojot.test.com:8080
datagram://:555
file:///home/user/plik
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Protokół HTTP
Protokół ten wykorzystywany jest do przesyłania danych pomiędzy serwerem WWW, a klientem,
a w tym celu korzysta z gniazd. Jest też jest jedynym protokołem, o którym się zakłada, że jest obsługiwany
przez każde urządzenie spełniające założenia MIDP. Jednakże w przypadku małych urządzeń takich jak
telefon komórkowy istnieje problem braku wbudowanej przeglądarki WWW. Wprawdzie producent ma
obowiązek implementacji protokołu http, ale czasem jest to rodzaj bramy ,która tłumaczy komunikaty http na
postać rozumianą przez urządzenie. Poniżej przykład obrazujący sposób nawiązania połączenia z danym
adresem internetowym :
hc = (HttpConnection)Connector.open("http://www.wp.pl Connector.READ_WRITE");
Jak widać podaliśmy dwa parametry metodzie open : nazwę urządzenia (http), adres (www.wp.pl), oraz tryb
dostępu. Nie narzuciliśmy ograniczenia czasu dostępu (np. zakładamy, że dysponujemy dobrym łączem).
Podstawowe czynności które należy wykonać, aby skorzystać z HttpConection do pobrania strony www :
•Tworzymy łańcuch zawierający adres URL strony WWW którą chcemy pobrać, następnie wywołać
metodę open() i utworzyć obiekt klasy HttpConnection.
•Czasem trzeba ustalić rodzaj żądania oraz parametry . Domyślnym żądaniem jest GET.
•Następnie należy sprawdzić za pomocą metody getResponseCode() czy serwer odpowiedział
pozytywnie na żądanie.
•Podobnie jak w przypadku magazynów musimy posłużyć się strumieniami, zatem wywołujemy
metodę openInputStream() lub openDataInputStream() i w ten sposób uzyskujemy dostęp do
strumienia wejściowego. Na koniec zamykamy strumień wejściowy.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykład wykorzystania klasy HTTPConnection:
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
public void startApp() throws IOException{
HttpConnection hc = null;
InputStream is = null;
int ch;
try{
hc = (HttpConnection)Connector.open("http://www.wp.pl Connector.READ_WRITE");
is = hc.openInputStream();
while ((ch = is.read()) != -1) {
str.append((char)ch);
}
finally {
if (is != null) is.close();
if (hc != null) hc.close();
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Zatem obiekt typu HttpConection może być wykorzystywany do przesyłania danych w postaci
strumieni danych wejściowych i wyjściowych, dodatkowo można określić ich długość, typ i sposób
kodowania. Metody te pochodzą z klasy ContentConnection. Serwer www wysyła odpowiedź, którą można
odebrać za pomocą metody getResponseCode(), poniżej przykłady odpowiedzi :
stałe klasy HttpConnection
Znaczenie
HTTP_OK
Zasób dostępny bez błędu (200)
HTTP_MOVED_PERM
Zasób przeniesiony pod inny adres i jest podany w nagłówku (301)
HTTP_SEE_OTHER
Należy wysłać żądanie GET pod adres podany w nagłówku (303)
HTTP_BAD_REQUEST
Żądanie dotarło w postaci zniekształconej i nie może być
zrealizowane (400)
HTTP_FORBIDDEN
Żądanie nie może być zrealizowane (403)
HTTP_NOT_FOUND
Zasób nie istnieje (404)
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Zapytania i odpowiedzi w protokole http
Komunikat przesyłający żądanie do serwera www składa się z trzech elementów
•Wiersz zawierający żądanie HTTP, po nim nowa linia,
•Nagłówki żądania, każdy w nowym wierszu, po nich linia wolna – jest to element opcjonalny,
•Dane dodatkowe potrzebne do wykonania żądania - występuje gdy jest niezbędny.
Przykłady żądań :
Żądanie
Znaczenie
Wartość
GET
HttpConnection.GET
Prośba o przesłanie pliku o podanej
ścieżce
HEAD
HttpConnection.HEAD
Jak wyżej, z tą różnica, że wysyłane są
jedynie nagłówki, bez danych
POST
HttpConnection.POST
Metoda stosowana, gdy na stronie są
formularze.
Postać parametrów żądań umieszczanych w adresie lub w ciele żądania wygląda następująco:
nazwa1=wartość&nazwa2=wartość&nazwa3=wartość
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Gniazda ( Socket )
Gniazda w J2ME nie różnią się zbytnio od gniazd z innych wersji JAVY , czy też innych języków
(np. C/C++). Jedyna różnicą jest to, że standard MIDP nie wymaga obsługi gniazd. Powodowane jest to tym,
że gniazda wykorzystują protokół TCP/IP, a urządzenia mobilne nie koniecznie muszą mieć dostęp do
Internetu i w ogóle obsługiwać stosu TCP/IP. Klasa StreamConnection dziedziczy z Connection. Zatem
chcą uzyskać połączenie za pomocą gniazda, z serwerem świadczącym usługi na jakimś porcie musimy
utworzyć połączenie za pomocą metody open(). Otwarcie połączenia może mieć jedną z poniższych postaci :
StreamConenection sc = (StreamConnection)Connector.open("socket://:32839");
StreamConenection sc = (StreamConnection)Connector.open("socket://212.77.100.101:80")
StreamConenection sc = (StreamConnection)Connector.open("socket://jakis_adres:80") ;
Sposób nawiązywania połączenia jest nadal taki sam. Jak widać podaliśmy dwa parametry metodzie open :
nazwę urządzenia (socket), i adres (www.wp.pl). Jeżeli połączenie może być nawiązane, to należy otworzyć
strumień wyjściowy i
za pośrednictwem tego strumienia wysłać polecenie do nasłuchującego
serwera. Otwarcie strumienia wyjściowego może mieć poniższą postać:
OutputStream os = sc.openOutputStream();
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Za pomocą tego strumienia należy wysłać zrozumiałe dla serwera zapytanie. Jeżeli będzie to serwer www to
zapytanie może mieć postać:
"GET / HTTP/1.1\n\n"
Zapytanie należy przesłać jako ciąg bajtów. Należy pamiętać, że urządzenie może buforować dane i
polecenie niekoniecznie natychmiast zostanie wysłane. Zamknięcie strumienia Następnie należy otworzyć
strumień wejściowy oczekiwać na odpowiedź serwera. Otwarcie strumienia wejściowego ma poniższą
postać.
OutputStream os = sc.openInputStream() ;
Dane napływające to również ciąg bajtów o nieznanej długości. Jeżeli znany jest format danych przesyłanych
przez serwer, to można skorzystać z przesyłanych informacji. Można odczytać pewną liczbę bajtów, należy
pamiętać, że dane nie muszą napływać w jednolitych porcjach. Dane można odczytać podobnie jak w
poprzednim przykładzie.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykład wykorzystania gniazda (Socketa):
String ulr= ”www.wp.pl”
SocketConnection c = null;
InputStream s = null;
OutputStream os;
try {
c = (SocketConnection)Connector.open(url);
s = c.openInputStream();
os = sc.openOutputStream(); //wyslanie zapytania, oczekiwanie na odebranie danych…
} catch (ConnectionNotFoundException e) { // Połączenie nie może być zrealizowane
} catch (IllegalArgumentException e) { //Błędne zapytanie
} finally {
try {
if (s != null) s.close();
if (c != null) c.close();
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Połączenia sieciowe w J2ME
- bluetooth
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Składowanie danych w urządzeniach mobilnych
przy wykorzystaniu J2ME
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
„Pamięć nieulotna”
Midlety niekiedy muszą zapamiętywać i przechowywać informacje na stałe, są to dane
wprowadzane przez użytkowników(np. dane konfiguracyjne aplikacji). Specyfikacja MIDP wymaga, by
wszystkie urządzenia posiadały pamięć nieulotną, czyli taką, w której będzie przechowywana informacja
nawet wtedy, gdy midlet kończy swoje działanie lub w sytuacji, gdy urządzenie zostanie fizycznie
wyłączone. W praktyce problem ten rozwiązywany jest różnie przez różne urządzenia, chociaż dla
programisty nie ma to żadnego zdarzenia, ponieważ interfejs jest jeden.
Informacje są przechowywane w postaci kolekcji rekordów (record store). Każda kolekcja rekordów jest
identyfikowana przez nazwę, która jest rzecz jasna unikalna. Midlety dostęp mają jedynie do „swoich”
kolekcji, nie mają za to dostępu do kolekcji rekordów innych Milletów. Nie mają również dostępu do danych
utworzonych przez inne aplikacje.
Sposób zapisu danych może być różny na różnych modelach u różnych producentów. Jednak dla J2ME został
opracowany uniwersalny sposób dla wszystkich urządzeń o nazwie RMS - Record Management System.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Nad zbiorami rekordów w J2ME czuwa klasa RecordStore.
Aby utworzyć jakiś zbiór należy wywołać jej statyczną metodę:
public static RecordStore openRecordStore(String nazwa, boolean tryb)
Pierwszy parametr określa nazwę zbioru (nazwa może być dowolna)
Drugi parametr oznacza tryb dostępu / tworzenia do zbioru -Jeśli ustawiony jest na „true” wtedy, gdy w
momencie próby otwarcia nie istnieje – zostanie utworzony nowy. W przypadku wartości „false” można
otworzyć jedynie istniejący magazyn. W przypadku ,gdy nie istnieje – wyrzucany jest wyjątek.
W MIDP 2.0 dodano dwie nowe metody openRecordStore o innych parametrach i bardziej specjalistycznych
zadaniach. M.in. z ustawieniem uprawnień i przypisywaniem danego zbioru do konkretnego MIDletu.
Metoda zwraca nam utworzony (lub otworzony) zbiór na którym możemy wykonywać operacje zapisu i
odczytu. W razie błędów generowane są następujące wyjątki:
RecordStoreNotFoundException - zbiór nie istnieje (w przypadku gdy nie ma być automatycznie utworzony)
RecordStoreFullException - brak dostępnej pamięci
IllegalArgumentException - błędna nazwa zbioru
RecordStoreException - inny błąd
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Zatem:
RecordStore store = RecordStore.openRecordStore(„ZbiorTestowy", true);
//wyrzuci wyjątek „RecordStoreNotFoundException” jeśli zbiór nie istnieje
RecordStore secondStore = RecordStore.openRecordStore(„ZbiorTestowy", false);
Po zakończeniu pracy z kolekcją można ją zamknąć :
public static void closeRecordStore();
lub także skasować :
public static void deleteRecordStore() ; // O tym w dalszej części wykładu
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Magazyn rekordów składa się z rekordów, które są tablicą bajtów. Każdy rekord ma przypisany
identyfikator – jest to liczba całkowita dodatnia. Nie jest ona częścią rekordu, tylko jest przydzielana
podczas dopisywania rekordu do magazynu. Gdy dana wartość zostanie raz przydzielona to nie może już
zostać przydzielona żadnemu innego rekordowi, nawet w sytuacji ,gdy rekord ten zostanie usunięty z
magazynu.
Metoda dodająca nowy rekord do magazynu :
public static int addRecord(byte[] dane,int od_którego,int ile) ;
dodaje nowy rekord do zbioru i zwraca nam ID rekordu.
Parametr pierwszy to dane do zapisu w postaci tablicy bajtów.
Parametr drugi : od którego bajtu ma być zapisywane
Parametr trzeci: ile bajtów ma zostać zapisanych.
- void setRecord(int recordId, byte[] newData, int offset, int numBytes)
ta metoda służy do zastąpienia rekordu nowym.
Dodatkowym parametrem jaki trzeb podać jest ID
rekordu który ma być zastąpiony, reszta jak powyżej.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Każdy rekord, jak wspomniano wyżej ,jest tablicą bajtów. Zatem aby umieść w nim jakieś dane, trzeba je
najpierw zamienić na tablicę bajtów. Można to oczywiście przeprowadzić na wiele sposób, przykładowo za
pomocą klas DataOutputStream i ByteArrayOutputStream.
Przykład 1. Sposób zapisu rekordu
1. Tworzymy nowy magazyn :
RecordStore nowy_magazyn = null;
Klasa “Dane” będzie służyć to tworzenia obiektów zawierających dane do zapisu w magazynie
class Dane{
String DaneTxt;
int DaneNum;
Dane(String a, int b){
}
DaneTxt = a;
DaneNum = b;
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
2. Zapisujemy dane do strumienia :
private byte[] zapiszStrumien(Dane przyklad) throws IOException {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
DataOutputStream os = new DataOutputStream(bs);
os.writeUTF(przyklad.daneTxt);
os.writeInt(przyklad.daneNum);
return bs.toByteArray();
}
3. Zapisujemy dane w postaci strumienia do rekordu :
private void zapiszRecord(Dane przyklad)throws IOException,RecordStoreException {
try{
byte[] dane = zapiszStrumien(przyklad);
id = nowy_magazyn.addRecord(dane,0,dane.length);
}
}catch(Exception e){System.out.println(e);
}
zmienna id (niezdefiniowana nigdzie w metodzie ‘zapiszRecord’ ) może służyć do wyświetlania
identyfikatora nowego rekordu, jeśli jest to do czegoś potrzebne.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Ważne jest aby zamykać strumień i zbiór, urządzenia mobilne nie posiadają dużo pamięci więc należy je
oszczędzać (nie zamykanie strumieni może być jedną z przyczyn tzn. wycieków pamięci).
Podczas każdej operacji addRecord, setRecord i deleteRecord na zbiorze inkrementowana jest jego wersja.
Wersję zbioru można otrzymać poprzez wywołanie int getVersion().
Odczyt danych z rekordów można realizować na kilka sposobów, na przykład podając
identyfikator rekordu w magazynie. Metoda to wykonująca wygląda następująco :
byte[] dane = nowy_magazyn.getRecord(id);
Jeśli nie znamy zbiorów MIDletu możemy pobrać ich nazwy za pomocą metody statycznej
RecordStore.listRecordStores();
Zwraca ona tablicę Stringów lub null w przypadku gdy nie ma żadnego dostępnego zbioru.
Przydatną może okazać się tutaj metoda enumerateRecord():
enumerateRecord(RecordFilter filtr, RecordComparator porownaj, boolean kontrolowac);
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
•Argument RecordFilter filtr pozwala zdefiniować sposób wyboru rekordów z magazynu. Jest to
interfejs wymagający określenia metody o nazwie matches() . Dzięki niemu można dokładnie ustawić
jakie kryteria muszą spełnić rekordy, aby zostały odczytane, np. wybrać wszystkie rekordy (z
przykładu przedstawionego wyżej, które zawierają liczbę dodatnią.) Podanie wartości null spowoduje,
że rekordy odczytywane będą bez ograniczeń.
•Argument RecordComparator porownaj pozwala na uporządkowanie wg wybranego kryterium, np.:
uporządkuj rosnąco według wartości liczb. Podanie wartości null spowoduje, że rekordy odczytywane
będą kolejno zgodnie z natywną implementacją.
•Argument boolean kontrolowac pozwala na podjęcie decyzji , czy sposób odczytu rekordów (kryteria,
kolejność) będą mogły się zmieniać za każdym razem, gdy nastąpi zmiana w magazynie. W takiej
sytuacji zmianie musi ulec obiekt pozwalający na wyliczanie, jest to jednak dosyć czasochłonne. W
przypadku, gdy ten parametr przyjmuje wartość false, należy budować na nowo obiekt
enumerteRecord przy każdej zmianie.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
A oto przykład odczytu danych z magazynu, trzeba oczywiście pamiętać o zamianie danych z postaci tablicy
bajtów do postaci oryginalnej:
private Dane getDane(int id,RecordStore nowy_magazyn)throws IOException, RecordStoreException
{
byte[] dane = nowy_magazyn.getRecord(id);
DataInputStream is = new DataInputStream(
new ByteArrayInputStream(dane));
Dane przyklad2 = new Dane(is.readUTF(), is.readInt());
return przyklad2;
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Poniżej przykład metody odczytującej dane z całego magazynu (ze wszystkich rekordów danego magazynu,
przy wykorzystaniu metody enumerateRecord(); )
private String czytajMagazyn(String nazwa) throws Exception {
RecordStore nowy_magazyn = null;
int id;
String ret;
try{
nowy_magazyn = RecordStore.openRecordStore(nazwa,true);
}catch(Exception e){
System.out.println("Blad Otwarcia magazynu!");
}
RecordEnumeration wyl = nowy_magazyn.enumerateRecords(null,null,false);
while(wyl.hasNextElement()){
id = wyl.nextRecordId();
Dane przyklad = getDane (id,spis);
ret = id + " " + przyklad.daneTxt + " " + przyklad.daneNum;
System.out.println(id + " " + przyklad.daneTxt + " " + przyklad.daneNum + "\n";);
}
try{
wyl.destroy();
nowy_magazyn.closeRecordStore();
}catch(Exception e){
System.out.println("Blad zamkniecia" + e);
}
return ret;
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Na koniec usuwanie. Mamy do dyspozycji dwie proste metody:
void deleteRecord(int recordID);
usuwa rekord o podanym ID ze zbioru
static void deleteRecordStore(String recordStoreName);
usuwa cały zbiór rekordów o podanej nazwie. Ale uwaga - zbiór musi być zamknięty inaczej otrzymamy
wyjątek RecordStoreException.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Dystrybucja programów w J2ME
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Programowanie i testowanie w Symbian OS
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Symbian to nazwa systemu operacyjnego, dołączonych do niego
bibliotek, rozwiązań interfejsu użytkownika oraz specyfikacji dla
programów narzędziowych wyprodukowanych przez konsorcjum
Symbian.
W jego skład wchodzą najwięksi producenci telefonów komórkowych:
•Nokia
•Samsung
•Motorola
•Siemens
•Sony Ericsson
Symbian został stworzony w oparciu o system EPOC, wykorzystywany
w PDA firmy Psion PLC.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Obecnie licencje na wykorzystywanie systemu operacyjnego Symbian
posiadają:
•Arima
•BenQ
•Fujitsu
•Lenovo
•LG
•Matsushita
•Mitsubishi
•Motorola
•Nokia
•Samsung
•Sharp
•Siemens
•Sony Ericsson.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
EPOC jest rodziną systemów operacyjnych opracowanych przez firmę Psion przeznaczonych dla urządzeń
przenośnych, przede wszystkim PDA
EPOC16
EPOC16, początkowo nazywany po prostu EPOC. Jest to system operacyjny opracowanym przez Psion w
późnych latach 80. i wczesnych 90. Powstał z myślą o dla urządzenia "SIBO" (SIxteen Bit Organisers).
System ten pracował na platformach opartych o procesor Intel 8086. Jego architektura jest 16-bitowa, jest
systemem operacyjnym przeznaczonym dla pojedynczego użytkownika, mogącym pracować w trybie
wielozadaniowości (z wywłaszczaniem).
Napisany został w dwóch językach: asemblerze oraz języku C i zaprojektowanym tak, aby mógłbyć
umieszczony w pamięci ROM.
Pierwsze urządzenia pod kontrolą EPOC16, zostały wypuszczone na rynek w 1989.
W późnych latach 90. systemowi przypisano nazwę EPOC16, aby odróżnić go od nowego systemu
operacyjnego jakim był EPOC32.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
EPOC32, Symbian OS
Pierwsze wydanie EPOC32 (Release 1) pojawiło się w Series 5 ROM v1.0 w 1997. Powstało szybko wiele
jego wersji.
System operacyjny EPOC32 został później przemianowany na Symbian.
EPOC32 i EPOC16 były zupełnie odmiennymi systemami operacyjnymi.
EPOC32 napisany w języku C++, który był rozwijany w połowie lat 90.
Jest systemem operacyjnym przeznaczonym dla pojedynczego użytkownika, mogącym pracować w trybie
wielozadaniowości(z wywłaszczaniem). Posiada zabezpieczenie pamięci, zatem należy dzielić aplikacje na
silnik i interfejs użytkownika.
EPOC32 był początkowo przeznaczony dla rodziny procesorów ARM, włączając w to: ARM7, ARM9,
StrongARM i XScale Intela, ale może być kompilowany w odniesieniu do urządzeń korzystających z innych
typów procesorów.
W czerwcu 1998, Psion Software stała się firmą Symbian Ltd., spółką joint venture pomiędzy Psion i
wytwórcami telefonów: Ericsson, Motorola i Nokia. Jako wydanie szóste (Release 6), EPOC był już
nazywany po prostu Symbian.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Jakie możliwości daje SYMBIAN?
Symbian to system operacyjny dla telefonów komórkowych. Pozwala zmienić zwykły telefon komórkowy w
urządzenie wielofunkcyjne. użytkownik może dowolnie korzystać z dodatkowego oprogramowania.
Umożliwia m.in. korzystanie z internetu [przeglądanie stron www, poczta elektroniczna, ftp, komunikatory
internetowe etc.], przeglądanie i edycję dokumentów word, excel czy pdf, odtwarzanie i nagrywanie muzyki,
fotografowanie i edycję zdjęć, nagrywanie i odtwarzanie video [włącznie z formatami typu DivX, Xvid,
AVC], nawigację GPS, zapewnia również rozrywkę poprzez wiele różnego rodzaju gier.
Żeby móc korzystać z dobrodziejstw Symbiana trzeba kupić telefon oparty na tym systemie. Urządzenia te
dzielą się ze względu na interfejs użytkownika.
•S60
Dzieli się na 4 edycje.
•S60 1 edycji
•S60 2 edycji
•S60 3 edycji
•S60v3 dodatkowo dzieli się na wersje FP1 (Feature Pack 1) i FP2 (Feature Pack 2). Więcej informacji w
artykułach:
•S60 5 edycji
UIQ - aktualnie nie rozwijany(telefony z ekranem dotykowym). Dzieli się na 2 edycje.
•UIQ 2 edycji
•UIQ 3 edycji
•Series80 - Nokia - urządzenia typu Communicator z pełną klawiaturą QWERTY - aktualnie nie rozwijany
•Series90 - Nokia - tablety internetowe - aktualnie nie rozwijany
•NTT DoCoMo's MOAP - FOMA - dostępny tylko w Japonii
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Programowanie pod Symbian :
Wspieranie języki :
• C++
•Java
•Pyhton
Środowiska Programistyczne (Przykłady):
Carbide C++ Express
NetBeans (Java, C++)
Eclipse (Java)
Java – Sytuacja podobna jak w przypadku większości innym platform, wykorzystujących J2ME.
Symbian C++
Termin Symbian C++ odnosi się do specyficznej odmiany języka C++, wraz z towarzyszącymi mu
Frameworkami używanymi przez Symbiana. Symbian C++ znacząco różni się od powszechniejszego C++,
związane jest to z platformami, jak również i doświadczenia z przeszłości (Symbian jest przecież
kontynuacją systemu operacyjnego EPOC firmy Psion, którego pierwsze wersje powstały w latach 80.).
Różnice pomiędzy „Standardowym” C++, a Symbian C++ są duże. Przykładem jest zupełnie inny
mechanizm wyjątków.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Symbian C++ - krótkie wprowadzenie
Symbian C++ jest językiem bardzo restrykcyjnym. Wynika to z bardzo ograniczonych zasobów (w stosunku
np. Do komputerów PC). Twórcy starali się standaryzować wszystko, włączanie z odpowiednim
nazewnictwem w kodzie. A wszystko to między innymi, aby uniknąć błędów (np. wycieków pamięci).
Nazwę typu poprzedza duża litera T (od Type), zmienne które odpowiadają unsigned - posiadają przed
nazwą typu (po T) dużą literę U (od unsigned):
•TInt8, TUInt8 – zmienna całkowita 8-bitowa oraz jej odpowiednik typu unsigned
•TInt16, TUInt16 – analogicznie j.w., ale 16-bitowa
•TInt32, TUint32 – j.w., ale 32-bitowa (TInt, TUInt)
•TInt64 – zmienna całkowita 64-bitowa, w praktyce przechowywana jako 2 zmienne 32-bitowe
•TReal32 – zmienna zmiennoprzecinkowa o podwójnej precyzji 32-bitowa
•TReal, TReal64 – j.w., ale 64-bitowa
•TText8, TText16 – zmienne tekstowe (odpowiednikami w C++ są odpowiednio – unsigned char oraz
unsigned short int)
•TBool – zmienne booleanowskie
•TAny – odpowiednik void z C++, najczęściej używany jako TAny *
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Kiedy funkcja może wyjść (leave’ować)?
1. Funkcja może wychodzić, gdy zawiera w sobie inne funkcje mogące wychodzić, czyli oznaczone L na
końcu. Gdy wykorzystujemy jakąś funkcje leave’ującą, oznacza to że nasza funkcja także może leave’ować,
a więc musimy oznaczyć ją literką L.
2. Możemy także programowo wywołać leave’owanie, wywołując statyczną metodę
User::Leave //lub którąś z jej wersji. Mamy do wyboru:
User::Leave(jakiś_błąd); //Leave jest wywołany, jeżeli wystąpi jakiś_błąd.
Przykład:
User::Leave(KErNoMemory);
W tym momencie program wyjdzie, jeżeli zabraknie pamięci.
User::LeaveNoMemory() //funkcja wychodzi, gdy jest brak pamięci,odpowiednik funkcji poprzedniej
User::LeaveIfNull()
– funkcja wychodzi jeżeli zwrócony wskaźnik jest NULL.
User::LeaveIfError()
– czyli gdy wywoływana funkcja zwróci nam błąd.
Przykład (łączenie się z serwerem plików):
User::LeaveIfError(iFs.Connect());
W tym momencie jeżeli poprawnie połączymy się z serwerem plików, program pójdzie dalej. Jeżeli jednak wystąpi jakiś błąd
– zrobimy Leave.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
•Nazwy klas (prefiksy):
•T – typy
•Klasy T nie posiadają destruktora, występują w sposób jak typy wbudowane.
•C – klasy
•Klasy C to klasy dziedziczące po CBase.
•M – interfejsy (Mixin)
•Klasy M są interfejsami składającymi się z funkcji wirtualnych.
•Nazwy danych (prefiksy)
•E – stałe typów wyliczeniowych
•Stała typu wyliczeniowego, powinna być składową stałej o nazwie rozpoczynającej się od T
•K – stałe
•i – zmienne składowe
•Każda nie-statyczna zmienna składowa (i od instance).
•a – argumenty
•Wszystkie zmienne deklarowane jako argumenty.
•Nazwy funkcji (sufiksy)
•L – funkcje, które mogą leaveować (leaveowanie zostanie wyjaśnione później).
•C – funkcje, które zostawiają coś na Cleanup Stacku (Cleanup Stack zostanie wyjaśniony później).
•Nazwy makr
•Pisane dużymi literami, podkreślenia zamiast spacji.
•Symbole wbudowane
•Pisane z podwójnym podkreśleniem jako prefiks oraz sufiks.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
W przypadku zmiennych boolean prawda oraz fałsz programowo są oznaczane odpowiednio jako ETrue oraz
EFalse. :
TBool b= Etrue;
if (b == ETrue) { ... }
Tutaj mała uwaga – w C++ wszystko co nie jest zerem uznawane jest za prawdę, natomiast w Symbian C++
ETrue odpowiada za wartość 1.
TBool b = Funkcja(); if (b) { ... }
Otóż wszyscy programiści C++ na pewno mają na uwadze różnice w rozmiarze typów zmiennych w
przypadku różnych platform i/lub różnych kompilatorów.
Z uwagi, że pisząc aplikacje na Symbian OS należy uwzględnić różne telefony (również kompilatory,
środowiska), stosując typy zmiennych zaprezentowane w liście powyżej mamy pewność, iż zawsze będą
takie jakie mają być. Jedynym odstępstwem od tej reguły jest zwracany typ void przez funkcje (w przypadku
deklarowania wskaźników typu pustego, należy posługiwać się typem TAny).
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Od Symbian OS 8.1 możliwe jest użycie mechanizmów przechwytywania wyjątków znanych z języka C++,
chociaż takie podejście do sprawy nie jest zalecane. Twórcy systemu namawiają do pozostania przy bardziej
przetestowanym, bogatszym i zaimplementowanym w systemie od pierwszej wersji mechanizmie walki z
błędami.
Błędy Panics
W momencie powstawia bledu system najlepsze co moze zrobic , to zamknac aplikacje. Podstawową
używaną tutaj funkcją jest User::Panic(panicCategory, integer), gdzie panicCategory powinien być
maksymalnie 16 znakowym określeniem błędu, integer natomiast 32-bitowym numerem błędu.
Powszechnym sposobem używania Panics jest użycie makr __ASSERT_DEBUG oraz
__ASSERT_ALWAYS; pierwszy jest kompilowany w wersji Debug, drugi w wersji Debug jak również i
przy kompilowaniu wersji finalnej. Poniższy przykład obrazuje użycie opisanych makr:
void CMyClass::Foo(TInt aIndex) {
__ASSERT_ALWAYS (aIndex > 0, Panic(_L("Błąd typu Panic"), 11));
}
Prototyp funkcji wygląda jak pokazano poniżej:
__ASSERT_ALWAYS(warunek, wyrażenie);
Kiedy to wyrażenie jest wykonane gdy warunek nie jest prawdą. W tym przypadku Panic zostanie wywołane
gdy aIndex będzie wartością mniejszą bądź równą zero, natomiast błąd zwrócony będzie treści „Błąd typu
Panic” (_L() musi być używane do przekazywania własnych treści.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Mechanizm Leave służy do wychodzenia z funkcji, natomiast TRAP oraz TRAPD do przechwytywania tych
wyjść, przy czym używanie przechwytywania nie jest zalecane ze względu na ich szybkość (a raczej nieszybkość) działania oraz pamięciożerność.
TRAP
TInt err;
TRAP(err, funkcjaL());
TRAP(D)
TRAPD –zajmuje się od razu deklaracją zmiennej; przykład użycia TRAPD:
TRAPD(err, funkcjaL());
oraz przykład użycia TRAP
TInt err; TRAP(err, funkcjaL());
Jak widać, w przypadku wersji TRAPD kod skraca się o jedną linijkę. Warto tutaj zauważyć, iż w przypadku
gdy nie zastosujemy żadnego przechwycenia w programie, system zrobi to za nas.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Leave
Mechanizm leave jest pewnym odpowiednikiem wyjątków z „normalnego” C++. Służy określeniu miejsc w
programie, gdzie coś może pójść nie tak nie z winy programisty. Są to na przykład funkcje, w których
alokujemy pamięć. Programista nie może wiedzieć, czy pamięć jest akurat dostępna. Jeżeli tak – wszystko w
porządku. Jeżeli nie – funkcja leave’uje. Funkcje które mogą leave’ować oznaczane są dużą literką L na
końcu. Nie jest to tylko kosmetyka.
•User::Leave()
•Wyjście z funkcji
•User::Leave(kodBłędu)
•Wyjście z funkcji z kodem błędu (jest przekazywany do TRAP(D))
•User::LeaveIfError(kodBłędu)
•Wyjście z funkcji tylko w przypadku gdy kodBłędu jest negatywny (mniejszy od 0, wszystkie
błędy są wartościami ujemnymi)
•User::LeaveNoMemory()
•Odpowiednik User::Leave(KErrNoMemory)
•User::LeaveIfNull(wskaźnik)
•Wychodzi z funkcji z KErrNoMemory jeśli przekazany wskaźnik jest NULL
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Należy zwrócić uwagę co się dzieje ze wszystkimi wskaźnikami, które zostały zainicjowane przed takim
wyjściem – otóż jeżeli zostanie on usunięty, natomiast miejsce w pamięci nadal jest zajęte. Miejsce w
pamięci nadal jest zajęte, jednak nie mamy do niego już dostępu - następuje wyciek pamięci.
CleanupStack
CleanupStack wykorzystywany jest, gdy po zaalokowaniu pamięci na dany obiekt, funkcja może wywołać
Leave nie dochodząc do momentu w którym uprzednio stworzony obiekt jest poprawnie usuwany.
Przykład użycia:
void JakasKlasa::FunkcjaL()
{
TInt * liczba = new (ELeave) TInt; //tutaj może dojść do wycieku pamięci…
…
delete liczba;
}
Klasa * nowy_obiekt = new (ELeave) Klasa; // tu może coś nie wyjść…
Nowy_obiekt->Funkcja();
delete nowy_obiekt;
Oraz jak to wygląda z CleanupStack:
Klasa * nowy_obiekt = new (ELeave) Klasa;
CleanupStack::PushL(nowy_obiekt);
Nowy_obiekt->FunkcjaL();
CleanupStack:PopAndDestroy(nowy_obiekt);
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
W takim przypadku, od razu po alokacji pamięci dla obiektu w następuje zachowanie tego wskaźnika na
CleanupStack. W momencie, gdy Funkcja() zakończy swe działanie nie powodując żadnego błędu, funkcja
CleanupStack::PopAndDestroy(nowy_obiekt) zdejmuje ten wskaźnik od razu go niszcząc, oraz usuwane
przydzielone mu zasoby. Natomiast jeżeli Funkcja() wyjdzie, wtedy jako część procesu czyszczenia
wszystkie obiekty znajdujące się na CleanupStack są poprawnie usuwane.
Istnieje kilka wariacji funkcji zdejmujących z CleanupStack:
•CleanupStack:Pop() – zdejmuje ze stosu ostatnio położony wskaźnik
•CleanupStack:Pop(2) – zdejmuje ze stosu ostatnie dwa położone wskaźniki
•CleanupStack:Pop(wsk) – zdejmuje ze stosu i sprawdza czy jest to wsk
•CleanupStack::PopAndDestroy(); oraz CleanupStack::PopAndDestroy(wskaźnik);
Funkcja zdejmuje wskaźnik do obiektu i od razu go niszczy (czyli wywołuje delete na obiekcie,
który ten wskaźnik pokazuje).
•CleanupStack::PushL(wskaźnik); - odkładanie wskaźników.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
-Nie odkładamy składowych klas na CleanupStack. Dlatego, że składowe klasy niszczymy w
destruktorze tej klasy, który będzie wywołany kiedy ta klasa będzie niszczona. Jeżeli odłożymy taką
zmienną, system będzie chciał zniszczyć obiekt dwa razy – pierwszy, bo będzie miał wskaźnik na stosie, a
drugi raz gdy będzie niszczył klasę w destruktorze.
-Podsumowując wskaźniki do obiektów odkładamy na stos wtedy, kiedy między stworzeniem obiektu a
jego zniszczeniem nie mamy gwarancji, że program na pewno nie wyjdzie. Jeśli takiego zagrożenia nie ma
– nie ma potrzeby stosowania tego mechanizmu. Tak więc że nie zawsze musimy odkładać na stos
wszystkiego, co tworzymy
Zatem Nie należy nadużywać tego mechanizmu i kłaść na CleanupStack tylko te wskaźniki, w których
pomiędzy stworzeniem a usunięciem może wystąpić Leave.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Programowanie i testowanie w Microsoft Mobile ASP.NET
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Rozwój oprogramowania
Systemy operacyjne urządzeń mobilnych
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Windows CE –
system operacyjny opracowany przez Microsoft jako system dla urządzeń
przenośnych typu PDA (np.: Pocket PC lub Palm) lub jako system wbudowany. Wersja 1.0 była bardziej
rozbudowanym organizerem niż systemem operacyjnym (z punktu widzenia użytkownika.)
Windows CE jest zoptymalizowany dla urządzeń o minimalnej pamięci – jądro Windows CE może być
uruchomione nawet w 1 MB pamięci. System nie wymaga d pracy dysku twardego, może być więc „system
zamkniętym”, i być umieszczony w pamięci ROM. Obsługuje 256 priorytetów wykonywania i korzysta z
dziedziczenia priorytetów w razie, przydatnych w sytuacji inwersji piorytetów. Podstawową jednostką
wykonywania jest wątek, co umożliwia prostsze zarządzanie procesami. Windows CE używany jest także w
komputerach pokładowych samochodów wraz z systemem rozpoznawania mowy mającym zapewnić
bezdotykową obsługę systemu operacyjnego.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Windows CE 1.x
specyfikacja urządzeń na których system miał pracować :
Wymiary nie większe niż 18x10x2.5 cm
Zasilanie z dwóch baterii AA
Waga mniejsza niż 500 g
Klawiatura QWERTY zawierająca klawisze takie jak SHIFT, CTRL i ALT
Dotykowy wyświetlacz LCD o rozdzielczości 480x240 pikseli w 4 odcieniach szarości
Minimum 4 MB pamięci ROM
Minimum 2 MB pamięci RAM
Port podczerwieni
Port COM zgodny z RS-232
Slot PC Card (PCMCIA)
Wbudowana obsługa dźwięku
Procesor SuperH 3, MIPS 3000 lub MIPS 4000
Microsoft nie wypowiedział się jednoznacznie co oznacza skrót CE, lecz twierdzi, że taka nazwa nie była
celowa. Oświadczył jednak, że CE wyrażać może w sobie wiele koncepcji, takich jak Compact (ang.
Kompaktowy), Connectable (ang. Łącznościowy), Compatible (ang. Kompatybilny). Najczęściej jednak
nazwę tłumaczy się jako "Compact Edition" lub "Consumer Electronics".
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Wygląd GUI systemu Windows CE 1.0
Źródło: Internet.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Wersje systemu
1 Windows CE 1.x
2 Windows CE HandheldPC 2.x
3 Windows CE 2.11 - Palm-Size PC 1.1
4 Windows CE 2.11 - Palm-Size PC 1.2
5 Windows CE HandeldPC 2.11 - HandheldPC Professional
6 Windows CE HandeldPC 3.x - HandheldPC 2000
7 Windows CE .net (4.x)
8 Windows CE 5.0
9 Windows CE 6.0
10 Windows Mobile (i ten system również posiada kilka wersji.)
Od wersji 4.0 z systemem zintegrowano .NET Compact Framework.
Windows CE 6.0 powstał we wrześniu 2006 roku. Nazwa kodowa "Yamazaki". M.in. zwiększono przestrzeń
adresową procesu z 32 MB do 1 GB i umożliwiono uruchomienie 32 768 procesów (w porównaniu z 32 w
wersji 5.0).
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Microsoft Windows Mobile
Microsoft Windows Mobile to 32-bitowy system operacyjny przeznaczony dla urządzeń typu Pocket PC oraz
Smartphone. Windows Mobile nie jest zupełnie osobnym systemem, lecz rozszerzeniem Windows CE o
dodatkową funkcjonalność, API (ang. Application Programming Interface) oraz Shell.
Dostępne wersje Systemu:
•Windows Mobile 2003
•Windows Mobile 2003SE
•Windows Mobile 5.0
•Windows Mobile 6.0 (64 MB RAM, wyświetlacz 3,5 cala)
•Windows Mobile 6.1 Classic
Istnieją wersje przeznaczone dla PocketPC z wbudowanym modułem GSM:
•Windows Mobile 2003 Premium Phone edition
•Windows Mobile 2003SE Phone edition
•Windows Mobile 5.0 (Magneto) Phone edition
•Windows Mobile 6.0 Phone edition
•Windows Mobile 6.1 Professional
•Windows Mobile 6.5 Professional
•Windows Mobile 6.5.1 Professional (w trakcie rozwoju)
•Windows Mobile 7 Professional (w trakcie rozwoju)
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Istnieją również wersje dla smartphone obsługujące ekrany 176x220 oraz 240x320 bez ekranu dotykowego:
•Smartphone 2002
•Windows Mobile 2003 for Smartphone
•Windows Mobile 2003SE for Smartphone
•Windows Mobile 5.0 for Smartphone
•Windows Mobile 6.0 for Smartphone
•Windows Mobile 6.1 Standard
Wygląd GUI systemu Windows Mobile 5.0
Źródło: Internet.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
.NET Compact Framework
Platforma umożliwiająca uruchamiane aplikacji napisanych w językach rodziny .NET, bedaca swego
rodzaju maszyną wirtualną (jak np. JVM).
Zatem można powiedzieć, że .Net Framework to maszyna wirtualna udostępniająca biblioteki,
odpowiedzialne za nisko-poziomową interakcję z systemem operacyjnym, językom zarządzanym (ang.
managed) wysokiego poziomu, np. C#.
Kod napisany w C# czy J# jest najpierw kompilowany do pośredniego języka MSIL (Microsoft
Intermediate Language). Wynikiem tego działania jest moduł zawierający instrukcje MSIL. Jedną z
przyczyn zastosowania MSIL jest mozliwość wykorzystywania wielu języków programowania (VB, C#,
J#, JScript, i Visual C++), skąd pojawia się konieczność pośredniej kompilacji kodu do MSIL. Następnie,
moduł ten zamieniany jest na natywne instrukcje danego systemu operacyjnego CLR (ang. Common
Language Runtime). Zatem .Net Framework postrzegać powinno się bardziej, jako platformę
wielojęzykową, a nie jak maszynę wirtualną (jak np. maszyna wirtualna Javy) – wieloplatformową.
Przeprowadzane są obecnie prace nad rozszerzeniem owych pięciu wspieranych języków programowania
do ponad dwudziestu pięciu .
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Architektura .NET Compact Framework
Źródło: Internet
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Common Language Runtime – wspólne środowisko uruchomieniowe. Jego podstawowym zadaniem jest
zlokalizowanie, wczytywanie oraz zarządzanie typami .NET w imieniu użytkownika. CLR zajmuje się
niskim poziomem pracy aplikacji np.: automatyczne zarządzanie pamięcią, integracją językową oraz
ułatwianie wdrożenia ( i wsparcie dla różnego rodzaju wersji ) bibliotek kodu binarnego.
CLR składa się z dwóch zasadniczych elementów:
Runtime execution engine - mechanizm wykonawczy środowiska uruchomieniowego – mscoree.dll.
Kiedy pakiet ( assembly ) jest wywoływany, automatycznie wczytywany jest mscoree.dll, który z kolei
wczytuje do pamięci potrzebny pakiet. Mechanizm uruchomieniowy jest odpowiedzialny za wykonanie
szeregu zadań. Pierwszym i najważniejszym jest określenie położenia pakietu i znalezienie wymaganego
typu ( np. klasy, interfejsu, struktury itp. ) w kodzie binarnym przez odczytanie dostarczonych metadanych.
Mechanizm wykonawczy kompiluje zasocjowany IL ( Intermediate Language ) do instrukcji specyficznych
dla danej platformy.
Biblioteka klas podstawowych. Składa się z kilku oddzielnych pakietów, najważniejszym jest mscorlib.dll.
Zawiera dużą liczbę podstawowych typów, które hermetyzują dużą różnorodność najczęściej spotykanych
zadań programistycznych. Każde rozwiązanie oparte na platformie .NET, zawsze wykorzystuje się ten pakiet
i czasem kilka innych .NET ( zarówno oferowanych przez system jak i przygotowanych przez użytkownika ).
Common Language Specification – specyfikacja wspólnego języka. Jest zbiorem zasad definiujących
podzbiór wspólnych typów (dla różnych języków), który daje pewność, że kod binarny .NET może zostać
bez klejenia wykorzystany przez wszystkie języki współpracujące na platformie .NET.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Common Type System – zbiór wbudowanych podstawowych i wspólnych typów. Zawiera
pełny opis wszystkich możliwych typów danych, obsługiwanych przez środowisko uruchomieniowe.
Zawiera także informacje, o tym, jakie interakcje mogą zachodzić między nimi, oraz określa szczegóły ich
reprezentacji w formie metadanych .NET.
Managed Code
- Kompilatory zgodne z CLR zamieniają kod źródłowy aplikacji na kod
wykonywalny, zapisany w standardowym języku pośrednim MSIL, oraz na metadane — informacje na temat
kodu wykonywalnego oraz danych wykorzystywanych przez ten kod. Platforma .NET umożliwia pisanie
aplikacji w wielu językach, ale dzięki MC kompilator zamienia wszystkie operacje na typach danych, to jest
klasach, strukturach, liczbach całkowitych, łańcuchach znaków — na język MSIL i metadane.
W czasie wykonywania aplikacji, CLR tłumaczy kod MSIL na kod maszynowy (natywny) procesora, na
którym wykonywana jest aplikacja. Taka konwersja kodu z MSIL na kod maszynowy daje możliwość
zarządzania wykonywaniem aplikacji, co pozwala uniknąć wielu problemów — stąd nazwa
”kod zarządzany”.
Garbage Collection – .NET Compact Framework zapewnie zwalnianie wszystkich zasób, z jakich
korzysta aplikacja, po jej zakończeniu. W tym celu wykorzystywany jest mechanizm o nazwie Garbate
Collection. Compact Framework decyduje kiedy powinien zostać uruchomiony proces Garbate Collection.
Może on zostać uruchomiony w pojedynczej domenie aplikacji bądź też we wszystkich dostępnych. Pozwala
to zapobiegać sytuacją, gdy jedna aplikacja zużywa zbyt dużo pamięci w porównaniu z innymi.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Class Library Support
Klasy są zorganizowane hierarchicznie wewnątrz przestrzeni nazw ( namespace ). .NET Compact
Framework współdzieli około 2/3 klas z pełną wersją .NET Framework. Mimo to występują pomiędzy nimi
pewne istotne różnice, i trzeba być tego świadom podczas tworzenia aplikacji z wykorzystaniem .NET
Compact Framework.
Klasy współdzielone:
.NET Compact Framework dostarcza szeroki podzbiór klas i metod do budowania aplikacji, które są
później uruchamiane na urządzeniach z ograniczonymi zasobami. Wszystkie te klasy są semantycznie
kompatybilne z klasami o tych samych nazwach w .NET Framework. .NET Compact Framework
posiada wsparcie dla istotnych elementów takich jak:
·
Usługi sieci Web oparte na XML
·
Zarządzanie relacyjnymi danymi
·
Rozbudowana funkcjonalność XML
·
Rozbudowane klasy do rysowania, takie jak Image Controls
·
Potężne możliwości budowania interfejsu użytkownika.
.NET Compact Framework nie wspiera klas ASP .NET.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Klasy tylko dostępne w Compact Framework:
Podczas tworzenia aplikacji z wykorzystaniem .NET Compact Framework należy pamiętać o klasach
dostępnych jedynie w tym środowisku. Chodzi np. o klasę Infrared Data Association ( IrDA ) do
nawiązywania połączeń do serwera i dostarczania informacji o porcie podczerwieni. Kolejnym przykładem
jest klasa SQL Server CE, która pozwala na pracę z lokalnym serwerem bazy danych SQL Server CE.
Narzędzie Class Library Comparison Tool – pozwala na przeglądanie różnic między klasami dostępnymi w
.NET Framework i Compact Framework. Dla każdej klasy można sprawdzić, które pola, metody i
właściwości są dostępne w obydwu lub też w jednym z nich.
Wiele z klas dostępnych w .NET Framework nie jest dostępnych w Compact Framework. Powodem tego są
ograniczenia co do zasobów i wydajności urządzeń mobilnych.
CLR dla .NET Compact Framework stanowi około 12 % rozmiaru całego .NET Compact Framework.
Rozmiar ten jest ograniczony, po to aby zwiększyć wydajność. Pomimo braku wsparcia dla GDI+ Compact
Framework obsługuje podstawowe rysowanie GDI takie jak: bitmapy, pędzle, pióra, czcionki i ikony.
Compact Framework nie pozwala na tworzenie nowych usług sieci Web, ale umożliwia wykonywanie
istniejących usług sieci Web.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Dalsze różnice:
·
- COM Interop – nie wspierane, należy wykonywać funkcje DLL, które wywołują obiekty COM
- Data – podzbiór implementacji ADO .NET oraz SQL Server CE
- ASP .NET – nie wspierany. Należy używać ASP .NET Mobile Web Controls do tworzenia stron sieci WWW
dla urządzeń przenośnych
- XML – ze względu na rozmiar brak obsługi walidacji XML schema lub zapytań XPath w dokumentach
XML.
- Aby zmniejszyć rozmiary środowiska zrezygnowano z wielu przeładowanych metod
- Brak niektórych kontrolek ( np. wsparcia dla drukowania )
- Ze względu na wydajność brak klas BinaryFormatter i SoapFormatter
- Bezpieczeństwo – brak zabezpieczenia dostępu do kodu niezarządzanego. Dowolna aplikacja może
wywołać dowolny system lub nie systemowe API. Brak systemu bezpieczeństwa opartego na rolach
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
•W tablicach .NET Compact Framework nie zwraca wyjątku MissingMethodException;
•Możliwość pisania aplikacji ASP .NET za pomocą kontrolek przeznaczonych dla urządzeń mobilnych;
•Możliwość stosowania assemblies (bez używania wielu modułów w .NET Compact Framework);
•Common Language Runtime oraz kompilacja Just-In-Time (JIT) są używane przed obydwa
framework’i;
•.NET Compact Framework dziedziczy większość kontrolek używanych do pisania aplikacji Windows
Forms;
•.NET Compact Framework nie ma metod GetCurrentDirectory oraz SetCurrentDirectory. Zamiast tego
programista powinien używać właściwości WorkingDirectory oraz obiektu ProcessStartInfo;
•Aplikacje na .NET Compact Framework można pisać z wykorzystaniem C# lub Visual Basic.
Aktualnie C++ nie jest wspierany;
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Platformy, narzędzia i technologie
Narzędzia:
Smart Device Extensions (SDE) for Microsoft Visual Studio .NET – tworzenie aplikacji, które w całości
działają na urządzeniach przenośnych. SDE rozszerza funkcjonalność Microsoft Visual Studio o tworzenie
aplikacji na różnego rodzaju urządzenia mobilne przy czym pozwala wykorzystać praktycznie wszystkie
dostępne możliwości Visual Studio. Stwarza to jedno środowisko do tworzenia aplikacji na urządzenia
przenośne, komputery PC i serwery. SDE pozwala na projektowanie, debugowanie i wykonywanie aplikacji
na wielu z dzisiejszych urządzeń mobilnych. SDE zawiera ponadto kilka dobrym, ekranowych emulatorów
dla urządzeń przenośnych. Dostępne są emulatory dedykowane dla Pocket PC, Pocket PC 2002, Smart
phones i dla urządzeń działających pod kontrolą systemu Windows CE .NET.
Microsoft Mobile Internet Toolkit (MMIT) – służy do tworzenia aplikacji, których kod wykonywany jest
na serwerze. W takich aplikacjach po stronie serwera mamy Microsoft SQL Server oraz Microsoft
Information Services ( IIS ).
MMIT pozwala na łatwe tworzenie złożonych aplikacji Webowych, których docelową (kliencką) platformę
stanowią urządzenia mobilne. Dzięki temu rozwiązaniu pisanie oprogramowanie na urządzenia mobilne staje
się proste i wydajne.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
MMIT dostarcza wszelkich korzyści projektowania aplikacji z pomocą ASP .NET. Ponadto MMIT
posiada następujące udogodnienia:
- Wsparcie dla szerokiej gamy urządzeń. Pozwala na używanie ASP .NET na wielu urządzeniach mobilnych,
począwszy na telefonach komórkowych, skończywszy na urządzeniach Pocket PC.
- Strony WWW stworzone z wykorzystaniem MMIT są tak samo prezentowane na wszystkich wspieranych
urządzeniach, nie trzeba jej dostosowywać do poszczególnych urządzeń. Można tworzyć złożoną aplikację
wykorzystując zbiór mobilnych kontrolek serwerowych bez żadnej wiedzy na temat WML-a lub innych
podobnych języków. Środowisko uruchomieniowe bierze na siebie odpowiedzialność za różnice w
implementacjach pomiędzy różnymi przeglądarkami, urządzeniami i bramkami sieciowymi.
- Możliwość personalizacji i rozszerzania funkcjonalności. MMIT dostarcza takie same możliwości
personalizacji i rozszerzalności jak ASP .NET. W dodatku narzędzie pozwala na dodawanie obsługi nowych
urządzeń, bez konieczności jakiejkolwiek zmiany w kodzie aplikacji. Dzięki temu można mieć pewność, że
aplikacja stworzona dzisiaj będzie w przyszłości działała na nowej generacji urządzeń.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Możliwości programistyczne w Windows Mobile 5.0
Windows Mobile 5.0 zapewnia programistom nowe, liczne interfejsy programistyczne. Dzięki nim,
programista może się skupić na konkretnych celach aplikacji, a nie sposobach ich realizacji.
Elementy wspomaganie przez interfejsy to np.: rysowanie 2D i 3D, dostarczają nowych możliwości
komunikacyjnych oraz ułatwiają obsługę elementów sprzętowych takich jak kamera czy też system nawigacji
satelitarnej. Inne usprawnienia to m. in. :
1.
2.
3.
4.
5.
6.
7.
8.
Nowe interfejsy API dostarczają wielu nowych możliwości np.: zarządzanie obrazami,
kontaktami,
Większa przenośność kodu i aplikacji pomiędzy urządzeniami Pocket PC a Smartphone.
Nowe API do śledzenia aktywności systemu takich jak: zmiany w połączeniu z siecią, odbiór
wiadomości SMS lub nadejście połączenia telefonicznego;
Rozbudowane narzędzia do testowania aplikacji w zależności od orientacji ekranu, rozdzielczości
czy też rodzaju urządzenia – przyspieszają tworzenie aplikacji w Visual Studio.
API do obsługi wbudowanego aparatu.
Windows Media Player 10Mobile pozwala na łatwa dołączenie multimediów do tworzonej
aplikacji (np. wbudowanie odtwarzacza multimedialnego).
Obsługa Direct3D dostarcza możliwości tworzenia aplikacji trójwymiarowych.
Obsługa DirectDraw zapewnia większą kontrolę i elastyczność w aplikacjach 2D.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Windows Mobile 5.0 posiada zainstalowane domyślnie w pamięci ROM środowisko .NET Compact
Framework 1.0 wraz z SP3. Możemy wyróżnić trzy rodzaje API:
- Nowo dodane API kierowane do programistów tworzących aplikacje w kodzie natywnym;
- Istniejące wcześniej natywne API, ale teraz dodatkowo dostępne dla programistów kodu
zarządzanego;
- Nowo dodane API dostępne zarówno dla programistów kodu natywnego jak i zarządzanego.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Podstawy działa Garbage collection
Garbage collection (zbieranie nieużytków) to architektura zarządzania pamięcią, w której proces zwalniania
nieużywanych jej obszarów odbywa się automatycznie. Mechanizm taki stosuje się na przykład w
wysokopoziomowych językach programowania, przy czym za jego obsługę nie odpowiada sam język, lecz
wirtualna maszyna.
Garbage collection zostało wymyślone przez Johna McCarthy'ego około roku 1959 do rozwiązania
problemu ręcznego zarządzania pamięcią w Lispie. Był to pierwszy język obsługujący ten mechanizm.
Przykładowymi językami obsługującymi ten mechanizm są Smalltalk, Python, Ruby, Java, C#. Istnieje co
najmniej kilka metod pracy GC.
Liczenie odnośników (reference counting)
W tej metodzie każda jednostka zarezerwowanej pamięci ma licznik, w którym jest zapisana liczba odwołań
do tej jednostki.
Za każdym razem, kiedy dodajemy odwołanie, zwiększamy licznik we wskazywanej jednostce, a kiedy
odwołanie usuwamy, zmniejszamy licznik. Jeśli wartość licznika osiągnęła zero, to usuwamy wszystkie
odnośniki wychodzące z tego obszaru pamięci i zwalniamy go.
Metoda ta nie gwarantuje zwolnienia wszystkich niepotrzebnych obszarów w sytuacji, gdy występują tzw.
wzajemne (cykliczne) odwołania. Przykładowo, jeśli X zawiera wskaźnik na Y, a Y zawiera wskaźnik na X
(np. są to dwa komunikujące się ze sobą obiekty), licznik w żadnym z nich nigdy nie osiągnie zera.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
W liczeniu odnośników dodatkowe obliczenia związane z pracą kolektora nieużytków są rozłożone w czasie,
gdyż wszystkie operacje muszą dbać o liczniki, co może skutkować znacznie mniejszym - lub też przeciwnie
- znacznie większym, obciążeniem w porównaniu z innymi metodami.
Mark and Sweep. W tej metodzie każda jednostka pamięci zawiera pojedynczy bit, który jest na początku
czysty. Kiedy maszyna wirtualna przechodzi w fazę "garbage collection", zaczyna sprawdzać obiekty, o
których wie, że istnieją do nich odwołania, zaznacza w nich ten bit i rekursywnie przechodzi przez wszystkie
komórki przez nie wskazywane. Kiedy już wszystko zostało oznaczone, komórki bez znacznika są zwalniane,
bo na pewno nic na nie nie wskazuje, po czym znacznik jest czyszczony wszystkim komórkom.
Mark and Sweep jest obecnie najpopularniejszą metodą.
Garbage collection przez kopiowanie
Ta metoda polega na tym, że wszystko zostaje rekursywnie przekopiowane do innego obszaru w pamięci najpierw kopiowany jest początkowy zestaw danych, potem wszystko co było przez niego wskazywane, itd.
Na końcu zwalniamy początkową pamięć.
W ten sposób „przez odsiew” usuwane zostają elementy, na które nic nie wskazuje.
I w ten sposób oszczędza się na konieczności ustawiania bitów w "mark and sweep", dodatkowo, regularnie
defragmentuje się pamięć. Problemy jakie mogą wystąpić to konieczność poniesienia kosztu kopiowania
oraz konieczność posiadania dużej ilości wolnej pamięci. Ten sposób byłby bardziej praktyczny na
systemach, na których możliwa jest tymczasowa alokacja dużej ilości pamięci.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Programowanie i testowanie w Microsoft Mobile ASP.NET
przykłady
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykład Tworzenia aplikacji, spełniającej funkcje klienta poczty elektronicznej (Outlook).
Co będzie potrzebne ?
Visual Studio 2005 - środowisko programistyczne, które jest także platformą do rozwijania aplikacji mobilnych
wykorzystujących biblioteki i narzędzia Microsoftu. Niestety do naszych potrzeb jest wymagana wersja
minimum Standard i nie wystarczy nam darmowa Express Edition.
Windows Mobile 5.0 SDK - zestaw bibliotek i narzędzi do tworzenia aplikacji na urządzenia mobilne
wyposażone w systemy operacyjne firmy Microsoft.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Pocket Outlook. Zawiera w sobie zarządzanie kontaktami, notatkami i zadaniami, jest to usługa, która działa
„w tle”. Pełni ona tutaj rolę serwera danych, udostępniającego je na życzenie innych, korzystających z nich
aplikacji. Jedną z nich będzie, ta, którą zaraz przygotujemy.
using Microsoft.WindowsMobile.PocketOutlook;
(1)
public static OutlookSession outlook = new OutlookSession();
(2)
foreach (Contact contact in outlook.Contacts.Items)
(3)
{
lstAll.Items.Add(contact);
}
(1) dodanie na przestrzeni nazw pakietu „Outlook”
(2) dodanie zmienną statyczną "outlook”.
(3) kod wypełniający naszą listę kontaktami otrzymanymi od Outlooka (umieszczony jest on w konstruktor
naszej aplikacji).
lstAll - kontrolka listy (ListBox), znajduje się w zasobniku, w grupie Common Device Controls.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Klasa OutlookSession jest głównym interfejsem do komunikacji z programem Pocket Outlook i pobierania
wszystkich udostępnianych przez niego danych. Wystarczy zatem jeden obiekt tego typu, ale musi być on
udostępniony dla wszystkich komponentów aplikacji. Dlatego też udostępniliśmy go jako publiczną zmienną
statyczną w klasie, która reprezentuje główna formę aplikacji.
Windows Mobile pozwala na przechowanie prawie czterdziestu różnych informacji o pojedynczej osobie –
Jest to zadanie klasy Contact.
if(!string.IsNullOrEmpty(textBox1.Text))
(4)
{
Contact newContact = new Contact();
newContact.FirstName = textBox1.Text;
newContact.MobileTelephoneNumber = textBox2.Text;
Form1.outlook.Contacts.Items.Add(newContact);
Close();
}
(4)
Metoda dodająca nowy kontakt.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
private void ReadContacts()
(5)
{
lstAll.Items.Clear();
foreach (Contact contact in outlook.Contacts.Items)
{
lstAll.Items.Add(contact);
}
}
(5) Metoda odczytująca zapisane kontakty.
Należy te operacje powtarzać po dodaniu każdego nowego rekordu, jeśli chcemy zobaczyć nowy rekord.
Dzięki gotowej bibliotece Microsoft Telephony API nawiązanie polaczenia jest czynnością bardzo prostą.
Przedstawiona aplikacja pokazuje zaledwie mały procent możliwości, jakie daje nam to środowisko.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
private void lstAll_SelectedIndexChanged(object sender, EventArgs e)
(7)
{
if(lstAll.SelectedItem != null)
{
Contact selected = (Contact)lstAll.SelectedItem; // ustanowienie połączenia
Phone phone = new Phone();
phone.Talk(selected.MobileTelephoneNumber);
}
}
(7) Metoda nawiązująca połączenie. Uruchomiona zostanie, gdy wystąpi zdarzenie „SelectedValueChanged”.
Środowisko stworzy szkielet metody do obsługi zdarzenia, a nam pozostanie wypełnić ją treścią.
Funkcja najpierw sprawdza, czy element listy został zaznaczony (użytkownik mógł go również "odznaczyć"),
potem zamienia element listy na obiekt typu Contact w celu wyłuskania z niego numeru telefonicznego,
po czym wykonuje faktyczne połączenie
Obiekt typu Phone pozwala na nawiązywanie połączeń. Można to zrobić wywołując jego metodę Talk() i
podając jako parametr żądany numer telefonu. Warto zauważyć, że parametr ten jest literałem i można go
podać w postaci alfanumerycznej, jak często podaje się numery telefonów w Stanach Zjednoczonych - na
przykład 1-800-MY-APPLE.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
using Microsoft.WindowsMobile.Telephony;
(8)
private void lstAll_SelectedIndexChanged(object sender, EventArgs e)
(9)
{
if(lstAll.SelectedItem != null)
{
Contact selected = (Contact)lstAll.SelectedItem;
SmsMessage sms = new SmsMessage(selected.MobileTelephoneNumber, "Cześć!"); //wysłanie SMS-a
outlook.SmsAccount.Send(sms);
}
}
(8) – potrzebne, aby móc nawiązywać połączenia telefoniczne.
(9) – Metoda wysyłająca sms.
Ponieważ rozmowy i wysyłanie krótkich wiadomości tekstowych SMS są funkcjami dostępnymi tylko w
fizycznych urządzeniach i nie działają w emulatorze, to aby przetestować pełne działanie naszej aplikacji,
trzeba użyć fizycznego urządzenia. Cała pozostała funkcjonalność może być jednak bez żadnych problemów
testowana w emulatorze, jednak kiedy wywołamy funkcję połączenia, czy wysłania widomości, skończy się
to błędem.
Przykład pochodzi z :
http://www.pcworld.pl/news/126721_5/Programowanie.komorek.z.Windows.Mobile.latwiejsze.niz.myslisz.html
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Dalsze możliwości:
Phone telefon = new Phone();
telefon.Talk("112");
telefon.Talk("112", true);
using Microsoft.WindowsMobile.PocketOutlook; // Dodajemy nowe spotkanie I ustawiamy mu szczegóły
Appointment spotkanie = new Appointment();
spotkanie.Subject = "Nowe spotkanie testowe"; // Ustawiamy temat naszego spotkania
// Ustawiamy początek spotkania na 21 luty 2006 o
// 18:30
spotkanie.Start = new DateTime(2006, 02, 21, 18, 30, 00);
spotkanie.Duration = new TimeSpan(01, 00, 00); // Długość trwania spotkania ustalamy na 1 godz.
spotkanie.ReminderVibrate = true; // Jako przypomnienie ustawiamy wibrację
using (OutlookSession sesja = new OutlookSession()) // Tworzymy sesję Outlooka i dodajemy nasze nowe spotkanie
{
sesja.Appointments.Items.Add(spotkanie);
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
using Microsoft.WindowsMobile.PocketOutlook;
EmailMessage wiadomosc = new EmailMessage(); //tworzymy nową wiadomość email
wiadomosc.To.Add(new Recipient("[email protected]")); //dodajemy adresata naszej wiadomości
wiadomosc.Subject = "temat"; //ustawiamy temat wiadomości
wiadomosc.BodyText = "Przykładowy email z jakimś załącznikiem"; //wpisujemy treść wiadomości
wiadomosc.Attachments.Add(new Attachment(@"\pim")); //dodajemy załącznik do naszego email-a
using (OutlookSession sesja = new OutlookSession()) //wysyłamy wiadomość przy użyciu domyślnego konta pocztowego
{
sesja.EmailAccounts[0].Send(wiadomosc);
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykład wykorzystania Bluetooth
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Sockets;
using InTheHand.Net.Ports;
using InTheHand.Net;
BluetoothClient BClient = new BluetoothClient();
BluetoothDeviceInfo[] DevicesInfo = BClient.DiscoverDevices();
StringBuilder Info = new StringBuilder();
ClassOfDevice Class;
DeviceClass Device;
ServiceClass Service; // uslugi, oddzielone przecinkiem
foreach (BluetoothDeviceInfo device in DevicesInfo)
{
Info.Append("Class of device: " + Class.ToString() + "\r\n");
Info.Append("Device: " + Device.ToString() + "\r\n");
Info.Append("Service: " + Service.ToString() + "\r\n");
}
InTheHand – bibioteka dla platformy .NET, dostepna pod adresem: http://inthehand.com/content/32feet.aspx
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
private void ConnectBT(String Adres)
{
try
{
bluetoothClient.Connect(new BluetoothEndPoint((BluetoothAddress)Adres);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Programowanie i testowanie w Adroid OS
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Historia
Historia Androida rozpoczyna się w lipcu 2005 roku, kiedy to Google zakupiło Android Inc., niewielką firmę
z Kalifornii. Założyciele firmy, którzy zaczęli pracę w Google to m.in. Andy Rubin (współzałożyciel firmy
Danger), Rich Miner (współzałożyciel Wildfire), Nick Sears (T-Mobile) i Chris White (jeden z pierwszych
inżynierów w WebTV). Wtedy o Android Inc wiedziano tylko tyle, że produkuje oprogramowanie dla
urządzeń mobilnych. Już w Google zespół pod kierownictwem Rubina stworzył system operacyjny dla
urządzeń mobilnych, oparty na Linuksie, z myślą o wytwórcach sprzętu mobilnego i operatorach telefonii
komórkowej. Google już wtedy dobrał sobie partnerów w świecie sprzętu komputerowego i oprogramowania
oraz zasygnalizował operatorom komórkowym gotowość do współpracy.
5 listopada 2007 roku powstło Open Handset Alliance, konsorcjum w którego skład wchodzą Google, HTC,
Intel, Motorola, Qualcomm, T-Mobile, Sprint Nextel oraz NVIDIA. Powstało z myślą o rozwoju otwartych
standardów dla telefonii mobilnej. Wraz z ogłoszeniem powstania OHA zaprezentowano platformę Android.
12 listopada 2007 roku OHA opublikowało pierwszą wersją Android SDK, w którego skład wchodzą
narzędzia programistyczne, debugger, biblioteki, emulator, dokumentacja, przykładowe projekty, tutoriale,
FAQ i inne. Programiści muszą zainstalować Android SDK na komputerze kompatybilnym z x86 z systemem
Windows XP lub Vista, Mac OS X 10.4.8 (lub późniejszym), bądź Linux (testowane na Ubuntu Linux Dapper
Drake). SDK wymaga także Java Development Kit, Apache Ant i Pythona 2.2 (bądź późniejszego). Eclipse
3.2 (bądź późniejsze) jest jedynym oficjalnie obsługiwanym IDE dzięki wtyczce Android Development Tools
Plugin, ale programiści mogą także używać narzędzi konsolowych w celu tworzenia i debugowania aplikacji
na Androida.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Pierwszym telefonem wyposażonym w ten system operacyjny stał się HTC Dream, w Polsce sprzedawany
pod marką Era G1 przez sieć Era od lutego 2009 roku. Kolejne telefony z Androidem to HTC Magic, (W
Polsce sprzedawany od czerwca 2009), oraz Samsung I7500 Galaxy. W czerwcu 2009 HTC zaprezentowało
telefon HTC Hero który został wyposażony w HTC Sense, autorski interfejs użytkownika, wdrożony do
platformy Android przez producenta telefonu. W związku z warunkami licencji telefon z HTC Sense nie
może posiadać znaczka "with Google" nadrukowanego na obudowie, gdyż HTC wprowadziło daleko idące
zmiany w platformie Android.
Architektura Systemu
System Android oparty jest o system Linux, posiada jadro w wersji 2.6, dostarcza ono podstawowy
system usług takich jak ochrona, zarządzanie pamięcią, zarządzanie procesem, obsługa sieci itp. Jądro
również służy jako warstwa komunikacji między hardwar'em a softwar'em.
Wyższa warstwa zawiera biblioteki systemowe zapewniające obsługę m. in.
•
Bazy danych SQLlite
•
Protokołu SSL
•
Multimediów (MPEG4, H.264, MP3, AAC, AMR, JPG, PNG, gif)
•
Grafiki 2D / 3D, grafika 3D oparta na OpenGL ES 1.0 (przyśpieszenie sprzętowe jako opcja)
•
System C library
•
Inne
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Architektura Systemu Android
Źródło: http://android.gsm.pl
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Linux Kernel
Linux Kernel 2.6.25 for ARM
bezpieczeństwo, zarządzanie pamięcią, zarządzanie procesami, obsługa sieci i sterowniki.
Wspiera architekturę ARM od wersji V5T Do obsługi androida wykorzystuje się szereg rozszerzeń:
alarm, ashmem, binder, power management, low memory killer, kernel degugger, and logger.
Obsługa systemu plików FAT32
Obsługa TCP/IP (TCP, UDP, etc)
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Cechy systemu:
1.
Platforma aplikacji umożliwiająca ponowne wykorzystanie i wymianę modułów
2.
Dalvik maszyna wirtualna zoptymalizowana dla urządzeń mobilnych
3.
Zintegrowana przeglądarka oparta na wolnym oprogramowaniu WebKit
4.
Zoptymalizowana grafika wykorzystująca grafikę 2D; grafika 3D oparta na OpenGL ES 1.0
(przyśpieszenie sprzętowe jako opcja)
5.
SQLite dla przechowywania danych
6.
Obsługa formatów multimedialnych audio, wideo, obraz (MPEG4, H.264, MP3, AAC, AMR,
JPG, PNG, gif)
7.
Obsługa GSM
8.
Obsługa Bluetooth, EDGE, 3G, i WiFi, CDMA.
9.
Obsługa aparatu fotograficznego, GPS, kompas, and accelerometr
10. Przyjazne środowisko programistyczne z możliwością emulacji urządzenia, narzędzie do
usuwania usterek, ustawienia wydajności oraz wykorzystania pamięci, plugin dla środowiska
Eclipse
11. Wsparcie dla XML.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Framework Aplikacji
Programiści mają dostęp do tego samego API z jakich korzystają podstawowe aplikacje. Pod spodem
działających aplikacji znajduje się szereg aplikacji, usług i podsystemów:
•Zestawi Widoków, które można używać do budowania aplikacji (listy, siatki, kontenery tekstowe,
przyciski, wbudowana przeglądarka)
•"Content Providers", czyli system umożliwiający dostęp do danych innych aplikacji (np. Kontaktów),
lub do ich współdzielenia.
•Menedżer Zasobów zapewniający dostęp do zasobów takich jak lokalizacje, grafika i pliki layoutów
•Menedżer Powiadomień pozwalający wyświetlać własne powiadomienia w pasku stanu
•Menedżer Aktywności zarządzający cyklem życia aplikacji i udostępniający standardową nawigację
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Biblioteki
Android zawiera zbiór bibliotek C/C++ używanych przez różne componenty systemu. Te funkcje są
prezentowane dla programistów poprzez "Android application framework". Niektóre z głównych bibliotek są
wymienione poniżej:
- System C - pochodzaca z BSD implementacja standardowej biblioteki C (libc), przystosowana do urządzeń
bazujących na Linuxie
- Media Libraries- oparta na PacketVideo's OpenCORE; biblioteki wspierają odtwarzanie i nagrywanie wielu
popularnych formatów audio i video tak jak i statycznych plików graficznych: MPEG4, H.264, MP3, AAC,
AMR, JPG, PNG
- Surface Manager- zarządza dostępem do podsystemu wyświetlania aby bezkolizyjnie tworzyć ramki grafiki
2D i 3D z wielu aplikacji
- LibWebCore - nowoczesny silnik przeglądarki sieciowej, ktory zasila zarówno przeglądarkę Androida jak i
wbudowaną przeglądarkę internetową
- SGL - silnik grafiki 2D
- 3D libraries - implementacja bazująca na OpenGl ES 1.0 API; biblioteka używa zarówno sprzetowej
alceleracji 3D (tam gdzie to możliwe) jak i włączonego w nią wysoko zoptymalizowanego programowego
rasterizera 3D
- FreeType - renderowanie bitmap i grafiki vektorowej
- SQLite - potężna i lekka relacyjna baza danych dostępna dla wszystkich aplikacji
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przykłady urządzeń z zainstalowanych systemem Android
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Dalvik virtual machine
Językiem, w którym pisane są aplikacje na Androida jest Java. Zwykle pliki z kodem źródłowym napisanym
w Javie kompilowane są do plików .class, zawierających instrukcje dla wirtualnej maszyny. Instrukcje te
nazywa się bytecode ‘em Javy (Java Bytecode). W momencie uruchomienia aplikacji wirtualna maszyna
(JVM) ładuje owe pliki do pamięci i uruchamia zawarty w nich kod.
Android nie posiada JVM! Zamiast JVM, Google zdecydował się wyposażyć Androida w technologię Dalvik.
Dlaczego powstał Dalvik?
Java nie jest już nową technologią, także od dłuższego czasu znajduje zastosowanie w urządzeniach
mobilnych, pozwoliło to znaleźć pewne (choć) nieliczne, słabe punkty JVM. Jednakże Sun nie zdecydował
się na radykalne zmiany, zatem Google postanowił takowych dokonać. Tak właśnie powstał Dalvik –
nowoczesna wirtualna maszyna, przystosowana specjalnie do urządzeń mobilnych, gdzie szczególną uwagę
należy zwrócić na małe zasoby pamięci, energii i niewielką prędkość procesorów.
Wśród narzędzi zawartych w SDK znajduje się kompilator. Kompilator ten nie tworzy jednak plików .class z
bytecode’m Javy, lecz pliki .dex z bytecode’m Dalvik’a. Następnie skompilowane pliki, wraz ze strukturą
katalogów i znajdującymi się w nich multimediami, zostają spakowane – zamiast do pliku .jar - do pliku .apk
(Android Package). Tak przygotowana aplikacja uruchamiana jest przez wirtualną maszynę Dalvik’a.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Podstawowe różnice pomiędzy JVM Javy i DVM.
• Lepsza obsługa pamięci,
• Lepszy Garbage Collector,
• Większą wydajność.
• Aplikacje pobierają mniej energii.
• Bytecode Dalvik’a nie jest w 100% kompatybilny z bytecode’m Javy. Nie zadziałają więc na Adnroidzie
bardziej wyrafinowane sztuczki programistyczne, korzystające z Class Loader’ów czy Java Reflection API.
Powoduje to także problemy z uruchomieniem na Androidzie projektów korzystających np. z języków takich
jak Groovy, JRuby czy Jython.
• Brak wsparcia dla niektórych klas znanych z J2ME, np. AWT czy Swing.
• Brak JIT (ang. just-in-time compilation)
Niekompatybilność Darvick VM jest jednak pewną wadą – dlatego Google rozważa możliwość pewnego
„upodobnienia” DVM do JVM, m. in.: wprowadzenie ClassLoader’ów takie jak w Javie, a także pełne
wsparcie dla Reflection API.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Programowanie aplikacji dla platformy Android
Co będzie potrzebne?
Abyśmy mogli programować, musimy najpierw pobrać odpowiednie SDK ze strony
http://code.google.com/android/download.html.
Należy także spełnić stosowne wymagania systemowe – SDK zadziała na Windows XP lub Vista, MacOS X
10.4.8 lub nowszy (tylko na platformie x86)), Linux, będziemy potrzebować także JDK w wersji 5 lub 6.
Wskazane jest zainstalowanie również środowiska Eclipse, ze względu na prostotę zarządzania projektami,
nad którymi będziemy pracować.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Model aplikacji
Pakiet android (.apk)
Plik zawierający kod i ewentualne zasoby aplikacji,
Task
Jest to ta cześć pakietu, która użytkownik uważa za aplikację
Proces
proces jadra, w którym uruchamiana jest aplikacja, zwykle cały kod .apk uruchamiany w jednym procesie,
Watek
w ramach procesu jeden lub więcej wątków. Android unika tworzenia własnych dodatkowych
wątków, dopóki nie jest to konieczne
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Cykl życia aplikacji
Tworząc nową aktywność (Activity) wywoływana jest metoda onCreate(), a
następnie onStart() i onResume(). Dziedzicząc po klasie Activity, nie jest
konieczne implementowanie każdej z tych metod. Najczęściej nadpisuje się
metodę onCreate(), zawierając w niej kod, który jest uruchamiany podczas
uruchomienia aktywności.
W chwili gdy użytkownik uruchomi nową aktywność czy wręcz aplikację,
poprzednia jest wstrzymywana, co objawia się wywołaniem metod
onPause() oraz onStop(). W przypadku gdy użytkownik powróci do ekranu,
system wywołuje metodę onRestart(), a gdy aplikacja jest zamykana onDestroy().
W przypadku tworzenia rozbudowanego systemu z dużą liczbą klas
dziedziczących po Activity, należy mieć na uwadze cykl ich życia. W
przeciwnym wypadku łatwo można pogubić się w całym procesie, co może
skutkować np. niemożnością zamknięcia całej aplikacji przez użytkownika.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Programowanie i testowanie w Android OS
przykłady
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Adroid rozdziela tworzenie Gui od logiki programu. W klasie „MainActivity” zawarta jest logika programu,
Natomiast w plikach „main.xml” i „strings.xml” znajdują się elementy GUI.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Klasa „Activity”
public class HelloAndroid extends Activity
{ /** Called when the activity is first created. */
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); s
etContentView(R.layout.main);
}
}
Do metody onCreate przekazywany jest stan Activity z poprzedniego uruchomienia. Na początku trzeba
wywołać metodę onCreate klasy Activity po której dziedziczymy (super.onCreate – żeby pojawiło się czarne
okienko, które będziemy mogli wypełnić).
Podstawową “jednostką” w aplikacji jest Activity, czyli aktywność z którą użytkownik ma do czynienia,
pojedyncza “strona” aplikacji. Aplikacja może mieć wiele Activity.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Android rozdziela funkcje „logiki” programu, od jego części wizualnej. Ta bowiem zapisana jest w dwóch
plikach, w formacie XML-a – „main.xml” oraz „Strings.xml”
main.xml opisuje 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 podawana jest
otwartym tekstem zawartość, która ma zostać wyświetlona. lub referencję do wartości podanej w pliku
res/values/strings.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>
Przykładowy plik „main.xml”
<?xml version="1.0" encoding="utf-8"?> <resources>
<string name="app_name">Hello Android</string> <string name="hello">Hello World,
HelloAndroid!>/string>
</resources>
Przykładowy plik „Strings.xml”
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android
"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=„Tytul Pola"/>
</RelativeLayout>
Przykład pliku „Main.xml” – GUI będzie zawierał tylko jedno pole tekstowe o id „label”
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
<EditText
android:id="@+id/Liczba1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:layout_below="@id/label"/>
<EditText
android:id="@+id/Liczba2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:layout_below="@id/label"/>
/EditText>
Definicja dwóch pól tekstowych, w których można zapisać dwie liczby
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dip"
android:text=„Oblicz" />
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/ok"
android:layout_alignTop="@id/ok"
android:text=„Wyjdz" />
Definicja dwóch przycisków typu Button.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
<TextView
android:id="@+id/wynik"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=„Wynik"/>
</RelativeLayout>
Definicja pola tekstowego, w którym umieszczony zostanie wynik działania.
<RadioGroup android:id="@+id/dzialanie" android:layout_height="wrap_content" android:layout_width="fill_parent">
<TextView android:text="@string/dzialanie" android:layout_height="wrap_content" android:layout_width="fill_parent"/>
<RadioButton android:checked="false" android:text="@string/dodaj" android:id="@+id/Dodaj"/>
<RadioButton android:checked="false" android:text="@string/odejmnij" android:id="@+id/odemij"/>
<RadioButton android:checked="false" android:text="@string/mnoz" android:id="@+id/mnoz"/>
<RadioButton android:checked="false" android:text="@string/dziel" android:id="@+id/dziel"/>
</RadioGroup>
Definicja pola wyboru działania.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
package pl.przem.android.bac;
import android.app.Activity;
import android.os.Bundle; import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
public class CalculatorActivity extends Activity {
private EditText L1= null ;
private EditText L2 = null;
private EditText wynik = null;
private RadioGroup dzialanie = null;
Private Button Oblicz = null;
Private Button wyjdz = null
private TextView result = null; /** Called when the activity is first created. */
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
L1 = (EditText) findViewById(R.id.Liczba1);
L2 = (EditText) findViewById(R.id.Liczba1);
wynik = (TextView) findViewById(R.id.wynik);
oblicz = (Button) findViewById(R.id.ok);
wyjdz evaluateBtn = (Button) findViewById(R.id.cancel);
}
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Oblicz.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View pV) {
CalculatorActivity.this.Kalkulator();
}
};
private void Kalkulator()
{
int liczba1 = Integer.valueOf(L1.getText().toString());
int liczba2 = Integer.valueOf(L2.getText().toString());
int wynik = 0;
String dzial = dzialanie.getCheckedRadioButtonId().tostring();
if(dzial==„dodaj”) wynik = liczba1 + liczba2;
else if(dzial==„odejmij”) wynik = liczba1 - liczba2;
else if(dzial==„mnoz”) wynik = liczba1 * liczba2;
else if(dzial==„dziel”)
{
if(liczba <>0)wynik = liczba1 / liczba2;
else wynik = 0;
}
wynik.setText(wynik+””);
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
private String urlGet(String urlString){
Przykład ilustruje sposób odczytu danych z serwera www
URLConnection urlConnection = null;
URL url = null;
String string = null;
try {
url = new URL(urlString);
urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(inputStreamReader);
StringBuffer stringBuffer = new StringBuffer();
while((string = reader.readLine()) != null){
stringBuffer.append(string + "\n");
}
inputStream.close();
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
string = stringBuffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return string;
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
Przykład ilustruje sposób obsługi bazy danych (SQLlite)
private final String DB_NAME = "mojaBaza";
SQLiteDatabase baza = null;
try{
baza = this.openOrCreateDatabase(DB_NAME, MODE_PRIVATE, null);
baza.execSQL("CREATE TABLE IF NOT EXISTS Osoby (Imie VARCHAR, Nazwisko VARCHAR)");
baza.execSQL("INSERT INTO Osoby Values('Lech','Kaczynski');");
baza.execSQL("INSERT INTO Osoby Values('Donald','Tusk');");
baza.execSQL("INSERT INTO Osoby Values('Lech','Walesa');");
baza.close();
Przykład ilustruje sposób łączenia się z baza danych, tworzenie tabeli oraz wstawianie do niej danych.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
ArrayList<string> results = new ArrayList<string>();
Cursor cursor = baza.rawQuery("SELECT LastName FROM Osoby WHERE Imie like 'Lech'",null);
if(cursor.moveToFirst()){ //Metoda zwraca FALSE jesli cursor jest pusty
do{
String Imie = cursor.getString(cursor.getColumnIndex("LastName"));
results.add(Imie);
}while(cursor.moveToNext()); //Metoda zwraca FALSE wówczas gdy cursor przejdzie ostatni wpis
}
baza.execSQL("DELETE FROM Osoby");
baza.close();
Przykład ilustruje odczyt danych z bazy (przez wywołanie odpowiedniego zapytania), oraz zamknięcie bazy.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Objective-C i Objective-C++
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Historia Objective-C i Objective-C++
Historia rozwoju języków programowania od (1927 do 2007)
Źródło : objective c tutorial
Historia rodziny języków Objective C zaczyna się mniej więcej ok. roku 1972, jednak trudno tutaj podać
Dokładna datę. Język objective-c powstał jako obiektowa alternatywa do języka C, jednocześnie bardzo
silnie korzystając z Smalltalk-80.
Objective-C++ jest językiem, która znajduje się pomiędzy Objective-C a C++.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Cocoa to zorientowane obiektowo API, działające pod systemem Mac OS X firmy Apple. Jest to jedno z
pięciu głównych API dostępnych dla tego systemu - oprócz Cocoa istnieje jeszcze Carbon, Toolbox (dla
środowiska Classic), POSIX (do programowania środowiska BSD) i Java. Nie bierze się pod uwagę innych,
jak Perl czy Python, ponieważ za ich pomocą nie tworzy się zazwyczaj w pełni integralnych aplikacji.
Aplikacje tworzone w Cocoa są tworzone głównie przy użyciu narzędzi programistycznych dostarczonych
przez firmę Apple. Są to Xcode i Interface Builder, używający języka Objective-C.
Jezyk Objective-C “rozszeza” w pewnien spsob jezyk C, zatem elementy składniowe, o jakie rozszerzono w
tym celu język C, używają dwóch symboli: [] oraz @ (Istnieje wiecej rozszerzeń składni, ale tylko te
wchodzą w jakiekolwiek interakcje ze składnią języka C). Nawiasy kwadratowe są używane do
wywoływania metod, natomiast @ do definicji specyficznych dla języka Objective-C. Istnieją oprocz tego
specjalnie dla Objective-C wprowadzone typy, istniejące już według reguł języka C, z których
najważniejszym jest id. Typ ten jest uniwersalną "referencją do obiektu" (dokładnie to wskaźnikiem, z
punktu widzenia języka C).
W Objective-C obiektem jest tylko to, co jest dostarczone przez samo rozszezenie, jakim jest ten jezyk,
elementy takie jak liczby całkowite, czy zmiennoprzecinkowe, są obsługiwane już zgodnie z językiem C.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Podstawy Objective-C 2.0
Komentaże w kodzie wyglądają tak samo jak w przypadku języków C czy C++
/*---------*/ lub //
Tryb bool:
BOOL (TRUE lub FALSE)
C++
//Pilk Foo.h
#ifndef __FOO_H__
#define __FOO_H__
class Foo
{
...
};
#endif
//Plik Foo.cpp
#include "Foo.h"
© 2009 mgr inż. Łukasz Jopek
Objective-C
//Plik Foo.h
@interface Foo : NSObject
{
...
}
@end
//Plik Foo.m
#import "Foo.h"
@implementation Foo
...
@end
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Klasy i obiekty
C++
Objective-C
class klasa
@interface klasa : NSObject
{
{
double liczba;
double Liczba;
public:
}
int funkcja1(int x);
-(int) funkcja1:(int)x;
float funkcja2(int x, int y);
-(float) funkcja2:(int)x :(int)y;
};
@end
@implementation klasa
int klasa::funkcja1(int x) {...}
-(int) funkcja1:(int)x {...}
float klasa::funkcja2(int x, int y) {...}
-(float) funkcja2:(int)x :(int)y {...}
@end
Porównanie sposobu Tworzenia klas w językach C++ i Objective-C
Znak “-”, że jest to metoda obiektu. Znak '+‘ oznaczalby, ze jest to metoda klasy (odpowiednik
metody statycznej w C++).
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Objective-C definiuje klase- korzen (w Javie wystepuje podobny mechanizm, tam stanowi to klasa
“Object”). Wszystkie wbudowane lub tworzone przez programiste klasy powinny być potomkiem klasy
głównej. W Framworku Cocoa jest to NSObject. Smalltalk i Java korzystaja z tego mechnizmu, a zate
Objective-C rowniez, C++ natomiast nie.
public, private, protected
C++
Objective-C
class Klasa
@interface Foo : NSObject
{
{
public:
@public
int x;
int Metoda_publiczna();
int x;
@protected:
protected:
int y;
int y;
@private:
int Metoda_chroniona();
private:
int z;
}
int z;
-(int) Metoda_publiczna;
int Metoda_prywatna();
-(int) Metoda_chroniona;
};
-(int) Metoda_prywatna; //wszystkie są metodami
publicznymi
© 2009 mgr inż. Łukasz Jopek
@end
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
W C++ istnieją trzy modyfikatory dostępu : publiczny, chroniony i prywatny, domyślnym jest ten ostatni.
W Objective-C tez występują trzy wymienione atrybuty dostępności, jednak zastosowane mogą być tylko do
pól (zmiennych), funkcje (metody) mogą być tylko publiczne.
Można jednak utrudnić dostęp do metod, które w języku C++ miały być prywatne.
Pewnym sposobem jest zaimplementowanie tych metod, ale bez umieszczania ich deklaracji w interfejsie.
Nie utrudnia to bowiem ich późniejszego wywołania, lecz nie będą one widoczne dla osób, które nie wiedzą
o ich istnieniu. Taka możliwość (implementacji metody bez jej wcześniejszej deklaracji jest cechą
Objective-C )
Pola Statyczne.
Pola statyczne jako takie w Objective-C nie występują, zastąpić je można za pomocą zmiennym globalnych.
W kompilatorze GCC można też używać pól klasy (W POC już nie.), natomiast metody (funkcje) mogą być
Metodami klasy, a nie obiektu (odpowiednik metod statycznych w C++).
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Metody (funkcje) w klasach
• Typy zwracane umieszczone są w nawiasach.
• Parametry rozdzielane są za pomocą dwukropka (:).
• Nazwa Metody może być taka sama jak nazwy atrybutów.
C++
void Array::insertObject(void *anObject, unsigned int atIndex)
shelf.insertObject(book, 2);
Objective-C
-(void) insertObject:(id)anObject:(unsigned int)index
[shelf insertObject:book:2];
Objective-C, przykład 2
-(void) insertObject:(id)anObject:(unsigned int)index
[shelf insertObject:book:2]; //Error !
[shelf insertObject:book atIndex:2]; //OK
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Ważna Uwaga!
W przypadku Objective-C nie wywołujemy metody na rzecz obiekty, a wysyłamy wiadomość
(sending the message) z metody do obiektu.
[odbiorca wiadomosc/polecenie]
Wysłać można wiadomośc nie tylko do obiektu z klasy, w której dana metoda istnieje, zawdzięczamy to
mechanizmowi forwarding facility. Jeśli jednak wysłana zostanie wiadomość do metody, która nie istnieje
To błąd pojawi się dopiero podczas wykonywania programu, a nie podczas kompilacji !
Istnieją dwa rodzaje celów w Objective-C : self i super.
self – to odpowiednik konkretnego obiektu w C++
super – podobnie jak w Javie – odpowiednik klasy-rodzica.
Dostęp do zmiennych wewnątrz metod (funkcji)
W C++ odbywa się to za pomocą „this->”, a w Objective-C „self->”
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
C++
Objective-C
class Klasa
@interface Klasa : NSObject
{
{
int x;
int x;
int y;
int y;
void funkcja(int x);
}
};
-(void) funkcja:(int)x;
void Klasa::funkcja(int x)
@end
{
@implementation Klasa
This->x =x;
-(void) funkcja:(int)x
}
{
self->x =x;
}
@end
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Przeciążanie metod (funkcji) w Objective-C
W języku Objective-C nie można przeciążać funkcji (chyba, że dysponujemy kompilatorem obsługującym
Standard C99, jak np. GCC). Jednak nawet wtedy wygląda to inaczej niż w języku C++.
int f(int);
int f(float); //Error : C functions cannot be overloaded
-(int) g:(int) x;
-(int) g:(float) x; //Error : this method is not different
-(int) g:(int) x :(int) y; //OK : two anonymous labels
-(int) g:(int) x :(float) y; //Error : not different from the
-(int) g:(int) x andY:(int) y; //OK : second label is "andY"
-(int) g:(int) x andY:(float) y; //Error : not different from the
//previous one
-(int) g:(int) x andAlsoY:(int) y; //OK : second label is
//"andAlsoY", different from "andY"
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Delegacja wiadomości do nieznanego obiektu (Delegating a message to an unknown object).
W objective-C istnieje możliwość delegowania wiadomości do nieznanego obiektu, lub np. cześć zadania
Może delegować na tzn. asystenta.
W C++, jeśli chcemy wywołać metodę, to musi być ona wcześniej zaimplementowana, już w momencie
kompilacji. Inaczej jest w języku Objective-C, tutaj można takie działanie wykonać. Jeśli, podczas działania
Programu metoda nie będzie nadal zaimplementowana to wiadomość będzie zignorowana, może też
Zostać zgłoszony odpowiedni wyjątek.
Obsługa wyjątków
Obsługa wyjątków w języku Objective-C jest podobna bardziej do Javy niż do C++. Jednym z powodów
jest występowanie słowa kluczowego „Finally”. „Finally” jest oczywiście blokiem opcjonalnym.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
@try{
dangerousAction(); // Tutaj może wystąpić błąd
}
@catch (MyException* e){
doSomething(); //Akcja w przypadku wystąpienia wyjątku nr1
}
@catch (NSException* e){
doSomethingElse(); //Akcja w przypadku wystąpienia wyjątku nr2
@throw // Tutaj może wystąpić kolejny błąd. Rzucamy wyjątek.
}
@finally{
cleanup();
}
Przykład obsługi błędów w języku Objective-C
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Obsługa wątków w Objective-C
Generalnie obsługa wątków jest podobna jak w Javie, synchronizacja wątków odbywa się przy pomocy
mechanizmu „Mutex”, ale słowo kluczowe dla tego bloku jest identyczne jak w Javie – @Synchronized.
@ synchonized wymaga obiektu jako parametr (dowolny obiekt, na przykład własny) do stosowania jako
blokady.
@implementation MyClass
-(void) criticalMethod:(id) anObject
{
@synchronized(self)
{
@synchronized(self)
}
@synchronized(anObject)
{
@synchronized(anObject)
}
}
@end
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Tworzenie obiektów w Objective-C, Przykład programu.
Obiekt w Objective-C stworzyć można po wywołaniu (ściślej mówiąc po wysłaniu wiadomości) na obiekcie
klasy metody new:
id object = [Klasa new];
Klasa *Obiekt;
Obiekt = [Klasa alloc];
Klasa = [Klasa init];
Wszystkie obiekty podczas ich deklaracji muszą być poprzedzone gwiazdką "*", ponieważ są to
wskaźniki (referencje) do tych obiektów. Każdy obiekt musi mieć przydzieloną pamięć - alloc
oraz musi być zainicjowanym - init.
Pamięć przydziela się poprzez wywołanie metody alloc z klasy, która jest dziedziczona po NSObject.
Metoda alloc jest metodą klasy nie obiektu - o tym trochę później, który zwraca typ. Natomiast metoda init
jest wywołana już dla naszego obiektu. Jest ona dziedziczona również poprzez NSObject.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
int main(int argc, char *argv[])
{
kalkulator *przyklad = [[kalkulator alloc] init];
[przyklad dzialanie: @„dodaj"];
[przyklad setA: 25];
[przyklad setB: 30];
[przykład dodaj];
printf(„wynik %d \n", [kalkulator wynik]);
[kalkulator release];
return 0;
}
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Programowanie Iphone z wykorzystaniem języka Objective-C
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Środowisko Pracy
Niestety wymaganiem by rozpocząć przygodę z programowaniem na iPhone jest posiadanie komputera Mac
z systemem operacyjnym Mac OS. Teoretycznie istnieje możliwość instalacji systemu Mac Os na
komputerze PC, ale jest tu zadanie raz, że trudne (problemy ze sprzętem, sterownikami itp.), a dwa, ze
niezgodne z prawem - System jest przeznaczony tylko dla komputerów ze stajni Apple.
Jest to zapewne świadome działanie firmy Apple na rzecz rozpowszechniania ich systemy kosztem ilości
osób zaangażowanych w tworzenie aplikacji na iPhone.
Środowisko programistyczne
XCode i Interface Builder
Apple dostarcza w swoim centrum dla programistów paczkę SDK (obecnie – iPhone SDK for iPhone OS 2.1
). Po pobraniu SDK dostajemy w pakiecie:
•XCode – środowisko programistyczne
•Interface Builder – środowisko do graficznego projektowania interfejsu
•Instruments – oprogramowanie do testowania aplikacji.
•interface simulator – symulator iPhone na Maca
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Cały system, jaki znajduje się w telefonie…
Uruchamiając aplikację mamy cały system, jaki jest uruchomiany na urządzeniu, a więc jest do dyspozycji
sprzęt taki jak kamery, żyroskop sprzętowy, czy wspomagania grafiki. Dostępne są także ustawienia telefonu
czy też albumy zdjęć.
Multitouch
Użytkownicy iPhone dostali do dyspozycji ekran dotykowy z wykrywaniem wielu punktów dotykowych.
Tym samym programiści muszą zwrócić uwagę by elementy, które można dotknąć są wystarczająco duże. Na
szczęście standardowe elementy interfejsu podpowiadają swoją wielkością jakie są zalecenia ze strony Apple.
Apple wspierał kiedyś także SDK dla Javy jednak zaprzestał na rzecz własnego języka.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Objective-C raz jeszcze…
Klasy
Klasy definiujemy w plikach o rozszerzeniu *.h natomiast implementacje klasy dokonujemy w plikach o
rozszerzeniu *.m lub *.mm dla C++. W pliku *.h definiujemy zmienne oraz metody klasy. Poniżej składnia
deklaracji klasy:
@interface Klasa : NSObject
@implementation Klasa
{
-(void) funkcja:(int)x
int x;
{
int y;
self->x =x;
}
}
-(void) funkcja:(int)x;
@end
@end
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
-(void)insertObject:(id)anObject atIndex:(NSUInteger)index
Powyżej deklaracja metody dla instancji obiektu ( + na początku deklaracji oznaczałby metodę statyczną). insertObject
przyjmującej dwa parametry
Pierwszyz nich : ((id)anObject) to wskaźnik. Natomiast drugi parametr - atIndex jest obiektem typu NSUInteger przypisany
do zmiennej wewnętrznej index.
Wysyłanie wiadomości
NSMutableArray* myArray = nil; // tworzenie nowej modyfikowalnej tablicy
myArray = [NSMutableArray arrayWithCapacity:0];
Wiadomość jest opisana pomiędzy nawiasami kwadratowymi []. Na początku wpisany zostaje odbiorca, a następnie
parametry. Można wykorzystać wyniki wiadomości jako obiekty w parametrach lub odbiorcach wiadomości.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Projekt aplikacji na Iphone – aplikacja typu „Hello world”
Aby móc przetestować aplikację w rzeczywistym środowisku pracy bez uczestnictwa w Developer Program
należy zainstalować wersję firmware, pozbawioną zabezpieczeń. (można to wykonać na Windowsie lub Mac
OS X), jednak stoi to w sprzeczności z prawem…
Tworzenie nowego projektu
W celu stworzenia naszej pierwszej aplikacji musimy uruchomić środowisko XCode oraz stworzyć nowy
projekt wybierając z menu File -> New Project, z możliwych projektów wybierz iPhone -> View Based. Z
głównego okna wybierz plik nazwa_aplikacji.xib i kliknij na nim dwukrotnie.
Otworzy się Interface Builder, w którym można dowolnie zmieniać wygląd widoków, jakie umieszczone są
w projekcie. Pliki *.xib opisują widoki, natomiast Interface Builder jest pomocny w szybkim edytowaniu
podstawowego zachowania elementów interfejsu. By wypisać “Hello world” wystarczy umieścic jedynie
odpowiedni Label. Do tego potrzebny będzie Object Inspector, którego wywołać można z menu Window w
IB. W oknie aplikacji umieścimy podstawowy widok, by to uczynić przeciągnij z OI ikonkę View do okna
aplikacji. Następnie dodać do niego trzeba element Label (przeciągnij go do wcześniej przeciągniętego
widoku). Kliknij dwukrotnie na upuszczonym elemencie, a następnie wpisz “Hello World!“.
Uruchomienie projektu
Sprawdź czy aplikacja działa w symulatorze. Projekt można zbudować klikając ikonkę Build and Go albo
użyj skrótu Cmd + Enter. Po zbudowaniu się projektu powinien uruchomić się symulator iPhona oraz nasza
aplikacja.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Aplikacja „Kalkulator”
#import int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; return retVal;
}
plik main.m
Kolejnym plikiem, który generowany jest automatycznie, jest delegator aplikacji, w projekcie nazywa on się
Base<nazwa_projektu>AppDelegate. Definicja klasy jest w pliku o rozszerzeniu .h a implementacja w
pliku .m. Tak stworzony projekt można uruchomić kombinacją Cmd + B lub klikając Buil and Go. To co się
pokaże to pusty ekran bez funkcjonalności.
Ważne zasady:
1.Aplikacja posiada tylko jedno okno. W programie tworzymy tylko widoki, które pokazujemy lub
ukrywamy
2.iPhone OS nie wspiera zarządzaniem poprzez garbage collection.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Tworzenie Widoku
W celu stworzenia widoku, należy stworzyć plik o rozszerzeniu xib, służą one do projektowania interfejsu
używając programu Interface Builder, dostarczanego wraz z SDK. Generowany jest automatycznie jeden
plik tego typu, który opisuje główne okno, można je obejrzeć po uruchomieniu projektu w symulatorze. By
edytować ten plik wystarczy dwa razy kliknąć na MainWindow.xib. Automatycznie generowane są:
1.File’s Owner – obiekt reprezentujący aplikację (UIApplication).
2.First Responder – obiekt przechwytujący zdarzenia multi-touch (pol. zdarzenia wielodotykowe).
3.Base Calculator App Delegate – Obiekt odpowiedzialny za wyświetlenie okna i zainicjalizowanie
widoku. Jest także odpowiedzialny za przywrócenie aplikacji do poprzedniego stanu, przechwytywanie
ostrzeżeń o braku pamięci, odpowiadanie na zmiany orientacji urządzenia. Obiekt ten jest powiązany z
klasą Delegatorem aplikacji.
4.Window – obiekt reprezentujący okno, które widać w aplikacji.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Interfejs użytkownika – wykorzystanie wbudowanych kontrolek
Tworzenie interfejsu użytkownika (GUI), w oparciu o wbudowane kontrolki
Przypomina tworzenie GUI w innych środowiskach (np.. MS Visual Basic 6.0,
czy C# / vb# w MS Visual Studio 2005/2008).
Każda kontrolka posiada swoje właściwości, które można edytować zarówno
Programowo, jak i korzystając z graficznego interfejsu środowiska Xcode.
Rysunek po prawej przestawia wygląd okna właściwości dla kontrolki typu
„TextField”. W przypadku aplikacji „Kalkulator” należy zatem dodać
Przykładowo : dwa pola typu „TextField” – do wpisywania liczb, pole typu
„TextField” lub „Label”, które będzie zwierało wynik działania, oraz kontrolka
Typu „Button”, która spełniać będzie rolę przycisku.
Zakładamy, ze nasz kalkulator jedynie dodanie do siebie dwie, wprowadzone
Liczby i wyświetla wynik tej sumy.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Kontroler Aplikacji
Kontroler aplikacji odpowiedzialny jest m.in. za obsługę akcji wykonywanych przez użytkownika, nawigację
oraz zarządzanie pamięcią. Każdy widok w aplikacji musi być połączony z takim kontrolerem, który będzie
obsługiwał funkcjonalności.
Klasą obsługująca widoki jest UIViewController. Dostarcza ona podstawowe funkcjonalności. W celu
stworzenia kontrolera w XCode wybieramy File -> New File wybierając jako typ pliku
UIViewController subclass.
Następnie trzeba stworzyć zmienne dla elementów stworzonych w widoku. Pozwoli to na połączenie widoku
z kontrolerem oraz na sterowanie widokiem. Tworzymy:
BaseCalculatorViewController.h :
#import
@interface BaseCalculatorViewController : UIViewController {
IBOutlet UITextField *firstNumber; //Słowo IBOutlet mówi kompilatorowi, że dana
IBOutlet UITextField *secondNumber; //zmienna ma być widoczna dla Interface Buildera.
IBOutlet UILabel *result; NSInteger fNumber, sNumber;
}
@property (nonatomic, retain) UITextField *firstNumber; //linijki kodu oznaczone jako ‘@property’
@property (nonatomic, retain) UITextField *secondNumber; //definiują właściwości klasy
@property (nonatomic, retain) UILabel *result; //Atrybut retain oznacza, że przy przypisywaniu obiekt jest zachowywany.
@property (nonatomic) NSInteger fNumber;
@property (nonatomic) NSInteger sNumber;
-(IBAction)displayMessage:(id)sender; //ta metoda posłuży do obsługi zdarzenia(kliknięta klawisza)
@end
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Obsługa zdarzeń
Tworzymy plik BaseCalculatorViewController.m :
@implementation BaseCalculatorViewController
@synthesize firstNumber, secondNumber, result, fNumber, sNumber;
-(IBAction)displayMessage:(id)sender {
self.fNumber = [firstNumber.text integerValue];
self.sNumber = [secondNumber.text integerValue];
NSString *tmpString = nil;
if(self.fNumber == 0 || self.sNumber == 0) {
tmpString = [[NSString alloc] initWithFormat:@"Insert some number"];
} else {
tmpString = [[NSString alloc] initWithFormat:@"Result: %d", (self.fNumber + self.sNumber)];
}
result.text = tmpString; [tmpString release];
}
W celach edukacyjnych została tu nadmiarowo stworzona zmienna tmpString. Pokazuje ona jak alokować
(alloc), inicjalizować (initWithFormat) i uwalniać pamięć (release). Przy użyciu metody initWithFormat
można tworzyć sformatowane ciągi znaków. %@ jest podmieniany na parametr podany dalej. Można też
używać innych znaków formatujących np. %s, %d występujące w funkcji printf z języka C.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
W stworzonym kontrolerze zawarte jest kilka właściwości o atrybucie retain, które powinniśmy uwolnić
z pamięci. Zrobić to można następująco:
-(void)dealloc {
-[firstNumber release];
-[secondNumber release];
-[result release];
-[super dealloc];
}
Dodanie widoku do okna
Kolejnym krokiem jest dodanie widoku jako podwidoku istniejącego okna. Utworzyć trzeba plik
BaseCalculatorAppDelegate.h, a w nim zmienną typu BaseCalculatorViewController. Jest to typ nieznany
kompilatorowi, dlatego też trzeba zadeklarować ten typ używając słówka @class.
#import
@class BaseCalculatorViewController;
@interface BaseCalculatorAppDelegate : NSObject {
IBOutlet UIWindow *window;
BaseCalculatorViewController *viewController;
}
@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) BaseCalculatorViewController *viewController;
@end
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
W pliku implementującym (.m) W celu przypisania stworzonego widoku do okna wykorzystać trzeba metodę
applicationDidFinishLaunching. Jest ona wywoływana jak tylko aplikacja zakończy proces uruchamiania się.
Wykorzystać można ją do ustawiania pierwszego widoku i przywracania stanu aplikacji.
#import "BaseCalculatorAppDelegate.h"
#import "BaseCalculatorViewController.h"
@implementation BaseCalculatorAppDelegate @synthesize window, viewController;
-(void)applicationDidFinishLaunching:(UIApplication *)application { //załadowanie widoku z bliku nib
BaseCalculatorViewController *vController = [[BaseCalculatorViewController alloc]
initWithNibName:@"BaseCalculatorView" bundle:[NSBundle mainBundle]];
self.viewController = vController; //ustawienie widoku
[vController release]; //uwolnienie zmiennej
[window addSubview:[viewController view]]; //dodanie widoku do okna
[window makeKeyAndVisible]; } //uwidocznienie widoku
-(void)dealloc {
-[viewController release];
-[window release];
-[super dealloc]; }
@end
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Połączenie elementów w widoku z obiektami w kontrolerze widoku
Pierwszym krokiem jest połączenie stworzonych obiektów z elementami widoku.
Można to uczynić za pomocą Identity Inspector (opcja dostepna w Interface
Buildera.). Obok zmiennej view jest puste kółko, co oznacza, że nie jest połączone.
Połączenie tworzy się poprzez przeciągniecie na widok tego ‘kółka’ i puszczeniu
klawisza. Zamalowane kółko będzie informowało o połączeniu. Podobnie sytuacja
wygląda z reszta elementów : result, firstNumber, secondNumber – należy je
połączyć z odpowiednimi elementami na widoku.
Ostatnie połączenie to połączenie metody wyświetlającej wynik z akcją kliknięcia
przycisku. W connection inspector wybrać należy metodę displayMessage i połączyć
ją ze zdarzeniem: “Touch Up Inside”.
Projekt jest gotowy, można go skompilować i uruchomić w Xcode.
Aplikacja powinna już działać, ale pojawi się pewna niedogodność. Po wpisaniu
liczb klawiatura nie będzie się chowała. By to naprawić trzeba dodać protokół do
klasy kontrolera. Deklaracja interfejsu kontrolera widoku.
@interface BaseCalculatorViewController : UIViewController <UITextFieldDelegate>
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
Kolejnym krokiem jest ustawienie kontrolera widoku jako odbiorcę zdarzeń pól tekstowych oraz
zaimplementowanie metody obsługującej ukrywanie klawiatury:
-(void)viewDidLoad {
firstNumber.delegate = self;
secondNumber.delegate = self;
}
Metoda viewDidLoad ustanawia kontroler widoku jako obiekt odbierający zdarzenia pól tekstowych.
-(BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if(theTextField == firstNumber || theTextField == secondNumber) {
[firstNumber resignFirstResponder];
[secondNumber resignFirstResponder];
}
return YES; }
Metoda textFieldShouldReturn sprawdza jaki obiekt wywołał metodę, jeżeli te obiekty mogą powodować
ukrycie klawiatury, wysłana zostaje wiadomość resignFirstResponder do obiektów oraz zwracany jest
wartość logiczna ‘YES’.
Pozostało jeszcze ustawienie delegacji dla pól tekstowych na File’s Owner (obiekt proxy dla naszego
kontrollera). W Interface Builderze wybierać należy widok, a następnie dla każdego pola tekstowego z menu
Connections Inspector przeciągnąć trzeba pole delegate na obiekt File’s Owner. Teraz można ostatecznie
skompilować i uruchomić projekt.
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ
Programowanie urządzeń mobilnych
W wykładzie wykorzystano tutorial, dostępny pod adresem :
http://sparhawk.pl/2008/10/18/iphone-os-tutorial-czesc-3/
© 2009 mgr inż. Łukasz Jopek
Katedra Informatyki Stosowanej PŁ