Materiały na egzamin PDF

Title Materiały na egzamin
Course Programowanie aplikacji mobilnych
Institution Politechnika Lubelska
Pages 36
File Size 656.1 KB
File Type PDF
Total Downloads 130
Total Views 169

Summary

Spis treści: Aktywność i cykl życia aktywności Intencje i przekazywanie wartości przez intencje Uruchamianie nowych aktywności i aplikacji programowo, filtry intencji Tworzenie GUI w Javie 5 Tworzenie GUI w XML Wagi i jednostki w graficznym interfejsie użytkownika Tworzenie okien dialogowych Tworzen...


Description

Spis treści: 1. Aktywność i cykl życia aktywności

2

2. Intencje i przekazywanie wartości przez intencje

3

3. Uruchamianie nowych aktywności i aplikacji programowo, filtry intencji

5

4. Tworzenie GUI w Javie

7

5 Tworzenie GUI w XML

8

6. Wagi i jednostki w graficznym interfejsie użytkownika

10

7. Tworzenie okien dialogowych

12

8. Tworzenie i obsługa powiadomień

14

9. Zachowanie stanu aplikacji podczas zmian konfiguracji

16

10. Obsługa zdarzeń poprzez odbiorców zdarzeń

17

11. Obsługa gestów

18

12. Tworzenie dostawcy treści

20

13. Obsługa bazy danych SQLite

23

14. Uprawnienia aplikacji

24

15. Komunikacja sieciowa w Androidzie - HTTP

25

16. Wysyłanie SMS i MMS

26

17. Rysowanie na ekranie

27

18. Obsługa kamery - robienie zdjęć

28

19. Odtwarzanie i zapis dźwięku

30

20. Obsługa czujników ruchu

33

1. Aktywność i cykl życia aktywności Aktywność: Podstawowy składnik aplikacji dla systemu Android. Reprezentują czynność, którą może wykonać użytkownik. Wywoływane przez użytkownika (za pomocą tzw. launchera) lub przez inne aktywności (nawet w innych aplikacjach). Dziedziczą najczęściej po Activity bądź AppCompatActivity. Cykl życia aktywności: aktywna – aktywność na pierwszym planie, użytkownik może jej używać wstrzymana – aktywność jest częściowo przesłonięta przez inny element (nie otrzymuje informacji o zdarzeniach). Powinna: - zatrzymać animacje i inne działania obciążające CPU - zachować niezapisane zmiany (tylko gdy użytkownik oczekuje, że zostaną zapisane na stałe) - zwolnić zasoby takie jak odbiorcy komunikatów, sensory (np. GPS, aparat) itp. zatrzymana – całkowicie niewidoczna (w tle). - powinna zwolnić wszystkie zasoby, które nie są potrzebne - może zostać zniszczona przez system gdy potrzebuje system pamięci

2. Intencje i przekazywanie wartości przez intencje Intencje obok Aktywności są jednym z podstawowych komponentów z których zbudowane są androidowe aplikacje. Mechanizm ten odpowiedzialny jest przede wszystkim za obsługę rozkazów wydawanych przez użytkownika. Za pomocą intencji możemy wprowadzić komunikację pomiędzy aplikacjami (lub mniejszymi komponentami, jak Usługi, Aktywności itp.). Jednak najważniejszym zadaniem tego komponentu jest uruchamianie odpowiednich aplikacji/Aktywności. Intencje uruchamiające podzielone zostały na dwa główne typy: Jawne (explicit) – czyli takie, w których jasno precyzujemy obiekt, który chcemy stworzyć. W tym wypadku jednym z argumentów konstruktora Intencji jest obiekt typu Class (np. MainActivity.class) wskazujący na klasę, której obiekt chcemy stworzyć. Najprostszy przykład to: Intent intent = new Intent(context, MainActivity.class); Intencja tak, jak łatwo się domyślić, uruchomi aktywność MainActivity.

Niejawne (implicit) – są to intencje, w których zawieramy informacje o tym co chcemy zrobić, bez podawania konkretnych klas, które mają to zrealizować. Najczęściej opisujemy to dwoma informacjami – co chcemy zrobić i na jakich danych chcemy tą czynność wykonać. W takim wypadku to system (za pomocą Filtrów Intencji) decyduje jaka Aktywność ma być uruchomiona. Przykład: Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.google.com")); W tym wypadku informujemy nasz system o tym, że chcemy zobaczyć dane (Intent.ACTION_VIEW) zapisane pod adresem URI (w tym wypadku adres URL strony) Przesyłanie danych

