Pokazywanie postów oznaczonych etykietą J2ME. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą J2ME. Pokaż wszystkie posty

czwartek, 28 czerwca 2012

Mój pierwszy publiczny screencast z programowania w J2ME


Jakiś czas temu wspominałem, że opublikuje filmik z tworzenia implementacji gry tank2012 (klonu tank1990). I o to jest (oglądać w HD):


Post produkcja zajęła mi więcej niż przypuszczałem. Musiałem trochę powycinać, gdy gdzieś pod koniec nagrywania musiałem zaglądać do ściągawki. Jednak jak popełniałem jakieś błędy w kodzie, to je naprawiałem. Teraz każdy może sobie popatrzeć jak programuję. Nie jest to może najefektywniejsze wykorzystanie możliwości jakie daje IDE, ale już dawno nie siedziałem na NetBeansie.

Opublikowałem również pełen kod na githubie. Jest on nie bardzo obiektowy, ale nie to było celem ćwiczenia, a pokazanie jak można tą grę zaimplementować. Co prawda w oryginalnej wersji cegły można było niszczyć stopniowo, ale w przypadku j2me wymagało by to sporo wysiłku. No i zapomniałem po każdym zadaniu wykonać commita, więc mamy rewizję początkową i końcową.

Wszelkie uwagi odnośnie kodu / screencast'a mile widziane. A teraz czas się zwijać na Confiturę.

poniedziałek, 28 maja 2012

Wrażenia po prowadzeniu mini praktyk niestudenckich


Ostatnio, w czasie gdy większość z Was oddawała się GeeCON'owemu szaleństwu, lub spędzała kolejny nudny dzień w pracy tworząc super tajne projekty, ja miałem okazję podszlifować i wypróbować moje zdolności mentorskie (o ile takie w ogóle posiadam). Od zawsze lubiłem dzielić się swoją wiedzą z innymi. W przypadku programowania, to już na pierwszym roku studiów udzielałem korepetycji koleżankom z liceum, w zamian za ciepły obiadek :) Później zaangażowałem się w Warsztaty programowania urządzeń mobilnych przy Studenckim Kole Naukowym Informatyki Systemów Autonomicznych i Adaptacyjnych. Później zacząłem pisać tego bloga i coś tam od czasu do czasu ludziom przedstawiać w ramach JUG-ów. A teraz prowadzenie praktyki było czymś nowym dla mnie.

W minionym tygodniu dostałem od Marcin Saneckiego pod opiekę praktykanta Adriana. Uczęszcza On do technikum informatycznego i nastał taki moment, że musiał odbyć / odbębnić praktykę w zawodzie. Inni jego rówieśnicy, albo przeinstalowują systemy operacyjne w swoim liceum, albo idą do jakiegoś sklepu komputerowego składać blaszaki. Ostatecznie, jak nie mogą nigdzie znaleźć firmy, która przyjmie ich na praktykę, to idą do jakiś urzędów państwowych, gdzie można się tylko zniechęcić i uwstecznić.

Jako że Adrian nie do końca jest przekonany, co chce w życiu robić, miałem utrudnione zadanie. Miałem go zachęcić (a jeszcze lepiej przekonać go), aby szedł w stronę IT, a najlepiej programowania. Czy musiałem mu pokazać coś ciekawego, gdzie szybko widać fajny efekt pracy i co daje przyjemność samo w sobie. No i do tego miałem niewiele czasu (właściwie wyszły 2 dni po około 5 godzin). Mój praktykant miał podstawy Pascala (tzn. gdzieś tam w technikum się go kiedyś uczył) i trochę widział Html'a i Java Script'a. Ja słysząc tą ostatnią informację, trochę się przeraziłem, gdyż ja sam byłbym mocno zniechęcony do dalszej nauki po pobieżnym poznaniu JS.

Miałem więc bardzo trudny orzech do zgryzienia, gdyż młody adept sztuki programistycznej miał niewielkie doświadczenie, a musiałem w krótkim czasie coś go nauczyć i pokazać, że programowanie może być fajne i dawać satysfakcje. Zacząłem więc sobie przypominać, jak to było kiedyś ze mną, co mi dawało motywację, było łatwe, a efekt końcowy był szybko widoczny.

Mój wybór padł na Javę Micro Edition i postanowiłem stworzyć razem z Adrianem coś co by przypominało grę tank 1990. Odgrzebałem więc swoją starą prezentację na temat Tworzenia graficznego inferface’u użytkownika niskiego poziomu w J2ME, gdzie właśnie przedstawiałem jak operować prostymi obiektami dwuwymiarowymi. Prezentacja co prawda z 2009 roku, przygotowana na potrzeby wspominanych wcześniej warsztatów z J2ME, ale teraz po latach się przydała w celach szkoleniowych. Odgrzebałem też kod (jest on również przypięty do tamtej prezentacji) i pousuwałem z niego bardziej zaawansowane wynalazki, zostawiając namalowany jeden czołg i resztę szkieletu całej aplikacji. Był to nasz punkt wyjścia. Pozostałe prezentacje moje i kolegów z tego okresu można również znaleźć na slideshare.net.

