Mobile App Development - Activities -
Inhalt Activity Lifecycle Erstellen Starten & Stoppen Spezielle Activities
Ac3vi3es
Ac3vi3es Definition Eine Aktivität repräsentiert eine Interaktion mit einem Benutzer (1)... is an application component that provides a screen with which users can interact... (III)
Ac3vi3es App enthält meist mehrere Activities, die untereinander aufgerufen werden können Beispiel E-Mail App 1 Activity mit Mail-List 1 Activity zur Mail-Anzeige 1 Activity zum Mail-Schreiben
Manifest- Eintrag Jede Activity muss im Android Manifest eingetragen werden Es wird u. a. festgelegt, wie die Activity gestartet werden kann ob sie von außen (für andere Apps) erreichbar ist...
Manifest- Eintrag <manifest xmlns:android="..." package="de.htwds.emrolab.mada.activities" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="8"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name=".mainactivity" android:label= "@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> </application> </manifest>
Ac3vi3es Activity erstellen neue Klasse unter src anlegen Klasse von Activity ableiten public class SettingsActivity extends Activity { @Override public void oncreate( Bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_settings);...
Manifest- Eintrag <manifest xmlns:android="..." package="de.htwds.emrolab.mada.activities"... >... <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name=".mainactivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name= "android.intent.action.main" /> <category android:name= "android.intent.category.launcher" /> </intent-filter> </activity> <activity android:name=".settingsactivity" android:label="@string/title_activity_settings" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.default" /> </intent-filter> </activity> </application> </manifest>
Ac3vi3es Activities über Wizard anlegen New => Other => Android => Android Activity gleicher Dialog, wie bei Projekterstellung Manifest-Eintrag wird automatisch erstellt
Ac3vity Lifecycle
Lifecycle Eine Activity hat einen definierte Lebenszyklus Unterscheidung von Zuständen Abfolge von Methodenaufrufen Interaktionsverhalten mit dem Benutzer
Lifecycle Android unterscheidet vier Zustände einer Activity Laufend (Running) Pausiert (Paused) Gestoppt (Stopped) Zerstört (Destroyed)
Lifecycle Zustand: Laufend (Running) Activity ist im Vordergrund Benutzer kann mit der Activity interagieren Activity reagiert auf Eingaben
Lifecycle Zustand: Pausiert (Paused) Activity ist nicht mehr im Vordergrund Sie hat den Fokus verloren Sie wird teilweise von einer anderen Activity oder einem Dialog verdeckt
Lifecycle Zustand: Gestoppt (Stopped) Activity ist nicht mehr sichtbar Sie wird durch eine andere Activity vollständig verdeckt bleibt im Speicher, kann aber gekillt werden
Lifecycle Zustand: Zerstört (Destroyed) Activity wurde aus dem Speicher entfernt und muss neu gestartet werden Gründe Benutzer beendet Activity Speicher-Mangel Konfigurationsänderungen
Lifecycle In einer Activity kann auf die verschiedenen Zustände reagiert werden durch sog. Lifecycle-Hooks
Ac3vity Lifecycle Activity launched Activity shutdown oncreate() ondestroy() onstart() onrestart() onstop() onresume() Activity running onpause() process killed
Ac3vity Lifecycle oncreate() wird u. a. aufgerufen, wenn die Activity das erste mal Activity launched oncreate() erstellt wird Initialisierung der Views Starten von Diensten
Ac3vity Lifecycle Activity launched onstart() wird aufgerufen, kurz bevor die Activity sichtbar wird oncreate() onstart()
Ac3vity Lifecycle onresume() wird aufgerufen, sobald der Benutzer mit der Activity interagieren kann Activity liegt ganz oben auf dem Activity Stack Activity launched oncreate() onstart() onresume() Activity running
Ac3vity Lifecycle Activity running onpause() wird aufgerufen, wenn die Activity in den Hintergrund onpause() verschoben wird letzter Callback, der mit Sicherheit aufgerufen wird
Ac3vity Lifecycle Activity running onstop() wird aufgerufen, wenn der sichtbare Teil der Aktivity onpause() onstop() endet Activity ist nun killable
Ac3vity Lifecycle Activity running ondestroy() wird aufgerufen, bevor die Activity Instanz zerstört wird onpause() onstop() ondestroy() Activity shutdown
Ac3vity Lifecycle Activity launched Activity shutdown oncreate() ondestroy() onstart() onrestart() onstop() onresume() Activity running onpause() process killed
Activity Lifecycle Bildquelle: http://developer.android.com/guide/components/activities.html#savingactivitystate
Ac3vity Life3me Unterscheidung von Lifetimes Entire Lifetime von oncreate() bis ondestroy() Visible Lifetime von onstart() bis onstop() Foreground Lifetime von onresume() bis onpause()
Lifecycle implemen3eren public class MainActivity extends Activity { @Override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // TODO Auto-generated method stub @Override protected void onstart() { super.onstart(); // TODO Auto-generated method stub @Override protected void onresume() { super.onresume(); // TODO Auto-generated method stub
Lifecycle implemen3eren public class MainActivity extends Activity { @Override protected void onpause() { // TODO Auto-generated method stub super.onpause(); @Override protected void onstop() { // TODO Auto-generated method stub super.onstop(); @Override protected void ondestroy() { // TODO Auto-generated method stub super.ondestroy();
Ac3vity Stop & Go
Ac3vi3es starten Activities werden über die Methode Context.startActivity(Intent) gestartet Der Intent kapselt den Klassennamen der zu startenden Activity Über den Intent können zusätzlich Informationen mitgegeben werden
Ac3vi3es starten Starten der SettingsActivity aus MainActivity heraus public class MainActivity extends Activity {... public void startsettingsactivity() { /* Erstellen eines Intents, der den Namen der Ziel Activity übergeben bekommt */ Intent intent = new Intent(this, SettingsActivity.class); /* Starten der Activity startactivity(intent);...
Ac3vi3es starten Zusatzinformationen werden über intent.putextra(key, value) Methoden mitgegeben public class MainActivity extends Activity { public static final String MY_KEY = "my.key"; public void startsettingsactivity() { /* Erstellen des Intents */ Intent intent = new Intent(this, SettingsActivity.class); /* Zusatzliche Informationen mitgeben */ intent.putextra(my_key, "my.value"); /* Starten der Activity startactivity(intent);...
Ac3vi3es starten In der Ziel Activity können die Zusatzinformationen über getintent() ausgelesen werden public class SettingsActivity extends Activity { @Override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); /* Liefert den Intent, mit dem die Activity gestartet wurde */ Intent intent = getintent(); /* Auslesen der Infos über entsprechenden Key*/ String myvalue = intent.getstringextra(mainactivity.my_key);
Ac3vi3es starten Oft ist es notwendig eine Activity zu starten und ein Ergebnis zurück zu bekommen start Activity get Result
Ac3vi3es starten Starten von Activities mit Rückgabewert public class MainActivity extends Activity {... public static final int MY_REQUEST_CODE = 1337; private void startsettingsactivity() { /* Intent für die zu startende Activity erstellen*/ Intent intent = new Intent(this, SettingsActivity.class); /* Activity starten */ startactivityforresult(intent, MY_REQUEST_CODE);
Ac3vi3es starten Rückgabewert & -daten setzen public class SettingsActivity extends Activity {... /* beliebiger Key für einen Rückgabewert */ public static final String RESULT_KEY = "my.result.key"; /* eigene Methode */ private void somethingchanged() { /* Intent für den Rückgabewert erzeugen */ Intent resultdata = new Intent(); resultdata.putextra(result_key, "my.value"); /* Rückgabewert und -daten setzen */ setresult(result_ok, resultdata);
Ac3vi3es starten Rückgabewert auswerten public class MainActivity extends Activity {... /* wird aufgerufen, wenn gestartete Activity zurück kommt */ @Override protected void onactivityresult( int requestcode, int resultcode, Intent data) { /* requestcode entspricht dem Code, mit dem gestartet wurde */ if (requestcode == MY_REQUEST_CODE) { /* Ergebnis auswerten */ String resultdata = data.getstringextra(settingsactivity.result_key);
Ac3vi3es stoppen Activities können explizit gestoppt werden Dies sollte nur in Ausnahmefällen und gut begründet gemacht werden z.b. bei startactivityforresult(...) public class MainActivity extends Activity { /* eigene Methode */ private void somethinghappend() { /* Stoppen der aktuellen Activity */ finish();
Spezielle Ac3vi3es
Spezielle Ac3vi3es Android bietet verschiedene spezialisierte Activities, die häufig benutzt werden ListActivity PreferenceActivity
ListAc3vity Eine ListActivity ist eine vorgefertigte Activity, die eine Liste von Elementen darstellt ListActivity ist eine Activity, deren Layout eine ListView beinhaltet
ListAc3vity ListActivity implementieren public class MyListActivity extends ListActivity { private static final String[] BIG_BANG = new String[]{ "Leonard Hofstadter", "Sheldon Cooper", "Penny", "Howard Wolowitz", "Dr. Rajesh Koothrappali", "Bernadette Rostenkowski", "Amy Farrah Fowler" ; private ArrayAdapter<String> adapter; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); adapter = new ArrayAdapter<String>( // Initialisierung this, android.r.layout.simple_list_item_1); // des Adapters for (int i = 0; i < BIG_BANG.length; i++) { // Adapter mit adapter.add(big_bang[i]); // Werten befüllen setlistadapter(adapter); // Adapter und settitle(r.string.title_big_bang); // Titel setzen
ListAc3vity Auf Klicks reagieren public class MyListActivity extends ListActivity { private static final String[] BIG_BANG = new String[]{ "Leonard Hofstadter", "Sheldon Cooper", "Penny", "Howard Wolowitz", "Dr. Rajesh Koothrappali", "Bernadette Rostenkowski", "Amy Farrah Fowler" ; private ArrayAdapter<String> adapter; protected void oncreate(bundle savedinstancestate) {... /* wird aufgerufen, wenn ein Element aus der Liste ausgewählt wurde */ @Override protected void onlistitemclick( ListView listview, View view, int position, long id) { /* ausgewähltes Element behandeln */ Toast.makeText(this, listview.getitematposition(position).tostring(), Toast.LENGTH_SHORT).show();
PreferenceAc3vity Viele Apps enthalten eine Settings-Activity, um Einstellungen zu ändern Hierfür gibt es in Android vorgefertigte Preference- Views
PreferenceAc3vity Eine Preference bildet eine bestimmte Eigenschaft ab Alle Preferences werden automatisch gespeichert
PreferenceAc3vity Preferences werden in einer eigenen Datei definiert Im Ordner res/xml wird eine Datei xyz.xml angelegt, in der der PreferenceScreen angelegt wird
PreferenceAc3vity Preferences anlegen <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="..." > <EditTextPreference android:key="server" android:title="server" android:summary="the Server URL" android:defaultvalue= "http://emrolab.htw-saarland.de/ android" android:order="1"/> <CheckBoxPreference android:key="autosync" android:title="auto Sync" android:summary= "Synchronize automatically" android:defaultvalue="true" android:order="2"/> </PreferenceScreen>
PreferenceAc3vity Gemeinsame Eigenschaften key: ist der Schlüssel unter dem der Preference-Wert abgerufen werden kann title: ist der Titel der Preference summary: ist eine kurze Zusammenfassung der Preference order: gibt die Sortierreihenfolge an
PreferenceAc3vity EditTextPreference <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="..." > <EditTextPreference android:key="server" android:title="server" android:summary="the Server URL" android:defaultvalue= "http://emrolab.htw-saarland.de/android" android:order="1"/> </PreferenceScreen>
PreferenceAc3vity CheckBoxPreference <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="..." > <CheckBoxPreference android:key="autosync" android:title="auto Sync" android:summary= "Synchronize automatically" android:defaultvalue="true" android:order="2"/> </PreferenceScreen>
PreferenceAc3vity ListPreference <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="..." > <ListPreference android:entries="@array/list_values" android:entryvalues="@array/list_values" android:key="thesimpsons" android:summary="comic" android:title="the Simpsons" /> </PreferenceScreen>
PreferenceAc3vity MultiSelectListPreference (ab API 11) <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="..." > <MultiSelectListPreference android:key="multiselect" android:title="the Simpsons Multi Select" android:entries="@array/list_entries" android:entryvalues= "@array/list_entries" android:defaultvalue= "@array/empty_array"/> </PreferenceScreen>
PreferenceAc3vity SwitchPreference (ab API 14) <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="..." > <SwitchPreference android:key="myswitch" android:summaryoff="summary Off" android:summaryon="summary On" android:switchtextoff="off" android:switchtexton="on" android:title="switch" /> </PreferenceScreen>
PreferenceAc3vity Screens verschachteln <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="..." > <CheckBoxPreference android:defaultvalue="true" android:key="autosync" android:summary= "Synchronize automatically" android:title="auto Sync" /> <PreferenceScreen android:title="server Settings" android:key="serversettings"> <EditTextPreference android:key="serverurl" android:summary="the Server URL" android:title="url" /> <EditTextPreference android:key="serverport" android:summary="the Server Port" android:title="port"/> </PreferenceScreen> </PreferenceScreen>
PreferenceAc3vity PreferenceCategory <PreferenceScreen xmlns:android="..." > <PreferenceCategory android:title="connection"> <EditTextPreference android:key="serverurl" android:summary="the Server URL" android:title="url" /> <EditTextPreference android:inputtype="number" android:key="serverport" android:summary="the Server Port" android:title="port" /> </PreferenceCategory> <PreferenceCategory android:title="synchronization" > <CheckBoxPreference android:defaultvalue="true" android:key="autosync" android:summary="synchronize automatically" android:title="auto Sync" /> </PreferenceCategory> </PreferenceScreen>
PreferenceAc3vity Implementierung (deprecated, wird bei Fragmenten noch einmal behandelt) /* Die Activity wird nicht von Activity sondern von PreferenceActivity abgeleitet */ public class MyPreferenceActivity extends PreferenceActivity { @Override protected void oncreate(bundle instancestate) { super.oncreate(savedinstancestate); /* Die in XML definierten Preferences werden hier der Activity hinzugefügt */ addpreferencesfromresource(r.xml.preferences);
PreferenceAc3vity Preferences verwenden public class SomeActivity extends Activity { public static final String PREF_KEY = "my.pref.key"; private void usingpreferences() { /* Über den PreferenceManager können die SharedPreferences abgerufen werden */ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); /* Entsprechend der verschiedenen Preference Views gibt es Methoden zum Auslesen der gesetzten Werte */ prefs.getstring(pref_key, "default"); prefs.getboolean(pref_key, false); prefs.getint(pref_key, 0); prefs.getlong(pref_key, 0); prefs.getfloat(pref_key, 0);
PreferenceAc3vity Preferences editieren public class SomeActivity extends Activity { private void editingpreferences() { /* SharedPreferences über den PreferenceManager abrufen*/ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); /* Öffnen eines Editors für die SharedPreferences */ SharedPreferences.Editor editor = prefs.edit(); /* Werte in den SharedPreferences ändern */ editor.putstring(pref_key, "my.new.value"); editor.putboolean(pref_key, true); editor.putint(pref_key, 42); editor.putlong(pref_key, 73); editor.putfloat(pref_key, 1337); /* Änderungen schreiben */ boolean success = editor.commit(); if (! success) { /* Fehlerbehandlung */
Ac3vity Zustand
Ac3vity Zustand Wird eine Activity pausiert oder gestoppt, verbleiben ihre Variablen, Werte, usw. im Speicher D. h. Änderungen, die der Benutzer gemacht hat sind immer noch vorhanden
Ac3vity Zustand Wird eine Activity aus einem bestimmten Grund zerstört, gehen ihre Werte verloren D.h. alles, was ein Benutzer eingegeben hat (z. B. in EditText Felder) geht verloren Lösung: savedinstancestate
Ac3vity Zustand Über den savedinstancestate können Werte aus der Activity zwischen gespeichert werden Wird eine Activity zerstört, wird vorher die Methode onsaveinstancestate aufgerufen Wann werden Activities zerstört?
Ac3vity Zustand Bildquelle: http://developer.android.com/guide/components/activities.html#savingactivitystate
Ac3vity Zustand Implementierung public class MyActivity extends Activity {... /* Wird aufgerufen, bevor die Activity zerstört wird */ @Override protected void onsaveinstancestate(bundle outstate) { /* Speichern des Wertes von i unter MY_VALUE_KEY */ outstate.putint(my_value_key, i); super.onsaveinstancestate(outstate);...
Ac3vity Zustand outstate.putxxx(...) Es existieren put-methoden für viele Datentypen primitive Typen: int, long, double,... komplexe Typen: String, Serializable,... Arrays: intarray, stringarray,...
Ac3vity Zustand savedinstancestate auslesen public class MyActivity extends Activity { private static final String MY_VALUE_KEY = "my.value.key"; private int i; @Override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_settings); /* Wird aufgerufen, wenn die Activity wieder hergestellt wird */ @Override protected void onrestoreinstancestate(bundle savedinstancestate) { super.onrestoreinstancestate(savedinstancestate); /* gespeicherten Wert wieder auslesen */ this.i = savedinstancestate.getint(my_value_key);
Ac3vity Zustand getxxx-methoden analog zu den putxxx-methoden existieren entsprechende getxxx- Methoden default Werte den get-methoden können default- Werte mitgegeben werden, falls noch kein instancestateexistiert
Ac3vity Zustand Vorsicht!!! Der savedinstancestate ist nicht als richtige Persistenz-Schnittstelle gedacht onsaveinstancestate wird nicht garantiert aufgerufen, wenn die Activity gekillt wird onsaveinstancestate wird nicht aufgerufen, wenn die Activity bewusst vom Benutzer beendet wird
Übung
Übung - TODO Liste Es soll eine TODO-Listen App erstellt werden. Die App soll insgesamt aus drei Activities bestehen, einer Haupt-Activity, einer Detail-Activity und einer Settings-Activity. Die Haupt-Activity stellt in Listenform die Titel aller eingetragenen TODOs dar. Über einen Menü-Eintrag kann ein neues TODO erstellt werden. Es öffnet sich dann die Detail-Activity, in der der neue Eintrag bearbeitet werden kann. Außerdem öffnet sich die Detail-Activity, wenn ein Eintrag in der Liste der Haupt-Activity ausgewählt wird. In der Detail-Activity wird das TODO-Element mit Titel, Beschreibung und Priorität (hoch, mittel, niedrig) dargestellt und kann bearbeitet werden. Es existieren zwei Button zum Löschen und Speichern des TODO-Elements. Über einen Menü-Eintrag in der Haupt-Activity soll eine Settings-Activity geöffnet werden. Hier kann die Schriftgröße für die Einträge in der Haupt-Activity geändert werden. Für die Änderung der Schriftgröße wird ein angepasster ArrayAdapter in der ListView verwendet. Dieser wird als Klasse separat auf dem Android-Blog bereitgestellt und soll in der Übung verwendet werden. Hinweis: In der Vorlesung wurde bisher keine Persistenz (abgesehen von Shared Preferences) behandelt. Daher ist es in der Übung nicht notwendig, die TODO-Elemente über die Lebensdauer der App hinaus zu speichern. Die TODOs sollen lediglich zur Laufzeit der App im Speicher gehalten werden.
Übung - TODO Liste