Laboratorium Systemów Mobilnych 2015-03-06 Wykład 2 (Aktywności proste zapamiętywanie danych) Wojciech Wawrzyniak
Przypomnienie (elementy aplikacji)
Składniki aplikacji Aktywności (Activity) Widoki (Views) Usługi (Services) Dostarczyciele zawartości (Content Providers) Intencje (Intents) Odbiorniki (Broadcast receivers)
Aktywności (Podstawowe informacje, zadania)
Co to są aktywności Aplikacja składa się z aktywności (osobne ekrany). Intencje reprezentują zdarzenia lub akcje.
Jak stworzyć nową aktywność? Kroki: Stworzyć własny layout (XML) Wyprowadzić klasę z klasy bazowej Activity Dodać ustawienia w pliku AndroidManifest.xml
Aktywność Layout <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/ res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/secondactivity" /> <Button android:id="@+id/button1" android:text="@string/thirdactivity" android:layout_width="match_parent" android:layout_height="wrap_content" android:onclick="onclick"></button> </LinearLayout>
Aktywność - Activity public class DrugaAktywnosc extends Activity { public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.second); } public void onclick(view view) { Intent intent = new Intent(this, TrzeciaAktywnosc.class); startactivity(intent); } }
ApplicationManifest.xml <activity android:cleartaskonlaunch="true" android:name="com.example.w02emailactivities.listactivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> <activity android:name="com.example.w02emailactivities.emailactivity" android:label="@string/app_name" > </activity> <activity android:name="com.example.w02emailactivities.responseactivity " android:label="@string/app_name" > </activity>
KilkaAktywnosci - przykład Przykład stworzenia kliku aktywności oraz obsługi przycisków za pomocą dwóch metod: setonclicklistener() public void onclick(view view) Co się stanie gdy zapomnimy o dodaniu definicji aktywności w pliku AndroidManifest.xml?
SetOnClickListener() button.setonclicklistener(new View.OnClickListener() { public void onclick(view v) { Intent i = new Intent(KAA.this, Aktywnosc2.class); startactivity(i); }}); //Layout.xml <Button android:text="button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
SetOnClickListener() button.setonclicklistener(new View.OnClickListener() { public void onclick(view v) { Intent i = new Intent(KAA.this, Aktywnosc2.class); startactivity(i); }}); //Layout.xml <Button android:text="button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
onclick() public void onclick(view s) { Intent i = new Intent(KAA.this, Aktywnosc2.class); startactivity(i); } //Layout.xml <Button android:text="button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onclick="onclick" />
Przepełnienie stosu W02KilkaAktywnosci public class DrugaAktywnosc extends Activity { private int values[]; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.second); values = new int[1000000]; } public void onclick(view view) { Intent intent = new Intent(this, TrzeciaAktywnosc.class); startactivity(intent); } }
Dlaczego nastąpiło przepełnienie? Wielokrotne uruchamianie nowej instancji aktywności: Procesy w Android posiadają bardzo ograniczony rozmiar stosu np. 16 MB lub np. 24, 32, 48, 64 MB zależne od telefonu
Task i BackTask - stosy
Program pocztowy przykład Aktywności: Okno lista wiadomości Okno tylko jedna wiadomość Okno odpisanie na email Jak powinna działać aplikacja po wyjściu przyciskiem home? I powrocie do aplikacji poprzez: listę ostatnio używanych aplikacji, ponowne uruchomienie aplikacji. W02EmailActivities
Zadanie (task): Zarządzanie Task-ami Wspólny zbiór aktywności, Jeden wspólny stos dla aktywności, Zadanie jest usuwane dopiero po zakończeniu działania wszystkich aktywności, Jedna aplikacja może posiadać wiele zadań, Mogą być zarządzane przez użytkownika
Zadania - zarządzanie
Aktywności: LaunchMode "standard (domyślny)" nowa instancja za każdym razem. "singletop" aktywność tworzona jeżeli nie znajduje się na górze stosu A-B-C-B-D (D). Wywołana zostanie metoda onnewintent(). "singletask" aktywność w nowym zadaniu. Jeżeli aktywność już istnieje to nie jest tworzona nowa "singleinstance" nie ma wielu instancji danej aktywności oraz w danym zadaniu nie zostanie dodana żadna inna aktywność
Modyfikacja naszego przykładu <activity android:label="@string/app_name" android:launchmode="singletop" android:name=".wykladexampleactivity" > <intent-filter> <action android:name = "android.intent.action.main" /> <category android:name = "android.intent.category.launcher" /> </intent-filter> </activity>
Flaga "SingleTop" If an instance of the activity already exists at the top of the target task, the system routes the intent to that instance t h r o u g h a c a l l t o i t s onnewintent() method, rather than creating a new instance of the activity.
Flagi przy uruchamianiu aktywności FLAG_ACTIVITY_NEW_TASK - identyczne działanie jak "singletask", FLAG_ACTIVITY_CLEAR_TOP jeżeli w danym zadaniu istnieje dana aktywność usuwane są wszystkie elementy z góry stosu aż do danej aktywności, Np. A-B-C-D-E (wywołamy B) to uzyskamy A-B. FLAG_ACTIVITY_SINGLE_TOP identyczne działanie jak "SingleTop
Przykład Przykład uruchomienia aktywności z ustawioną flagą: Intent i = new Intent(Akt1.this, Akt2.class); i.addflags(intent.flag_activity_new_task);
Przykład 1 - konfiguracja aktywności <activity android:name=".activity1" android:launchmode="singletask">... </activity> <activity android:name=".activity2">... </activity> <activity android:name=".activity3">... </activity> <activity android:name=".activity4">... </activity> 1 2 3 4 1 BACK Jaki będzie wynik?
Przykład 2 - konfiguracja aktywności <activity android:name=".activity1" </activity> <activity android:name=".activity2" android:launchmode="singleinstance"> </activity> <activity android:name=".activity3" </activity> <activity android:name=".activity4" </activity> 1 2 3 4 B B B B Jaki będzie wynik? A jaki po 1 2 3 B B B Jaki będzie wynik?
Aktywności ( Back vs up )
Nawigacja - rodzeństwo
Nawigacja elementy luźno powiązane
Nawigacja różne zadania (task)
Tworzenie przycisku up @Override protected void oncreate(bundle savedinstancestate) {... getactionbar().sethomebuttonenabled(true); ActionBar actionbar = getactionbar(); actionbar.setdisplayhomeasupenabled(true); } @Override public boolean onoptionsitemselected(menuitem item) { switch (item.getitemid()) { case android.r.id.home: // app icon in action bar clicked; go home Intent intenthome = new Intent(this, ListActivity.class); intenthome.addflags(intent.flag_activity_clear_top); startactivity(intenthome); return true; } } default: return super.onoptionsitemselected(item);
Aktywności (Przechowywanie danych)
Kiedy potrzebujemy przechowywać dane? Zmiana parametrów (np. poziom pion), Przechowywanie danych po zamknięciu aplikacji, Współdzielenie danych pomiędzy aplikacjami, Zawsze niedeterministyczne zachowanie wstrzymanych aktywności w systemie Android (możliwość zabicia).
Stany aktywności
oncreate() Called when the activity is first created. This is where you should do all of your normal static set up: create views, bind data to lists, etc. This method also provides you with a Bundle containing the activity's previously frozen state, if there was one.
onrestart() Called after your activity has been stopped, prior to it being started again.
onstart() Called when the activity is becoming visible to the user.
onresume() Called when the activity will start interacting with the user. At this point your activity is at the top of the activity stack, with user input going to it.
onpause() Called when the system is about to start resuming a previous activity. This is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, etc. Implementations of this method must be very quick because the next activity will not be resumed until this method returns.
onstop() Called when the activity is no longer visible to the user, because another activity has been resumed and is covering this one. This may happen either because a new activity is being started, an existing one is being brought in front of this one, or this one is being destroyed.
StanyAktywności przykład własny Przykład z wszystkimi metodami onxxx() oraz debug aplikacji.
Możliwości przechowywania stanów Preferencje lub onsaveinstancestate() (klucz, wartość) Pliki (lokalnie oraz na karcie) Baza danych SQLite Dostawca treści (np. kontakty)
on...instancestate() - kod @Override protected void onsaveinstancestate(bundle outstate) { super.onsaveinstancestate(outstate); outstate.putint(bundle_random_number, randomvalue); } @Override protected void onrestoreinstancestate(bundle savedis) { super.onrestoreinstancestate(savedis); randomvalue = savedis.getint(bundle_random_number); }
Lekki mechanizm Preferencje Zapisywanie w postaci klucz wartość Mogą być widoczne dla wszystkich aktywności w aplikacji lub tylko dla danej aktywności getpreferences(mode) getsharedpreferences(name, mode)
SharedPreferences() - przykład SharedPreferences sp = getpreferences( Activity.MODE_PRIVATE); Editor editor = sp.edit(); String onestring = null; //... (onestring =?) editor.putstring( SHARED_PREFERENCE_SHORT_NOTES,oneString); editor.commit();
Kiedy i gdzie zapisywać preferencje? Zapisywanie: onpause() Wczytywanie oncreate()
Przykład lista zakupów Prosty projekt umożliwiający dodawanie elementów do listy zakupów itp.
Lista zakupów cz.1 (Zarządzanie Notatkami) public class ShoppingList { private final String SHOPPING_LIST_SHARED_PREFERENCE_ NAME = "ShoppingList"; private final String SHOPPING_LIST_KEY = "notes"; private List<String> shoppinglist; private Context context; public ShoppingList(Context context) { shoppinglist = new ArrayList<String>(); this.context = context; loadnotes(); }
Lista zakupów cz.2 (Zarządzanie Notatkami - zapis) public void savenotes() { // utworzenie napisu String notes = Połączony tekst ; // zapisanie danej SharedPreferences sp = context.getsharedpreferences( SHOPPING_LIST_SHARED_PREFERENCE_NAME, Activity.MODE_PRIVATE); Editor ed = sp.edit(); ed.putstring(shopping_list_key, notes); ed.commit(); }
Lista zakupów cz.3 (Zarządzanie Notatkami - odczyt) public void loadnotes() { SharedPreferences sp = context.getsharedpreferences( SHOPPING_LIST_SHARED _PREFERENCE_NAME, Activity.MODE_PRIVATE); String notes = sp.getstring(shopping_list_key,null); } if (notes!= null) { shoppinglist = new ArrayList<String>(Arrays. aslist(notes.split( NOTES_SEPARATOR ))); }
Lista zakupów cz.4 projekt GUI
Lista zakupów cz.5 (Aktywność - layout) <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TableLayout android:layout_width="match_parent" android:layout_height ="match_parent" android:stretchcolumns="1" > <TableRow > <EditText android:id="@+id/edittextnote" android:layout_width="0dip" android:layout_weight="1" > </EditText> </TableRow> <TableRow > <Button android:id="@+id/buttonadd" android:layout_width="0dip" android:layout_weight="1" android:onclick="onclick" android:text="dodaj" /> <Button android:id="@+id/buttonremove" android:layout_width="0dip" android:layout_weight="1" android:onclick="onclick" android:text="usuń" /> </TableRow> <ListView android:id="@+id/todolist" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:clickable="false" android:drawselectorontop="true" android:focusable="false" android:focusableintouchmode="false" > </ListView> </TableLayout> </LinearLayout>
Lista zakupów cz.6 (Aktywność) public void oncreate(bundle savedinstancestate) { //... - inicjalizacja aktywności shoppinglist=new ShoppingList(getApplicationContext()); shoppinglistview.setonitemclicklistener(new OnItemClickListener() { public void onitemclick(adapterview<?> arg0, View arg1, int pos, long arg3) { lastitemselected = pos; } }); } refreshshoppinglistview();
Lista zakupów cz.7 (Aktywność) public void refreshshoppinglistview() { ArrayAdapter<String> adapter = new ArrayAdapter<String>( this, android.r.layout.simple_list_item_single_choice, (String[]) shoppinglist.getnotes().toarray( new String[0])); shoppinglistview.setadapter(adapter); shoppinglistview.setchoicemode( ListView.CHOICE_MODE_SINGLE); } public void removenote() { int pos_to_remove = shoppinglistview.getcheckeditem Position(); if (pos_to_remove!= ListView.INVALID_POSITION) { shoppinglist.removenote(pos_to_remove); refreshshoppinglistview(); }
Zasoby
Rodzaje zasobów Obrazy drawable:.png,.9.png,.jpg,.gif Układy layouts: np. main.xml Napisy values: np. strings.xml Wiele wiele innych Animator, anim, color, menu, raw, xml
Zasoby przypisane do urządzenia
en, pl, fr, en-rus sw<n>dp Grupowanie zasobów - wersje językowe - smallestwidth (nie zależna od orientacji notouch, stylus, finger - czy jest touchpad Itp... Złe: drawable-hdpi-port/ Dobre: drawable-port-hdpi/
Wielokrotne użycie zasobów: XML Gdy nie chcemy wrzucać elementu jako zasób domyślny w katalogu: drawable Zawsze powinien istnieć katalog domyślny!
KONIEC