Na początku wspólnej praktyki z Adrianem (i częściowo z Marcinem) przygotowaliśmy niezbędne środowisko programistyczne, czyli JDK7 (32 bit), NetBeans i dodatkowo WTK od Sony Ericsson'a (jakby standardowy emulator z nowym WIndowsem 7 nie chciał działać). Zeszło nam na to trochę czasu, ale końcem końców udało i można było zacząć zabawę.

Zaczęliśmy od jednego namalowanego czołgu. Nie tłumaczyłem w ogóle czym jest obiekt, a czym klasa a jedynie uczyłem przez analogię: „Aby przesunąć czołg trzeba wywołać na nim metodę move()...”, „tu masz wczytywanie obrazka, teraz wczytaj inny...” itd. Adrian często kopiował kod i zmieniał niewielkie fragmenty, rozszerzając w ten sposób funkcjonalność. Odwoływałem się również do języków, które on znał. Było o tablicach, praktycznym zastosowaniu pętli for i warunku if. Całość dopełniona slajdami i moją cierpliwością do tłumaczenia i poprawiania błędów składniowych. Ostatecznie dotarliśmy na koniec drugiego dnia do jeżdżącego czołgu po ładnej mapie z wykrywaniem kolizji z przeszkodami i niewyjeżdżaniem po za ekran.

Chciałem jeszcze zrobić strzelanie do cegieł, ale teraz wiem, że to trochę bardziej skomplikowana historia i mogła by on zniechęcić do dalszej nauki. Zresztą widziałem, że Adrian był już wymęczony tym kodowaniem.

Pewnie się zastanawiacie, czemu nie skorzystałem z Androida (pytał o to Jacek Laskowski na Twitterze)? Otóż żaden z nas nie posiadał telefonu z tym systemem, musiałbym wcześniej przygotować szkielet startowy (decyzja, że dzisiaj zaczynamy kodowanie wyszła bardzo spontanicznie), emulator androida dłużej startuje i miałem akurat prezentację na temat J2ME pod ręka. Technologia ta (Android w sumie też) daje nam szybką pętlę zwrotną, czyli wprowadzamy małą zmianę uruchamiamy emulator i oglądamy efekt. Dzięki temu praktykant może widzieć postęp swoich prac i kojarzyć, że napisanie pewnych linijek kodu, powoduje jakąś zmianę. Również efekt końcowy jest fajny, gdyż można wrzucić na telefon i pokazać kolegom w szkole. No i nie jest to nudna kolejna strona w HTMLu.

Całe wydarzenie uważam za udane. Czy Adrian się przekonał do kodowania? Nie wiem (ciągle czekam na feedback). Na pewno poczuł jak wygląda praca programisty i że można się przy niej zmęczyć, np. szukając babola w kodzie.

Dla zainteresowanych powtórzeniem ćwiczenia udostępniam kod na githubie. Proponuję zaczynać od rewizji 1d6ca27cc7be0507f4a9eda86e48957d1717c8d3, czyli mniej więcej od kodu z którego razem z Adrianem wychodziłem. Jest tam prezentacja przedstawiająca podstawy, jak i wyjaśniająca, co należy robić. Wrzuciłem również prezentację na slideshare.net, ale tam po kompresji prezentacja już nie wygląda tak jak powinna. Za jakiś czas udostępnię rozwiązanie w postaci kodu, jak i filmu z mojego kodowania. Materiał już nagrany, czeka tylko na post produkcję. A Was zachęcam do spróbowania swoich sił w J2ME i do zadawania pytań. Chętnie odpowiem.

niedziela, 23 października 2011

Mobilization – konferencja o technologiach mobilnych - wrażenia


Ledwie tydzień temu byłem na Warsjawie, a tu już następna konferencja: Mobilization.pl, która odbyła się w sobotę w Łodzi. Była to pierwsza edycja konferencji i jeszcze sporo pozostawia do życzenia co do poziomu wykładów, ale miejmy nadzieję, że w przyszłości się to poprawi.

O 9.50 było szybkie powitanie uczestników, parę spraw organizacyjnych i rozpoczął się pierwszy wykład Bartłomieja Zassa na temat programowania Windows Phone Mango. Mimo, że nie jestem fanem rozwiązań tej firmy, byłem pod wielki wrażeniem tej prelekcji jak i prelegenta. Przede wszystkim prezentacja była bardzo dobrze przygotowana, było kodowanie na żywo (które działało), opcja zoom na ekranie, zaznaczanie kursorem elementów na ekranie, pokaz działania telefonu na rzutniku, płynne przełączanie się pomiędzy kodem a prezentacją i jeszcze parę innych fajnych drobnostek. Istny majstersztyk. Jedyne co mi się nie spodobało, to częściowe ucięcie prawej strony ekranu prezentacji (złe wyskalowanie ekranu – można było wcześniej ustawić), i mówienie „na pan/państwo”. Ja wolę luźniejszy sposób prowadzenia prezentacji i zwracanie się „na Ty/Wy”.

Na samej prezentacji najpierw było trochę historii. W 2010 była premiera Windows Phone, ale nie w Polsce (gdyż nie było tłumaczenia na nasz ojczysty język) i oficjalnie nie można było kupić u nas takiego telefonu. Jednak jesienią 2011 pojawił się Windows Phone 7.5 Mango dostępny dla Polaków. Były na prezentacji podane minimalne wymagania sprzętowe, które musi posiadać telefon, aby obsługiwać ten system. Wymagania są dość spore co może wpływać na cenę urządzeń z produktem Microsoftu. Na dniach Nokia ma wypuścić Nokię 800 która ma działać na Windows Phone 7.