Oprócz uruchamiania komponentów Intencje pozwalają na dołączanie informacji, które mogą być przesłane do uruchamianego obiektu. Służy do tego zestaw metod putExtra(…), które pozwalają na dołączanie danych w postaci typów prostych (lub paczek Bundle). Przykładem takiej operacji niech będzie: intent.putExtra("UserID", 123); Aby pobrać powyższe dane w nowo uruchomionej Aktywności należy wykonać komplet poniższych operacji: Intent intent = getIntent();

int userId = intent.getIntExtra("UserID", 0); Pierwsza linijka pobiera Intencję, która uruchomiła Aktywność (należy pamiętać o sprawdzeniu czy przypadkiem zwracana wartość nie jest nullem). Druga linijka to pobranie wartości za pomocą jednej z metod get…Extra(…). Pierwszym argumentem tych metod jest nazwa pod którą dana wartość została zapisana. Drugim natomiast – wartość domyślna, na wypadek gdyby Intencja nie zawierała żadnych danych zapisanych pod podanym ciągiem znaków.

3. Uruchamianie nowych aktywności i aplikacji programowo, filtry intencji Aktywność może uruchomić inną aktywność i przekazać do niej dane. Może otrzymać wyniki. Uruchamiane aktywności układane są na stosie (tzw. back stack). Do poprzedniej aktywności można wrócić za pomocą przycisku wstecz. Wszystkie aktywności muszą być zadeklarowane w manifeście Przykład uruchomienia aktywności: Intent zamiar=new Intent(this, Druga.class); startActivity(zamiar); pierwszy parametr przy tworzeniu nowej intencji to kontekst a drugi to nazwa klasy aktywności którą chcemy wywołać. Przykład uruchomienia przeglądarki w celu wyświetlenia strony (niejawnie) private void openUrlAddress() { Uri url = Uri.parse("http://www.google.com"); Intent intent = new Intent(Intent.ACTION_VIEW, url); startActivity(intent); }

Filtry Intencji w Androidzie są bardzo ważnym elementem, który pozwala decydować systemowi jaki komponent (Aktywność, Usługa, Odbiorca treści) ma zostać wywołany dla Intencji posiadającej konkretną akcję lub dane. Aby zarejestrować nasz komponent do obsługi konkretnej intencji w pliku AndroidManifest.xml, wewnątrz elementu (lub service, receiver) musimy dodać element . Oto przykładowy szkielet takiego kodu:





Element posiada jeden atrybut – android:name, w którym podajemy unikalny ciąg znaków identyfikujący akcję. również posiada tylko jeden atrybut: android:name. Ciąg znaków, który podajemy tutaj możemy pobrać z android.intent.category.*

jest elementem, która wskazuje jaki typ danych ma obsługiwać nasz komponent. W przeciwieństwie do powyższych elementów posiada kilka atrybutów pozwalających dokładnie określić typ danych

4. Tworzenie GUI w Javie Polega na stworzeniu kodu, który tworzy obiekty klas pochodnych View i budowaniu hierarchii komponentów w kodzie Java. Klasy pochodne View są to komponenty, które rysują po ekranie i z którymi użytkownik może wchodzić w interakcje. Przykład: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Button myButton = new Button(this); myButton.setText("Press me"); myButton.setBackgroundColor(Color.YELLOW); RelativeLayout myLayout = new RelativeLayout(this); myLayout.setBackgroundColor(Color.BLUE); RelativeLayout.LayoutParams buttonParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); buttonParams.addRule(RelativeLayout.CENTER_HORIZONTAL); buttonParams.addRule(RelativeLayout.CENTER_VERTICAL); myLayout.addView(myButton, buttonParams); setContentView(myLayout); }

