Slide 1

Slide 1 text

Android School Warsztat 02 Adam Jodłowski

Slide 2

Slide 2 text

2 Odwoływanie się do zasobów ● zasoby umieszczone w odpowiednich podkatalogach lub definiowane w XML (/res/values) zarządzane przez plik R, mają nadane symboliczne identyfikatory tekstowe @id/moj_przycisk @string/komunikat_sukces @drawable/logo ● zasoby pobieramy programowo dzięki kontekstowi Drawable pic = getResources().getDrawable(R.drawable.pic); String hello = getResources().getString(R.string.hello); String[] arr = getResources().getStringArray(R.array.arr);

Slide 3

Slide 3 text

3 Formatowanie i stylizowanie łańcuchów znaków ● znaczniki formatujące tekst Hello %1$s! String formattedHello = String.format( getResources().getString(R.string.hello), "Android"); ● ostylowanie tekstu za pomocą znaczników HTML <font color=\"green\">Goodbye</font> <b> %1$s</b>! String formattedGoodbye = String.format(getResources().getString(R.string.goodbye ), "Android"); textView.setText(android.text.Html.fromHtml(formattedGo odbye));

Slide 4

Slide 4 text

4 Przejrzyj różne rodzaje zasobów istniejące w projekcie, pobierz je w kodzie, sformatuj i ostyluj treść TextView.

Slide 5

Slide 5 text

5 Menu opcji ● strukturę menu opcji definiujemy jako plik XML w katalogu /res/menu korzeń pliku, jest kontenerem dla menu grupuje elementy w jednej kategorii reprezentuje pojedyńczy element, może zawierać zagnieżdżony element tworząc podmenu

Slide 6

Slide 6 text

6 Podpinanie menu opcji do aktywności ● musimy przesłonić metodę zwrotną tworzenia menu i reakcji na wybór @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); return true; // wyswietl menu } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.informacje: pokazInformacje(); return true; case R.id.pomoc: pokazPomoc(); return true; default: return super.onOptionsItemSelected(item); } }

Slide 7

Slide 7 text

7 Toasty ● podstawowy mechanizm nieinwazyjnych powiadomień Toast toast = Toast.makeText(kontekst, wiadomosc, czas trwania); toast.show(); ● czas trwania to jedna z dwóch stałych Toast.LENGTH_SHORT i Toast.LENGTH_LONG ● możemy wypozycjonować toast na ekranie toast.setGravity(...); używając flag zdefiniowanych w android.view.Gravity.* i podając wielkości marginesów (w pikselach) ● możemy ustawić layout całego toastu na własny (uwaga na root!) LayoutInflater inflater = getLayoutInflater(); View layout = inflater.inflate(R.layout.toast_layout, (ViewGroup) findViewById(R.id.toast_layout_root)); toast.setView(layout);

Slide 8

Slide 8 text

8 Stwórz menu (opcjonalnie z zagnieżdżeniem) i podepnij je do aktywności. Wyświetl Toast na naciśnięcie przycisku menu, zmień jego domyślną pozycję, ustaw marginesy w jednostkach niezależnych od gęstości (dp) korzystając z programowego pobierania zasobów typu dimen.

Slide 9

Slide 9 text

9 Okna dialogowe ● są modalne, asynchroniczne i zarządzane ● najprostszym sposobem na utworzenie okna dialogowego jest skorzystanie z buildera klasy AlertDialog AlertDialog.Builder dialog = new AlertDialog.Builder(aktywnosc); dialog.setTitle("Potwierdzenie"); dialog.setMessage("Zapisac zmiany?"); dialog.setPositiveButton("Tak", listener); dialog.setNegativeButton("Nie", listener); dialog.setNeutralButton("Anuluj", listener); dialog.show(); ● Klasa listenerów to DialogInterface.OnClickListener()

Slide 10

Slide 10 text