Na przedstawiany system można tworzyć oprogramowanie z wykorzystaniem Silverlight 4 czy też XNA (api dla XBoxa). Mango zawiera również Internet Explorer’a 9 (niby ten sam engine co w PC’tach), czyli daje to nam wsparcie dla Html’a 5 i sprzętowej akceleracji graficznej. Bartłomiej pokazywał słynny test FishIETank  odpalany na telefonie i wyglądał dobrze.

Telefony z Windowsem Phone 7 prezentują trochę inne podejście od obecnie popularnych smartfonów. Zamiast w menu wyświetlać ikonki, które uruchamiają poszczególne aplikacje, wprowadzono koncepcję kafelków. Są to takie większe ikonki, które pokazują jakiś stan aplikacji, np. informację, czy przyszły nowe e-maile. I nasze aplikacje (o ile to obsługują) można przypiąć do pulpitu jako taki kafelek. Ciekawe podejście, choć gusta są podzielone na temat tego rozwiązania.

Inną wprowadzoną do systemu koncepcją są Hub’y, czyli integracja informacji z wielu miejsc. Przykładowo w książce telefonicznej pod konkretnym kontaktem możemy mieć zagregowane informacje o danej osobie z facebook’a, linkedin’a gmail’a i innych. Fajna funkcjonalność.

Następnie było na prezentacji już bardziej praktycznie. Prelegent pokazał kilka przykładowych aplikacji i jak można prosto i szybko tworzyć własne. Bartek stworzył na szybko aplikację o konferencji dla Windows Phone 7.5. Pokazał przy tym jak można to robić z poziomu Visual Studio jak i Expression Blend 4. Oba narzędzia dobrze się integrują i synchronizują. Pierwsze służy programistom, a drugie jest bardziej dla grafików i projektantów interfejsów graficznych, ale można w nim również sporo funkcjonalności wyklikać. Jeśli chodzi o licencjonowanie to narzędzia są bezpłatne.

Microsoft udostępnił również (podobnie jak konkurencja) miejsce gdzie można umieszczać i sprzedawać swoje aplikacje, czyli Marketplace. Studenci mogą sobie za darmo konto założyć, osoby prywatne i firmy płacą 100 $ rocznie.

Prezentację uważam za najbardziej udaną i pokazującą najwięcej ze wszystkich prezentacji w jakich uczestniczyłem w ramach tej konferencji. Wystąpienie się przedłużyło, przez co cała agenda się przesunęła o 15 minut.

