Java » Java ME

Rozwiązywanie problemów z uruchamianiem MIDletów

Pewnie niektórzy zetknęli się z taką sytuacją: piszemy MIDlet, kompilacja przebiega prawidłowo, program pod emulatorem chodzi jak burza, chcemy przetestować program na telefonie i... dostajemy komunikat "Operacja nie powiodła się", "Aplikacja nieprawidłowa", "Błąd aplikacji", itd... Jeżeli masz taki właśnie problem, ten artykuł może pomóc ci go rozwiązać.

Sprawdź wersje MIDP i CLDC


Najczęstszym błędem jest wybranie złych wersji MIDP i CLDC. MIDP, jak pamiętamy, definiuje możliwości środowiska uruchomieniowego - czyli mówiąc prościej - jakie klasy mamy do dyspozycji. CLDC z kolei definiuje platformę, a więc - ilość pamięci, obsługa typów zmiennoprzecinkowych, i tak dalej.
Jeżeli skompilujesz swój program z ustawieniem MIDP 2.0, a następnie spróbujesz go wrzucić na, dajmy na to, Sony Ericssona T610, napotkasz zdecydowany opór ze strony telefonu. Telefon ten obsługuje MIDP 1.0 i nic nowszego na nim nie ruszy. Takich telefonów jednak jest już w obiegu niewiele. Jest za to gorszy problem, a nazywa się MIDP 2.1. Jest to najnowsza wersja MIDP, która w zasadzie ma wszystko co do tej pory wymyślono. Ma jednak jedną wadę - o ile w ogóle są jakieś telefony "łykające" MIDP 2.1, to jest ich niewiele. Natomiast środowisko WTK narzuca nam domyślnie MIDP 2.1. Jeżeli przeoczysz ten fakt, twoje programy nie będą się uruchamiać.
Co gorsza, o ile emulatory telefonów z MIDP 1.0 nie pozwolą nam uruchomić aplikacji z MIDP 2.0, o tyle emulatory tych nowszych (ale z MIDP 2.0) uruchomienie aplikacji MIDP 2.1 puszczą nam płazem.
To samo tyczy się CLDC. Jeżeli wybierzemy dla starszego telefonu CLDC 1.1, program nie wystartuje. Nie daj się jednak zwieść - to, że program obsługuje MIDP 2.0, to nie znaczy, że obsługuje automatycznie CLDC 1.1 (czy na odwrót). Przykładem jest ciągle dość popularna Motorola V3, która obsługuje MIDP 2.0, ale CLDC 1.0.
Tu mała dygresja: obsługa liczb zmiennoprzecinkowych (np. double) jest zdefiniowana w CLDC 1.1. Dlatego też, jeżeli chcesz napisać pod SE T610 czy P800 kalkulator naukowy, musisz poradzić sobie bez typu double.
Podsumowując: pisząc nowy program, ustawiaj domyślnie najbardziej archaiczne ustawienia. Jeżeli dostaniesz błąd kompilatora, że nie potrafi znaleźć jakiejś klasy czy pakietu, to możesz mieć pewność, że musisz podnieść poprzeczkę. Co musisz zmieniać - sprawdź w manualu od WTK, które klasy są od kiedy obsługiwane.

Wyłącz zbędne rozszerzenia


W ustawieniach projektu najlepiej wyłącz wszystkie rozszerzenia w sekcji Optional. Są to dodatkowe możliwości nieujęte w standardach JME, ale dostarczone przez jakiegoś zewnętrznego producenta. Jeżeli będziesz wykorzystywać jakieś rozszerzenie (np. JSR-75 - dostęp do filesystemu telefonu), włącz je w sekcji Optional (o takiej konieczności poinformuje cię kompilator, zgłaszając brak jakichś klas).
O tym, że jakiś telefon jest zbyt archaiczny dla jakiegoś rozszerzenia, dowiesz się próbując uruchomić emulator danego telefonu. Jeżeli napisałeś program wykorzystujący dostęp do filesystemu (JSR-75), emulatory telefonów K300, K500, K700 wyrzucą błąd i pozamykają się, podczas gdy K750 będzie chodzić prawidłowo.
Warto wiedzieć, że niewykorzystane klasy i pakiety nie są linkowane z programem. To dlatego mogłeś uruchamiać swoje programy pod starszymi telefonami, mimo, że miałeś zaznaczone wszystkie checkboxy w sekcji Optional. W zasadzie można by je zostawić włączone, ale trzeba na taki krok zdecydować się świadomie - kompilator Javy nie będzie nas w stanie ostrzec przed tym, że telefon nie będzie w stanie uruchomić naszej aplikacji. Dlatego wiedząc, co telefon potrafi, najlepiej od razu ustawić odpowiednie checkboxy, zaś powyłączać te od nieobsługiwanych funkcji.

Przed wrzuceniem na telefon - przebuduj archiwum JAR


Zawsze przed wrzuceniem aplikacji na telefon (po modyfikacjach kodu źródłowego czy ustawień projektu) wybieraj Project | Package | Create package. Samo Build nie wystarczy, nawet, jeżeli powstanie nowy plik .jad. Niektórzy, pomijając ten krok, dziwią się, dlaczego program w emulatorze chodzi prawidłowo, a do telefonu ciągle ładowana jest starsza wersja. Najlepiej wyrób sobie nawyk, aby używać Create package zamiast Build. Pierwsza opcja i tak automatycznie przekompiluje od nowa kod (tak jak Build), a przy okazji wyprodukuje zaktualizowane wersje plików wynikowych.

Dlaczego "Błąd aplikacji"?


Co jednak robić, gdy wiemy, że ustawienia projektu są dobre, ale telefon odrzuca nasz program z tytułowym błędem? Od razu sprawdź, co się dzieje w konstruktorze MIDletu. Jeżeli w programie już w czasie pracy gdzieś wystąpi nieprzechwycony wyjątek, dostaniemy odpowiedni komunikat na telefonie. Jeżeli jednak wyjątek zostanie rzucony (i nieprzechwycony) w konstruktorze MIDletu, program nie uruchomi się w ogóle. Jeżeli tak się dzieje, uruchom program w emulatorze i sprawdź, co zgłasza się na konsoli. Jeżeli zobaczysz informację o wyłapaniu jakiegoś wyjątku, wiesz już gdzie szukać błędu.
Praktyka pokazuje, że najczęściej powodem błędu jest jakiś nieutworzony jeszcze obiekt:
 JakasKlasa obiektKlasy; // nie ma jeszcze: = new JakasKlasa();
 /* ... */
 obiektKlasy.foo(); // !!!

Rezultatem takiego kodu będzie wyjątek NullPointerException.

1 komentarz

Koziołek 2008-09-07 20:51

Zasadna najważniejsza napisz testy.