5 Tworzenie GUI w XML Tworzenie plików XML opisujących układ elementów. Obiekty zostaną stworzone na podstawie XML w momencie wywołania metody setContentView(id) w aktywności. Nazwy elementów w XML odpowiadają nazwom klas np. ↔ TextView, ↔ LinearLayout Elementy posiadają atrybuty. Najbardziej typowe to: android:id="@+id/unikalnyIdentyfikator" definiuje unikalny identyfikator elementu android:text="@string/unikalnyIdentyfikator" określa tekst etykiety lub początkową wartość pola tekstowego (zalecane odwołanie do zasobów) android:orientation="vertical" lub "horizontal" pozwala (m.in.) na określenie sposobu rozmieszczenia elementów przez liniowego zarządcę układu android:layout_width="match_parent" lub "wrap_content" i android:layout_height="match_parent" lub "wrap_content" pozwalają na ustalenie szerokości oraz wysokości zarządcy/komponentu. Wartość: - match_parent - zarządca/komponent wypełni cały obszar zajmowany przez swojego rodzica - wrap_content - rozmiar komponentu zostanie dopasowany do zawartości android:paddingBottom = "@dimen/activity_vertical_margin", android:paddingLeft = "@dimen/activity_horizontal_margin", android:paddingRight = "@dimen/activity_horizontal_margin", android:paddingTop = "@dimen/activity_vertical_margin" określają odpowiednio dolny, lewy, prawy i górny margines wewnętrzny. Są podobne do atrybutu margin, który określa margines zewnętrzny. Najważniejsze typy układów to: Układ liniowy - Układ względny Układ tabelaryczny

Przykład układu w XML:





