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);
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
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); } }
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);
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.
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()
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
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)
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 android:port="80" android:path="/search" />
● dokumentacja zawiera informacje o priorytetach składowych filtrów
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
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.