summaryrefslogtreecommitdiffstats
path: root/Android
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2014-03-02 12:08:46 +0100
committerJérémy Zurcher <jeremy@asynk.ch>2016-11-10 17:40:55 +0100
commitd1d4b77dccabb24d88cb3de78d6e9c374ddf5676 (patch)
tree213594b3435b002f2b92e99c6c833e82f360e236 /Android
parent36280db96fe3e135b64e85365b346d387b5dba18 (diff)
downloadcoursera-d1d4b77dccabb24d88cb3de78d6e9c374ddf5676.zip
coursera-d1d4b77dccabb24d88cb3de78d6e9c374ddf5676.tar.gz
Android : 05-UserInterface: add
Diffstat (limited to 'Android')
-rw-r--r--Android/05-UserInterface/Lab-UserInterface.pdfbin0 -> 1557884 bytes
-rw-r--r--Android/05-UserInterface/UILab/AndroidManifest.xml20
-rw-r--r--Android/05-UserInterface/UILab/ant.properties17
-rw-r--r--Android/05-UserInterface/UILab/build.xml92
-rw-r--r--Android/05-UserInterface/UILab/local.properties10
-rw-r--r--Android/05-UserInterface/UILab/proguard-project.txt20
-rw-r--r--Android/05-UserInterface/UILab/project.properties14
-rw-r--r--Android/05-UserInterface/UILab/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--Android/05-UserInterface/UILab/res/drawable-ldpi/ic_launcher.pngbin0 -> 2729 bytes
-rw-r--r--Android/05-UserInterface/UILab/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--Android/05-UserInterface/UILab/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--Android/05-UserInterface/UILab/res/layout/add_todo.xml181
-rw-r--r--Android/05-UserInterface/UILab/res/layout/footer_view.xml10
-rw-r--r--Android/05-UserInterface/UILab/res/layout/todo_item.xml73
-rw-r--r--Android/05-UserInterface/UILab/res/values/dimens.xml7
-rw-r--r--Android/05-UserInterface/UILab/res/values/strings.xml23
-rw-r--r--Android/05-UserInterface/UILab/src/course/labs/todomanager/AddToDoActivity.java258
-rw-r--r--Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoItem.java107
-rw-r--r--Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoListAdapter.java114
-rw-r--r--Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoManagerActivity.java185
-rw-r--r--Android/05-UserInterface/UILab/tests/AndroidManifest.xml21
-rw-r--r--Android/05-UserInterface/UILab/tests/ant.properties18
-rw-r--r--Android/05-UserInterface/UILab/tests/build.xml92
-rw-r--r--Android/05-UserInterface/UILab/tests/libs/robotium-solo-5.0.2-SNAPSHOT.jarbin0 -> 111472 bytes
-rw-r--r--Android/05-UserInterface/UILab/tests/local.properties10
-rw-r--r--Android/05-UserInterface/UILab/tests/proguard-project.txt20
-rw-r--r--Android/05-UserInterface/UILab/tests/project.properties14
-rw-r--r--Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestCancel.java95
-rw-r--r--Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestReset.java100
-rw-r--r--Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestSubmit.java120
30 files changed, 1621 insertions, 0 deletions
diff --git a/Android/05-UserInterface/Lab-UserInterface.pdf b/Android/05-UserInterface/Lab-UserInterface.pdf
new file mode 100644
index 0000000..57c5412
--- /dev/null
+++ b/Android/05-UserInterface/Lab-UserInterface.pdf
Binary files differ
diff --git a/Android/05-UserInterface/UILab/AndroidManifest.xml b/Android/05-UserInterface/UILab/AndroidManifest.xml
new file mode 100644
index 0000000..a4ea0d6
--- /dev/null
+++ b/Android/05-UserInterface/UILab/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="course.labs.todomanager"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity android:name="ToDoManagerActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".AddToDoActivity" >
+ </activity>
+ </application>
+</manifest>
diff --git a/Android/05-UserInterface/UILab/ant.properties b/Android/05-UserInterface/UILab/ant.properties
new file mode 100644
index 0000000..b0971e8
--- /dev/null
+++ b/Android/05-UserInterface/UILab/ant.properties
@@ -0,0 +1,17 @@
+# This file is used to override default values used by the Ant build system.
+#
+# This file must be checked into Version Control Systems, as it is
+# integral to the build system of your project.
+
+# This file is only used by the Ant script.
+
+# You can use this to override default values such as
+# 'source.dir' for the location of your java source folder and
+# 'out.dir' for the location of your output folder.
+
+# You can also use it define how the release builds are signed by declaring
+# the following properties:
+# 'key.store' for the location of your keystore and
+# 'key.alias' for the name of the key to use.
+# The password will be asked during the build when you use the 'release' target.
+
diff --git a/Android/05-UserInterface/UILab/build.xml b/Android/05-UserInterface/UILab/build.xml
new file mode 100644
index 0000000..48c44de
--- /dev/null
+++ b/Android/05-UserInterface/UILab/build.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="UILab" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ For other overridable properties, look at the beginning of the rules
+ files in the SDK, at tools/ant/build.xml
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="ant.properties" />
+
+ <!-- if sdk.dir was not set from one of the property file, then
+ get it from the ANDROID_HOME env var.
+ This must be done before we load project.properties since
+ the proguard config can use sdk.dir -->
+ <property environment="env" />
+ <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+ <isset property="env.ANDROID_HOME" />
+ </condition>
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+ unless="sdk.dir"
+ />
+
+ <!--
+ Import per project custom build rules if present at the root of the project.
+ This is the place to put custom intermediary targets such as:
+ -pre-build
+ -pre-compile
+ -post-compile (This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir})
+ -post-package
+ -post-build
+ -pre-clean
+ -->
+ <import file="custom_rules.xml" optional="true" />
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: 1 -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/Android/05-UserInterface/UILab/local.properties b/Android/05-UserInterface/UILab/local.properties
new file mode 100644
index 0000000..12a0114
--- /dev/null
+++ b/Android/05-UserInterface/UILab/local.properties
@@ -0,0 +1,10 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+
+# location of the SDK. This is only used by Ant
+# For customization when using a Version Control System, please read the
+# header note.
+sdk.dir=/opt/android-sdk
diff --git a/Android/05-UserInterface/UILab/proguard-project.txt b/Android/05-UserInterface/UILab/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/Android/05-UserInterface/UILab/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/Android/05-UserInterface/UILab/project.properties b/Android/05-UserInterface/UILab/project.properties
new file mode 100644
index 0000000..ce39f2d
--- /dev/null
+++ b/Android/05-UserInterface/UILab/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-18
diff --git a/Android/05-UserInterface/UILab/res/drawable-hdpi/ic_launcher.png b/Android/05-UserInterface/UILab/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/Android/05-UserInterface/UILab/res/drawable-ldpi/ic_launcher.png b/Android/05-UserInterface/UILab/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..9923872
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/Android/05-UserInterface/UILab/res/drawable-mdpi/ic_launcher.png b/Android/05-UserInterface/UILab/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/Android/05-UserInterface/UILab/res/drawable-xhdpi/ic_launcher.png b/Android/05-UserInterface/UILab/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/Android/05-UserInterface/UILab/res/layout/add_todo.xml b/Android/05-UserInterface/UILab/res/layout/add_todo.xml
new file mode 100644
index 0000000..095ecf2
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/layout/add_todo.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <!-- Title -->
+
+ <TextView
+ android:id="@+id/TitleLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/title_string"
+ android:textAppearance="?android:attr/textAppearanceLarge" >
+ </TextView>
+
+ <EditText
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/TitleLabel"
+ android:layout_marginTop="14dp"
+ android:ems="10"
+ android:hint="@string/enter_title_string"
+ android:inputType="textShortMessage">
+
+ <requestFocus />
+ </EditText>
+
+ <!-- Status -->
+
+ <TextView
+ android:id="@+id/status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/title"
+ android:layout_marginTop="25dp"
+ android:text="@string/status_string"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <RadioGroup
+ android:id="@+id/statusGroup"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@id/status"
+ android:orientation="horizontal"
+ android:layout_marginTop="12dp" >
+
+ <RadioButton
+ android:id="@+id/statusDone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done_string" />
+
+ <RadioButton
+ android:id="@+id/statusNotDone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/not_done_string" />
+ </RadioGroup>
+
+ <!-- Priority -->
+
+ <TextView
+ android:id="@+id/priority"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@id/statusGroup"
+ android:layout_marginTop="25dp"
+ android:text="@string/priority_string"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <RadioGroup
+ android:id="@+id/priorityGroup"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@id/priority"
+ android:orientation="horizontal"
+ android:layout_marginTop="12dp"
+ android:text="@string/priority_string" >
+
+ <RadioButton
+ android:id="@+id/lowPriority"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/priority_low_string" />
+
+ <RadioButton
+ android:id="@+id/medPriority"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/priority_medium_string" />
+
+ <RadioButton
+ android:id="@+id/highPriority"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/priority_high_string" />
+ </RadioGroup>
+
+ <!-- Time and Date -->
+
+ <TextView
+ android:id="@+id/time_and_date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@id/priorityGroup"
+ android:layout_marginTop="25dp"
+ android:text="@string/time_and_date_string"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/time_and_date"
+ android:layout_marginTop="12dp"
+ android:text="@string/no_date_set_string" />
+
+ <TextView
+ android:id="@+id/time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_below="@+id/time_and_date"
+ android:text="@string/no_time_set_string" />
+
+ <Button
+ android:id="@+id/date_picker_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@id/date"
+ android:text="@string/choose_date_string" />
+
+ <Button
+ android:id="@+id/time_picker_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_alignTop="@id/date_picker_button"
+ android:layout_below="@id/time"
+ android:text="@string/choose_time_string" />
+
+ <!-- Buttons -->
+
+ <Button
+ android:id="@+id/cancelButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_marginTop="25dp"
+ android:text="@string/cancel_string" />
+
+ <Button
+ android:id="@+id/resetButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_centerHorizontal="true"
+ android:text="@string/reset_string" />
+
+ <Button
+ android:id="@+id/submitButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:text="@string/submit_string" />
+
+</RelativeLayout>
diff --git a/Android/05-UserInterface/UILab/res/layout/footer_view.xml b/Android/05-UserInterface/UILab/res/layout/footer_view.xml
new file mode 100644
index 0000000..311856f
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/layout/footer_view.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/footerView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:text="@string/add_new_todo_item_string"
+ android:textSize="24sp" >
+
+</TextView> \ No newline at end of file
diff --git a/Android/05-UserInterface/UILab/res/layout/todo_item.xml b/Android/05-UserInterface/UILab/res/layout/todo_item.xml
new file mode 100644
index 0000000..44ef9fc
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/layout/todo_item.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/RelativeLayout1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/titleView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:textAppearance="?android:attr/textAppearanceLarge" >
+ </TextView>
+
+ <TextView
+ android:id="@+id/StatusLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/statusCheckBox"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginTop="17dp"
+ android:text="@string/done_string" >
+ </TextView>
+
+ <CheckBox
+ android:id="@+id/statusCheckBox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginTop="52dp"
+ android:layout_toRightOf="@+id/StatusLabel" >
+ </CheckBox>
+
+ <TextView
+ android:id="@+id/PriorityLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/statusCheckBox"
+ android:layout_alignTop="@+id/StatusLabel"
+ android:layout_toLeftOf="@+id/priorityView"
+ android:text="@string/priority_string" >
+ </TextView>
+
+ <TextView
+ android:id="@+id/priorityView"
+ android:layout_width="50dip"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/statusCheckBox"
+ android:layout_alignParentRight="true"
+ android:layout_alignTop="@+id/StatusLabel" >
+ </TextView>
+
+ <TextView
+ android:id="@+id/DateLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/statusCheckBox"
+ android:text="@string/date_string" >
+ </TextView>
+
+ <TextView
+ android:id="@+id/dateView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/DateLabel"
+ android:layout_toRightOf="@+id/DateLabel" >
+ </TextView>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/Android/05-UserInterface/UILab/res/values/dimens.xml b/Android/05-UserInterface/UILab/res/values/dimens.xml
new file mode 100644
index 0000000..2e0e2ae
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/Android/05-UserInterface/UILab/res/values/strings.xml b/Android/05-UserInterface/UILab/res/values/strings.xml
new file mode 100644
index 0000000..626fa58
--- /dev/null
+++ b/Android/05-UserInterface/UILab/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">UILabs</string>
+ <string name="done_string">Done:</string>
+ <string name="priority_string">Priority:</string>
+ <string name="date_string">Date:</string>
+ <string name="add_new_todo_item_string">Add New ToDo Item</string>
+ <string name="title_string">Title</string>
+ <string name="status_string">Status</string>
+ <string name="not_done_string">Not Done</string>
+ <string name="priority_low_string">Low</string>
+ <string name="priority_medium_string">Medium</string>
+ <string name="priority_high_string">High</string>
+ <string name="time_and_date_string">Time and Date</string>
+ <string name="no_date_set_string">0000-00-00</string>
+ <string name="no_time_set_string">00:00:00</string>
+ <string name="choose_date_string">Choose Date</string>
+ <string name="choose_time_string">Choose Time</string>
+ <string name="cancel_string">Cancel</string>
+ <string name="reset_string">Reset</string>
+ <string name="submit_string">Submit</string>
+ <string name="enter_title_string">Enter Title</string>
+</resources>
diff --git a/Android/05-UserInterface/UILab/src/course/labs/todomanager/AddToDoActivity.java b/Android/05-UserInterface/UILab/src/course/labs/todomanager/AddToDoActivity.java
new file mode 100644
index 0000000..6604871
--- /dev/null
+++ b/Android/05-UserInterface/UILab/src/course/labs/todomanager/AddToDoActivity.java
@@ -0,0 +1,258 @@
+package course.labs.todomanager;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import android.app.Activity;
+import android.app.DatePickerDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.TimePickerDialog;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.DatePicker;
+import android.widget.EditText;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+import android.widget.TimePicker;
+import course.labs.todomanager.ToDoItem.Priority;
+import course.labs.todomanager.ToDoItem.Status;
+
+public class AddToDoActivity extends Activity {
+
+ // 7 days in milliseconds - 7 * 24 * 60 * 60 * 1000
+ private static final int SEVEN_DAYS = 604800000;
+
+ private static final String TAG = "Lab-UserInterface";
+
+ private static String timeString;
+ private static String dateString;
+ private static TextView dateView;
+ private static TextView timeView;
+
+
+ private Date mDate;
+ private RadioGroup mPriorityRadioGroup;
+ private RadioGroup mStatusRadioGroup;
+ private EditText mTitleText;
+ private RadioButton mDefaultStatusButton;
+ private RadioButton mDefaultPriorityButton;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.add_todo);
+
+ mTitleText = (EditText) findViewById(R.id.title);
+ mDefaultStatusButton = (RadioButton) findViewById(R.id.statusNotDone);
+ mDefaultPriorityButton = (RadioButton) findViewById(R.id.medPriority);
+ mPriorityRadioGroup = (RadioGroup) findViewById(R.id.priorityGroup);
+ mStatusRadioGroup = (RadioGroup) findViewById(R.id.statusGroup);
+ dateView = (TextView) findViewById(R.id.date);
+ timeView = (TextView) findViewById(R.id.time);
+
+ // Set the default date and time
+ setDefaultDateTime();
+
+ // OnClickListener for the Date button, calls showDatePickerDialog() to show
+ // the Date dialog
+ final Button datePickerButton = (Button) findViewById(R.id.date_picker_button);
+ datePickerButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showDatePickerDialog();
+ }
+ });
+
+ // OnClickListener for the Time button, calls showTimePickerDialog() to show
+ // the Time Dialog
+ final Button timePickerButton = (Button) findViewById(R.id.time_picker_button);
+ timePickerButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showTimePickerDialog();
+ }
+ });
+
+ // OnClickListener for the Cancel Button
+ final Button cancelButton = (Button) findViewById(R.id.cancelButton);
+ cancelButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ log("Entered cancelButton.OnClickListener.onClick()");
+ //TODO - Implement onClick().
+ }
+ });
+
+ // OnClickListener for the Reset Button
+ final Button resetButton = (Button) findViewById(R.id.resetButton);
+ resetButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ log("Entered resetButton.OnClickListener.onClick()");
+ //TODO - Reset data fields to default values
+ }
+ });
+
+ // OnClickListener for the Submit Button
+ // Implement onClick().
+ final Button submitButton = (Button) findViewById(R.id.submitButton);
+ submitButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ log("Entered submitButton.OnClickListener.onClick()");
+
+ // Gather ToDoItem data
+
+ //TODO - Get Priority
+ Priority priority = null;
+
+ //TODO - Get Status
+ Status status = null;
+
+ //TODO - Title
+ String titleString = null;
+
+ // Date
+ String fullDate = dateString + " " + timeString;
+
+ // Package ToDoItem data into an Intent
+ Intent data = new Intent();
+ ToDoItem.packageIntent(data, titleString, priority, status, fullDate);
+ //TODO - return data Intent and finish
+ }
+ });
+ }
+
+ // Do not modify below here
+ // Use this method to set the default date and time
+ private void setDefaultDateTime() {
+
+ // Default is current time + 7 days
+ mDate = new Date();
+ mDate = new Date(mDate.getTime() + SEVEN_DAYS);
+
+ Calendar c = Calendar.getInstance();
+ c.setTime(mDate);
+
+ setDateString(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
+
+ dateView.setText(dateString);
+
+ setTimeString(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), c.get(Calendar.MILLISECOND));
+
+ timeView.setText(timeString);
+ }
+
+ private static void setDateString(int year, int monthOfYear, int dayOfMonth) {
+ // Increment monthOfYear for Calendar/Date -> Time Format setting
+ monthOfYear++;
+ String mon = "" + monthOfYear;
+ String day = "" + dayOfMonth;
+
+ if (monthOfYear < 10)
+ mon = "0" + monthOfYear;
+ if (dayOfMonth < 10)
+ day = "0" + dayOfMonth;
+
+ dateString = year + "-" + mon + "-" + day;
+ }
+
+ private static void setTimeString(int hourOfDay, int minute, int mili) {
+ String hour = "" + hourOfDay;
+ String min = "" + minute;
+
+ if (hourOfDay < 10)
+ hour = "0" + hourOfDay;
+ if (minute < 10)
+ min = "0" + minute;
+
+ timeString = hour + ":" + min + ":00";
+ }
+
+ private Priority getPriority() {
+
+ switch (mPriorityRadioGroup.getCheckedRadioButtonId()) {
+ case R.id.lowPriority:
+ return Priority.LOW;
+ case R.id.highPriority:
+ return Priority.HIGH;
+ default:
+ return Priority.MED;
+ }
+ }
+
+ private Status getStatus() {
+
+ switch (mStatusRadioGroup.getCheckedRadioButtonId()) {
+ case R.id.statusDone:
+ return Status.DONE;
+ default:
+ return Status.NOTDONE;
+ }
+ }
+
+ // DialogFragment used to pick a ToDoItem deadline date
+ public static class DatePickerFragment extends DialogFragment implements
+ DatePickerDialog.OnDateSetListener {
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Use the current date as the default date in the picker
+ final Calendar c = Calendar.getInstance();
+ int year = c.get(Calendar.YEAR);
+ int month = c.get(Calendar.MONTH);
+ int day = c.get(Calendar.DAY_OF_MONTH);
+ // Create a new instance of DatePickerDialog and return it
+ return new DatePickerDialog(getActivity(), this, year, month, day);
+ }
+
+ @Override
+ public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
+ setDateString(year, monthOfYear, dayOfMonth);
+ dateView.setText(dateString);
+ }
+ }
+
+ // DialogFragment used to pick a ToDoItem deadline time
+ public static class TimePickerFragment extends DialogFragment implements
+ TimePickerDialog.OnTimeSetListener {
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Use the current time as the default values for the picker
+ final Calendar c = Calendar.getInstance();
+ int hour = c.get(Calendar.HOUR_OF_DAY);
+ int minute = c.get(Calendar.MINUTE);
+ // Create a new instance of TimePickerDialog and return
+ return new TimePickerDialog(getActivity(), this, hour, minute, true);
+ }
+ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+ setTimeString(hourOfDay, minute, 0);
+ timeView.setText(timeString);
+ }
+ }
+
+ private void showDatePickerDialog() {
+ DialogFragment newFragment = new DatePickerFragment();
+ newFragment.show(getFragmentManager(), "datePicker");
+ }
+
+ private void showTimePickerDialog() {
+ DialogFragment newFragment = new TimePickerFragment();
+ newFragment.show(getFragmentManager(), "timePicker");
+ }
+
+ private void log(String msg) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ Log.i(TAG, msg);
+ }
+}
diff --git a/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoItem.java b/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoItem.java
new file mode 100644
index 0000000..7990eb7
--- /dev/null
+++ b/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoItem.java
@@ -0,0 +1,107 @@
+package course.labs.todomanager;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import android.content.Intent;
+
+// Do not modify
+
+public class ToDoItem {
+
+ public static final String ITEM_SEP = System.getProperty("line.separator");
+
+ public enum Priority {
+ LOW, MED, HIGH
+ };
+
+ public enum Status {
+ NOTDONE, DONE
+ };
+
+ public final static String TITLE = "title";
+ public final static String PRIORITY = "priority";
+ public final static String STATUS = "status";
+ public final static String DATE = "date";
+ public final static String FILENAME = "filename";
+
+ public final static SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
+
+ private String mTitle = new String();
+ private Priority mPriority = Priority.LOW;
+ private Status mStatus = Status.NOTDONE;
+ private Date mDate = new Date();
+
+ ToDoItem(String title, Priority priority, Status status, Date date) {
+ this.mTitle = title;
+ this.mPriority = priority;
+ this.mStatus = status;
+ this.mDate = date;
+ }
+
+ // Create a new ToDoItem from data packaged in an Intent
+ ToDoItem(Intent intent) {
+ mTitle = intent.getStringExtra(ToDoItem.TITLE);
+ mPriority = Priority.valueOf(intent.getStringExtra(ToDoItem.PRIORITY));
+ mStatus = Status.valueOf(intent.getStringExtra(ToDoItem.STATUS));
+ try {
+ mDate = ToDoItem.FORMAT.parse(intent.getStringExtra(ToDoItem.DATE));
+ } catch (ParseException e) {
+ mDate = new Date();
+ }
+ }
+
+ public String getTitle() {
+ return mTitle;
+ }
+
+ public void setTitle(String title) {
+ mTitle = title;
+ }
+
+ public Priority getPriority() {
+ return mPriority;
+ }
+
+ public void setPriority(Priority priority) {
+ mPriority = priority;
+ }
+
+ public Status getStatus() {
+ return mStatus;
+ }
+
+ public void setStatus(Status status) {
+ mStatus = status;
+ }
+
+ public Date getDate() {
+ return mDate;
+ }
+
+ public void setDate(Date date) {
+ mDate = date;
+ }
+
+ // Take a set of String data values and
+ // package them for transport in an Intent
+ public static void packageIntent(Intent intent, String title, Priority priority, Status status, String date) {
+
+ intent.putExtra(ToDoItem.TITLE, title);
+ intent.putExtra(ToDoItem.PRIORITY, priority.toString());
+ intent.putExtra(ToDoItem.STATUS, status.toString());
+ intent.putExtra(ToDoItem.DATE, date);
+ }
+
+ public String toString() {
+ return mTitle + ITEM_SEP + mPriority + ITEM_SEP + mStatus + ITEM_SEP + FORMAT.format(mDate);
+ }
+
+ public String toLog() {
+ return "Title:" + mTitle + ITEM_SEP + "Priority:" + mPriority
+ + ITEM_SEP + "Status:" + mStatus + ITEM_SEP + "Date:"
+ + FORMAT.format(mDate);
+ }
+}
diff --git a/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoListAdapter.java b/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoListAdapter.java
new file mode 100644
index 0000000..5f16ac8
--- /dev/null
+++ b/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoListAdapter.java
@@ -0,0 +1,114 @@
+package course.labs.todomanager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import course.labs.todomanager.ToDoItem.Status;
+
+public class ToDoListAdapter extends BaseAdapter {
+
+ // List of ToDoItems
+ private final List<ToDoItem> mItems = new ArrayList<ToDoItem>();
+
+ private final Context mContext;
+
+ private static final String TAG = "Lab-UserInterface";
+
+ public ToDoListAdapter(Context context) {
+ mContext = context;
+ }
+
+ // Add a ToDoItem to the adapter
+ // Notify observers that the data set has changed
+ public void add(ToDoItem item) {
+ mItems.add(item);
+ notifyDataSetChanged();
+ }
+
+ // Clears the list adapter of all items.
+ public void clear(){
+ mItems.clear();
+ notifyDataSetChanged();
+ }
+
+ // Returns the number of ToDoItems
+ @Override
+ public int getCount() {
+ return mItems.size();
+ }
+
+ // Retrieve the number of ToDoItems
+ @Override
+ public Object getItem(int pos) {
+ return mItems.get(pos);
+ }
+
+ // Get the ID for the ToDoItem
+ // In this case it's just the position
+ @Override
+ public long getItemId(int pos) {
+ return pos;
+ }
+
+ //Create a View to display the ToDoItem
+ // at specified position in mItems
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ //TODO - Get the current ToDoItem
+ final ToDoItem toDoItem = null;
+
+ //TODO - Inflate the View for this ToDoItem
+ // from todo_item.xml.
+ RelativeLayout itemLayout = null;
+
+ //TODO - Fill in specific ToDoItem data
+ // Remember that the data that goes in this View
+ // corresponds to the user interface elements defined
+ // in the layout file
+
+ //TODO - Display Title in TextView
+ final TextView titleView = null;
+
+ // TODO - Set up Status CheckBox
+ final CheckBox statusView = null;
+
+ statusView.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ log("Entered onCheckedChanged()");
+ // TODO - Set up and implement an OnCheckedChangeListener, which
+ // is called when the user toggles the status checkbox
+ }
+ });
+
+ //TODO - Display Priority in a TextView
+ final TextView priorityView = null;
+
+ // TODO - Display Time and Date.
+ // Hint - use ToDoItem.FORMAT.format(toDoItem.getDate()) to get date and time String
+ final TextView dateView = null;
+
+ // Return the View you just created
+ return itemLayout;
+ }
+
+ private void log(String msg) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ Log.i(TAG, msg);
+ }
+}
diff --git a/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoManagerActivity.java b/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoManagerActivity.java
new file mode 100644
index 0000000..fe8d9eb
--- /dev/null
+++ b/Android/05-UserInterface/UILab/src/course/labs/todomanager/ToDoManagerActivity.java
@@ -0,0 +1,185 @@
+package course.labs.todomanager;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.text.ParseException;
+import java.util.Date;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+import course.labs.todomanager.ToDoItem.Priority;
+import course.labs.todomanager.ToDoItem.Status;
+
+public class ToDoManagerActivity extends ListActivity {
+
+ // Add a ToDoItem Request Code
+ private static final int ADD_TODO_ITEM_REQUEST = 0;
+
+ private static final String FILE_NAME = "TodoManagerActivityData.txt";
+ private static final String TAG = "Lab-UserInterface";
+
+ // IDs for menu items
+ private static final int MENU_DELETE = Menu.FIRST;
+ private static final int MENU_DUMP = Menu.FIRST + 1;
+
+ ToDoListAdapter mAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create a new TodoListAdapter for this ListActivity's ListView
+ mAdapter = new ToDoListAdapter(getApplicationContext());
+
+ // Put divider between ToDoItems and FooterView
+ getListView().setFooterDividersEnabled(true);
+
+ //TODO - Inflate footerView for footer_view.xml file
+ TextView footerView = null;
+ //TODO - Add footerView to ListView
+
+ footerView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ log("Entered footerView.OnClickListener.onClick()");
+ //TODO - Attach Listener to FooterView. Implement onClick().
+ }
+ });
+
+ //TODO - Attach the adapter to this ListActivity's ListView
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ log("Entered onActivityResult()");
+
+ // TODO - Check result code and request code.
+ // If user submitted a new ToDoItem
+ // Create a new ToDoItem from the data Intent
+ // and then add it to the adapter
+ }
+
+ // Do not modify below here
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Load saved ToDoItems, if necessary
+ if (mAdapter.getCount() == 0)
+ loadItems();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // Save ToDoItems
+ saveItems();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ menu.add(Menu.NONE, MENU_DELETE, Menu.NONE, "Delete all");
+ menu.add(Menu.NONE, MENU_DUMP, Menu.NONE, "Dump to log");
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_DELETE:
+ mAdapter.clear();
+ return true;
+ case MENU_DUMP:
+ dump();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void dump() {
+ for (int i = 0; i < mAdapter.getCount(); i++) {
+ String data = ((ToDoItem) mAdapter.getItem(i)).toLog();
+ log("Item " + i + ": " + data.replace(ToDoItem.ITEM_SEP, ","));
+ }
+ }
+
+ // Load stored ToDoItems
+ private void loadItems() {
+ BufferedReader reader = null;
+ try {
+ FileInputStream fis = openFileInput(FILE_NAME);
+ reader = new BufferedReader(new InputStreamReader(fis));
+
+ String title = null;
+ String priority = null;
+ String status = null;
+ Date date = null;
+
+ while (null != (title = reader.readLine())) {
+ priority = reader.readLine();
+ status = reader.readLine();
+ date = ToDoItem.FORMAT.parse(reader.readLine());
+ mAdapter.add(new ToDoItem(title, Priority.valueOf(priority),
+ Status.valueOf(status), date));
+ }
+
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ParseException e) {
+ e.printStackTrace();
+ } finally {
+ if (null != reader) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ // Save ToDoItems to file
+ private void saveItems() {
+ PrintWriter writer = null;
+ try {
+ FileOutputStream fos = openFileOutput(FILE_NAME, MODE_PRIVATE);
+ writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter( fos)));
+ for (int idx = 0; idx < mAdapter.getCount(); idx++) {
+ writer.println(mAdapter.getItem(idx));
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (null != writer) {
+ writer.close();
+ }
+ }
+ }
+
+ private void log(String msg) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ Log.i(TAG, msg);
+ }
+}
diff --git a/Android/05-UserInterface/UILab/tests/AndroidManifest.xml b/Android/05-UserInterface/UILab/tests/AndroidManifest.xml
new file mode 100644
index 0000000..5844f05
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="course.labs.todomanager.tests"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <!--
+ This declares that this application uses the instrumentation test runner targeting
+ the package of course.labs.todomanager. To run the tests use the command:
+ "adb shell am instrument -w course.labs.todomanager.tests/android.test.InstrumentationTestRunner"
+ -->
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="course.labs.todomanager"
+ android:label="Tests for course.labs.todomanager"/>
+</manifest>
diff --git a/Android/05-UserInterface/UILab/tests/ant.properties b/Android/05-UserInterface/UILab/tests/ant.properties
new file mode 100644
index 0000000..1624402
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/ant.properties
@@ -0,0 +1,18 @@
+# This file is used to override default values used by the Ant build system.
+#
+# This file must be checked into Version Control Systems, as it is
+# integral to the build system of your project.
+
+# This file is only used by the Ant script.
+
+# You can use this to override default values such as
+# 'source.dir' for the location of your java source folder and
+# 'out.dir' for the location of your output folder.
+
+# You can also use it define how the release builds are signed by declaring
+# the following properties:
+# 'key.store' for the location of your keystore and
+# 'key.alias' for the name of the key to use.
+# The password will be asked during the build when you use the 'release' target.
+
+tested.project.dir=..
diff --git a/Android/05-UserInterface/UILab/tests/build.xml b/Android/05-UserInterface/UILab/tests/build.xml
new file mode 100644
index 0000000..b03f208
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/build.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="UILabTest" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ For other overridable properties, look at the beginning of the rules
+ files in the SDK, at tools/ant/build.xml
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="ant.properties" />
+
+ <!-- if sdk.dir was not set from one of the property file, then
+ get it from the ANDROID_HOME env var.
+ This must be done before we load project.properties since
+ the proguard config can use sdk.dir -->
+ <property environment="env" />
+ <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+ <isset property="env.ANDROID_HOME" />
+ </condition>
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+ unless="sdk.dir"
+ />
+
+ <!--
+ Import per project custom build rules if present at the root of the project.
+ This is the place to put custom intermediary targets such as:
+ -pre-build
+ -pre-compile
+ -post-compile (This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir})
+ -post-package
+ -post-build
+ -pre-clean
+ -->
+ <import file="custom_rules.xml" optional="true" />
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: 1 -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/Android/05-UserInterface/UILab/tests/libs/robotium-solo-5.0.2-SNAPSHOT.jar b/Android/05-UserInterface/UILab/tests/libs/robotium-solo-5.0.2-SNAPSHOT.jar
new file mode 100644
index 0000000..1df1903
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/libs/robotium-solo-5.0.2-SNAPSHOT.jar
Binary files differ
diff --git a/Android/05-UserInterface/UILab/tests/local.properties b/Android/05-UserInterface/UILab/tests/local.properties
new file mode 100644
index 0000000..12a0114
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/local.properties
@@ -0,0 +1,10 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+
+# location of the SDK. This is only used by Ant
+# For customization when using a Version Control System, please read the
+# header note.
+sdk.dir=/opt/android-sdk
diff --git a/Android/05-UserInterface/UILab/tests/proguard-project.txt b/Android/05-UserInterface/UILab/tests/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/Android/05-UserInterface/UILab/tests/project.properties b/Android/05-UserInterface/UILab/tests/project.properties
new file mode 100644
index 0000000..ce39f2d
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-18
diff --git a/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestCancel.java b/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestCancel.java
new file mode 100644
index 0000000..ab9d3d9
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestCancel.java
@@ -0,0 +1,95 @@
+package course.labs.todomanager.tests;
+
+import course.labs.todomanager.ToDoManagerActivity;
+import com.robotium.solo.*;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class TestCancel extends
+ActivityInstrumentationTestCase2<ToDoManagerActivity> {
+ private Solo solo;
+
+ public TestCancel() {
+ super(ToDoManagerActivity.class);
+ }
+
+ public void setUp() throws Exception {
+ solo = new Solo(getInstrumentation());
+ getActivity();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ solo.finishOpenedActivities();
+ }
+
+ public void testRun() {
+
+ int timeout = 10;
+
+ // Wait for activity: 'course.labs.todomanager.ToDoManagerActivity'
+ assertTrue(
+ "'course.labs.todomanager.ToDoManagerActivity' not found",
+ solo.waitForActivity(
+ course.labs.todomanager.ToDoManagerActivity.class, 2000));
+
+ // Click on action bar item
+ solo.clickOnActionBarItem(0x1);
+
+ // Click on Add New ToDo Item
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.footerView));
+
+ // Wait for activity: 'course.labs.todomanager.AddToDoActivity'
+ assertTrue(
+ "course.labs.todomanager.AddToDoActivity is not found!",
+ solo.waitForActivity(course.labs.todomanager.AddToDoActivity.class));
+
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+ // Enter the text: 't3'
+ solo.clearEditText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title));
+ solo.enterText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title), "t3");
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+ // Click on Done:
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.statusDone));
+ // Click on High
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.highPriority));
+
+ // Click on Cancel
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.cancelButton));
+
+ // Click on Add New ToDo Item
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.footerView));
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+ // Enter the text: 't4'
+ solo.clearEditText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title));
+ solo.enterText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title), "t4");
+
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+ // Click on Done:
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.statusDone));
+ // Click on Low
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.lowPriority));
+
+ // Click on Submit
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.submitButton));
+
+ // Wait for activity: 'course.labs.todomanager.ToDoManagerActivity'
+ assertTrue(
+ "course.labs.todomanager.ToDoManagerActivity is not found!",
+ solo.waitForActivity(course.labs.todomanager.ToDoManagerActivity.class));
+
+ assertFalse("'A ToDoItem with title, t3', was found", solo.searchText("t3"));
+
+ // Click on action bar item to dump items to log
+ solo.clickOnActionBarItem(0x2);
+
+ assertTrue("Menu didn't close", solo.waitForDialogToClose());
+
+ // Wait for Log Message 'Title:t4,Priority:LOW,Status:NOT DONE'
+ assertTrue("Log message 'Title:t4,Priority:LOW,Status:NOT DONE' not found",
+ solo.waitForLogMessage("Title:t4,Priority:LOW,Status:DONE",timeout));
+ }
+}
diff --git a/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestReset.java b/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestReset.java
new file mode 100644
index 0000000..41f62f3
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestReset.java
@@ -0,0 +1,100 @@
+package course.labs.todomanager.tests;
+
+import course.labs.todomanager.ToDoManagerActivity;
+import com.robotium.solo.*;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class TestReset extends
+ActivityInstrumentationTestCase2<ToDoManagerActivity> {
+ private Solo solo;
+
+ public TestReset() {
+ super(ToDoManagerActivity.class);
+ }
+
+ public void setUp() throws Exception {
+ solo = new Solo(getInstrumentation());
+ getActivity();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ solo.finishOpenedActivities();
+ }
+
+ public void testRun() {
+
+ int timeout = 10;
+
+ // Wait for activity: 'course.labs.todomanager.ToDoManagerActivity'
+ assertTrue(
+ "'course.labs.todomanager.ToDoManagerActivity' not found.",
+ solo.waitForActivity(
+ course.labs.todomanager.ToDoManagerActivity.class, 2000));
+
+ // Click on action bar item
+ solo.clickOnActionBarItem(0x1);
+
+ // Click on Add New ToDo Item
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.footerView));
+
+ // Wait for activity: 'course.labs.todomanager.AddToDoActivity'
+ assertTrue(
+ "course.labs.todomanager.AddToDoActivity is not found!",
+ solo.waitForActivity(course.labs.todomanager.AddToDoActivity.class));
+
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+
+ // Enter the text: 't2'
+ solo.clearEditText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title));
+ solo.enterText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title), "t2");
+
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+ // Click on Done:
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.statusDone));
+
+ // Click on Reset
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.resetButton));
+
+ // Enter the text: 'Empty Text View'
+ solo.clearEditText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title));
+ solo.enterText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title), "");
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+
+ // Enter the text: 't3'
+ solo.clearEditText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title));
+ solo.enterText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title), "t3");
+
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+ // Click on High
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.highPriority));
+
+ // Click on Submit
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.submitButton));
+
+ // Click on Empty Text View
+ assertFalse(solo.isCheckBoxChecked(0));
+
+ // Change status to DONE
+ solo.clickOnCheckBox(0);
+
+ // Wait for activity: 'course.labs.todomanager.ToDoManagerActivity'
+ assertTrue(
+ "course.labs.todomanager.ToDoManagerActivity is not found!",
+ solo.waitForActivity(
+ course.labs.todomanager.ToDoManagerActivity.class, 2000));
+
+ // Click on action bar item to dump items to log
+ solo.clickOnActionBarItem(0x2);
+
+ assertTrue("Menu didn't close", solo.waitForDialogToClose());
+
+ // Wait for Log Message 'Item 0: Title:t3,Priority:HIGH,Status:DONE'
+ assertTrue("Log message: 'Title:t3,Priority:HIGH,Status:DONE' not found",
+ solo.waitForLogMessage("Title:t3,Priority:HIGH,Status:DONE", timeout));
+ }
+}
diff --git a/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestSubmit.java b/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestSubmit.java
new file mode 100644
index 0000000..4ffe078
--- /dev/null
+++ b/Android/05-UserInterface/UILab/tests/src/course/labs/todomanager/TestSubmit.java
@@ -0,0 +1,120 @@
+package course.labs.todomanager.tests;
+
+import course.labs.todomanager.ToDoManagerActivity;
+import com.robotium.solo.*;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class TestSubmit extends
+ActivityInstrumentationTestCase2<ToDoManagerActivity> {
+ private Solo solo;
+
+ public TestSubmit() {
+ super(ToDoManagerActivity.class);
+ }
+
+ public void setUp() throws Exception {
+ solo = new Solo(getInstrumentation());
+ getActivity();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ solo.finishOpenedActivities();
+ }
+
+ public void testRun() {
+
+ int timeout = 10;
+
+ // Wait for activity: 'course.labs.todomanager.ToDoManagerActivity'
+ assertTrue(
+ "course.labs.todomanager.ToDoManagerActivity is not found!",
+ solo.waitForActivity(
+ course.labs.todomanager.ToDoManagerActivity.class, 2000));
+
+ // Click on action bar item to delete all items
+ solo.clickOnActionBarItem(0x1);
+
+ // Click on Add New ToDo Item
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.footerView));
+
+ // Wait for activity: 'course.labs.todomanager.AddToDoActivity'
+ assertTrue(
+ "course.labs.todomanager.AddToDoActivity is not found!",
+ solo.waitForActivity(course.labs.todomanager.AddToDoActivity.class));
+
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+
+ // Enter the text: 't1'
+ solo.clearEditText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title));
+ solo.enterText((android.widget.EditText) solo.getView(course.labs.todomanager.R.id.title), "t1");
+
+ // Hide the soft keyboard
+ solo.hideSoftKeyboard();
+
+ // Click on Done:
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.statusDone));
+ // Click on Low
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.lowPriority));
+ // Click on Choose Date
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.date_picker_button));
+
+ // Wait for dialog
+ solo.waitForDialogToOpen(10000);
+ // Enter the text: 'Feb'
+ solo.clearEditText((android.widget.EditText) solo.getView("numberpicker_input"));
+ solo.enterText((android.widget.EditText) solo.getView("numberpicker_input"),"Feb");
+ // Enter the text: '28'
+ solo.clearEditText((android.widget.EditText) solo.getView("numberpicker_input", 1));
+ solo.enterText((android.widget.EditText) solo.getView("numberpicker_input", 1),"28");
+ // Enter the text: '2014'
+ solo.clearEditText((android.widget.EditText) solo.getView("numberpicker_input",2));
+ solo.enterText((android.widget.EditText) solo.getView("numberpicker_input", 2),"2014");
+
+ // Really set the date
+ solo.setDatePicker(0, 2014, 1, 28);
+
+ // Click on Done
+ solo.clickOnView(solo.getView(android.R.id.button1));
+
+ // Click on Choose Time
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.time_picker_button));
+ // Wait for dialog
+ solo.waitForDialogToOpen(10000);
+ // Enter the text: '9'
+ solo.clearEditText((android.widget.EditText) solo.getView("numberpicker_input"));
+ solo.enterText((android.widget.EditText) solo.getView("numberpicker_input"),"9");
+ // Enter the text: '19'
+ solo.clearEditText((android.widget.EditText) solo.getView("numberpicker_input", 1));
+ solo.enterText((android.widget.EditText) solo.getView("numberpicker_input", 1),"19");
+
+ // Really set the time
+ solo.setTimePicker(0, 9, 19);
+
+ // Click on Done
+ solo.clickOnView(solo.getView(android.R.id.button1));
+
+ // Click on Submit
+ solo.clickOnView(solo.getView(course.labs.todomanager.R.id.submitButton));
+
+ // Wait for activity: 'course.labs.todomanager.ToDoManagerActivity'
+ assertTrue(
+ "course.labs.todomanager.ToDoManagerActivity is not found!",
+ solo.waitForActivity(course.labs.todomanager.ToDoManagerActivity.class, 2000));
+
+ // Click on action bar item to dump items to log
+ solo.clickOnActionBarItem(0x2);
+
+ assertTrue("Menu didn't close", solo.waitForDialogToClose());
+
+
+ // Wait for Log Message 'Item 0:
+ // Title:t1,Priority:LOW,Status:DONE,Date:2014-02-28 09:19:00'
+ assertTrue(
+ "Log message: 'Title:t1,Priority:LOW,Status:DONE,Date:2014-02-28 09:19:00' not found",
+ solo.waitForLogMessage(
+ "Title:t1,Priority:LOW,Status:DONE,Date:2014-02-28 09:19:00",
+ timeout));
+ }
+}