6. Wagi i jednostki w graficznym interfejsie użytkownika Atrybut komponentu android:layout_weight="1" - określa, w jakim stopniu komponenty są rozciągane przez liniowego zarządcę układu (LinearLayout) ● 0 - komponent nie jest rozciągany. ● w innym wypadku piksele dostępne w układzie będą rozdysponowane proporcjonalnie do wartości atrybutu (np. gdy layout_weight jest równe 2 i 3, to pierwszy otrzyma 2/5 a drugi 3/5 wolnej przestrzeni. Przykład: mamy 3 elementy w layoucie o układzie poziomym. Pierwszy element ma wagę 5, drugi 3,a trzeci 2. Musimy zsumować te wagi, wychodzi nam 10. Pierwszy element zajmuje połowę całego layoutu (bo ma wagę 5, a suma wag wynosi 10: 5/10=0,5), drugi element zajmuje 3/10 całego layoutu, a trzeci 2/10.



Jednostki: Zalecane jest stosowanie układów elementów, które się skalują (duża różnorodność urządzeń). Czasami trzeba podać konkretne wymiary. Można stosować następujące jednostki: ● dp (=dip) – density-independent pixels (na ekranie 160dpi 1dp ≈ 1px) ● sp – jak dp dla rozmiarów czcionek (uwzględniają ustawienia rozmiaru czcionki) ● pt – punkt 1/72 cala na ekranie ● px – piksel ● mm – milimetr na ekranie ● in – cale na ekranie

Przykład zastosowania :

7. Tworzenie okien dialogowych Zgodnie z zalecanym sposobem tworzenia okien dialogowych, należy utworzyć klasę pochodną DialogFragment. Fragment wymaga układu w pliku XML. Klasa definiuje standardowe elementy – interfejs, onAttach(), onDetach(), onCreateDialog(). Okna są odporne na obracanie urządzenia. {Okno dialogowe reprezentowane jest poprzez klasę Dialog. Jest elementem interfejsu, który może w znaczący sposób rozszerzyć interakcję z użytkownikiem. Daje nam ono możliwość wyświetlania krótkich komunikatów, pytań, próśb o podjęcie decyzji. Dialog wyświetla statyczne informacje, które do zniknięcia z ekranu potrzebują reakcji użytkownika.} Przykład: public class DialogWartoscFragment extends DialogFragment { private WartoscWDialogu mListener; public interface WartoscWDialogu { // wysyłanie wprowadzonej wartości do aktywności public void wartoscWprowadzonaWDialogu(int wartosc); } public DialogWartoscFragment() { } // podłączenie do aktywności @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (WartoscWDialogu) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " aktywność musi implementować WartoscWDialogu"); } } // odłączenie od aktywności @Override public void onDetach() { super.onDetach(); mListener = null; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder budowniczy = new AlertDialog.Builder(getActivity()); LayoutInflater pompka = getActivity().getLayoutInflater(); budowniczy // utworzenie układu dialogu .setView(pompka.inflate(R.layout.dialog_wartosc, null)) .setTitle("Wprowadź wartość") // obsługa przycisku zatwierdzającego .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { // konwersja wartości z pola do int i wysłanie do

// aktywności warto zwrócić uwagę na getDialog() // przed findViewById() TextView dialogWartoscEdycja = (TextView) (getDialog() .findViewById(R.id.dialog_wartosc_edycja)); String wartoscStr = dialogWartoscEdycja.getText().toString(); mListener.wartoscWprowadzonaWDialogu(Integer. parseInt(wartoscStr)); } }) // obsługa przycisku anulującego .setNegativeButton("Anuluj", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // anulowanie dialogu DialogWartoscFragment.this.getDialog().cancel(); } }); // utworzenie układu dialogu return budowniczy.create(); } }

8. Tworzenie i obsługa powiadomień Powiadomienia wyświetlane są na belce powiadomień systemu Android. Wyświetlane są niezależnie od tego, czy aktywność aplikacji jest widoczna. Przez kliknięcie powiadomienia można wrócić do aktywności. Najprostszym sposobem tworzenia powiadomień jest wykorzystanie klasy Notification.Builder. Rodzaje powiadomień: diody, wibracje, dźwięki, pasek stanu telefonu. Powiadomienia muszą posiadać: ikonę, tytuł i treść Aby utworzyć powiadomienie należy: • Pobrać usługę NotificationManager: mManager = (NorificationManager) getSystemService( NOTIFICATION_SERVICE); • Utworzyć budowniczego powiadomień: • •

mBudowniczyPowiadomien = new Notification.Builder( this ); Wywołać szereg metod ustawiających zawartość powiadomienia Zbudować (metoda build() ) I wyświetlić powiadomienie: mManager.notify( mIdPowiadomienia , mBudowniczyPowiadomien .build());

9. Zachowanie stanu aplikacji podczas zmian konfiguracji Aktywność może zostać zniszczona i utworzona na nowo z powodu zmian w systemie (np. zmiana rozdzielczości). Domyślnie przechowywane są dane z obiektów View (tych, które mają id). Dane są zapisywane w obiekcie typu Bundle. Jeżeli dojdzie do zniszczenia i odtworzenia instancji aktywności, system przywróci ostatni stan układu aplikacji bez korzystania z dodatkowego kodu. Do zapisu stanu aplikacji służy metoda onSaveInstanceState(), natomiast do jego odtworzenia onRestoreInstanceState(). Kiedy następuje zatrzymanie aktywności, po wywołaniu onSaveInstanceState(), system zapisuje dane dotyczące stanu aktywności w zestawie par klucz - wartość.

Przykład: public static final String NAPIS="napis_na_etykiecie"; @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); TextView tv=(TextView) findViewById(R.id. text_view); tv.setText(savedInstanceState.getString(NAPIS)); } @Override protected void onSaveInstanceState(Bundle outState) { TextView tv=(TextView) findViewById(R.id. text_view); //getText() zwraca CharSequence a nie String outState.putString(NAPIS,tv.getText().toString()); super.onSaveInstanceState(outState); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState!=null) { TextView tv=(TextView) findViewById(R.id. text_view); tv.setText(savedInstanceState.getString(NAPIS)); } }

10. Obsługa zdarzeń poprzez odbiorców zdarzeń W Javie do obsługi zdarzeń wykorzystuje się obiekty słuchaczy (listener), które implementują odpowiedni interfejs. Dodawane są metodami setCostamListener() lub addCostamListener(). Interfejsy często zdefiniowane są wewnątrz innych klas, np. View.onClickListener. Sposoby obsługi zdarzeń: - klasa anonimowa z obsługą zdarzenia - klasa anonimowa wywołująca metodę pomocniczą - XML + metoda (tylko onClick) – metoda musi być wtedy publiczna i mieć parametr klasy View. Inne rodzaje zdarzeń to np. TextWatcher, View.OnFocusChangeListener, OnCheckedListener.

11. Obsługa gestów Gest występuje, gdy użytkownik umieszcza jeden lub więcej palców na ekranie dotykowym, a aplikacja interpretuje ten gest według odpowiedniego wzoru. Istnieją dwa etapy wykrywania gestów: ● zbieranie danych na temat Touch Events ● interpretacja danych w celu sprawdzenia czy odpowiadają jakiemuś gestowi który jest wspierany przez aplikacje. Do zbierania informacji o zdarzeniu dotyku służy metoda onTouchEvent() którą należy nadpisać w aktywności.

public class MainActivity extends Activity { … @Override public boolean onTouchEvent(MotionEvent event){ } } Wewnątrz nadpisanej metody należy zaimplementować rozpoznawanie wykonywanego gestu na podstawie zdarzenia MotionEvent. Można tego dokonać wykorzystując metodę getActionMasked(event) klasy MotionEventCompat w celu określenia gestu.

int action = MotionEventCompat.getActionMasked(event); switch(action) { case (MotionEvent.ACTION_DOWN) : Log.d(DEBUG_TAG,"Action was DOWN"); return true; case (MotionEvent.ACTION_MOVE) : Log.d(DEBUG_TAG,"Action was MOVE"); return true; default : return super.onTouchEvent(event);

Alternatywnie zamiast metody onTouchEvent możemy zdefiniować słuchacza pojedynczego elementu widoku: View myView = findViewById(R.id.my_view); myView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // ... Respond to touch events return true; } }); Do wykrywania gestów można również zaimplementować interfejs GestureDetector wraz z metodami obsługującymi poszczególne gesty.

Gesty podstawowe Czynność

Gest

Przechodzenie do następnego elementu na ekranie

Przesuń w prawo

Przechodzenie do poprzedniego elementu na ekranie

Przesuń w lewo

Przełączanie się między ustawieniami nawigacji

Przesuń palcem w górę lub w dół

Wybór aktywnego elementu

Kliknij dwukrotnie

12. Tworzenie dostawcy treści Dostawcy treści standaryzują dostęp do danych, udostępniają dane w sposób podobny do bazy SQLite i mogą udostępniać je innym aplikacjom. Dane identyfikowane są za pomocą URI. Dostawca treści posiada metody insert(), query(), update(), delete(), które zwracają kursor lub liczbę rekordów, których dotyczyła operacja. Klasa SQLiteOpenHelper ułatwia tworzenie bazy i zarządzanie nią. Należy stworzyć własną klasę potomną. Musi ona przeciążać metody onCreate oraz onUpdate. Aby korzystać z bazy danych musimy stworzyć obiekt klasy pomocniczej, a następnie wywołać na jego rzecz metodę getWriteableDatabase() - jeśli baza ma umożliwiać zapis i odczyt, lub getReadableDatabase() - jeśli baza ma być tylko do odczytu. Gdy baza danych nie jest już potrzebna, należy ją zamknąć za pomocą metody close(). Przykład: public class WartosciProvider extends ContentProvider { private PomocnikBD mPomocnikBD; //identyfikator (ang. authority) dostawcy private static final String IDENTYFIKATOR = "com.example.baza_danych.WartosciProvider"; //stała – aby nie trzeba było wpisywać tekstu samodzielnie public static final Uri URI_ZAWARTOSCI = Uri.parse("content://" + IDENTYFIKATOR + "/" + PomocnikBD.NAZWA_TABELI); //stałe pozwalające zidentyfikować rodzaj rozpoznanego URI private static final int CALA_TABELA = 1; private static final int WYBRANY_WIERSZ = 2; //UriMacher z pustym korzeniem drzewa URI (NO_MATCH) private static final UriMatcher sDopasowanieUri = new UriMatcher(UriMatcher.NO_MATCH); static { //dodanie rozpoznawanych URI sDopasowanieUri.addURI(IDENTYFIKATOR, PomocnikBD.NAZWA_TABELI, CALA_TABELA ); sDopasowanieUri.addURI(IDENTYFIKATOR, PomocnikBD.NAZWA_TABELI + "/#",WYBRANY_WIERSZ); } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { //czy wiersz czy cała tabela i otworzenie bazy int typUri = sDopasowanieUri.match(uri); SQLiteDatabase baza = mPomocnikBD.getWritableDatabase(); long idDodanego = 0; switch (typUri) { case CALA_TABELA: idDodanego = baza.insert(PomocnikBD.NAZWA_TABELI, //tablela null, //nullColumnHack values); //wartości

break; default: throw new IllegalArgumentException("Nieznane URI: " + uri); } //powiadomienie o zmianie danych (->np. odświeżenie listy) getContext().getContentResolver().notifyChange(uri, null); return Uri.parse(PomocnikBD.NAZWA_TABELI + "/" + idDodanego); } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { int typUri = sDopasowanieUri.match(uri); SQLiteDatabase baza = mPomocnikBD.getWritableDatabase(); Cursor kursorTel = null; switch (typUri) {...


Similar Free PDFs