Programowanie urządzeń mobilnych

Slides:



Advertisements
Podobne prezentacje
Praca dyplomowa inżynierska
Advertisements

20041 Projektowanie dynamicznych witryn internetowych Paweł Górczyński ASP 3.0.
Wstęp do strumieni danych
C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Programowanie wizualne PW – LAB5 Wojciech Pieprzyca.
Mechanizmy pracy równoległej
Programowanie obiektowe
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Wzorce.
Sieci komputerowe Usługi sieciowe Piotr Górczyński 27/09/2002.
Autor Roman Jędras Prowadzący: dr inż. Antoni Izworski Przedmiot:
Projektowanie programu obsługującego gniazdka
Nguyen Hung Son Uniwersytet Warszawski
Inżynieria oprogramowania Lecture XXX JavaTM – część IV: IO
Błażej Pietrzak J2ME CLDC MIDP 1.0 Błażej Pietrzak
Programowanie sieciowe w Javie
Struktury.
1 Dygresja: cztery płyty główne…. 2 Dygresja: osobliwości C /* cos o nieistniejacym typie Boolean */ /* oraz o operatorze przecinkowym */ #include int.
Gniazda komunikacji sieciowej w języku Java
Język ANSI C Operacje we/wy
Projektowanie i programowanie obiektowe II - Wykład IV
Język Java Wielowątkowość.
Semafory według normy POSIX
Technologie informacyjne MCE Pudełko. Zakładanie strony internetowej Technologie informacyjne Marek Pudełko.
Serializacja Serializacja pozwala zamienić obiekt na sekwencję bajtów, w sposób umożliwiający później wierne odtworzenie jego zawartości Inna nazwa to.
Wykonawcy:Magdalena Bęczkowska Łukasz Maliszewski Piotr Kwiatek Piotr Litwiniuk Paweł Głębocki.
Wprowadzenie do JSP Copyright © Politecnico di Milano September 2003 Translation: Kamil Żyła, Politechnika Lubelska.
Podstawy programowania
Pakiety w Javie Łukasz Smyczyński (132834). Czym są pakiety? Klasy w Javie są grupowane w pewne zbiory zwane pakietami. Pakiety są więc pewnym podzbiorem.
Podstawy programowania II
Podstawy programowania II Wykład 2: Biblioteka stdio.h Zachodniopomorska Szkoła Biznesu.
Java 3 MPDI Programowanie obiektowe W7. import java.io.*; public class X { // kontrukcja throws – określenie jakie wyjątki może dana metoda // sygnalizować
W większości języków programowania biblioteki wejścia/wyjścia ukrywają szczegóły obsługi poszczególnych mediów pod abstrakcją strumienia (ang. stream).
Sieci komputerowe.
Programowanie obiektowe – zastosowanie języka Java SE
JAVA c.d.. Instrukcji wyboru SWITCH używamy, jeśli chcemy w zależności od wartości pewnego wyrażenia wykonać jeden z kilku fragmentów kodu. Jest to w.
Java – coś na temat Klas Piotr Rosik
Inicjalizacja i sprzątanie
Seminarium problemowe
Systemy wejścia i wyjścia Michał Wrona. Co to jest system wejścia i wyjścia? Pobierania informacji ze źródeł danych, zdolnych przesyłać sekwencje bajtów,
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Tworzenie Aplikacji Internetowych dr Wojciech M. Gańcza 8.
Wybrane zagadnienia relacyjnych baz danych
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Programowanie obiektowe 2013/2014
1 Strumienie Hierarchie klas strumieniowych, strumienie bajtowe - klasy InputStream i OutputStream i ich metody, klasa File, strumienie plikowe, strumienie.
Sieci komputerowe.
PL/SQL – dalsza wędrówka
Programowanie w języku C++
Projektowanie stron WWW
Kurs języka C++ – wykład 4 ( )
Technologie internetowe Wykład 5 Wprowadzenie do skrytpów serwerowych.
Andrzej Majkowski 1 informatyka +. 2 Bezpieczeństwo protokołu HTTP Paweł Perekietka.
Informatyka Stosowana – ROK II / III
Piotr Czapiewski Wydział Informatyki ZUT. Web Services Description Language.
Model warstwowy ISO-OSI
ASP.NET Dostęp do bazy danych z poziomu kodu Elżbieta Mrówka-Matejewska.
Strumienie w języku Java Bartosz Walter InMoST Wielkopolska sieć współpracy w zakresie innowacyjnych metod wytwarzania oprogramowania Termin realizacji:
Programowanie Obiektowe – Wykład 6
Piotr Kawałek , Mateusz Śliwowski
Strumienie, Wczytywanie, Zapisywanie, Operacje na plikach
Wątki, programowanie współbieżne
(według:
Programowanie Obiektowe – Wykład 2
Sieci komputerowe Usługi sieciowe 27/09/2002.
Programowanie obiektowe – zastosowanie języka Java SE
Aplikacje i usługi internetowe
Zapis prezentacji:

Programowanie urządzeń mobilnych Paweł Fiderek 2011

Wykład drugi: Połączenia sieciowe w J2ME Paweł Fiderek 2011

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 Paweł Fiderek 2011

{protokół}:[{adres_sieciowy}][{parametry}] 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 Paweł Fiderek 2011

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. Paweł Fiderek 2011

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) Paweł Fiderek 2011

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. Paweł Fiderek 2011

Bluetooth Paweł Fiderek 2011

Bluetooth– technologia bezprzewodowej komunikacji krótkiego zasięgu pomiędzy różnymi urządzeniami elektronicznymi, takimi jak klawiatura, komputer, laptop, palmtop, telefon komórkowy i wieloma innymi. Jest to darmowy standard opisany w specyfikacji IEEE 802.15.1. Jego specyfikacja obejmuje trzy klasy mocy nadawczej 1-3 o zasięgu 100, 10 oraz 1 metra w otwartej przestrzeni. Najczęściej spotykaną klasą jest klasa druga. Technologia korzysta z fal radiowych w paśmie ISM 2,4 GHz. Paweł Fiderek 2011

Architektura systemu Bluetooth Podstawową jednostką technologii Bluetooth jest pikosieć (ang. piconet), która zawiera węzeł typu master oraz maksymalnie 7 węzłów typu slave. Wiele pikosieci może istnieć w jednym pomieszczeniu, a nawet mogą być ze sobą połączone przy pomocy węzła typu bridge. Połączone ze sobą pikosieci określa się mianem scatternet. Dodatkowo, oprócz siedmiu węzłów typu slave, w jednej pikosieci może pracować do 255 węzłów, pozostających w stanie synchronizacji z urządzeniem typu master (jest to tzw. tryb wyczekiwania i niskiego poboru mocy). Urządzenia te nie uczestniczą w wymianie danych. Mogą tylko otrzymać sygnał aktywacyjny lub nawigacyjny od węzła typu master. Istnieją jeszcze dwa przejściowe stany hold oraz sniff. Przyczyną podziału węzłów na master i slave jest minimalizacja kosztów technologii. Konsekwencją tego jest fakt, że węzły typu slave są w 100% podporządkowane węzłom master. Pikosieć jest scentralizowanym systemem TDM, urządzenie master kontroluje zegar i określa, które urządzenie i w którym slocie czasowym (szczelina czasowa) może się z nim komunikować. Wymiana danych może nastąpić tylko pomiędzy węzłem master i slave. Komunikacja slave – slave nie jest możliwa. Paweł Fiderek 2011

Paweł Fiderek 2011

Zasięg klasa 1 (100 mW) ma największy zasięg, do 100 m klasa 2 (2,5 mW) jest najpowszechniejsza w użyciu, zasięg do 10 m klasa 3 (1 mW) rzadko używana, z zasięgiem do 1 m Paweł Fiderek 2011

Przepustowość Bluetooth 1.0 – 21 kb/s Bluetooth 1.1 – 124 kb/s Bluetooth 2.0 – transfer maksymalny przesyłania danych na poziomie 2,1 Mb/s, wprowadzenie Enhanced Data Rate wzmocniło transfer do 3,1 Mb/s Bluetooth 3.0 + HS (High Speed) – 24 Mb/s (3 MB/s) Bluetooth 3.1 + HS (High Speed) – 40 Mb/s(5 MB/s) Paweł Fiderek 2011

Przykłady Paweł Fiderek 2011

Programowanie j2me bluetooth Po stronie klienta: LocalDevice localDevice = LocalDevice.getLocalDevice(); discoveryAgent = localDevice.getDiscoveryAgent(); discoveryAgent.startInquiry(DiscoveryAgent.GIAC,this); Paweł Fiderek 2011

Discovery Listener Paweł Fiderek 2011

for(int i=0;i &nbsp serviceUrl = servRecord[i] for(int i=0;i &nbsp serviceUrl = servRecord[i].getConnectionURL(0,false);} // pobranie adresu URL potrzebnego do utworzenia połączenia z urządzeniem String msg = "Say Hello World"; conn = (StreamConnection)Connector.open(serviceUrl); OutputStream output = conn.openOutputStream(); output.write(msg.length()); output.write(msg.getBytes()); output.close(); //standardowe połączenie przez klasę Connector Paweł Fiderek 2011

Programowanie od strony serwera Bt private static String serverUrl = "btspp://localhost:" + BluetoothEchoDemo.RFCOMM_UUID + ";name=rfcommtest;authorize=true"; . conn = null; localDevice = LocalDevice.getLocalDevice(); localDevice.setDiscoverable( DiscoveryAgent.GIAC ); notifier = (StreamConnectionNotifier)Connector.open(serverUrl); Paweł Fiderek 2011

scheme://host:port;parameters Paweł Fiderek 2011

//czekamy na odpowiedź klienta conn = notifier.acceptAndOpen(); //gdy klient odpowie // czytamy przesłane dane String msg = BluetoothEchoDemo.readData(conn); System.out.println("Received Message from Client: " + msg); // wysyłamy wiadomość zwrotną msg = "Hello Back from Server"; output = conn.openOutputStream(); output.write(msg.length()); // length is 1 byte output.write(msg.getBytes()); output.close(); Paweł Fiderek 2011

Programowanie połączeń sieciowych w J2ME import javax.microedition.lcdui.*; import javax.microedition.midlet.MIDlet; import javax.microedition.io.*; import java.io.*; Paweł Fiderek 2011

public class KursEuro extends MIDlet implements CommandListener { private TextBox tb; public KursEuro() { StringBuffer sb = new StringBuffer(); try { HttpConnection c = (HttpConnection) Connector.open("http://rss.nbp.pl/kursy/TabelaA.xml", Connector.READ, true); InputStream is = c.openInputStream(); int ch=0; while ((ch = is.read()) != -1) { sb.append((char) ch); } } catch (IOException x){ System.out.println ("Błąd wejścia wyjścia"); Paweł Fiderek 2011

String wyn = sb.toString(); int i = wyn.indexOf("EUR") + 14; //szukamy wystąpienia EUR String sKurs = wyn.substring(i, i + 6); //wycinamy wartość sKurs = sKurs.replace(',','.'); float kurs = Float.parseFloat(sKurs); i = wyn.indexOf("Tabela nr") + 10; String sTabela = wyn.substring(i, i + 32); tb = new TextBox("Aktualny kurs EUR", "EUR: " + kurs + " wg kursu z tabeli nr " + sTabela, 100, TextField.ANY); tb.setCommandListener(this); } public void startApp() { Display.getDisplay(this).setCurrent(tb); } public void pauseApp() { } public void destroyApp(boolean u) { } Paweł Fiderek 2011

Wykorzystanie wątków w programowaniu w języku J2ME Paweł Fiderek 2011

Teoria wątków w J2ME Działający wątek jest to nic innego jak kod wykonywalny Gotowy wątek jest gotowy do wykonywania kodu Wątek zawieszony czeka na wystąpienie konkretnego zdarzenia. Na przykład może on czekać na dostarczenie danych z innego urządzenia, gdy oczekiwanie zdarzenie wystąpi wątek zmienia swój stan na aktywny Zakończony wątek skończył wykonywać kod Paweł Fiderek 2011

W J2ME klasą odpowiedzialną za tworzenie i zarządzanie wątkami jest klasa: java.lang.Thread Użytkownik może uzyskać dostęp do aktualnie przetwarzanego wątku w każdej chwili poprzez odwołanie: Thread.currentThread(). Paweł Fiderek 2011

Metody znajdujące się w klasie Thread to: activeCount() currentThread() getPriority() isAlive() join() run() setPriority() sleep() start() yield() Paweł Fiderek 2011

Rozpoczęcie pracy z wątkami public class DoSomething implements Runnable { public void run(){ // tutaj znajduję się kod wykonywalny } Paweł Fiderek 2011

Tworzenie obiektów wykonywalnych DoSomething doIt = new DoSomething(); Thread myThread = new Thread( doIt ); myThread.start(); Paweł Fiderek 2011

Inna metoda tworzenia wątków public class DoAnotherThing extends Thread { public void run(){ // Tutaj znajduję się kod wykonywalny } I analogicznie: ... DoAnotherThing doIt = new DoAnotherThing(); doIt.start(); Paweł Fiderek 2011

Zatrzymywanie wykonywania wątków public class MyThread implements Runnable { private boolean quit = false; public void run(){ while( !quit ){ // tutaj znajduję się kod wykonywalny } public void quit(){ quit = true; Paweł Fiderek 2011

public class AnotherThread implements Runnable { private Thread mostRecent = null; public Thread restart(){ mostRecent = new Thread( this ); mostRecent.start(); } public void run(){ Thread thisThread = Thread.currentThread(); while( mostRecent == thisThread ){ // do something public void stopAll(){ mostRecent = null; Paweł Fiderek 2011

Kolejkowanie, pętla nieskończona w wątku import java.util.Vector; public class Worker implements Runnable { private boolean quit = false; private Vector queue = new Vector(); private Thread thread; public Worker(){ new Thread( this ).start(); } Paweł Fiderek 2011

public void run(){ Object o; while(. quit ){ // zajęty, czekaj public void run(){ Object o; while( !quit ){ // zajęty, czekaj! o = null; synchronized( queue ){ if( queue.size() > 0 ){ o = queue.elementAt( 0 ); queue.removeElementAt( 0 ); } if( o != null ){ // kolejne polecenia Paweł Fiderek 2011

public boolean addToQueue( Object o ){ if(. quit ){ queue public boolean addToQueue( Object o ){ if( !quit ){ queue.addElement( o ); return true; } return false; public void quit(){ quit = true; Paweł Fiderek 2011

Składowanie danych w urządzeniach mobilnych przy wykorzystaniu J2ME Paweł Fiderek 2011

„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. Paweł Fiderek 2011

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 Paweł Fiderek 2011

RecordStore store = RecordStore.openRecordStore(„ZbiorTestowy", true); 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 Paweł Fiderek 2011

RecordStore store = RecordStore.openRecordStore(„ZbiorTestowy", true); 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 Paweł Fiderek 2011

RecordStore nowy_magazyn = null; 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; } } Paweł Fiderek 2011

byte[] dane = nowy_magazyn.getRecord(id); 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); Paweł Fiderek 2011

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. Paweł Fiderek 2011

Dane przyklad2 = new Dane(is.readUTF(), is.readInt()); 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; } Paweł Fiderek 2011

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; } Paweł Fiderek 2011

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. Paweł Fiderek 2011