10 Dialog z listą checkboksów ● przykład bardziej złożonego dialogu final String[] colors = new String[] {"niebieski", "biały", "czerwony"}; AlertDialog.Builder dialog = new AlertDialog.Builder(activity); dialog.setTitle("Wybierz kolory"); dialog.setMultiChoiceItems(colors, new boolean[] {false, true, false}, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { // reakcja na klikniecie checkboksa } }); dialog.setPositiveButton("Zatwierdz", listener); dialog.setNegativeButton("Anuluj", listener); dialog.show();

Slide 11

Slide 11 text

11 Utwórz i wyświetl okno dialogowe, zareaguj na decyzję użytkownika za pomocą listenerów.

Slide 12

Slide 12 text

12 Zezwolenia ● wiele czynności systemowych wymaga zezwoleń udzielonych przez użytkownika podczas instalacji aplikacji (wysyłanie SMS, odbieranie połączeń, łączenie z Internetem, itd.) ● dodajemy je w manifeście, zakładka Permissions > Add > Uses Permission ● CALL_PHONE, CAMERA, INTERNET, VIBRATE, ... ● próba wykonania czynności, na którą aplikacja nie otrzymała zezwolenia, zakończy się niepowodzeniem

Slide 13

Slide 13 text

13 Intencje niejawne ● poznaliśmy dotychczas intencje jawne (explicit), dzięki którym przechodziliśmy pomiędzy aktywnościami naszej własnej aplikacji ● w intencji niejawnej (implicit) nie specyfikujemy nazwy (klasy) komponentu docelowego ● podajemy nazwę akcji do wykonania i opcjonalnie dane (data) w postaci URI, ich typ MIME, kategorię intencji i wartości extras ● określamy jaką czynność chcemy wykonać, ale nie musimy znać komponentu, który to potrafi (nie mamy też gwarancji, że takowy istnieje w systemie)

Slide 14

Slide 14 text

14 Intencje niejawne ● aktywności odpalamy w sposób tradycyjny Intent intent = new Intent(akcja, [URI]); startActivity(intent); ● przykładowe parametry dla intencji systemowych Intent.ACTION_VIEW Uri.parse("http://www.android.com") Intent.ACTION_CALL Uri.parse("tel:(+48)111222333") Intent.ACTION_DIAL Uri.parse("tel:(+48)111222333") Intent.ACTION_VIEW Uri.parse("geo:52.408333,16.908333?z=18") Intent.ACTION_VIEW Uri.parse("http://maps.google.com/maps?saddr=" + s_lat + "," + s_lon + "&daddr=" + d_lat + "," + d_lon) Intent.ACTION_VIEW Uri.parse("market://details?id=com.rovio.angrybirds")

Slide 15

Slide 15 text

15 Przetestuj działanie niejawnych intencji systemowych, pamiętaj o zezwoleniach!

Slide 16

Slide 16 text

16 Jak to działa? ● aktywności, usługi (services) i odbiorcy komunikatów rozgłoszeniowych (broadcast receivers) mogą deklarować filtry intencji ● intencje niejawne przechodzą przez te filtry i trafiają do wszystkich pasujących do nich komponentów, deklarujących ich obsługę ● chęć odbioru intencji rejestrujemy w manifeście, w węźle danego komponentu – ustalamy nazwę akcji i jej schemat URI w postaci ● aby ograniczyć obsługiwane intencje do specyficznych przypadków, możemy dodać kolejne węzły filtrujące ● dokumentacja zawiera informacje o priorytetach składowych filtrów

Slide 17

Slide 17 text

17 Reakcja na intencję niejawną ● jeśli intencja pasuje do jednego z filtrów komponentu i ma on najwyższy priorytet albo zostanie ręcznie wybrany przez użytkownika – zostanie on uruchomiony przez system operacyjny ● przykładowa aktywność odbierająca intencję, może odczytać akcję, składowe URI i inne dane pomocnicze, aby sprawdzić, czy dane wejściowe są poprawne Intent intent = getIntent(); String action = intent.getAction(); String uriPath = intent.getDataString(); if (uruchomiono aktywnosc przez odpowiednia intencje) { // przetwarzamy dane... } ● w razie potrzeby, zamykamy aktywność odbiorczą i zwracamy rezultat

Slide 18

Slide 18 text

18 W pierwszej aplikacji zaimplementuj nową aktywność przyjmującą intencję swojego własnego typu, przetestuj jej działanie wywołując tę intencję niejawną z drugiej, osobnej aplikacji. Stwórz trzecią aplikację z aktywnością zdolną do przetworzenia tej samej intencji niejawnej co pierwsza aplikacja, odpal intencję niejawną w drugiej aplikacji i zaobserwuj co się stanie.

Slide 19

Slide 19 text

19 Zadanie domowe: Połącz wiedzę z dotychczasowych warsztatów i stwórz przykładową aplikację demonstrującą poznane techniki.