Kolejną prezentacją na której byłem, było Programowanie Android 3.0 prowadzone przez Krzysztofa Janika. Prezentacja słaba, już na drugim slajdzie były jakieś błędy. Prelegent chciał zrobić małe demo pokazywane z tableta (bo tam działa Android 3.0), ale miał jakieś problemy z kablem. Próbował jeszcze włączyć live streaming (cała konferencja była stream’owana na giwebcast.pl) na rzutniku, by pokazać tablet do kamery. Niestety nie udało się załadować streamingu na komputerze prelegenata :( Dodatkowo Krzysiek często patrzył na slajdy i zadawał dużo pytań publiczności, które nie wnosiły nic do tematu. Bardzo słabe wystąpienie.

Jedyne co wyniosłem z prelekcji to obecność w Androidzie 3.0 czegoś co nazywamy Fragments. Są to jakby miniActivity, które możemy dynamicznie osadzać w innych Activity.

Kolejne wystąpienie było Konrada Hołowińskiego na temat Multiplatform mobile apps. Konrad przedstawił dwa rozwiązania pozwalające pisać raz i uruchamiać aplikację na różnych urządzeniach mobilnych.

Pierwszym omawianym rozwiązaniem było Appcelerator Titanium. Aplikację tworzymy za pomocą JavaScript’u wykorzystując dodatkowo natywne komponenty dla konkretnych platform. Titanium dorzuca później do kodu własny interpreter JS, co zwiększa wielkość aplikacji. Jeśli dobrze zrozumiałem, to od pewnego czasu produkt ten używa statycznej analizy i kompilacji kodu, generując kod natywny dla danej maszyny. Zdecydowano się na taki krok ze względów wydajnościowych, ale przez to pojawiały się przez jakiś czas wycieki pamięci.

Titanium wspiera Androida, iOSa i BlackBery (nie w pełni). Dzięki  kompilacji do natywnego kodu, aplikacje przyjmują wygląd platformy na której są uruchamiane. Pojawiają się przez to często różnice w wyglądzie na innych urządzeniach, co zostało pokazane podczas prezentacji na emulatorach iPhone’a i Androida. Mamy również dostępne darmowe jak i płatne plugin’y rozszerzające możliwości dostarczane przez Titanium.

Następnie było o konkurencyjnym rozwiązaniu PhoneGap, które wspiera więcej (bo aż 6) platform. Tutaj piszemy w HTMLu 5, JavaScript’cie i CSS3. Produkt jest typu open-source i wszelkie plugin’y są rozwijane przez społeczność.

PhoneGap jest uruchamiany w natywnym silniku JS danego urządzenia. Daje on jednak też dostęp do większości funkcjonalności dostępnych w smartfonach, za pomocą „zmostkowania” ich do JS. Podejście to ma swoje wady jak i zalety. Wadą jest brak wsparcia dla wielowątkowości i wolniejsze działanie od aplikacji tworzonych w Titanium, lub natywnie. Za to naszą aplikację możemy uruchomić w przeglądarce i podejrzeć cos się dzieje np. za pomocą FireBug’a.

Z ciekawostek, to PhoneGap zostało ostatnio przejęte przez firmę Adobe, które się stara zaistnieć na rynku urządzeń mobilnych. Zobaczymy co z tego wyjdzie.

Na konferencji miałem okazję poznać Tomka Dziurko. Po prezentacji Konrada poszliśmy na obiad i po nim chcieliśmy pójść na Advanced layouts on the Android battlefield. Jacka Niedzwieckiego, ale chwilkę się spóźniliśmy, a sala była wypchana po brzegi. Alternatywny wykład o Windows 7 nas nie interesował, więc se posiedzieliśmy w holu konferencji.

Następnie miał być wykład o Androidzie i SmartTV, ale prelegent nie przyjechał. W jego miejsce wrzucono Testowanie w Systemie Android Marka Defecińskiego. Marek był jednym z organizatorów konferencji i prowadzi Blog Progamisty Android. Marek jest niespełnionym fanem testów. Swoją opowieść zaczynał od J2ME, w której sam miałem przyjemność się sprawdzić. I rzeczywiście potwierdzam, że o testowaniu w J2ME nie ma co mówić.

Później już było o Androidzie i testowaniu funkcjonalnym za pomocą robotium. Projekt się reklamuje jako Selenium ale dla Androida i działa na emulatorze Androida. Prelegent nie był jednak do końca zadowolony z tego rozwiązania.

Innym ciekawym, omawianym projektem był Robolectric. Jest to framework do testów, który za pomocą Javassist podmienia to co siedzi w android.jar. Dzięki temu możemy nasze testy odpalać na komputerze, działa refaktoryzacja i jest to szybkie.

Było jeszcze wspomniane o android-mock i paru innych frameworkach do testowania. Niestety Marek nie pokazał żadnych przykładów, zrzucając winę na aktualizacje maven’a. Brakuje mu jeszcze oswojenia z publiką i rozluźnienia podczas prowadzenia prezentacji. Na problem suchego gardła polecam wodę z cytryną przed i w trakcie prezentacji (powoduje wydzielanie śliny) jak i unikania słodyczy oraz nadmiernego picia wody (wysusza gardło). Ponadto bujanie się na boki jest trochę denerwujące / rozpraszające dla słuchaczy. Niestety pewność na tego typu wystąpieniach można wyćwiczyć jedynie występując.

Następne prelekcje były dla mnie mniej interesujące. Spotkałem na konferencji Pawła Zubkiewicza, którego znam dzięki WrocJUG. Jako, że Paweł jest z Wrocławia, postanowiłem się zabrać z Nim i innymi pracownikami QNH do domu, gdyż powrót autobusem o 21.35 z Łodzi jakoś mi się nie uśmiechał.

W drodze powrotnej nie mogło się obejść bez niespodzianek, mianowicie klocki hamulcowe się starły i musieliśmy się zatrzymać. Na całe szczęście wylądowaliśmy w miejscowości Szadek, a nie gdzieś w lesie. Dobrą pizze tam mają i gdyby nie ta awaria nigdy bym się tam nie pojawił. Pomoc drogowa zawiozła nas z powrotem do Łodzi i tam już czekał na nas samochód zastępczy, którym dojechaliśmy do Wrocławia.

Podsumowując, jak na pierwszą edycję konferencji, organizacja wypadła dobrze. Były dostępne przekąski w postaci kanapek i jogurtów (świetny pomysł) jak i kawa / herbata. Jedna sala była trochę mała, przez co nie chciałem się dociskać na jeden wykład. Na krzesełkach konferencyjnych były fajne podkładki przyczepiane do krzesła rzemykiem, na których się wygodnie notowało. Trzeba jedynie poziom prezentacji podnieść i będzie cacy.

poniedziałek, 2 maja 2011

Warunkowa kompilacja j2me w srodowisku NetBeans

Pisanie aplikacji na urządzenia mobilne w j2me nie jest prostą sprawą. Niby specyfikacja KVM (Kilobyte Virtual Machine) jest jedna i narzucona przez Oracle’a (dawniej Sun’a), ale konkretną implementację dostarcza producent danego telefonu komórkowego. Ponadto mamy sporo różnych modelów telefonów, różniących się od siebie wielkością ekranu, ułożeniem przycisków, szybkością procesora itd. Często przychodzi potrzeba dostarczenia aplikacji zoptymalizowanej pod konkretny telefon. Przedstawię poniżej w artykule jak można tego dokonać za pomocą warunkowej kompilacji w NetBeans’ie.

Warunkowa kompilacja to bardzo stary pomysł znany mi z czasów języka C (a może i był używany wcześniej). Polega ona na dodaniu do kodu źródłowego pewnych instrukcji, które zostaną wykonane jeszcze przed właściwą kompilacją. Spowoduje to wybranie odpowiednich fragmentów kodu, które zostaną dołączone do wynikowego programu. Projektanci języka Java całkowicie zrezygnowali z warunkowej kompilacji ze względu, że jest ona wrogiem numer 1 obiektowości. Gdy J2ME ujrzała światło dzienne i gdy coraz więcej telefonów zaczęło wspierać tą funkcjonalność, zrozumiano że jednak pewna możliwość konfigurowania kodu przed właściwą kompilacją jest niezbędna. I tak się narodziła warunkowa kompilacja w NetBeans'ie. Oczywiście wiem, że obecnie mamy XML’e, Dependency injection, Inversion of control i inne możliwości konfiguracji naszych aplikacji, ale nie mają one zastosowania w świecie j2me. Powstały co prawda projekty Signal Framework i Spring ME coś ala IoC dla j2me, ale jak dla mnie to sztuka dla sztuki i zastosowanie zerowe (i tak trzeba całość kompilować).

Dobra czas przejść do konkretów. Poniżej prezentuję fragment kodu, który używam w swojej aplikacji, z wykorzystaniem warunkowej kompilacji:

private void drawHelpMenu(Graphics g) {
//#if MobileTouchScreen
    helpSprite.setPosition(getWidth() - helpSprite.getWidth(),
            getHeight() - helpSprite.getHeight());
    helpSprite.paint(g);
//#else
    String  back = I18n.getText(I18n.LESSON_HELP);
    g.setFont(getSmallFont());
    g.drawString(back, getWidth(), getHeight(),
            Graphics.RIGHT | Graphics.BOTTOM);
//#endif
}

Interesujące fragmenty to te zaczynające się od //#. Są to instrunkcje preprocesora. Jak to działa? Gdy mamy ustawione ability MobileTouchScreen, to wówczas linijki 3-5 zostaną skompilowane, w przeciwnym wypadku linijki 7-10 zostaną wstawione w ciało metody drawHelpMenu(...). Prawda ze proste?

Teraz nadszedł czas na zarządzanie naszymi “zdolnościami” (chyba nienajlepsze tłumaczenie). Klikamy prawym przyciskiem myszy na nazwę projektu i wybieramy z menu opcję Properties. Tam w kategorii Abilities możemy zobaczyć jakie mamy ustawione właściwości dla obecnej konfiguracji naszego projektu. Właściwości mogą posiadać wartość, ale nie muszą.


Proponuję teraz utworzyć sobie nową konfigurację. Z pola Project Configuration wybieramy Add Configuration I wpisujemy nazwę nowej konfiguracji I następnie klikamy OK. Możemy tutaj jeszcze wybrać szablon, na podstawie którego zostanie utworzona konfiguracja.


Po kliknięciu OK wracamy do poprzedniego ekranu i teraz możemy modyfikować naszą konfigurację. Najpierw musimy odznaczyć pole Use Values from „DefaultConfiguration”. Dzieki temu przycisk Add staje się aktywny. Klikamy i w nowym oknie wpisujemy nasze ability MobileTouchScreen.


Klikamy OK i w oknie z właściwościami naszego projektu pojawiła się nowa pozycja w tabelce właściwościami danej konfiguracji.

Teraz chcąc skompilować projekt, używając nowej konfiguracji, należy ją wybrać z menu w górnej części okna.


Jak popatrzymy na nasz kod to zobaczymy, że NetBeans koloruje tło pod kodem nalezącym do warunkowej kompilacji:


Dodatkowo dodał komentarze na początku linii pomiędzy //#else a //#endif. Dzięki temu kod nie będzie dołączony do kompilowanej aplikacji. Zmiany te są zapisywane w pliku na dysku (polecam sprawdzić) i NetBeans nie zawsze chce się odświeżyć (w sensie widoku pliku źródłowego). Warto wtedy zamknąć i otworzyć na nowo plik, aby wiedzieć co edytować. Ponadto mechanizm ten zapewnia bezbolesny eksport do innego środowiska IDE, które nie wspiera tego mechanizmu. Całość zostanie potraktowana jako zwykły komentarz.

Z drugiej strony mechanizm może utrudniać merge’owanie i śledzenie zmian w kodzie. No chyba że wszyscy będą pamiętać, aby przed commit’em jedną, zawsze tą samą konfigurację ustawić.

Czy blok if else endif to wszystko co daje nam warunkowa kompilacja w NetBeans? Nie. Z ciekawszych opcji mamy jeszcze //#condition NAZWA_ABILITY i dzięki której decydujemy czy dany plik ma być dołączony do danego build’a, czy nie. Deklaracja musi być jednak umieszczona na początku pliku!

No dobra, mamy już skonfigurowany kod, ale co z innymi zasobami? Np, z grafiką, którą np. potrzebujemy tylko do wersji z obsługiwanym ekranem dotykowym? Mamy możliwość zdefiniowania zasobów, które mają się w takiej konfiguracji znaleźć. W tym celu przechodzimy do właściwości projektu i wybieramy Librares & Resources. Odznaczamy Use Values from „DefaultConfiguration” i już możemy dodawać katalogi, biblioteki i inne wymagane projekty.

Nie pozostaje teraz nic innego jak wziąć się do roboty i zacząć odpowiednio dostosowywać nasze mobilne aplikacje.

sobota, 19 lutego 2011

Kilka porad na temat MIDP Visual Design w Netbeans'ie

Dzisiaj chciałbym opowiedzieć o kilku sztuczkach, w MIDP Visual Design, który jest dostępny w Netbeans’ie. Tak wiem, że technologia J2ME (czy też JME) jest już trochę przestarzała, gdyż teraz mamy Androidy iPhone’y, BlackBery, Windows 7 i inne ciekawsze cuda na kiju ;) Zamierzam jednak jeszcze kilka postów o j2me na blogu opublikować, ot tak dla potomności.

