FSIV10 THORSTEN WEISKOPF 
APPLIKATIONSENTWICKLUNG FÜR ANDROID
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
2 
1 Einführung ......................................................
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
3 
1 Einführung 
Dieses Dokument entstand im Rahmen einer abschließ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
4 
2 Kapitel 1 – Android Grundlagen 
2.1 Was ist Android? 
Android ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
5 
Development Enviroment) gerade in der Java Entwicklung. Eclipse ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
6 
Android API und Besonderheiten 
Die Google API (Application Prog...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
7 
Abbildung 1- Eclipse New Android Application
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
8 
2.4 Grober Aufbau einer Android App 
Grundsätzlich ist es jedem ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
9 
Vereinfachte Schematische Darstellung: 
Activity.XML - VIEW 
Act...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
10 
2.5 Grundlagen der Android Entwicklung 
2.5.1 View-Activity-Eve...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
11 
Abbildung 3- Zusammenarbeit Activity und View (Quelle http://ww...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
12 
2.5.2 Activity Lebenszyklus 
Da auf dem Handy die Ressourcen li...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
13 
Abbildung 4 - Activity Lebenszyklus (Quelle http://www.androidp...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
14 
2.5.3 Die wichtigsten XML Dateien ausserhalb der Layouts 
Strin...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
15 
2.5.4 Persistenz und Datenspeicherung in Adnroid 
Zur persisten...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
16 
3 Kapitel 2 - App Dokumentation LittleProjectManager 
3.1 Besch...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
17 
• Optimiert für die Benutzung mit Smartphone, sollte aber auch ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
18 
3.2 Architektur und Funktionsweise der Applikation 
Hierzu empf...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
19 
<Button 
android:id="@+id/button1" 
android:layout_width="wrap_...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
20 
werden. 
3.2.2 Activitys (Controller) 
Jede Activity-View hat a...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
21 
Aktiviert OnClickListner welcher das markierte Objekt der Liste...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
22 
Die ganze Berechnung der Zeit erfolgt über ein java.util.Calend...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
23 
Ein- wie Ausbuchungen vorhanden sind, errechnet dann die neue A...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
24 
3.2.4 Plain-Old-Java-Objects (Model) 
Hier finden sich klassisc...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
25 
der Klasse als privat gekennzeichnete Hilfsmethoden geschrieben...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
26 
* Tabelle erstellen 
*/ 
public static void onCreate(SQLiteData...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
27 
SQLite Datentyp Equivalent in JAVA 
INTEGER 
Long 
TEXT 
String...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
28 
Ist eine unabhängige Tabelle mit eigener _id als Primärschlüsse...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
29 
3.4 Projekt und Paketstruktur 
3.4.1 Pakete und Klassen 
Da der...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
30 
src: Hier liegen die eigenen Klassen. 
Unter dem Hauptpaket bef...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
31 
3.4.2 Projektdateien und Ressourcen 
Das Android Projekt besteh...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
32 
/res:Ordner für Resource-Dateien 
/res/drawable-hdpi: Logos in ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
33 
4 Ausblick und Fazit 
Die Applikation „LittleProjektMananer“ ha...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
34 
5 Abbildungsverzeichnis 
Abbildung 1 - Eclipse New Android Appl...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
35 
6 Abkürzungsverzeichnis 
App 
Application (Anwendung) 
IDE 
Int...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
36 
7 Anlagen
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
37 
7.1 Eclipse Workbench 
(QUELLE: http://www.admin-wissen.de/tuto...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
38 
7.2 Screenshots LittleProjectManager 
Projektübersicht 
Projekt...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
39 
Arbeitszeitverwaltung zum Buchen und Anzeigen von Zeiten 
Dialo...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
40 
7.3 Architekturschaubild
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
41 
7.4 Quellcode der Applikation 
AndroidManifest.xml 
<manifest x...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
42 
stringx.xml 
<resources> 
<string name="app_name">LittleProject...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
43 
ACTIVITY-VIEWS 
activity_project_view.xml 
<RelativeLayout xmln...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
44 
additem.xml 
<?xml version="1.0" encoding="utf-8"?> 
<LinearLay...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
45 
activity_time_manager_view.xml 
<LinearLayout xmlns:android="ht...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
46 
<Button 
android:id="@+id/button_checkout" 
android:layout_widt...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
47 
MENUS 
acitivity_project_view 
<menu xmlns:android="http://sche...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
48 
JAVA KLASSEN 
MyTodosOverview.java 
package de.thorstenweiskopf...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
49 
TextView lable = (TextView) findViewById(R.id.todo_lable); 
lab...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
50 
listView.setAdapter(adapter); 
//Set a OnClickListner to the Li...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
51 
return super.onOptionsItemSelected(item); 
} 
/* 
* Method of t...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
52 
ProjectView.java 
package de.thorstenweiskopf.lpm; 
import java...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
53 
} catch (Exception ex) { 
Toast.makeText(this, ex.toString(), T...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
54 
// show the main view 
setContentView(R.layout.activity_project...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
55 
TimeManager.java 
package de.thorstenweiskopf.lpm; 
import java...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
56 
//get the datasourceobject needed 
datasource = new TimeTableDa...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
57 
long checkout = out_entrys.get(i).getDatetime() ; 
long checkin...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
58 
/* 
* Hilfsmethode: Setzt die Listner auf alle Buttons 
* und f...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
59 
datasource.open(); 
datasource.creatTimeEntry(time, Long.toStri...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
60 
* setze Neue Daten im Calender und Zeige es an 
*/ 
public OnDa...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
61 
if (extras == null) { 
return; 
} 
// Get data via the key 
pro...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
62 
MySQLiteHelper.java 
package de.thorstenweiskopf.lpm.database; ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
63 
ProjectDatasource.java 
/* 
* Klasse ist das DAO (Database Acce...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
64 
values.put(ProjectTable.COLUM_NAME, name); 
values.put(ProjectT...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
65 
pj.setName(cursor.getString(1)); 
pj.setTime(cursor.getLong(2))...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
66 
TimeTableDatasource.java 
/* 
* Klasse ist das DAO (Database Ac...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
67 
values.put(TimeTable.COLUM_PJ_ID, pjid); 
values.put(TimeTable....
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
68 
timeentry.setPj_id(cursor.getLong(2)); 
timeentry.setEntrytype(...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
69 
TodosDatasource.java 
package de.thorstenweiskopf.lpm.database;...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
70 
return makeTodoFromCursor(cursor); 
} 
/* 
* Entfernt ToDo aus ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
71 
* @param projectid 
* @return ArrayList<ToDo> 
*/ 
public List<...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
72 
ProjectTable.java 
/* 
* Klasse stellt die Tabelle myprojects d...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
73 
TimeTable.java 
/* 
* Klasse stellt die Tabelle timetable dar 
...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
74 
TodoTable.java 
/* 
* Klasse stellt die Tabelle mytodos dar 
* ...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
75 
DatePickerFragment.java 
/* 
* Klasse muss als sogenantes DateP...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
76 
TimePickerFragment.java 
/* 
* Klasse muss als sogenantes TimeP...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
77 
TimeEntry.java 
/* 
* Klasse stellt ein TimeEntry dar wie es 
*...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
78 
ToDo.java 
/* 
* Klasse stellt ein ToDo dar wie es 
* in der Da...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
79 
R.java 
/* AUTO-GENERATED FILE. DO NOT MODIFY. 
* 
* This class...
10. Januar 
2013 
APPLIKATIONSENTWICKLUNG FÜR ANDROID 
80 
public static final int time_hourbutton=0x7f04000f; 
public sta...
Nächste SlideShare
Wird geladen in …5
×

Einführung in die Android Applikationsentwicklung

679 Aufrufe

Veröffentlicht am

Einführung in die Android Applikationsentwicklung

Veröffentlicht in: Technologie
0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Keine Downloads
Aufrufe
Aufrufe insgesamt
679
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
7
Aktionen
Geteilt
0
Downloads
11
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Einführung in die Android Applikationsentwicklung

  1. 1. FSIV10 THORSTEN WEISKOPF APPLIKATIONSENTWICKLUNG FÜR ANDROID
  2. 2. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 2 1 Einführung ................................................................................................... 3 2 Kapitel 1 – Android Grundlagen ................................................................... 4 2.1 Was ist Android? ........................................................................................................... 4 2.2 Die Entwicklungsumgebung .......................................................................................... 4 2.3 Google ADT.................................................................................................................... 5 2.4 Grober Aufbau einer Android App ................................................................................ 8 2.5 Grundlagen der Android Entwicklung ......................................................................... 10 2.5.1 View-Activity-Event-Intent .................................................................................. 10 2.5.2 Activity Lebenszyklus........................................................................................... 12 2.5.3 Die wichtigsten XML Dateien ausserhalb der Layouts ........................................ 14 2.5.4 Persistenz und Datenspeicherung in Adnroid ..................................................... 15 3 Kapitel 2 - App Dokumentation LittleProjectManager ................................ 16 3.1 Beschreibung der Applikation ..................................................................................... 16 3.2 Architektur und Funktionsweise der Applikation ....................................................... 18 3.2.1 Activity-View und Layout (VIEW) ........................................................................ 18 3.2.2 Activitys (Controller) ........................................................................................... 20 3.2.3 Dialogfragmente (Controller) .............................................................................. 23 3.2.4 Plain-Old-Java-Objects (Model) .......................................................................... 24 3.2.5 DataAccessObjects (Model) ................................................................................ 24 3.2.6 MySQLiteHelper und seine Tabellenklassen (Model) ......................................... 25 3.3 SQLite Datenbank ........................................................................................................ 26 3.3.1 Datenbankstruktur .............................................................................................. 27 3.4 Projekt und Paketstruktur ........................................................................................... 29 3.4.1 Pakete und Klassen ............................................................................................. 29 3.4.2 Projektdateien und Ressourcen .......................................................................... 31 4 Ausblick und Fazit ..................................................................................... 33 5 Abbildungsverzeichnis ............................................................................... 34 6 Abkürzungsverzeichnis .............................................................................. 35 7 Anlagen ..................................................................................................... 36 7.1 Eclipse Workbench ...................................................................................................... 37 7.2 Screenshots LittleProjectManager .............................................................................. 38 7.3 Architekturschaubild ................................................................................................... 40 7.4 Quellcode der Applikation .......................................................................................... 41
  3. 3. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 3 1 Einführung Dieses Dokument entstand im Rahmen einer abschließenden Leistungsfeststellung des Modules Softwareentwicklung. Vorgabe war es das Gebiet der Android Applikationsentwicklung zu erschließen und eine für den Bereich typische Applikation zu realisieren. Das Dokument gliedert sich daher auch in zwei Bereiche. Kapitel eins beschreibt die Grundlagen der Applikationsentwicklung, während Kapitel zwei die Architektur und Funktionsweise der, im Rahmen der ALF erstellten, Applikation „LittleProjektManager“ beschreibt. Im Anhang finden sich unter anderem Screenshots der Applikation, Diagramme und der gesamte Quellcode der Applikation.
  4. 4. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 4 2 Kapitel 1 – Android Grundlagen 2.1 Was ist Android? Android ist ein hauptsächlich von Google getriebenes „Open Source Projekt“ und wurde ursprünglich als Betriebssystem für mobile Geräte entwickelt. Es findet jedoch mittlerweile auch auf anderen Geräten wie Fernsehern Anwendung. Nach meiner persönlichen Einschätzung wird es nicht lange dabei bleiben. Es gibt bereits Modelle für Uhren, Spielekonsolen und „intelligente Haushaltsgeräte“ wie Kühlschränke und Spiegel auf denen Android läuft. Im Kern besteht das Betriebssystem aus einem Linux Kernel welcher den Hardwarezugriff und die Speicherverwaltung regelt. Gleich darauf aufgesetzt läuft eine auf Java Technologie basierende virtuelle Maschine mit einer entsprechenden Android Klassenbibliothek. Die virtuelle Maschine führt dann den Bytecode bestimmter Module oder der programmierten Android Applikation aus. Um jetzt Applikationen, also Anwendungen oder Apps, zu entwickeln stellt Google ein „Java Programming Interface“ mit einer Reihe von Tools zur Verfügung. Zusätzlich können auch bereits vorhandene Softwarekomponenten mit verwendet werden. Zum Beispiel die Tastatur, die Medienwiedergabe, der Browser, die SQLite Datenbank oder OpenGL für 3D Grafik, um nur mal einen Auszug zu nennen. 2.2 Die Entwicklungsumgebung Im Prinzip könnten die Apps in einem einfachen Editor geschrieben werden und per Android Service Development Kid zu Bytecode kompiliert, um anschließend in der virtuellen Maschine des Android Gerätes ausgeführt zu werden. Das wäre aber weder zeitgemäß, noch komfortabel oder besonders effizient. Heute setzt man auf eine starke Entwicklungsumgebung. Google selbst unterstützt hier mit zahlreichen Erweiterungen (PlugIns) die Entwicklungsumgebung Eclipse, eine der meist verbreiteten IDEs (Integrated
  5. 5. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 5 Development Enviroment) gerade in der Java Entwicklung. Eclipse ist ebenfalls Opensource und damit kostenlos. Dies bietet sehr viel Flexibilität und Erweiterungsmöglichkeiten. (Kurzer Einblick in Eclipse unter, 7.1 Eclipse Workbench, im Anhang auf Seite 37 ) Um nun mit der Entwicklung beginnen zu können benötigt man lediglich: • Eclipse http://www.eclipse.org/downloads/ • Android SDK (Service Development Kid) http://developer.android.com/sdk/index.html • ADT (Android Development Tools) Eclipse Plugin http://developer.android.com/tools/sdk/eclipse-adt.html Das ADT beinhaltet, neben vielen kleinen Hilfen wie einen grafischen Editor für die Benutzeroberfläche, auch einen Emulator, welcher ein beliebiges Android System emulieren kann und so ein schnelles Testen während der Entwicklung auch ohne Endgerät ermöglicht. Man kann sich mehrere verschiedene virtuelle Geräte konfigurieren und so verschiedene Displaygrößen und andere Hardwareeigenschaften emulieren und testen. 2.3 Google ADT Das Plugin bietet viele nützliche Dienste und Hilfen. Hier die wichtigsten: • Assistent zum Erstellen eines neuen Android Projektes • Assistent zum Erstellen von Attributen und Variablen • Visueller Editor für die Benutzeroberfläche der App • Einfaches Verwalten und Starten des Emulators • Ausgabe vom Systemlog-Meldungen (Logcat) des Android Systems auf dem Emulator • Android SDK Manager (Verwaltet und hält SDK aktuell)
  6. 6. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 6 Android API und Besonderheiten Die Google API (Application Programming Interface) stellt die zentrale Programmierschnittstelle dar. Ohne diese ist keine Entwicklung einer Android- App möglich, da bereits bei der Darstellung bis hin zur Interaktion mit dem Nutzer über das Touchscreen native Android-Funktionen benötigt werden. Es reicht also nicht aus Java entwickeln zu können, sondern es ist zwingend notwendig sich mit der Android API auseinander zu setzen und sich an deren Regeln zu halten. Die API existiert bisher in verschiedenen Versionen. Leider sind hier nicht alle Funktionen abwärtskompatibel, was es zwingend erforderlich macht Android mitzuteilen gegen welche API Version die App kompiliert ist. Dies geschieht in der AndroidManifest.xml. Hier wird die minimale API Anforderung und die zuletzt getestete API angegeben gegen die auch kompiliert wurde. Ist die angegebene „Minimum Required SDK“ neuer als die auf dem Installationsgerät so kann die Applikation dort nicht installiert werden. Fehlt diese Angabe kann die Applikation zwar installiert werden es wird aber womöglich zu Problemen bei der Ausführung kommen und damit zu schlechten Bewertungen im Play Store.
  7. 7. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 7 Abbildung 1- Eclipse New Android Application
  8. 8. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 8 2.4 Grober Aufbau einer Android App Grundsätzlich ist es jedem Entwickler frei gestellt wie er seine Anwendung gestaltet und entwickelt. Android oder die API machen hier keine Vorgaben sondern sind extrem flexibel in der Wahl der Softwarearchitektur. So können bestimmte Probleme mittels XML oder direkt im Java Code gelöst werden. Google treibt aber eine modulare Softwarearchitektur voran für ein modulares Bestriebssystem. Und nur das macht auch Sinn. Die Vorteile von, im weitesten Sinne losgelösten Einzelmodulen welche als Gesamtpaket eine Applikation bilden, liegen auf der Hand. Hier wird nicht nur die einfachere Entwicklung im Team oder Softwarepflege vereinfacht, sondern auch eine stabilere und schnellere Ausführung der Applikation für das Android System ermöglicht. XML- Dateien beispielsweise welche bestimmte Eigenschaften oder das Aussehen der Applikation beschreiben, werden vor der eigentlichen Codeausführung geladen und zwar schnell und stabil. Genauso gut könnte man die komplette View, also das Aussehen, im Java-Code schreiben. Das wäre aber nicht nur schlechter Stil, sondern würde auch zu Lasten der Performance gehen im Vergleich zu dem XML-Layout. In der Softwareentwicklung gibt es bestimmte Entwurfs- oder Architekturmuster darunter auch das „Model View Controller“ Modell. Dieses Modell lässt sich auch auf Android Applikationen anwenden und beschreibt eine klare Trennung der angesprochenen drei Bereiche. Während das „Model“ den Businessbereich und die Logik darstellt ist die „View“ für das Aussehen und die Interaktion mit dem Anwender zuständig. Der „Controller“ kontrolliert nun die Nutzung des „Models“ von der „View“ aus und weiß welche „View“ welches „Model“ verwendet.
  9. 9. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 9 Vereinfachte Schematische Darstellung: Activity.XML - VIEW Activity.JAVA - Controller PlainOldJavaObject – Model Zusätzlich gibt es noch eine Persistenzschicht zur dauerhaften Datenspeicherung in einer Datenbank. Im Fall von Android sind das SQLite Datenbanken welche ganz einfach über die API angelegt und genutzt werden können. Und das ist im Groben auch alles was eine Android App heute nutzt um seine Aufgaben erfüllen zu können. Im nachfolgenden Kapitel werde ich hier noch etwas mehr ins Detail gehen. Abbildung 2- MVC Architektur Quelle: wikipedia.de (MVC)
  10. 10. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 10 2.5 Grundlagen der Android Entwicklung 2.5.1 View-Activity-Event-Intent Activity Die Activity stellt so zu sagen das Herzstück der Android Applikation dar mit dem entscheidenden Programmcode welcher für die Ausführung der Aplikation verantwortlich ist. Jede App muss mindestens eine Activity haben und eine davon muss als Hauptactivity definiert sein. Also die, welche beim Starten der App als erstes geladen und ausgeführt wird (Equivalent zur Main Methode eines klassischen Java-Programmes). Die Activity definiert eine „View“ zur Anzeige auf dem Bildschirm und behandelt dort auftretende Events wie beispielsweise ein Klick auf einen Button. Die Activity benutzt „Intents“ um andere Activitys zu starten. View Die View ist der sichtbare Teil der Activity und wird üblicherweise in einer XML- Layout-Datei definiert. Event Ein Event wird ausgelöst, wenn etwas geschieht wie das Klicken auf einen Button oder das Drücken des Suchen und Zurück Buttons. In der Activity muss dann ein Listener definert sein welcher auf diese Events reagiert und entsprechende Operationen durchführt. Intent Startet eine andere Activity also eine zweite Benutzeroberfläche auf dem Bildschirm. Mittels „Bundels“ können dann einfache Parameter an die Activity übergeben werden. Es können sogar Activities aus anderen Apps gestartet werden so lange diese verfügbar und im Android System als öffentlich gekennzeichnet sind. Beispielsweise könnte die Google Maps App gestartet werden und Koordinaten übergeben werden.
  11. 11. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 11 Abbildung 3- Zusammenarbeit Activity und View (Quelle http://www.androidpit.de/de/android/wiki/view/Android_Anf%C3%A4nger_Workshop)
  12. 12. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 12 2.5.2 Activity Lebenszyklus Da auf dem Handy die Ressourcen limitiert sind muss das Betriebssystem in der Lage sein auf den Lebenszyklus der Apps Einfluß nehmen zu können. Jede Activity hat ihren eigenen Lebenszyklus und so muss sich der Entwickler auch um die entprechenden Phasen des Zyklusses kümmern um Datenverluste oder unerwünschtes Verhalten zu vermeiden. Es gibt folgende Phasen: • onCreate() • onStart() • onPause() • onResume() • onStop() • onRestart() • onDestroy() Jede eigene Activity erbt diese Methoden von ihrer Vaterklasse Activity und kann diese überschreiben. OnPause() beispielsweise tritt ein wenn die Activity in den Hintegrund gerät weil ein Anruf herein kommt oder eine neue Activity aufgerufen wird. Vielleicht wäre es hier sinnvoll die bereits eingegebenen Daten in einer Datenbank zu speichern und bei onResume() wieder anzuzeigen. Folgendes Schaubild soll die verschiedenen Stati verdeutlichen:
  13. 13. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 13 Abbildung 4 - Activity Lebenszyklus (Quelle http://www.androidpit.de/de/android/wiki/view/Android_Anf%C3%A4nger_Workshop)
  14. 14. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 14 2.5.3 Die wichtigsten XML Dateien ausserhalb der Layouts Strings.xml Hier werden Variablen zur Darstellung definiert. Beispielsweise Beschriftungen und Text für die Buttons in den Views, Hilfemeldungen oder sonstige Texte. Android Manifest.xml Ist die Grundlage jeder App und unabdingbar. Hier werden Metainformationen wie das Icon, der Applikationsname und die Rechte, welche sich die Applikation einräumt, bekannt gegeben. Diese werden dem Nutzer auch vor der Installation bekannt gegeben und müssen bestätigt werden. Rechte sind beispielsweise Zugriffe auf das Netzwerk, die Kamera oder die Kontaktdaten. Ausserdem sollte noch die vorausgesetzte API Version angegeben werden, um zu verhindern, dass die App auf nicht lauffähigen Geräten installiert werden kann. Exemplarisches Beispiel einer AdroidManifest.xml mit Erläuterung. Abbildung 5- AndroidManifest.xml (Quelle http://www.androidpit.de/de/android/wiki/view/Android_Anf%C3%A4nger_Workshop/)
  15. 15. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 15 2.5.4 Persistenz und Datenspeicherung in Adnroid Zur persistenten Datenspeicherung bietet Android eine einfache Art SQLite als schlankes Datenbanksystem an. Durch das Erben und Überschreiben der Klasse SQLiteOpenHelper wird es erleichtert eigene Datenbanken an zu legen, welche dann per default als Datei auf der SD-Karte gespeichert werden. SQLite ist eine Open-Source-Datenbank, die in Android eingebettet ist. SQLite unterstützt Standardfunktionen von relationalen Datenbanken wie SQL-Syntax, Transaktionen und Prepared Statements. Darüber hinaus bedarf es nur wenig Speicher zur Laufzeit (ca. 250 KByte). SQLite unterstützt die Datentypen TEXT (ähnlich String in Java), INTEGER (ähnlich wie long in Java) und REAL (ähnlich wie double in Java). Alle anderen Formate müssen vor dem Speichern in einen dieser Datentypen konvertiert werden.
  16. 16. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 16 3 Kapitel 2 - App Dokumentation LittleProjectManager 3.1 Beschreibung der Applikation Die App soll eine einfache Verwaltung von Projekten und seinen ToDo`s möglich machen. Zusätzlich soll man die Zeit messen können wie lange man für das jeweilige Projekt gearbeitet hat. Der Anwendungsfall kommt aus der Praxis. Denn bei kleinen oder mittelgroßen Projekten wird häufig vergessen die eigene Zeit zu messen um hinterher die geschätzte Zeit und die verbrauchte Zeit gegenüber stellen zu können. Ausserdem soll es helfen dem Kunden die korrekten Zeiten in Rechnung zu stellen. Die Möglichkeit ToDo`s anzulegen dient lediglich der Übersichtlichkeit und stellt eine Art Notizzettel für das Projekt dar. Ich habe mich bewusst dagegen entschieden die Zeiten für einzelne ToDos zu tracken. Dies wäre zwar auf Grund der Datenbankstruktur möglich findet aber in der Praxis wenig Relevanz da zumindest bei den Projekten kleinerer Größenordnung diese Zeiten keine Rolle spielen und das Buchen für den Nutzer zu aufwendig wäre. Die Applikation bildet folgende funktionale und technische Leistungsmerkmale: • Projekte anlegen und entfernen • ToDo`s für Projekte anlegen und entfernen • Einfaches „Einbuchen“ bei Arbeitsbeginn • Einfaches „Ausbuchen“ bei Arbeitsende • Zusätzlich soll auch ein manuelles Buchen von Zeiten möglich sein • Die App soll direkt nach Buchung die aktuelle Zeit berechnen und anzeigen Technische Leistungsmerkmale: • Daten in der SQLite Datenbank speichern • Intuitive Bedienung über das Touch-Display
  17. 17. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 17 • Optimiert für die Benutzung mit Smartphone, sollte aber auch auf einem Tablet funktionsfähig sein • Android spezifische Bedienelemente wie der Zurück Button und Menü Button (vor Android 3.0) sollten unterstützt werden Screenshots zur Verdeutlichung finden sich im Anhang unter 7.2 Screenshots LittleProjectManager auf Seite 38.
  18. 18. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 18 3.2 Architektur und Funktionsweise der Applikation Hierzu empfiehlt es sich erst mal einen Blick auf das Schaubild aus Anlage 7.3 Architekturschaubild auf Seite 40 zu werfen. Dort ist ein Architekturdiagramm der Applikation abgebildet unter Berücksichtigung des MVC Entwurfsmusters. Es beinhaltet alle funktional wichtigen Klassen und XML Dateien der Applikation und deren Abhängigkeiten, welche nun im Detail erläutert werden. Es empfiehlt sich vorher im ersten Kapitel den Teil „Grober Aufbau einer Android Applikation“ gelesen zu haben. 3.2.1 Activity-View und Layout (VIEW) In der VIEW befinden sich die XML Dateien. Drei Activity-Views und ein Layout. Die activity_project_view und die activity_todo_view bestehen beide aus ListViews um eine Liste der jeweiligen Objekte, eben Projekte und Todos, darstellen zu können. Bei beiden kann über das Menü das Layout add_item.xml aufgerufen werden. Dies ist eine Art Formular, um neue Todo's oder Projekte an zu legen. Das Add-Item-Layout besteht aus einem Textfeld und einem Button und wird hier einmal exemplarisch dargestellt: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:inputType="textMultiLine" > <requestFocus /> </EditText>
  19. 19. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 19 <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Add" android:onClick="AddClick" /> </LinearLayout> Das ganze Layout besteht aus einem LinearLayout innerhalb dessen befinden sich ein EditText Feld zum Eingeben des neuen Projektes oder des Todo und ein Button zum Bestätigen. Zusätzlich werden Angaben zur Größe und Anordnung des jeweiligen Elementes gemacht. Die android:id beschreibt den Namen über den auf das Element später im JAVA Code zugegriffen werden kann und android:text="@string/Add gibt an welcher Text auf dem Button stehen soll. Unter android:id="@+id/editText1" kann das Textfeld in der JavaKlasse also der jeweiligen Activity, welche das Layout gestartet hat, erreicht werden. Und android:onClick="AddClick" gibt an, dass, wenn der Button Add gedrückt wird, in der Activity die Methode AddClick() ausgeführt wird. Die Dritte und letzte Activity-View ist die activity_time_manager.xml welche für die Zeitbuchungen und die Anzeige der Zeiten zuständig ist. Dementsprechend viele Elemente sind hier vorhanden:  ein Button zur Anzeig des aktuellen Datums  ein Button welcher die aktuelle Zeit anzeigt  ein Button zum Einbuchen  ein Button zum Ausbuchen  einen Button um nur die Zeit in Stunden und Minuten auf das Projekt nachträglich als Arbeitszeit zu buchen. Wird der Button für Datum gedrückt so öffnet sich ein spezielles Auswahlmenü von Android zur Datumsauswahl und bei der Zeit ist es das gleiche. Diese Auswahldialoge müssen als so genannte Dialogfragmente ausprogrammiert
  20. 20. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 20 werden. 3.2.2 Activitys (Controller) Jede Activity-View hat auch ihre eigene Klasse welche die verschiedenen Stati des Lebenszyklus und die Interaktion mit dem Benutzer behandelt. Die Hauptactivity ist in der AndroidManifest.xml beschrieben. Bei dieser Applikation handelt es sich um die Activity Project_View.java. Jede Activity die als solche fungieren soll hat als Vaterklasse die Klasse android.app.Activity und überschreibt mindestens eine Methode: Die onCreate() Methode, welche in unserem Fall nichts weiter macht als sich aktuelle Daten aus der Datenbank zu holen und darzustellen. Zusätzlich wird noch das Optionsmenu deklariert und auf das Drücken von Menüeinträgen, Listeinträgen und Buttons mit entsprechendem Programmcode reagiert. ProjectView.java Füllt die ListView mit Projekten. Projekte können ausgewählt und anschließend gelöscht werden. Genauso gut können nach Auswahl eines Projektes die dazugehörigen Todos geladen werden. Dies geschieht durch das Aufrufen der MyTodosOverview und die Übergabe der Projektid des ausgewählten Objektes. Ausserdem kann das Layout add_item.xml aufgerufen werden und neue Projekte angelegt werden. Kurze Beschreibung der Methoden: onCreate() Legt die Activity-View fest welche angezeigt werden soll. Ruft Hilsmethode showValuesFromDB() auf. showValuesFromDB() Holt sich die Projekte aus der Datenbank und setzt vorhandene Values in die Liste.
  21. 21. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 21 Aktiviert OnClickListner welcher das markierte Objekt der Liste festhält und einfärbt. onCreateOptionsMenu() Legt das Menü Fest welches angezeigt wird wenn auf den Menü Button gedrückt wird. onOptionsItemSelected(MenuItem item) Deklariert pro betätigtem Menüeintrag was passieren soll. AddClick(View view) Methode wird aufgerufen wenn im add_item.xml Layout der Button Add gedrückt wird. Der Inhalt des Textfeldes aus dem Layout wird als Projekt in die Datenbank geschrieben MyTodosOverview.java Funktioniert genauso wie die ProjectView.java, ausser dass es sich hierbei um die Todos handelt, die angezeigt, verwaltet und in die Datenbank geschrieben, sowie dort gelöscht werden können. TimeManager.java Diese Activity ist die Aufwendigste in der Applikation. Sie übernimmt nicht nur das Eintragen von Buchungen in die Datenbank sondern ist auch für die aktuelle Anzeige von Datum und Uhrzeit zuständig. Außerdem errechnet sie bei jeder Buchung die Arbeitszeit neu, sofern möglich und zeigt diese Information direkt über die VIEW an. Die beiden Dialoge zur Datums- und Zeitauswahl werden von ihr gestartet und beobachtet um Änderungen direkt zu erkennen. Daher handelt es sich auch um eine FragmentActivity welche ihrerseits erweiterte Funktionen anbietet als ihre Vaterklasse Activity.
  22. 22. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 22 Die ganze Berechnung der Zeit erfolgt über ein java.util.Calendar Objekt während die Anzeige über java.text.SimpleDateFormat formatiert wird. Erläuterung der wichtigsten Methoden: onCreate() Legt die Activity-View fest welche angezeigt werden soll. Ermittelt die aktuelle Zeit Steuert die interne Hilfsmethode setTimeOnView(Calendar c) und setDateOnView(Calendar c) an. Steuert interne Hilfsmethode addTimeandDateButtonListners() an. onResume() Ermittelt das aktuelle Projekt und zeigt dessen Namen an sowie die bisher gebuchte Arbeitszeit. Dies geschieht in der onResume() Methode so, dass die Anzeige nicht nur nach dem Erstellen der Activity aktualisiert wird sondern auch wenn die Activity im Hintergrund war. setTimeOnView(Calendar c) Zeigt die aktuelle Zeit im Button an setDateOnView(Calendar c) Zeigt aktuelles Datum im Datum Button an addTimeandDateButtonListners() Listner welcher auf das Drücken einer der Buttons reagiert checkin(), checkout() und justbookthetime() Bucht die entsprechende Zeit in die Datenbank. Steuert CalcWorkingTime() an CalcWorkingTime() Errechnet die Arbeitszeit wenn möglich. Es wird überprüft ob genau so viele
  23. 23. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 23 Ein- wie Ausbuchungen vorhanden sind, errechnet dann die neue Arbeitszeit und schreibt diese Informationen in die Datenbank. ShowDatePicker() und showTimePicker() Zeigen die Dialoge zur Auswahl von Datum und Zeit an OnTimeSetListener() und OnDateSetListener() Reagieren auf die Zeitauswahl in dem sie die Zeit im Calendar Objekt ändern und die ausgewählte Zeiten auf den Buttons der View visualisieren. 3.2.3 Dialogfragmente (Controller) Zur Auswahl von Datum und Zeit werden TimePicker und DatePicker verwendet. Dies sind Objekte um es dem Nutzer so komfortabel wie möglich zu machen über den Touchscreen Datum und Zeiteingaben zu tätigen. Diese werden von Android zur Verfügung gestellt. Um sie nutzen zu können, müssen sie in so genannte Dialogfragmente verpackt werden. Also Dialoge welche erscheinen während die eigentliche Activity im Hintergrund noch aktiv ist. Also weder in den Status onPause() gesetzt, noch beendet wird. Wird also nun in der Time_Manager.java Activity auf den Button mit dem Datum gedrückt so wird das DatePickerFragment gestartet. Über einen Datencontainer, bei Android das Bundle, werden die aktuellen Werte zur Anzeige übergeben und bei Auswahl durch den Nutzer die ausgewählten Werte zurück an die Activity übergeben.
  24. 24. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 24 3.2.4 Plain-Old-Java-Objects (Model) Hier finden sich klassische Java Objekte welche in der Applikation durch alle Instanzen hindurch genutzt werden wie Todo, TimeEntry oder Project. Klassisch deshalb weil sie als Vaterklasse lediglich die Klasse Object besitzen. Diese Objekte stellen immer jeweils ein Listeneintrag in der View oder eine Zeile in der Datenbank dar. Dementsprechend sind auch die Attribute pro Klasse gewählt: 3.2.5 DataAccessObjects (Model) Hierunter fallen die drei Klassen ProjectDatasource.java, TimeTableDatasource.java und TodosDatasource.java. Die Aufgabe des DAO ist das Erlauben des Zugriffs auf die Datenbank und das Anbieten von Methoden fürs Abholen und Schreiben von Daten. Dies beinhaltet den Verbindungsauf- und Abbau genauso wie das Zusammenbauen bestimmter SQL-Abfragen zum Herausholen aller oder nur eines bestimmten Datensatzes mittels Fremdschlüssel. Das Ergebnis aus der Datenbank kommt als so genannter Curser zurück und wird nicht einfach an die aufrufende Klasse zurückgegeben. Es werden POJOs (Plain-Old-Java-Objects) vom jeweiligen Typ erzeugt und einzeln oder in einer Liste zurück gegeben. Dazu wurden in Abbildung 6 - Klassendiagramm Models
  25. 25. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 25 der Klasse als privat gekennzeichnete Hilfsmethoden geschrieben. 3.2.6 MySQLiteHelper und seine Tabellenklassen (Model) MySQLiteHelper hat als Vaterklasse SQLiteOpenHelper und überschreibt onCreate() und onUpgrade(). OnCreate() wird vom Framework aufgerufen wenn die Datenbank noch nicht existiert und onUpdate() wenn sich die Versionsnummer ändert. Beide Methoden bekommen ein Datenbankobjekt beim Aufruf übergeben, welches die Datenbank repräsentiert. In der Applikation gibt es für jede Tabelle eine eigene Klasse: • ProjectTable.java • TodoTable.java • TimeTabl.java Jede dieser Tabellenklassen hat statische Variablen für den Tabellennamen und die Spalten. Ausserdem besitzt jede Klasse ihre eigene statische onCreate() und onUpdate() Methode in der der SQL-Befehl zum Erstellen und Updaten der Tabellen ausformuliert ist. Hier wird auch angegeben welche Datentypen in die Spalten gehören und ob es sich dabei um Schlüssel handelt. Als Beispiel hier ein Auszug der Klasse ProjectTable, welche auch genau diese Tabelle MYPROJECTS repräsentiert: public class ProjectTable // Database table public static final String TABLE_PJ = "myprojects"; public static final String COLUMN_ID = "_id"; public static final String COLUM_NAME = "name"; public static final String COLUM_WORKTIME = "worktime"; //SQL CREATE Statement private static final String TABLE_CREATE_MYPROJECTS ="" +"create table " +TABLE_PJ +" ( " +COLUMN_ID+ " integer primary key autoincrement, " +COLUM_NAME +" text not null, " +COLUM_WORKTIME +" integer" +");"; /*
  26. 26. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 26 * Tabelle erstellen */ public static void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_CREATE_MYPROJECTS); } Es wird von Android empfohlen als Primärschlüssel _id zu verwenden so wie hier geschehen. Zusätzlich wird noch durch „autoincrement“ angegeben, dass die Spalte automatisch hoch gezählt wird. Die Klasse MySQLiteHelper führt jetzt in seiner eigenen onCreate() Methode nur noch die statischen onCreate() Methoden der jeweiligen Tabellen aus: Auszug aus public class MySQLiteHelper @Override public void onCreate(SQLiteDatabase db) { ProjectTable.onCreate(db); TodoTable.onCreate(db); TimeTable.onCreate(db); } So ist sichergestellt, dass die Datenbanken alle angelegt sind und von Objekten der Datasource Klasse darauf zu gegriffen werden kann. 3.3 SQLite Datenbank Zur Datenspeicherung bietet Android eine sehr einfache Möglichkeit eine SQLite Datenbank an zu legen. Der LittleProjektManager greift darauf zu. Die Daten werden zwecks Normalisierung und einer einfachen Datenhaltung in drei Tabellen gespeichert. Android empfiehlt für jede Tabelle eine Spalte _id als Primärschlüssel zu verwenden. In unserem Falle deklarieren wir die Spalte _id zusätzlich noch als „autoincrement“, so dass sie bei jedem Eintrag automatisch hoch gezählt wird und uns die Verknüpfung somit vereinfacht. In SQLite gibt es vier Datentypen:
  27. 27. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 27 SQLite Datentyp Equivalent in JAVA INTEGER Long TEXT String REAL Double BLOB Data Die Datenbank selbst wird von Android auf der SD-Karte unter dem Ordner „data“ und dem jeweiligen Applikationsnamen als eine Datei gespeichert. 3.3.1 Datenbankstruktur Abbildung 7 - Datenbankdiagramm MYPROJECTS Beinhaltet alle relevanten Informationen zum Projekt. Der eingegebene Name als Text, eine _id als Primärschlüssel, der automatisch hoch gezählt wird und die workingtime als Integer. Die Workingtime ist zu Beginn 0 und wird dann je nach Buchungen hochgezählt und überschrieben. Einfache Zeitbuchen werden direkt und nur hier gespeichert. Ein- und Ausbuchungen mit Datumsangaben kommen in die Tabelle TIMETABLE. TODO
  28. 28. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 28 Ist eine unabhängige Tabelle mit eigener _id als Primärschlüssel und der Aufgabe todo selbst als Text. Da alle Todos einem Projekt zugeordnet werden müssen, sind sie über die pj_id als Fremdschlüssel mit der Tabelle MYPROJECTS verbunden. Es besteht eine 1-zu-n Beziehung. Ein Projekt kann viele Todos haben aber ein Todo kann nur zu einem Projekt gehören. TIMETABLE Hier werden alle Ein- und Ausbuchungen gespeichert, welche nicht nur als Zeitbuchung, sondern mit einer kompletten Zeitangabe gebucht werden also Datum und Uhrzeit. Beides zusammen wird im Java Code als Ganzzahl im Datentyp long dargestellt und kann daher auch so in der Datenbank eingetragen werden. Neben dem Primärschlüssel _id wird die Zeit als long, und datetime als Integer gespeichert. Unter entrytype wird eine 0 fürs Einbuchen und eine 1 fürs Ausbuchen geschrieben und die pj_id ist wieder die Verbindung in Form eines Fremdschlüssels zur Tabelle MYPROJECTS. Auch hier besteht vom Projekt der Tabelle MYPROJECTS ausgehend eine 1-zu-n Beziehung.
  29. 29. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 29 3.4 Projekt und Paketstruktur 3.4.1 Pakete und Klassen Da der Paketname eindeutig für die Applikation sein soll, um gezielt der eigenen Applikation zugeordnet werden zu können, wurde hier de.thorstenweiskopf.lpm gewählt. Das Kürzel de für die Länderdomäne, thorstenweiskopf als autor und lpm als kürzel für den Applikationsname LittleProjectManager. Danach werden noch Unterpakete verwendet um die unterschiedlichen Aufgabenbereiche darzustellen:
  30. 30. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 30 src: Hier liegen die eigenen Klassen. Unter dem Hauptpaket befinden sich die drei Activitys. .databse: alle datenbankrelevanten Klassen: Der SQLiteHelper welcher die Datenbank erstellt und updatet sowie die drei Datasources zum Zugriff auf die Datenbank. .tables: Tabellen selbst in Form von Java- Klassen die vom SQLiteHelper genutzt werden. .dialogframents ZeitAuswahlDialoge .model Daten Modelle für die verwendeten Datenobjekte: Projekt, Zeiteintrag und Todo. gen: Hier sind die von Android generierten Klassen abgelegt. Am wichtigsten ist die Klasse R welche über Referenzvariablen alle Ressourcen zur Verfügung stellt. Ressourcen sind: Layouts, Activity-Views, Strings, Menüs, Bilder usw.
  31. 31. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 31 3.4.2 Projektdateien und Ressourcen Das Android Projekt besteht allerdings aus mehr als nur den Java-Klassen selbst. Es gibt noch ein Ressourcen Verzeichnis mit Inhalten und die AndroidManifest.xml:
  32. 32. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 32 /res:Ordner für Resource-Dateien /res/drawable-hdpi: Logos in hoher Auflösung /res/drawable-ldpi Logos in niedriger Auflösung /res/drawable-mdpi: Logos in mittlerer Auflösung /res/drawable-xhdpi:Logos in sehr hoher Auflösung /res/layout alle Layout-Definitionen Activity-Views und Layouts /res/menu: Menüs activity_project_view: Menü für die Projektübersicht activity_project_view: Menü für die ToDos /res/values: Variablen strings.xml: String-Definitionen für Buttons und Überschriften styles.xml: Erscheinungsbild der App AndroidManifest.xml:"Manifest"-Datei, definiert Infos wie Name, Logo und Haupt-Activity default.properties:Projekt-Eigenschaften
  33. 33. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 33 4 Ausblick und Fazit Die Applikation „LittleProjektMananer“ hat noch Optimierungspotential hinsichtlich des Designs. Ausserdem fehlt noch eine Implementierung der seit Android 4.0 vorhandenen „ActionBar“ welche das Menü ersetzen soll. Eine Möglichkeit für statistische Auswertungen über die bereits getätigten Buchungen ist auch denkbar. Sind diese Leistungsmerkmale realisiert, was sich bereits in Planung befindet, steht einer Veröffentlichung über den Google „Playstore“ nichts mehr im Wege. Als Fazit für Android selbst ist zu sagen, dass Android eine solide Basis bietet native Applikationen zu entwickeln. Der modulare Aufbau bietet gute Möglichkeiten für Erweiterungen und die Realisierung von größeren Projekten. Diese Gründe und der Fakt, dass das Betriebssystem auf dem Vormarsch in vielen Bereichen elektronischer Geräte ist, verspricht Android und den Applikationsentwicklern eine aussichtsreiche Zukunft.
  34. 34. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 34 5 Abbildungsverzeichnis Abbildung 1 - Eclipse New Android Application .................................................. 7 Abbildung 2 - MVC Architektur ........................................................................... 9 Abbildung 3 - Zusammenarbeit Activity und View ........................................... 11 Abbildung 4 - Activity Lebenszyklus ............................................................... 13 Abbildung 5 - AndroidManifest.xml ................................................................. 14 Abbildung 6 - Klassendiagramm Models .......................................................... 24 Abbildung 7 - Datenbankdiagramm .................................................................. 27
  35. 35. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 35 6 Abkürzungsverzeichnis App Application (Anwendung) IDE Integrated Development Enviroment SDK Service Development Kit ADT Android Development Tools API Application Programming Interface MVC Model View Controller (Softwarearchitektur) POJO Plain Old Java Object (“simple” Javaklassen)
  36. 36. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 36 7 Anlagen
  37. 37. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 37 7.1 Eclipse Workbench (QUELLE: http://www.admin-wissen.de/tutorials/eclipse_workshop/ueberblick_workbench.html) Zu Eclipse selbst und der Benutzung gibt es eine Reihe von Büchern und Seminare. Ich möchte hier nur einen Auszug aus www.admin-wissen.de einbinden welcher ganz gut die Benutzung erläutert: 1. Im Bereich 1 findest einen Überblick über die vorhandenen Projekte. Du kannst zwischen den Projekten navigieren und Dateien öffnen, erstellen oder Ordner in denProjekten anlegen etc. 2. In diesem Bereich ist der Editor zu finden. Im Editor kannst du den Sourcecode schreiben, er wird farbig hervorgehoben und Fehler die Eclipse im Vorfeld erkennt werden markiert. In manchen Fällen signalisiert Eclipse mit einer Glühbirne, wie der Fehler möglicherweise behoben werden kann. 3. Hier befindet sich die Outline. Darin findest du wissenswertes über die im Moment geöffnete Datei. Bei einer Klasses siehst du hier die Attribute und Methoden und kannst sie sortieren oder anders in der Outline organisieren. Durch einen Klick auf die Methode kommst du z.B. direkt an die Stelle im Quelltext wo sie implementiert ist. Dadurch bekommt man bei umfangreichen Klassen schnell einen Überblick welche Methoden die Klasse bietet. 4. In diesem Bereich findest du verschiedene Konsolenausgaben. Eine mögliche Konsolenausgabe ist z.B. ein Kompilierungsfehler oder die Ausgabe des laufenden Programms.
  38. 38. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 38 7.2 Screenshots LittleProjectManager Projektübersicht Projektübersicht mit Auswahl und Menü Add Item Formular Todoübersicht mit Auswahl und Menü
  39. 39. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 39 Arbeitszeitverwaltung zum Buchen und Anzeigen von Zeiten Dialog zur Zeitauswahl wenn entsprechender Button gedrückt wurde
  40. 40. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 40 7.3 Architekturschaubild
  41. 41. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 41 7.4 Quellcode der Applikation AndroidManifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.thorstenweiskopf.lpm" android:versionCode="1" android:versionName="1.0" > <!-- welches min und max sdk wird supported von dieser app --> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <!-- applicationbeschreibung--> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <!-- alle Activitys also Views --> <activity android:name=".MyTodosOverview" android:label="@string/title_activity_my_todos_overview" > </activity> <activity android:name=".ProjectView" android:label="@string/title_activity_project_view" android:configChanges="orientation|keyboardHidden|keyboard|screenSize" > <intent-filter> <!-- Hauptactivity soll geöffnet werden beim start --> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".TimeManager" android:label="@string/title_activity_time_manager" > </activity> </application> </manifest>
  42. 42. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 42 stringx.xml <resources> <string name="app_name">LittleProjectManager</string> <string name="title_activity_my_todos_overview">My Todos</string> <string name="Add">Add</string> <string name="Remove">Remove</string> <string name="title_activity_my_todo_add">Add a Todo</string> <string name="title_activity_project_view">My Projects</string> <string name="title_activity_time_manager">My Project Times</string> <string name="menu_settings">Settings</string> <string name="menu_addpj">Add Project</string> <string name="menu_showtodos">Show ToDo Items</string> <string name="menu_remove_pj">Remove Project</string> <string name="menu_timemanager">Project TimeManagement</string> <string name="menu_timestats">Show Workingtime</string> <string name="time_checkinbutton">Check In</string> <string name="time_checkoutbutton">Check Out</string> <string name="time_hourbutton">Timebooking (Hour and Minute)</string> </resources>
  43. 43. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 43 ACTIVITY-VIEWS activity_project_view.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </RelativeLayout> activity_todos_view.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:layout_height="wrap_content" android:layout_width="wrap_content" > <TextView android:id="@+id/todo_lable" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/title_activity_my_todos_overview" android:textSize="30dp" /> </LinearLayout> <LinearLayout android:layout_height="match_parent" android:layout_width="match_parent" > <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout> </LinearLayout>
  44. 44. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 44 additem.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:inputType="textMultiLine" > <requestFocus /> </EditText> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/Add" android:onClick="AddClick" /> </LinearLayout>
  45. 45. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 45 activity_time_manager_view.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/Text_ProjectLable" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" android:textSize="30dp" /> <TextView android:id="@+id/Text_ProjectTime" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dip" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> <Button android:id="@+id/button_date" android:layout_width="199dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="5dip" android:text="Button" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="horizontal" > <Button android:id="@+id/button_time" android:layout_width="198dp" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" > <Button android:id="@+id/button_checkin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_margin="10dip" android:text="@string/time_checkinbutton" />
  46. 46. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 46 <Button android:id="@+id/button_checkout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dip" android:text="@string/time_checkoutbutton" /> </LinearLayout> <Button android:id="@+id/button_hours" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/time_hourbutton" /> </LinearLayout>
  47. 47. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 47 MENUS acitivity_project_view <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/addpj" android:title="@string/menu_addpj"></item> <item android:id="@+id/showTodos" android:title="@string/menu_showtodos"></item> <item android:id="@+id/removepj" android:title="@string/menu_remove_pj"></item> <item android:id="@+id/timemanager" android:title="@string/menu_timemanager"></item> </menu> activity_todos_view <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/addpj" android:title="@string/menu_addpj"></item> <item android:id="@+id/showTodos" android:title="@string/menu_showtodos"></item> <item android:id="@+id/removepj" android:title="@string/menu_remove_pj"></item> <item android:id="@+id/timemanager" android:title="@string/menu_timemanager"></item> </menu>
  48. 48. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 48 JAVA KLASSEN MyTodosOverview.java package de.thorstenweiskopf.lpm; import java.util.ArrayList; import java.util.List; import de.thorstenweiskopf.lpm.database.TodosDatasource; import de.thorstenweiskopf.lpm.model.ToDo; import de.thorstenweiskopf.lpm.R; import android.os.Bundle; import android.app.Activity; import android.graphics.Color; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class MyTodosOverview extends Activity { ArrayAdapter<ToDo> adapter; //Variablen der Todo Liste public static List<ToDo> values = new ArrayList<ToDo>(); int selectedItem = -999; private String projectname; private long projectid; //For Database Use private TodosDatasource datasource; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_todos_view); //Datasource benutzen datasource = new TodosDatasource(this); Bundle extras = getIntent().getExtras(); if (extras == null) { return; } // Get data via the key from Intent projectname = extras.getString("ProjectName"); projectid = extras.getLong("ProjectId"); if (projectname != null) { // Show projectname as lable
  49. 49. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 49 TextView lable = (TextView) findViewById(R.id.todo_lable); lable.setText(projectname); } showValuesFromDB(projectid); } /* * Methode um mittels projectid die entsprechenden Todos anzuzeigen */ private void showValuesFromDB(long projectid) { values.clear(); try { datasource.open(); values = datasource.getAllTodosFromProject(Long.toString(projectid)); datasource.close(); } catch (Exception ex) { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG).show(); } adapter = new ArrayAdapter<ToDo>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values); // Assign adapter to ListView ListView listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(adapter); //Set a OnClickListner to the ListView to choose one todo listView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectedItem = position; //the choosen one //change bgcolor of the selected item for(int a = 0; a < parent.getChildCount(); a++) { parent.getChildAt(a).setBackgroundColor(Color.WHITE); } view.setBackgroundColor(Color.GRAY); openOptionsMenu(); } }); } /* * Methode setzt alle vorhandene Todos in die Liste * DERZEIT nicht genutzt */ private void showValuesFromDB() { values.clear(); try { datasource.open(); values = datasource.getAllTodos(); datasource.close(); } catch (Exception ex) { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG).show(); } adapter = new ArrayAdapter<ToDo>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values); // Assign adapter to ListView ListView listView = (ListView) findViewById(R.id.listView1);
  50. 50. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 50 listView.setAdapter(adapter); //Set a OnClickListner to the ListView to choose one todo listView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectedItem = position; //the choosen one //change bgcolor of the selected item for(int a = 0; a < parent.getChildCount(); a++) { parent.getChildAt(a).setBackgroundColor(Color.WHITE); } view.setBackgroundColor(Color.GRAY); openOptionsMenu(); } }); } /* * (non-Javadoc) * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu) * OptionsMenuStuff */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_todos_view, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.Add){ ListView listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(adapter); // show the add view setContentView(R.layout.additem); } else if (item.getItemId() == R.id.Remove) { if (selectedItem != -999){ ToDo todo = adapter.getItem(selectedItem); selectedItem = -999; try { datasource.open(); datasource.removeTodo(todo); datasource.close(); } catch (Exception ex) { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG) .show(); } // show the main view setContentView(R.layout.activity_todos_view); showValuesFromDB(); } else{ Toast.makeText(this, "Please choose a Item from List", Toast.LENGTH_LONG).show(); } }
  51. 51. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 51 return super.onOptionsItemSelected(item); } /* * Method of the layout additem.xml * Beschrieben im Layout als AddClick */ public void AddClick(View view){ if (view.getId() == R.id.button1){ EditText text = (EditText)findViewById(R.id.editText1); //values.add(text.getText().toString()); //put the new value in the database try { datasource.open(); datasource.creatTodo(text.getText().toString(), Long.toString(projectid));//Fehlt noch die Projektid vom DB Objekt Projekt datasource.close(); } catch (Exception ex) { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG).show(); } //show the main view setContentView(R.layout.activity_todos_view); // Show projectname as lable TextView lable = (TextView) findViewById(R.id.todo_lable); lable.setText(projectname); showValuesFromDB(projectid); } } }
  52. 52. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 52 ProjectView.java package de.thorstenweiskopf.lpm; import java.util.ArrayList; import java.util.List; import de.thorstenweiskopf.lpm.database.ProjectDatasource; import de.thorstenweiskopf.lpm.database.TodosDatasource; import de.thorstenweiskopf.lpm.model.Project; import de.thorstenweiskopf.lpm.model.ToDo; import de.thorstenweiskopf.lpm.R; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; public class ProjectView extends Activity { ArrayAdapter<Project> adapter; //Adapter to fill the P //Variablen der Projekte Liste public static List<Project> values = new ArrayList<Project>(); int selectedItem = -999; private ProjectDatasource datasource; //Schnittstelle zur Datenbank /* * (non-Javadoc) * @see android.app.Activity#onCreate(android.os.Bundle) * wird aufgerufen wenn android Activity anzeigen soll */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_project_view); datasource = new ProjectDatasource(this); showValuesFromDB(); } /* * Methode holt sich Projekte aus DB * und setzt vorhandene Values in die Liste */ private void showValuesFromDB() { values.clear(); try { datasource.open(); values = datasource.getAllProjects(); datasource.close();
  53. 53. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 53 } catch (Exception ex) { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG).show(); //Fehler ausgabe ToDo: Überschreiben mit eigenem Fehlertext } adapter = new ArrayAdapter<Project>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values); // Assign adapter zur ListView ListView listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(adapter); /* * Setze Onclicklistner auf die ListView um projekte auswählen zu könnnen. */ listView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectedItem = position; // the choosen one // change bgcolor of the selected item for (int a = 0; a < parent.getChildCount(); a++) { parent.getChildAt(a).setBackgroundColor(Color.WHITE); } view.setBackgroundColor(Color.GRAY); openOptionsMenu(); } }); } /* * (non-Javadoc) * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu) * OptionsMenuStuff */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_project_view, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.addpj) { ListView listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(adapter); // show the add view -> No Activity just a "Formular" Layout to switch into setContentView(R.layout.additem); } else if (item.getItemId() == R.id.removepj) { if (selectedItem != -999) { Project project = adapter.getItem(selectedItem); selectedItem = -999; try { datasource.open(); datasource.removeProject(project); datasource.close(); } catch (Exception ex) { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG) .show(); }
  54. 54. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 54 // show the main view setContentView(R.layout.activity_project_view); showValuesFromDB(); } else { Toast.makeText(this, "Please choose a Item from List", Toast.LENGTH_LONG).show(); } } else if (item.getItemId() == R.id.showTodos) { //Intent nutzen um andere Activity zu starten und Werte zu übergen Intent i = new Intent(this, MyTodosOverview.class); Project project = adapter.getItem(selectedItem); i.putExtra("ProjectId", project.getId()); i.putExtra("ProjectName", project.getName()); startActivity(i); } else if (item.getItemId() == R.id.timemanager){ if (selectedItem != -999) { Intent i = new Intent(this, TimeManager.class); Project project = adapter.getItem(selectedItem); i.putExtra("ProjectId", project.getId()); i.putExtra("ProjectName", project.getName()); i.putExtra("workingtime", project.getTime()); startActivity(i); } else { Toast.makeText(this, "Please choose a Item from List", Toast.LENGTH_LONG).show(); } } return super.onOptionsItemSelected(item); } /* * Method of the Formular Layout additem.xml * Beschrieben im Layout als AddClick */ public void AddClick(View view) { if (view.getId() == R.id.button1) { EditText text = (EditText) findViewById(R.id.editText1); // values.add(text.getText().toString()); // put the new value in the database try { datasource.open(); datasource.creatProject(text.getText().toString()); datasource.close(); } catch (Exception ex) { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG).show(); } // show the main view setContentView(R.layout.activity_project_view); showValuesFromDB(); } } }
  55. 55. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 55 TimeManager.java package de.thorstenweiskopf.lpm; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import android.app.Activity; import android.app.DatePickerDialog; import android.app.TimePickerDialog; import android.app.DatePickerDialog.OnDateSetListener; import android.app.TimePickerDialog.OnTimeSetListener; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.DatePicker; import android.widget.TextView; import android.widget.TimePicker; import android.widget.Toast; import de.thorstenweiskopf.lpm.database.ProjectDatasource; import de.thorstenweiskopf.lpm.database.TimeTableDatasource; import de.thorstenweiskopf.lpm.dialogfragments.DatePickerFragment; import de.thorstenweiskopf.lpm.dialogfragments.TimePickerFragment; import de.thorstenweiskopf.lpm.model.TimeEntry; import de.thorstenweiskopf.lpm.R; import android.support.v4.app.FragmentActivity; //Fragmentactivity weil neu mit FragmentDialogen gearbeitet werdeb muss public class TimeManager extends FragmentActivity { //Buttons für Datum und Zeit private Button btnChangeTime, btnChangeDate; //Datum und Zeit Objekte //Kalender Objekt wird erzeugt und geändert vom Time und Datepicker bei Änderungen Calendar calendar = Calendar.getInstance(); final SimpleDateFormat date_format = new SimpleDateFormat("dd.MM.yyyy"); final SimpleDateFormat time_format = new SimpleDateFormat("HH:mm"); final SimpleDateFormat datetime_format = new SimpleDateFormat("dd.MM.yyyy HH:mm"); //Projektdaten private String projectname; private long projectid; private float workingtime_frompj; //DB Schnittstelle private TimeTableDatasource datasource; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_time_manager_view);
  56. 56. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 56 //get the datasourceobject needed datasource = new TimeTableDatasource(this); setTimeOnView(calendar); setDateOnView(calendar); addTimeandDateButtonListners(); } /* * (non-Javadoc) * @see android.support.v4.app.FragmentActivity#onStart() * Wird die App hier in den Hintergrund gelegt bleibt aber aktiv * und kommt wieder in den Vordergrund so wird diese Methode ausgeführt * Sie holt sich das aktuelle Projekt und Zeigt die Zeit an da Diese Daten mitlerweile * nicht mehr in der View gespeichert sind. //onStart() in onResume() geändert */ @Override protected void onResume() { super.onStart(); getProject(); showWorkingTime(); } /* * Hildmethode: Errechnet die Arbeitszeit des Projektes wenn möglich * und Schreibt sie in die Datenbank. In die ProjekteTabelle. * Wird nach jedem ein uns ausbuchen ausgeführt. */ private boolean CalcWorkingTime(){ //Get the bookings, show 0 if no bookings are available List<TimeEntry> entrys = new ArrayList<TimeEntry>(); long worktime =0; try { datasource.open(); entrys = datasource.getAllTimeEntrysFromProject(String.valueOf(projectid)); } catch (Exception ex) { Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG).show(); } if (entrys ==null | entrys.isEmpty()){ //Do NOTHING return false; } else { //Read the in and outs List <TimeEntry> in_entrys = new ArrayList<TimeEntry>(); List <TimeEntry> out_entrys = new ArrayList<TimeEntry>(); for (int i=0; i< entrys.size();i++ ){ if (entrys.get(i).getEntrytype() == 0){ in_entrys.add(entrys.get(i)); } else if (entrys.get(i).getEntrytype() == 1){ out_entrys.add(entrys.get(i)); } } //check if as many ins as outs if (in_entrys.size() == out_entrys.size()){ for (int i=0; i< in_entrys.size();i++ ){
  57. 57. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 57 long checkout = out_entrys.get(i).getDatetime() ; long checkin = in_entrys.get(i).getDatetime(); worktime += (checkout-checkin )/1000/60; //Store in DB ProjectDatasource pd = new ProjectDatasource(this); pd.open(); pd.updateTime(projectid, worktime); pd.close(); } return true; } else { if (in_entrys.size() > out_entrys.size()){ TimeEntry lastTimeEntry = in_entrys.get(in_entrys.size()-1); long time = lastTimeEntry.getDatetime(); Calendar c = Calendar.getInstance(); c.setTimeInMillis(time); Toast.makeText(this, "Last checkin (" +datetime_format.format(c.getTime())+") without checkout.", Toast.LENGTH_LONG).show(); return false; } else { TimeEntry lastTimeEntry = out_entrys.get(out_entrys.size()- 1); long time = lastTimeEntry.getDatetime(); Calendar c = Calendar.getInstance(); c.setTimeInMillis(time); Toast.makeText(this, "Last checkout (" +datetime_format.format(c.getTime()) +") without checkin.", Toast.LENGTH_LONG).show(); return false; } } } } /* * Hilfmethode holt Arbeitszeit aus der ProjekteDB und zeigt sie an. */ private void showWorkingTime() { String str_hours = "00"; String str_minutes = "00"; TextView tv = (TextView)findViewById(R.id.Text_ProjectTime); ProjectDatasource pd = new ProjectDatasource(this); pd.open(); workingtime_frompj = pd.getWorkingtime(projectid); pd.close(); int h = (int) workingtime_frompj/60; int minuten = (int)workingtime_frompj % 60; if (h < 10){ str_hours = "0"+h; } if (minuten < 10){ str_minutes = "0"+minuten; } tv.setText("Workingtime in hours: " +str_hours+":"+str_minutes); }
  58. 58. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 58 /* * Hilfsmethode: Setzt die Listner auf alle Buttons * und führt jeweilige Hilfsfunktion aus */ private void addTimeandDateButtonListners() { findViewById(R.id.button_date).setOnClickListener(new OnClickListener() { public void onClick(View v) { showDatePicker(); } }); findViewById(R.id.button_time).setOnClickListener(new OnClickListener() { public void onClick(View v) { showTimePicker(); } }); findViewById(R.id.button_checkin).setOnClickListener(new OnClickListener() { public void onClick(View v) { checkin(); } }); findViewById(R.id.button_checkout).setOnClickListener(new OnClickListener() { public void onClick(View v) { checkout(); } }); findViewById(R.id.button_hours).setOnClickListener(new OnClickListener() { public void onClick(View v) { justbookthetime(); } }); } /* * Hilfsmethode bucht eingestelle Zeit als Stunde und Minute * vom Calender Objetk */ public void justbookthetime(){ int hour = calendar.get(Calendar.HOUR); int minutes = calendar.get(Calendar.MINUTE); int time = hour*60+minutes; //Store in DB ProjectDatasource pd = new ProjectDatasource(this); pd.open(); long wtime= pd.getWorkingtime(projectid); wtime = time +wtime; pd.updateTime(projectid, wtime); pd.close(); Toast.makeText(this, "timebooking done", Toast.LENGTH_LONG).show(); showWorkingTime(); } /* * Hilfsmethode mach Einträge in die TimeTable */ public void checkin(){ long time = calendar.getTimeInMillis(); try {
  59. 59. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 59 datasource.open(); datasource.creatTimeEntry(time, Long.toString(projectid),0);//0 for in datasource.close(); Toast.makeText(this, "checkin done", Toast.LENGTH_LONG).show(); boolean newWorkingTime = CalcWorkingTime(); if (newWorkingTime){ showWorkingTime(); } } catch (Exception ex){ Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG) .show(); } } /* * Hilfsmethode macht Einträge in die TimeTable */ public void checkout(){ long time = calendar.getTimeInMillis(); try { datasource.open(); datasource.creatTimeEntry(time, Long.toString(projectid),1);//1 for out datasource.close(); Toast.makeText(this, "checkout done", Toast.LENGTH_LONG).show(); boolean newWorkingTime = CalcWorkingTime(); if (newWorkingTime){ showWorkingTime(); } } catch (Exception ex){ Toast.makeText(this, ex.toString(), Toast.LENGTH_LONG) .show(); } } /* * Hilfmethode öffnet DatePicker mit aktuellem Datum */ private void showDatePicker() { DatePickerFragment date = new DatePickerFragment(); /** * Set Up Current Date Into dialog */ Calendar calender = Calendar.getInstance(); Bundle args = new Bundle(); args.putInt("year", calender.get(Calendar.YEAR)); args.putInt("month", calender.get(Calendar.MONTH)); args.putInt("day", calender.get(Calendar.DAY_OF_MONTH)); date.setArguments(args); /** * setze die RückkehrMethode wenn Datum ausgewählt wurde */ date.setCallBack(ondate); date.show(getSupportFragmentManager(), "Date Picker"); } /* * Rückkehrmethode: Datum wurde ausgewählt vom Picker
  60. 60. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 60 * setze Neue Daten im Calender und Zeige es an */ public OnDateSetListener ondate = new OnDateSetListener() { public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { calendar.set(year, monthOfYear, dayOfMonth); setDateOnView(calendar); } }; /* * Helpermethod opens Timepicker and set current time */ private void showTimePicker() { TimePickerFragment timepicker = new TimePickerFragment(); /** * Set Up Current Date Into dialog */ Calendar calender = Calendar.getInstance(); Bundle args = new Bundle(); args.putInt("minute", calender.get(Calendar.MINUTE)); args.putInt("hour", calender.get(Calendar.HOUR_OF_DAY)); timepicker.setArguments(args); /** * Set Call back to capture selected date */ timepicker.setOnCallBack(ontime); timepicker.show(getSupportFragmentManager(), "Date Picker"); } /* * Helpermethod: Time was choosen from picker */ public OnTimeSetListener ontime = new OnTimeSetListener() { public void onTimeSet(TimePicker view, int hour, int minute) { calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minute); setTimeOnView(calendar); } }; /* * (non-Javadoc) * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu) * OptionsMenuStuff: Gibt es hier nicht! */ @Override public boolean onCreateOptionsMenu(Menu menu) { //getMenuInflater().inflate(R.menu.activity_time_manager, menu); return true; } /* * Hilfsmethode holt sich vom Intent die Werte * und Erzeugt das Projekt und Zeigt den Namen in View an */ public void getProject(){ //Lable anzeigen Bundle extras = getIntent().getExtras();
  61. 61. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 61 if (extras == null) { return; } // Get data via the key projectname = extras.getString("ProjectName"); projectid = extras.getLong("ProjectId"); workingtime_frompj = extras.getLong("workingtime"); if (projectname != null) { // Show projectname as lable TextView lable = (TextView) findViewById(R.id.Text_ProjectLable); lable.setText(projectname); } } /* * Hilfsfunktion zeigt Zeit im Button */ public void setTimeOnView(Calendar c){ Button time = (Button) findViewById(R.id.button_time); time.setText("Uhrzeit: "+time_format.format(c.getTime())); } /* * Hilfsfunktion zeigt Datum im Button */ public void setDateOnView(Calendar c){ Button date = (Button) findViewById(R.id.button_date); date.setText("Datum: "+date_format.format(c.getTime())); } }
  62. 62. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 62 MySQLiteHelper.java package de.thorstenweiskopf.lpm.database; import de.thorstenweiskopf.lpm.database.tables.ProjectTable; import de.thorstenweiskopf.lpm.database.tables.TimeTable; import de.thorstenweiskopf.lpm.database.tables.TodoTable; import android.annotation.TargetApi; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; @TargetApi(11) public class MySQLiteHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "LittleProjectManager.db"; private static final int DATABASE_VERSION= 1; /* * Datenbank wird erstellt wenn * sie noch nicht existiert mit diesem Namen */ @TargetApi(11) public MySQLiteHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } /* * (non-Javadoc) * @see android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase) * Wird automatisch aufgerufen wenn DB noch nicht existiert * Es Werden alle benötigten Tabellen erstellt */ @Override public void onCreate(SQLiteDatabase db) { ProjectTable.onCreate(db); TodoTable.onCreate(db); TimeTable.onCreate(db); } /* * (non-Javadoc) * @see android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int) * wird ausgeführt wen DB Version sich im Code ändert */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { TodoTable.onUpgrade(db, oldVersion, newVersion); } }
  63. 63. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 63 ProjectDatasource.java /* * Klasse ist das DAO (Database Access Object) * Erlaubt den Zugriff auf die Datenbank und bietet Methoden * für das Abholen und Schreiben von Daten. */ package de.thorstenweiskopf.lpm.database; import java.util.ArrayList; import java.util.List; import de.thorstenweiskopf.lpm.database.tables.ProjectTable; import de.thorstenweiskopf.lpm.database.tables.TodoTable; import de.thorstenweiskopf.lpm.model.Project; import de.thorstenweiskopf.lpm.model.ToDo; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; public class ProjectDatasource { private SQLiteDatabase db; private MySQLiteHelper dbhelper; private String[] allCollums = {ProjectTable.COLUMN_ID, ProjectTable.COLUM_NAME, ProjectTable.COLUM_WORKTIME}; public ProjectDatasource(Context context) { dbhelper = new MySQLiteHelper(context); } /* * Öffnet DB Verbindung */ public void open() throws SQLException { db = dbhelper.getWritableDatabase(); } /* * Schließt DB Verbindung */ public void close() { db.close(); } /* * Erstellt Projekt in der Datenbank * @param name Projektname * @return Project */ public Project creatProject(String name){ ContentValues values = new ContentValues();
  64. 64. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 64 values.put(ProjectTable.COLUM_NAME, name); values.put(ProjectTable.COLUM_WORKTIME, 0); long insertId = db.insert(ProjectTable.TABLE_PJ, null, values); Cursor cursor = db.query(ProjectTable.TABLE_PJ, allCollums, TodoTable.COLUMN_ID+" = " +insertId, null, null, null, null); cursor.moveToFirst(); return makeProjectFromCursor(cursor); } /* * Entfernt Proket aus der Datenbank * @param pj Projekt welches entfernt werden soll */ public void removeProject(Project pj){ long id = pj.getId(); System.out.println("Comment deleted with id: " + id); db.delete(ProjectTable.TABLE_PJ, ProjectTable.COLUMN_ID + " = " + id, null); } /* * Gibt Liste aller Projekte zurück * @return ArrayList<Project> */ public List<Project> getAllProjects(){ List<Project> projectlist = new ArrayList<Project>(); Cursor cursor = db.query(ProjectTable.TABLE_PJ, allCollums, null, null, null, null, null); cursor.moveToFirst(); if (cursor.getCount() == 0){ return projectlist; } while (cursor.isAfterLast() == false){ Project pj = makeProjectFromCursor(cursor); projectlist.add(pj); cursor.moveToNext(); } cursor.close(); return projectlist; } /* * Hilfmethode: Macht aus dem cursor(dbeintrag) ein neues Projekt * @param cursor: Db cursor * @return Project */ private Project makeProjectFromCursor(Cursor cursor) { Project pj = new Project(); pj.setId(cursor.getLong(0));
  65. 65. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 65 pj.setName(cursor.getString(1)); pj.setTime(cursor.getLong(2)); return pj; } /* * Trägt gesamte bisherige Arbeitszeit in die Tabelle ein * @param projectid: Id des Projektes * @param workingtime: arbeitszeit welche fürs Projekt in die DB soll */ public void updateTime(long projectid, long workingtime) { ContentValues updateTime = new ContentValues(); updateTime.put(ProjectTable.COLUM_WORKTIME, Long.toString(workingtime)); db.update(ProjectTable.TABLE_PJ, updateTime, ProjectTable.COLUMN_ID+"=?", new String[] {Long.toString(projectid)}); } /* * Gibt die Arbeitszeit zurück * @param projectid: Id des Projektes * @return Arbeitszeit */ public long getWorkingtime(long projectid) { Cursor cursor = db.query(ProjectTable.TABLE_PJ, new String[] {ProjectTable.COLUM_WORKTIME}, ProjectTable.COLUMN_ID+"=?", new String[]{Long.toString(projectid)}, null, null, null); cursor.moveToFirst(); return cursor.getLong(0); } }
  66. 66. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 66 TimeTableDatasource.java /* * Klasse ist das DAO (Database Access Object) * Erlaubt den Zugriff auf die Datenbank und bietet Methoden * für das Abholen und Schreiben von Daten. */ package de.thorstenweiskopf.lpm.database; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import de.thorstenweiskopf.lpm.database.tables.TimeTable; import de.thorstenweiskopf.lpm.model.TimeEntry; public class TimeTableDatasource { private SQLiteDatabase db; private MySQLiteHelper dbhelper; private String[] allCollums = {TimeTable.COLUMN_ID,TimeTable.COLUM_DATETIME, TimeTable.COLUM_PJ_ID, TimeTable.COLUM_ENTRYTYPE}; public TimeTableDatasource(Context context) { dbhelper = new MySQLiteHelper(context); } /* * Öffnet DB Verbindung */ public void open() throws SQLException { db = dbhelper.getWritableDatabase(); } /* * Schließt DB Verbindung */ public void close() { db.close(); } /* * Erstellt TimeEntry in der Datenbank * @param timeinms Zeit in Millisekunden * @param pjid Projektid des betreffenden Projektes * @param inOrOut 0 für einbuchen, 1 für ausbuchen * @return TimeEntry Objekt */ public TimeEntry creatTimeEntry(long timeinms, String pjid, int inOrOut){ ContentValues values = new ContentValues(); values.put(TimeTable.COLUM_DATETIME, timeinms);
  67. 67. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 67 values.put(TimeTable.COLUM_PJ_ID, pjid); values.put(TimeTable.COLUM_ENTRYTYPE, inOrOut); //in DB eintragen long insertId = db.insert(TimeTable.TABLE_TIMETABLE, null, values); //Eintrag holen Cursor cursor = db.query(TimeTable.TABLE_TIMETABLE, allCollums, TimeTable.COLUMN_ID+" = " +insertId, null, null, null, null); cursor.moveToFirst(); return makeTimeEntryFromCursor(cursor); } /* * Entfernt TimeEntry aus der Datenbank * @param te TimeEntry welches entfernt werden soll */ public void removeTimeEntry(TimeEntry te){ long id = te.getId(); System.out.println("Comment deleted with id: " + id); db.delete(TimeTable.TABLE_TIMETABLE, TimeTable.COLUMN_ID + " = " + id, null); } /* * Gibt Liste aller TimeEntry aus DB zurück * @return ArrayList<TimeEntry> */ public List<TimeEntry> getAllTimeEntrys(){ List<TimeEntry> timeentrys = new ArrayList<TimeEntry>(); Cursor cursor = db.query(TimeTable.TABLE_TIMETABLE, allCollums, null, null, null, null, null); cursor.moveToFirst(); if (cursor.getCount() == 0){ return timeentrys; } while (cursor.isAfterLast() == false){ TimeEntry entry = makeTimeEntryFromCursor(cursor); timeentrys.add(entry); cursor.moveToNext(); } cursor.close(); return timeentrys; } /* * Hilfmethode: Macht aus dem cursor(dbeintrag) ein neues TimeEntry * @param cursor: Db cursor * @return TimeEntry */ private TimeEntry makeTimeEntryFromCursor(Cursor cursor) { TimeEntry timeentry = new TimeEntry(); timeentry.setId(cursor.getLong(0)); timeentry.setDatetime(cursor.getLong(1));
  68. 68. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 68 timeentry.setPj_id(cursor.getLong(2)); timeentry.setEntrytype(cursor.getLong(3)); return timeentry; } /* * Gibt Liste aller TimeEntry aus DB abhängig vom Projekt zurück * @param projectid * @return ArrayList<TimeEntry> */ public List<TimeEntry> getAllTimeEntrysFromProject(String projectid) { List<TimeEntry> timeentrys = new ArrayList<TimeEntry>(); Cursor cursor = db.query(TimeTable.TABLE_TIMETABLE, allCollums, TimeTable.COLUM_PJ_ID +" = "+projectid, null, null, null, null); cursor.moveToFirst(); if (cursor.getCount() == 0){ return timeentrys; } while (cursor.isAfterLast() == false){ TimeEntry entry = makeTimeEntryFromCursor(cursor); timeentrys.add(entry); cursor.moveToNext(); } cursor.close(); return timeentrys; } }
  69. 69. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 69 TodosDatasource.java package de.thorstenweiskopf.lpm.database; import java.util.ArrayList; import java.util.List; import de.thorstenweiskopf.lpm.database.tables.TodoTable; import de.thorstenweiskopf.lpm.model.ToDo; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; public class TodosDatasource { private SQLiteDatabase db; private MySQLiteHelper dbhelper; private String[] allCollums = {TodoTable.COLUMN_ID,TodoTable.COLUM_TODO, TodoTable.COLUM_PJ_ID}; public TodosDatasource(Context context) { dbhelper = new MySQLiteHelper(context); } /* * Öffnet DB Verbindung */ public void open() throws SQLException { db = dbhelper.getWritableDatabase(); } /* * Schließt DB Verbindung */ public void close() { db.close(); } /* * Trägt ToDo in die Tabelle ein * @param projectid: Id des Projektes als Fremdschlüssel * @param todo: ToDo selbst als String * @return ToDo Objekt welches eingetragen wurde */ public ToDo creatTodo(String todo, String pjid){ ContentValues values = new ContentValues(); values.put(TodoTable.COLUM_TODO, todo); values.put(TodoTable.COLUM_PJ_ID, pjid); //in DB eintragen long insertId = db.insert(TodoTable.TABLE_TODO, null, values); //Eintrag holen Cursor cursor = db.query(TodoTable.TABLE_TODO, allCollums, TodoTable.COLUMN_ID+" = " +insertId, null, null, null, null); cursor.moveToFirst();
  70. 70. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 70 return makeTodoFromCursor(cursor); } /* * Entfernt ToDo aus der Datenbank * @param todo ToDo welches entfernt werden soll */ public void removeTodo(ToDo todo){ long id = todo.getId(); System.out.println("Comment deleted with id: " + id); db.delete(TodoTable.TABLE_TODO, TodoTable.COLUMN_ID + " = " + id, null); } /* * Gibt Liste aller ToDos zurück * @return ArrayList<ToDo> */ public List<ToDo> getAllTodos(){ List<ToDo> todolist = new ArrayList<ToDo>(); Cursor cursor = db.query(TodoTable.TABLE_TODO, allCollums, null, null, null, null, null); cursor.moveToFirst(); if (cursor.getCount() == 0){ return todolist; } while (cursor.isAfterLast() == false){ ToDo todo = makeTodoFromCursor(cursor); todolist.add(todo); cursor.moveToNext(); } cursor.close(); return todolist; } /* * Hilfmethode: Macht aus dem cursor(dbeintrag) ein neues ToDo * @param cursor: Db cursor * @return ToDo */ private ToDo makeTodoFromCursor(Cursor cursor) { ToDo todo = new ToDo(); todo.setId(cursor.getLong(0)); todo.setTodo(cursor.getString(1)); todo.setPj_id(cursor.getLong(2)); return todo; } /* * Gibt Liste aller ToDo aus DB abhängig vom Projekt zurück
  71. 71. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 71 * @param projectid * @return ArrayList<ToDo> */ public List<ToDo> getAllTodosFromProject(String projectid) { List<ToDo> todolist = new ArrayList<ToDo>(); Cursor cursor = db.query(TodoTable.TABLE_TODO, allCollums, TodoTable.COLUM_PJ_ID +" = "+projectid, null, null, null, null); cursor.moveToFirst(); if (cursor.getCount() == 0){ return todolist; } while (cursor.isAfterLast() == false){ ToDo todo = makeTodoFromCursor(cursor); todolist.add(todo); cursor.moveToNext(); } cursor.close(); return todolist; } }
  72. 72. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 72 ProjectTable.java /* * Klasse stellt die Tabelle myprojects dar * in der Datenbank gespeichert wird */ package de.thorstenweiskopf.lpm.database.tables; import de.thorstenweiskopf.lpm.database.MySQLiteHelper; import android.database.sqlite.SQLiteDatabase; import android.util.Log; public class ProjectTable { // Database table public static final String TABLE_PJ = "myprojects"; public static final String COLUMN_ID = "_id"; public static final String COLUM_NAME = "name"; public static final String COLUM_WORKTIME = "worktime"; //SQL CREATE Statement private static final String TABLE_CREATE_MYPROJECTS ="" +"create table " +TABLE_PJ +" ( " +COLUMN_ID+ " integer primary key autoincrement, " +COLUM_NAME +" text not null, " +COLUM_WORKTIME +" integer" +");"; /* * Tabelle erstellen */ public static void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_CREATE_MYPROJECTS); } /* * Tabelle Upgraden */ public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(MySQLiteHelper.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_PJ); onCreate(db); } }
  73. 73. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 73 TimeTable.java /* * Klasse stellt die Tabelle timetable dar * in der Datenbank gespeichert wird */ package de.thorstenweiskopf.lpm.database.tables; import android.database.sqlite.SQLiteDatabase; import android.util.Log; import de.thorstenweiskopf.lpm.database.MySQLiteHelper; public class TimeTable { // Database table public static final String TABLE_TIMETABLE = "timetable"; public static final String COLUMN_ID = "_id"; public static final String COLUM_DATETIME = "datetime"; public static final String COLUM_PJ_ID = "pj_id"; public static final String COLUM_ENTRYTYPE = "entrytype"; //SQL CREATE Statement private static final String TABLE_CREATE_TIMETABLE ="" +"create table " +TABLE_TIMETABLE +" ( " +COLUMN_ID+ " integer primary key autoincrement, " +COLUM_DATETIME +" integer not null, " +COLUM_PJ_ID + " integer, " +COLUM_ENTRYTYPE + " integer not null," + " FOREIGN KEY ("+COLUM_PJ_ID+") REFERENCES "+ProjectTable.TABLE_PJ+" ("+ProjectTable.COLUMN_ID+")" +");"; /* * Tabelle erstellen */ public static void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_CREATE_TIMETABLE); } /* * Tabelle Upgraden */ public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(MySQLiteHelper.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_TIMETABLE); onCreate(db); } }
  74. 74. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 74 TodoTable.java /* * Klasse stellt die Tabelle mytodos dar * in der Datenbank gespeichert wird */ package de.thorstenweiskopf.lpm.database.tables; import de.thorstenweiskopf.lpm.database.MySQLiteHelper; import android.annotation.TargetApi; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.util.Log; public class TodoTable { // Database table public static final String TABLE_TODO = "mytodos"; public static final String COLUMN_ID = "_id"; public static final String COLUM_TODO = "todo"; public static final String COLUM_PJ_ID = "pj_id"; //SQL CREATE Statement private static final String TABLE_CREATE_MYTODOS ="" +"create table " +TABLE_TODO +" ( " +COLUMN_ID+ " integer primary key autoincrement, " +COLUM_TODO +" text not null, " +COLUM_PJ_ID + " integer," + " FOREIGN KEY ("+COLUM_PJ_ID+") REFERENCES "+ProjectTable.TABLE_PJ+" ("+ProjectTable.COLUMN_ID+")" +");"; /* * Tabelle erstellen */ public static void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_CREATE_MYTODOS); } /* * Tabelle Upgraden */ public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(MySQLiteHelper.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO); onCreate(db); } }
  75. 75. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 75 DatePickerFragment.java /* * Klasse muss als sogenantes DatePickerFragment geschrieben werden * welche Ihrerseits bei der Erzeugung einen DatePickerDialog öffnet * Den Rest übernimmt dann Das Framework bzw. die Activity welches * diese Klasse mit Argumenten füttert und Ausführen lässt */ package de.thorstenweiskopf.lpm.dialogfragments; import android.app.DatePickerDialog; import android.app.DatePickerDialog.OnDateSetListener; import android.app.Dialog; import android.os.Bundle; import android.support.v4.app.DialogFragment; public class DatePickerFragment extends DialogFragment { //Klassenvariablen private int year, month, day; OnDateSetListener ondateSet; public DatePickerFragment() { } public void setCallBack(OnDateSetListener ondate) { ondateSet = ondate; } /* * (non-Javadoc) * * @see android.support.v4.app.Fragment#setArguments(android.os.Bundle) * Methode um Daten zu setzen */ @Override public void setArguments(Bundle args) { super.setArguments(args); year = args.getInt("year"); month = args.getInt("month"); day = args.getInt("day"); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new DatePickerDialog(getActivity(), ondateSet, year, month, day); } }
  76. 76. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 76 TimePickerFragment.java /* * Klasse muss als sogenantes TimePickerFragement geschrieben werden * welche Ihrerseits bei der Erzeugung einen TimePickerDialog öffnet * Den Rest übernimmt dann Das Framework bzw. die Activity welches * diese Klasse mit Argumenten füttert und Ausführen lässt */ package de.thorstenweiskopf.lpm.dialogfragments; import android.app.Dialog; import android.app.TimePickerDialog; import android.app.TimePickerDialog.OnTimeSetListener; import android.os.Bundle; import android.support.v4.app.DialogFragment; public class TimePickerFragment extends DialogFragment { //Klassen variablen private int hour, minute; OnTimeSetListener ontimeset; public TimePickerFragment() { } public void setOnCallBack (OnTimeSetListener ontime){ ontimeset = ontime; } /* * (non-Javadoc) * @see android.support.v4.app.Fragment#setArguments(android.os.Bundle) * Methode um Daten zu setzen */ @Override public void setArguments(Bundle args) { super.setArguments(args); hour = args.getInt("hour"); minute = args.getInt("minute"); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new TimePickerDialog(getActivity(), ontimeset, hour, minute, true); } }
  77. 77. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 77 TimeEntry.java /* * Klasse stellt ein TimeEntry dar wie es * in der Datenbank gespeichert wird */ package de.thorstenweiskopf.lpm.model; public class TimeEntry { private long datetime; private int entrytype; //0 in 1 out private long id; private long pj_id; public long getDatetime() { return datetime; } public void setDatetime(long datetime) { this.datetime = datetime; } public int getEntrytype() { return entrytype; } public void setEntrytype(long entrytype) { this.entrytype = (int) entrytype; } public long getId() { return id; } public void setId(long id) { this.id = id; } public long getPj_id() { return pj_id; } public void setPj_id(long pj_id) { this.pj_id = pj_id; } }
  78. 78. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 78 ToDo.java /* * Klasse stellt ein ToDo dar wie es * in der Datenbank gespeichert wird */ package de.thorstenweiskopf.lpm.model; public class ToDo { private String todo; private long id; private long pj_id; public String getTodo() { return todo; } public void setTodo(String todo) { this.todo = todo; } public long getId() { return id; } public void setId(long id) { this.id = id; } public long getPj_id() { return pj_id; } public void setPj_id(long pj_id) { this.pj_id = pj_id; } //Rückgabewert des Objektes für die Liste public String toString(){ return todo; } }
  79. 79. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 79 R.java /* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package de.thorstenweiskopf.lpm; public final class R { public static final class attr { } public static final class drawable { public static final int ic_action_search=0x7f020000; public static final int ic_launcher=0x7f020001; } public static final class id { public static final int Add=0x7f07000f; public static final int Remove=0x7f070010; public static final int Text_ProjectLable=0x7f070001; public static final int Text_ProjectTime=0x7f070002; public static final int addpj=0x7f07000b; public static final int button1=0x7f07000a; public static final int button_checkin=0x7f070005; public static final int button_checkout=0x7f070006; public static final int button_date=0x7f070003; public static final int button_hours=0x7f070007; public static final int button_time=0x7f070004; public static final int editText1=0x7f070009; public static final int listView1=0x7f070000; public static final int removepj=0x7f07000d; public static final int showTodos=0x7f07000c; public static final int timemanager=0x7f07000e; public static final int todo_lable=0x7f070008; } public static final class layout { public static final int activity_project_view=0x7f030000; public static final int activity_time_manager_view=0x7f030001; public static final int activity_todos_view=0x7f030002; public static final int additem=0x7f030003; } public static final class menu { public static final int activity_project_view=0x7f060000; public static final int activity_todos_view=0x7f060001; } public static final class string { public static final int Add=0x7f040002; public static final int Remove=0x7f040003; public static final int app_name=0x7f040000; public static final int menu_addpj=0x7f040008; public static final int menu_remove_pj=0x7f04000a; public static final int menu_settings=0x7f040007; public static final int menu_showtodos=0x7f040009; public static final int menu_timemanager=0x7f04000b; public static final int menu_timestats=0x7f04000c; public static final int time_checkinbutton=0x7f04000d; public static final int time_checkoutbutton=0x7f04000e;
  80. 80. 10. Januar 2013 APPLIKATIONSENTWICKLUNG FÜR ANDROID 80 public static final int time_hourbutton=0x7f04000f; public static final int title_activity_my_todo_add=0x7f040004; public static final int title_activity_my_todos_overview=0x7f040001; public static final int title_activity_project_view=0x7f040005; public static final int title_activity_time_manager=0x7f040006; } public static final class style { public static final int AppTheme=0x7f050000; } }

×