Krótkie podsumowanie mojego udziału w „Daj się poznać”

To jest mój 21 wpis na tym blogu. Napisałem 20 notek i mogę tylko powiedzieć, ze nie było to łatwe dla mnie 😉

Było kilka powodów, dla którego zdecydowałem zgłosić się do „Daj się poznać”.

  • większa motywacja do stworzenia aplikacji, nad którą i tak zaczynałem pracować
  • sprawdzenie się czy jestem w stanie pisać regularnie notki na blogu
  • chęć poćwiczenia umiejętności, którą bym nazwał ‚płynność pisania’

A jak to się sprawdziło w praktyce?

Motywacja do tworzenia aplikacji była taka sama jak wcześniej 🙂 Chciałem napisać tą aplikacje (w sumie to dalej chcę ;)) tak samo i w ramach wolnego czasu starałem się ją rozwijać. Rzeczą, którą zmieniłem po zgłoszeniu się do konkursu była decyzja o zmianie języka. Pierwsze dwa ekrany miałem już napisane w Javie, ale stwierdizłem, że jest to dobra okazja, żeby pouczyć się Scali 🙂 Więc w sumie gdyby nie konkurs to właściwie miałbym aplikacji napisane więcej niż teraz ;), ale za to mniej umiałbym Scali – więc w sumie sądzę, że dobrze wyszło 🙂

Czy udało mi się pisać notki regularnie? Prawie 🙂 Wpisy pojawiały się prawie zawsze 2 razy w tygodniu, więc tutaj prawie pełen sukces 🙂 Niestety czasem miałem wrażenie, że nie mam czasu na rozwijanie aplikacji, bo muszę pisać notkę 😉

Co prowadzi nas do punktu 3 🙂 Każda notka, szczególnie na początku, sprawiała mi sporo trudności, żeby ją napisać. Wraz z każdą kolejną notką było co raz lepiej, ale do pożądanego przeze mnie poziomu jeszcze daleka droga 🙂

Podsumowując jednym zdaniem swój udział w „Daj się poznać” – Jestem zadowolony 🙂

DatePicker w Androidzie

Kolejnym ekranem, nad którym będę pracował jest zaawansowane wyszukiwanie dokumentów. Przez słowo ‚zaawansowane’ rozumiem coś więcej niż tylko wyszukiwanie po tagach, po których możemy wyszuiwać na głównym ekranie. Chcę dodatkow zaimplementować możliwość wyszukiwania po tytułach dokumentów czy po datach kiedy zostały dodane.

Właśnie do wyszukiwania po datach postanowiłem użyć datepicker’a.

W formularzu chcę mieć dwie kontrolki:

  • pole tekstowe, gdzie będzie można ręcznie wpisać date
  • ikonka kalendarza, w którą jak klikniemy pojawi nam się nasz datepicker, a wybrana data zostanie zapisana we wcześniej wspomnianym polu tekstowym

Czyli na początku stworzyłem dwie wcześniej wspomniane kontrolki:

Pierwsza kontrolka to zwyczajne pole tekstowe. Druga kontrolka to przycisk, który po kliknięciu wywoła metodę datePicker. Metoda ta wygląda w następujący sposób:

Gdzie datePickerCode jest zdefiniowanym w aplikacji kodem dla danej akcji czyli po prostu liczba typu Int.

Wywołanie metody showDialog(Int) wywoła metodę onCreateDialog, która u mnie wyglada następująco:

Akcje wykonywane w tej metodzie są dosyć proste. W przypadku gdy metoda zostanie wywołana z naszym kodem tworzymy DatePickerDialog z naszą implementacją OnDateSetListener. U mnie wygląda to następująco:

Wydaję mi się, ze kod jest na tyle prosty oraz intuicyjny, że nie będę bardziej szczegółowo opisywał tych funkcji oraz klasy 🙂

Opis ekranów i funkcjonalności aplikacji cz. 2

Dzisiaj pokaże dwa kolejne screeny z mojej aplikajci.

  1. Wyświetlanie szczegółów dokumentu
    Screenshot_2010-04-13-01-21-06Na górze strony, na niebieskim tle, znajduje się tytuł dokumentu. Po prawej stronie znajduje się button uruchamiający edycje dokumentu.
    Poniżej są wypisane wszystkie tagi z dokumentu. Pod spodem znajdują się wyświetlone wszystkie pliki wraz z opisem plików. Każda miniaturka po kliknięciu uruchamia zdjęcię w pełnej rozdzielczości.
  2. Edycja dokumentu
    Screenshot_2010-04-13-01-21-35Edycja dokumentu jest praktycznie identyczna jak dodawanie dokumentu, które opisywałem jakiś czas temu. Główną różnicą jest oczywiście to, że do formularza zostają załadowane tytuł, tagi oraz pliki wraz z opisami.

Problem z GUI tworzonym w kodzie

Ostatnie kilka godzin pisania aplikacji poświęciłem na walce z dynamicznym tworzeniem elementów GUI w kodzie. Udało mi się w końcu wstępnie uzyskać efekt, który chciałem, i który jeszcze dopracuję. Problemem okazał się mały szczegół, o którym nie widziałem…