Z opcji MIDP Visual Design możemy skorzystać tworząc nowy projekt z grupy „Java ME” typu „Mobile Application” w NetBeans’ie. Wystarczy nie odznaczać (gdyż domyślnie jest zaznaczony) CheckBox’a „Create Hello MIDlet”.


Można również do istniejącego projektu dodać Visual MIDlet i uzyskamy podobny efekt.

Narzędzie pozwala nam w prosty sposób zbudować menu użytkownika, przechodzenie pomiędzy ekranami itp. Mamy ładny podgląd gdzie z danego miejsca możemy się przemieścić, czyli widzimy przepływ aplikacji (menu). Należy pamiętać, że generowane menu oparte jest na komponentach wysokopoziomowych (tych dziedziczących z klasy Screen). Przykładowy screen jak może taki przepływ wyglądać poniżej.


Oczywiście w ten sposób nie zrobimy całej aplikacji. Mamy możliwość dodawania kodu w pewnych miejscach i większość rzeczy można wyklikać. Generalnie narzędzie świetnie się nadaje do prototypowania, gdy na szybko trzeba coś pokazać. Nie widzę jednak przeciw wskazań, do użycia tego również na produkcji. Generowany kod jest całkiem dobry. Poniżej kilka wskazówek, związanych z tym oto narzędziem:

1. Możemy wybrać w jaki sposób poszczególne komponenty są inicjowane. Po wybraniu danego Screena w oknie Properties widzimy dostępne opcje. Po za zmianą wyświetlanego tekstu i innych właściwości, możemy wybrać czy mają być Lazy Initialized czy nie.


Proponuję każdemu sprawdzić, jaki kod zostaje wygenerowany przy zmianie tego komponentu. W małych aplikacjach może to nie mieć wielkiego znaczenia, czy komponent jest lazy czy nie, ale te duże / ciężkie komponenty (lub rzadko używane) powinny być leniwie inicjowane. Oczywiście część komponentów może być inicjowana tak, a druga inaczej.

2. Możemy również zmienić sposób generowania logiki, odpowiedzialnej za przechodzenie pomiędzy kolejnymi ekranami. Domyślnie to, która opcja z menu została wybrana, sprawdzane jest na podstawie etykiety (label’ki) przypisanej do danego elementu ekranu. Przykład poniżej:

public void mainMenuAction() {
    // enter pre-action user code here
    String __selectedString = getMainMenu().getString(getMainMenu().getSelectedIndex());
    if (__selectedString != null) {
        if (__selectedString.equals(“Etykieta”)) {
            // ...

Włączając opcję “Index Based Switch” powyższy kod zostanie przekształcony w coś takiego:

public void mainMenuAction() {
    // enter pre-action user code here
    switch (getMainMenu().getSelectedIndex()) {
        case 0:
            // ...

Zachowanie to może mieć znaczenie wówczas, gdy chcemy wprowadzić internacjonalizację do naszej aplikacji i podmianę tekstów na elementach „w locie”. W drugim przypadku logika aplikacji w żaden sposób nie zależy od przypisanej etykiety w danym komponencie, a jedynie na jego położeniu. Po takim zabiegu podmiana tekstów jest prostsza.

3. Odnośnie internacjonalizacji, to w większości kontrolek mamy możliwość podmiany wyświetlanego na niej tekstu (dziedziczymy z klasy Displayable metodę setTitle()). Problem jest jednak z obiektami typu Command, które są immutable, gdyż nie posiadają metod modyfikujących ich stan. Można za to skorzystać z następującej sztuczki: usunąć z danego ekranu istniejące obiekty Command, utworzyć je na nowo i podpiąć. Przykład poniżej:

getSettingsMenuList().removeCommand(getBackCommand());
backCommand = null;
getSettingsMenuList().addCommand(getBackCommand ());

W pierwszej linii usuwamy obecną powiązaną komendę z danym ekranem. W drugiej linii zerujemy referencję do obiektu zwracanego przed getBackCommand(). Na koniec tworzymy obiekt na nowo (wywolanie getBackCommand()) i przypisujemy nową komendę do żądanego elementu. Korzystamy tutaj z faktu, że dana komenda jest leniwie inicjowana i po wejściu w metodę  getBackCommand(), zostanie ona na nowo utworzona.

4. Generalnie często początkujący programiści zderzający się z MIDP Visual Design wkurzają się, że nie mogą tu wszystkiego zrobić czego chcą. Według mnie wszystko da się wyklikać (w zakresie oferowanym przez edytor), ewentualnie dopisując niewielkie kawałki kodu w miejscach, w których edytor nam na to pozwala. Na prawdę nie znalazłem niczego, w czym by edytor mnie ograniczał.

Jednakże chcąc się pozbyć wsparcia ze strony MIDP Visual Design można wykonać pewien trick. Usuwając z dysku plik .vmd i wszystkie komentarze, generowane przez edytor, z pliku .java. Oczywiście musimy zrobić to w innym edytorze tekstowym, a nie pod NetBeans’em. Nie będziemy mogli również wrócić do poprzedniego stanu, ani więcej zobaczyć przepływu aplikacji dla naszego kodu.

Usunięcie komentarzy (przynajmniej część) z pliku z kodem, jest równie ważne jak usunięcie pliku *.vmd. W przypadku usunięcia tylko tego pliku możemy napotkać na problemy z otwarciem projektu pod NetBeans’em.

Poniżej początki komentarzy dodawanych przez NetBeans’a:

//<editor-fold
//</editor-fold
//GEN-LINE
//GEN-BEGIN
//GEN-END

To tyle na dzisiaj. Zachęcam do korzystania z tego edytora. Jak było coś niejasne to piszcie!

poniedziałek, 26 lipca 2010

Dekompilacja kodu w J2ME

Kiedyś ściągnąłem pewną aplikację (napisaną w J2ME) na mój telefon i po pewnym czasie użytkowania okazało się, że należy podać do niej kod aktywacyjny (za który oczywiście należy zapłacić). Zastanawiałem się, czy da się jakoś to ominąć i poniżej opiszę rezultaty mojej rozkminki, jak sobie z tym poradzić.

Jak wiadomo kod Javy jest kompilowany do bytecode'u, a ten uruchamiany na wirtualnej maszynie Javy (eng. Java Virtual Machine, JVM). Dzięki temu kompilujemy raz, a uruchamiamy wszędzie (tzn. tam gdzie jest Java Wirtual Machine). Ilustruje to poniższy obrazek:




Skoro kod nie jest kompilowany do natywnego kodu języka danego urządzenia, to możemy skorzystać z tak zwanej wstecznej inżynierii (ang. reverse engineering). Właściwie to każdy plik wykonywalny można zdekompilować, tylko w przypadku aplikacji pisanych nie w Javie, zazwyczaj po dekompilacji mamy odczynienia z kodem asemblerowym, a ten nie należy do przyjemnych w czytaniu. W przypadku Javy mamy trochę lepiej.

W sieci dostępnych jest kilka dekompilatorów kodu Javowego (DJ Java Decompiler  Java Decompiler  Mocha i inne). Ja posłużę się tym pierwszym. Na cele tego artykułu stworzyłem niewielką aplikację, aby pokazać jak skorzystać z możliwości wstecznej dekompilacji. Nie chciałem łamać jakiejś innej aplikacji, aby nie być posądzonym o ingerencje w nią, co pewnie się wiąże z łamaniem prawa. Z własną aplikacją mogę robić co chcę :P

Zacznijmy więc. Na początek należy zawsze uruchomić aplikację i zobaczyć czego szukamy. Jak nie chce nam sie wrzucać jej na telefon, a mamy zainstalowane Java ME platform SDK możemy odpalić ją na komputerze w ten sposób:

<Java ME platform SDK path>\bin\emulator.exe -Xdescriptor:<JAD file path>

Oczywiście należy podać odpowiednie ścieżki, gdzie mamy zainstalowane SDK i gdzie leży nasza aplikacja. W innych SDK (starszych wersjach, lub innych producentów) mogą być graficzne narzędzia umożliwiające odpalenie aplikacji J2ME na komputerze. Poniżej przedstawiam jak wygląda moja aplikacja odpalona na emulatorze:



Po lewej mamy ekran startowy (specjalnie dodałem kilka opcji, aby coś było), a po prawej ekran po wybraniu opcji "Activation". W ekranie tym należy wpisać odpowiedni kod aktywacyjny. To jest miejsce na którym nam zależy i które chcemy złamać.

Odpalamy DJ Java Decompiler. Następnie File -> Open jako typ pliku wybieramy: Java Archive Files(*.jar) i wskazujemy naszego JARa. Ukazuje nam się poniżej okno podobne do poniższego:


Wciskamy Ctrl + A aby zaznaczyć wszystkie klasy i klikamy Decompile. Wskazujemy miejsce docelowe i w pojawiającym sie komunikacie klikamy Yes i po chwili w wybranym folderze otrzymujemy wynik. Plik *.class jest plikiem otrzymanym bezpośrednio przez wypakowanie JARa (gdyz de facto to zwykłe archiwum), a w pliku *.jad mamy zdekompilowany kod. Ciekaw jestem czemu akurat takie rozszerzenie zostało wybrane przez twórców aplikacji, skoro jest ono używane w procesie instalacji aplikacji komórkowych? Można było przecież utworzyć pliki *.java.

No dobra zajrzyjmy do zdekompilowanego pliku. Kod wygląda czytelnie. Porównałem go KDiff3'em z oryginalnym kodem i po za modyfikacją importów, zmianą standardu kodowania, niewielkimi modyfikacjami i dodanymi kilkoma komentarzami kod sie zasadniczo nie różnił. Utworzyłem nowy projekt i wrzuciłem ten "odzyskany" kod i się poprawnie skompilował i poprawnie działa!

Przejdźmy do analizy kodu. Na początku ukazuje nam się konstruktor klasy (część linii pominięto i zachowano oryginalne formatowanie):




Na początku są tworzone obiekty typu Command i widzimy, że to co nas interesuje ("Activation") jest dodawane do List'y. Następnie dodawane jest okCommand i co najważniejsze wywołanie setCommandListener z przekazaniem obiektu this. Oznacza to, że nasza klasa implementuje CommandListener, do którego są kierowane zdarzenia z naszej formatki. Sprawdzamy powyżej:



Rzeczywiście. Przejdźmy więc do metody zdefiniowanej przez ten interfejs:



Na początku jest sprawdzenie czy obiekt command odpowiada naszej liście opcji. Jeśli tak, to sprawdzane jest czy była to komenda okCommand. Jeśli tak to pobierany jest index aktualnie zaznaczonej opcji i coś się dalej dzieje. Jako, że opcja "Activation" byla na 3ciej pozycji w menu (widać to na screenie), to patrzymy co się dzieje pod dwójką ;)



Wywoływana jest jakaś metoda i następnie na wyświetlaczu jest ustawiane do wyświetlenia activationForm. Dowiedzmy się więcej o tym obiekcie. Wróćmy do konstruktora:



Do activationForm dodawane są dwie kontrolki i znów CommandListener ustawiony na this. Wróćmy wiec do metody commandAction() i zjedźmy trochę niżej:



Tak ten warunek to miejsce gdzie trafia wykonanie naszej aplikacji, gdy wciśniemy Ok na activationForm. Zobaczmy co się dzieje poniżej:



Najpierw pobierany jest tekst z kontrolki, która jest odpowiedzialna za wprowadzenie kodu aktywacyjnego. Następnie sprawdzana jest długość pobranego tekstu i gdy jest ona różna od 12 to wywoływana jest metoda showBadActivationCodeMessage(). Sama nazwa juz sugeruje, że nie jest to nic dobrego. Jaki wniosek z tego? Nasz kod aktywacyjny musi mieć 12 znaków długości. Sprawdźmy co się dzieje gdy warunek ten jest spełniony:



Pobierane są kolejno 3ci 8my i 11sty znak z naszego kodu aktywacyjnego. I jeśli odpowiadają one odpowiednio literom 'A', 'B' i 'C' to odnosimy sukces.

Sprawdźmy więc. Odpalamy naszą aplikację na emulatorze (lub telefonie) i wpisujemy np.: xxxAxxxxBxxCx i prosze: Code OK. Złamaliśmy w ten sposób aplikację J2ME.

Jak widać można w prosty sposób podejrzeć kod obecny w aplikacjach J2ME. Jak sie jednak ustrzec przed tego typu ingerencją w oprogramowanie? Właściwie nie można w 100% się ustrzec przed tego typu atakami. Można jedynie utrudnić śmiałkom zadanie.

Najprostszym sposobem ochrony naszego kodu jest stosowanie tzw. obfluskacji (eng. Obfuscation). Polega ona na "upiększaniu kodu", w taki sposób, aby po dekompilacji ciężej było go odczytać. Jest kilka tego typu narzędzi na rynku. Jedno jest dołączone do Netbeansa. Jeśli mamy projekt J2ME utworzony w tym środowisku klikamy prawym przyciskiem myszy na nasz projekt i przechodzimy do Properties. Następnie klikamy na Obfluscating. Tutaj możemy juz sobie ustawić żądany poziom obfluskacji:



Klikamy OK i przebudowujemy nasz projekt. Teraz po wstecznej dekompilacji kod jest mniej czytelny, np.: pole options zmieniło nazwę na a_javax_microedition_lcdui_List_fld, a inne pola skróciły się do jednoliterowych nazw. Jest to trudniejsze w czytaniu, ale narzędzia pozwalające kolorować składnię trochę nam pomagają. Tutaj pokazuję przykład działania na prostym przykładzie i może efekt nie jest powalający. Przy dużych projektach narzędzia takie potrafią namieszać tak, że kod uzyskany za pomocą wstecznej inżynierii nie uda sie ponownie skompilować!!!

Dlaczego tak sie dzieje? Otóż to co jest dozwolone z poziomu kompilatora javy jest również dozwolone w bytecode'dzie. Jednak są pewne elementy bytecode'u, które nie są dozwolone z poziomu składni języka Java. Np. w bytecode'dzie mogą być metody o tej samej nazwie, przyjmujące te same argumenty a zwracające różną wartość! Odpowiednia metoda zostanie wywołana na podstawie typu do którego będzie rezultat przypisywany, lub jeszcze jakiś innych przesłanek. Analiza takiego kodu jest o wiele trudniejsza i bez dobrego refaktoringu nie da się obejść.

Na nasze szczęście (lub nie) klasa rozszerzająca MIDlet możne być poddana tylko częściowej obfluskacji, więc zawsze łatwo będzie nam znaleźć miejsce wejścia do programu:) Również nazwy metod dostarczanych przez javę (np. w klasie String) nie mogą być zmienione, co trochę ułatwia analizę takiego kodu.

Jak jeszcze można się bronić przed wsteczną dekompilacją? W J2ME nie ma mechanizmu ClassLoader'a, więc w ten sposób nie zabezpieczymy naszej aplikacji. Jedyne co po za obfluskacją przychodzi mi do głowy to własna implementacja odpowiednich mechanizmów zabezpieczających.

Poniżej zamieszczam jeszcze spakowany projekt, na podstawie którego prezentowałem zagadnienie. Będziecie mogli się sami pobawić i zobaczyć jak to działa.


PasswordNeed.zip (17KB)