Problem, który chcę opisać, napotkałem przy tworzeniu ekranu wyświetlającego szczegóły dokumentu. Na tym ekranie powinien być widoczny tytuł dokumentu, tagi oraz wszystkie pliki wraz z ich opisami. I przy tym ostatnim elemencie powstały problemy.

Screenshot_2010-04-01-02-58-53

Powyżej wstawiłem efekt jaki bym chciał osiągnąć. Chodzi oczywiście o rozmieszczenie elementów – niebieskie linie oraz zielony kolor zostały dodane dla lepszej widoczności co się dzieję. Wracając do układu elementów – pliki chciałbym wyświetlić w formie tabelarycznej, gdzie w lewej kolumnie będzie miniaturka zdjęcia/pliku, a w prawej będzie dodany opis pliku.

Powyższy efekt udało się uzyskać przy pomocy następującego kodu:

Czy tworzę TableRow i są w nim dwa elementy:

  • FrameLayout, który w sobie zawiera ImageView z obrazem
  • TextView, który zawiera opis pliku

Oczywiście kod ten w XMLu stworzyłem tylko po to, żeby zobaczyć, których elementów mam użyć, żeby uzyskać efekt jaki chcę. Sama lista plików z opisami będzie oczywiście tworzona dynamicznie w kodzie.

Jeden wiersz tworzyłem mniej więcej w poniższy sposób:

Tworząc elementy tabeli w kodzie starałem się tworzył dokładnie te same elementy z tymi samymi parametrami, które użyłem w XMLu. Niestety tworzenie wiersza tabeli w powyższy sposób powodował, że na ekranie nic się nie pojawiało – tabela zostawała pusta. Metodą prób i błędów próbowałem dojść do tego co jest nie tak i w końcu mi się udało.

Okazało się, że przy tworzeniu ustawień layouty, czyli tworząc obiekty LayoutParams musimy użyć LayoutParams z klasy rodzica danego elementu, a nie z samego elementu. Czyli w przypadku gdzie tworzyłem wiersz tabeli w poniższy sposób

wystarczyło zamienić na:

Czyli użyć TableLayout.LayoutParams zamiast TableRow.LayoutParams, ponieważ TableLayout jest rodzicem naszego wiersza.

Po takich zmianach w kodzie ekran wyświelił elementy w taki sposób w jaki chciałem. Kod po modyfikacjach wyglada następująco:

Android Studio 2.1 i DEX 64K Methods Limit

W kwietniu została wypuszczona nowa wersja Android Studio opatrzone symbolem 2.1. Postanowiłem je ściągnąć i wypróbować.

Po ściągnięciu i uruchomieniu konfiguracja poszła gładko. Wszystkie ustawienia zostały zaimportowane z poprzedniej wersji środowiska, więc wszystko praktycznie ogarniczało się do klikania ‚Next’ i potwierdzenia przeczytania licencji 😉

Po skończonej konfiguracji uruchomiłem aplikacje na emulatorze. Wszystko poszło bez przeszkód. Problemy pojawiły się gdy chciałem uruchomić aplikacje na realnym urządzeniu. Przy próbie kompilacji i uruchomienia apki pojawiają się poniższe błędy:

Android posiada ograniczenie 64k referencji metod. Gdy przekroczymy ten próg to pojawia się na powyższy bład.

Na GitHubie pluginu do scali dla androida jest opisany ten problem w punkcie 5. Jako rozwiązanie problemu zaproponowane są dwa podejścia.

  1. Użycie ProGuard, który usuwa nieużywane metody/kod przy kompilacji, dzięki czemu nie przekracamy wyżej wspomnianego limitu.
  2. Uzycie opcji MultiDex, która pozwala utworzyć aplikacji więcej niż jeden plik Dex.

Odniosę się może najpiew do podejścia drugiego. Aby uruchomić tą opcje wystarczy dodać do pliku gradle poniższy wpis:

I to podejście działa w Android Studio 2.1, ale nie ukrywam, że nie podoba mi się. Nie po to tworzę SIMPLE Document Manager, żeby zajmował dużo miejsca 😉

Co do pierwszego podejścia, to ono działało w Android Studio 1.5 jak należy, natomiast przestało działać w Android Studio 2.1. Pokombinowałem trochę, szukałem w internecie i niestety nie udało mi się rozwiązać tego problemu. W związku z tym chcąc, nie chcąc, muszę póki co został przy Android Studio w wersji 1.5.

Zapis danych na dysku

W dzisiejszym wpisie przedstawię w jaki sposób dokonać zapisu danych na pamięci wewnętrznej urządzenia.

Pierwszym krokiem jaki musimy zrobić to dodanie do pliku AndroidManifest.xml poniższego wpisu:

Jak można wywnioskować, jest to dodanie uprawnień do zapisu danych na pamięci zewnętrznej do naszej aplikacji.

Sam zapis pliku nie jest specjalnie skomplikowany. Stworzyłem prostą metodę, której zadaniem jest skopiowanie wskazane pliku do wskazanego miejsca.

Dlaczego kopiowanie? W swojej aplikacji zapisuje dwa rodzaje plików:

  • zrobione zdjęcia, które są zapisywane do pliku tymczasowego; właśnie ten plik kopiuje to folderu z dokumentami dla aplikacji
  • pliki wskazane bezpośrednio przez użytkownika; w tym przypadku wskazany plik jest kopiowany do folderu z plikami aplikacji