diff --git a/Main/AndroidManifest.xml b/Main/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0f91d70937c7c7d5b3804a5560f55d5b956f661f
--- /dev/null
+++ b/Main/AndroidManifest.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="gr.grnet.academicid.merchant"
+          android:versionCode="1"
+          android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="8"
+              android:targetSdkVersion="16"/>
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.CAMERA"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+
+    <uses-feature android:name="android.hardware.camera" android:required="false"/>
+    <uses-feature android:name="android.hardware.camera.autofocus"/>
+
+
+    <application android:label="@string/app_name"
+                 android:name=".MerchantApplication"
+                 android:icon="@drawable/ic_launcher"
+                 android:allowBackup="true">
+        <activity android:name=".MainActivity"
+                  android:label="@string/app_name"
+                  android:screenOrientation="portrait"
+                  android:configChanges="keyboardHidden|orientation|screenSize"
+                  android:windowSoftInputMode="stateHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity android:name=".OfferList"
+                  android:screenOrientation="portrait"
+                  android:configChanges="keyboardHidden|orientation|screenSize"/>
+        <activity android:name=".SingleOffer"
+                  android:screenOrientation="portrait"
+                  android:configChanges="keyboardHidden|orientation|screenSize"
+                  android:windowSoftInputMode="stateHidden"/>
+        <activity android:name=".ScanQR"
+                  android:screenOrientation="portrait"
+                  android:configChanges="keyboardHidden|orientation|screenSize"/>
+        <activity android:name="com.dm.zbar.android.scanner.ZBarScannerActivity"
+                  android:screenOrientation="portrait"
+                  android:configChanges="keyboardHidden|orientation|screenSize"/>
+        <activity android:name=".Preferences"
+                  android:screenOrientation="portrait"
+                  android:configChanges="keyboardHidden|orientation|screenSize"/>
+        <activity android:name=".ChangePassword"
+                  android:screenOrientation="portrait"
+                  android:configChanges="keyboardHidden|orientation|screenSize"
+                  android:windowSoftInputMode="stateHidden"/>
+    </application>
+</manifest> 
diff --git a/Main/gen/gr/grnet/academicid/merchant/BuildConfig.java b/Main/gen/gr/grnet/academicid/merchant/BuildConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f261a820e98b2166f62a308db3023afc4cb8890
--- /dev/null
+++ b/Main/gen/gr/grnet/academicid/merchant/BuildConfig.java
@@ -0,0 +1,8 @@
+/*___Generated_by_IDEA___*/
+
+package gr.grnet.academicid.merchant;
+
+/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
+public final class BuildConfig {
+  public final static boolean DEBUG = Boolean.parseBoolean(null);
+}
\ No newline at end of file
diff --git a/Main/gen/gr/grnet/academicid/merchant/Manifest.java b/Main/gen/gr/grnet/academicid/merchant/Manifest.java
new file mode 100644
index 0000000000000000000000000000000000000000..de6dd25d0cf1e21e99bc66ab129ab9416429626a
--- /dev/null
+++ b/Main/gen/gr/grnet/academicid/merchant/Manifest.java
@@ -0,0 +1,7 @@
+/*___Generated_by_IDEA___*/
+
+package gr.grnet.academicid.merchant;
+
+/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
+public final class Manifest {
+}
\ No newline at end of file
diff --git a/Main/gen/gr/grnet/academicid/merchant/R.java b/Main/gen/gr/grnet/academicid/merchant/R.java
new file mode 100644
index 0000000000000000000000000000000000000000..27db171e2a5bc9f6511a1176561813661264129d
--- /dev/null
+++ b/Main/gen/gr/grnet/academicid/merchant/R.java
@@ -0,0 +1,7 @@
+/*___Generated_by_IDEA___*/
+
+package gr.grnet.academicid.merchant;
+
+/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
+public final class R {
+}
\ No newline at end of file
diff --git a/Main/res/drawable-hdpi/action_search.png b/Main/res/drawable-hdpi/action_search.png
new file mode 100644
index 0000000000000000000000000000000000000000..f12e005ebe835c1dd2f6ae324224c3ee296d2d68
Binary files /dev/null and b/Main/res/drawable-hdpi/action_search.png differ
diff --git a/Main/res/drawable-hdpi/action_settings.png b/Main/res/drawable-hdpi/action_settings.png
new file mode 100644
index 0000000000000000000000000000000000000000..3e4580e0534c913abc5560067866b162e2972945
Binary files /dev/null and b/Main/res/drawable-hdpi/action_settings.png differ
diff --git a/Main/res/drawable-hdpi/content_remove.png b/Main/res/drawable-hdpi/content_remove.png
new file mode 100644
index 0000000000000000000000000000000000000000..094eea589246b46e26d3cf02285f26c1abb33700
Binary files /dev/null and b/Main/res/drawable-hdpi/content_remove.png differ
diff --git a/Main/res/drawable-hdpi/grnet_logo.png b/Main/res/drawable-hdpi/grnet_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc4e4607c1b14ac1b92e637157e735d0bc219a30
Binary files /dev/null and b/Main/res/drawable-hdpi/grnet_logo.png differ
diff --git a/Main/res/drawable-hdpi/ic_launcher.png b/Main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..3496c98ec34de5a17935857cb51a65741f6d7598
Binary files /dev/null and b/Main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/Main/res/drawable-hdpi/rating_important.png b/Main/res/drawable-hdpi/rating_important.png
new file mode 100644
index 0000000000000000000000000000000000000000..11f8641448683e8d59f7ba0064d211ee9dac0116
Binary files /dev/null and b/Main/res/drawable-hdpi/rating_important.png differ
diff --git a/Main/res/drawable-hdpi/rating_not_important.png b/Main/res/drawable-hdpi/rating_not_important.png
new file mode 100644
index 0000000000000000000000000000000000000000..7259b06bccca43ceb26fbad5e71dac4bb468704c
Binary files /dev/null and b/Main/res/drawable-hdpi/rating_not_important.png differ
diff --git a/Main/res/drawable-ldpi/action_search.png b/Main/res/drawable-ldpi/action_search.png
new file mode 100644
index 0000000000000000000000000000000000000000..587d9e0bf392fc928947f04293ba009f7fc77b29
Binary files /dev/null and b/Main/res/drawable-ldpi/action_search.png differ
diff --git a/Main/res/drawable-ldpi/action_settings.png b/Main/res/drawable-ldpi/action_settings.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3e42edcb6db096d90d1b28a2d4609d3419c5751
Binary files /dev/null and b/Main/res/drawable-ldpi/action_settings.png differ
diff --git a/Main/res/drawable-ldpi/content_remove.png b/Main/res/drawable-ldpi/content_remove.png
new file mode 100644
index 0000000000000000000000000000000000000000..3336760d5f3efdfefefd6899317c3a09264430f6
Binary files /dev/null and b/Main/res/drawable-ldpi/content_remove.png differ
diff --git a/Main/res/drawable-ldpi/grnet_logo.png b/Main/res/drawable-ldpi/grnet_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc4e4607c1b14ac1b92e637157e735d0bc219a30
Binary files /dev/null and b/Main/res/drawable-ldpi/grnet_logo.png differ
diff --git a/Main/res/drawable-ldpi/ic_launcher.png b/Main/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..aed039e191b485f83122c3ccc9f10af342732003
Binary files /dev/null and b/Main/res/drawable-ldpi/ic_launcher.png differ
diff --git a/Main/res/drawable-ldpi/rating_important.png b/Main/res/drawable-ldpi/rating_important.png
new file mode 100644
index 0000000000000000000000000000000000000000..504785fb8924159dbf0778e08bb6bb176ebf90b8
Binary files /dev/null and b/Main/res/drawable-ldpi/rating_important.png differ
diff --git a/Main/res/drawable-ldpi/rating_not_important.png b/Main/res/drawable-ldpi/rating_not_important.png
new file mode 100644
index 0000000000000000000000000000000000000000..3925deb9e95d0f20187f4b0c97cdefe63cc3d791
Binary files /dev/null and b/Main/res/drawable-ldpi/rating_not_important.png differ
diff --git a/Main/res/drawable-mdpi/action_search.png b/Main/res/drawable-mdpi/action_search.png
new file mode 100644
index 0000000000000000000000000000000000000000..587d9e0bf392fc928947f04293ba009f7fc77b29
Binary files /dev/null and b/Main/res/drawable-mdpi/action_search.png differ
diff --git a/Main/res/drawable-mdpi/action_settings.png b/Main/res/drawable-mdpi/action_settings.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3e42edcb6db096d90d1b28a2d4609d3419c5751
Binary files /dev/null and b/Main/res/drawable-mdpi/action_settings.png differ
diff --git a/Main/res/drawable-mdpi/content_remove.png b/Main/res/drawable-mdpi/content_remove.png
new file mode 100644
index 0000000000000000000000000000000000000000..3336760d5f3efdfefefd6899317c3a09264430f6
Binary files /dev/null and b/Main/res/drawable-mdpi/content_remove.png differ
diff --git a/Main/res/drawable-mdpi/grnet_logo.png b/Main/res/drawable-mdpi/grnet_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc4e4607c1b14ac1b92e637157e735d0bc219a30
Binary files /dev/null and b/Main/res/drawable-mdpi/grnet_logo.png differ
diff --git a/Main/res/drawable-mdpi/ic_launcher.png b/Main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..aed039e191b485f83122c3ccc9f10af342732003
Binary files /dev/null and b/Main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/Main/res/drawable-mdpi/rating_important.png b/Main/res/drawable-mdpi/rating_important.png
new file mode 100644
index 0000000000000000000000000000000000000000..504785fb8924159dbf0778e08bb6bb176ebf90b8
Binary files /dev/null and b/Main/res/drawable-mdpi/rating_important.png differ
diff --git a/Main/res/drawable-mdpi/rating_not_important.png b/Main/res/drawable-mdpi/rating_not_important.png
new file mode 100644
index 0000000000000000000000000000000000000000..3925deb9e95d0f20187f4b0c97cdefe63cc3d791
Binary files /dev/null and b/Main/res/drawable-mdpi/rating_not_important.png differ
diff --git a/Main/res/drawable-xhdpi/action_search.png b/Main/res/drawable-xhdpi/action_search.png
new file mode 100644
index 0000000000000000000000000000000000000000..3549f84dd8f5e38665849b46e252bc34f29be027
Binary files /dev/null and b/Main/res/drawable-xhdpi/action_search.png differ
diff --git a/Main/res/drawable-xhdpi/action_settings.png b/Main/res/drawable-xhdpi/action_settings.png
new file mode 100644
index 0000000000000000000000000000000000000000..09b01483454788c435acf715c57d92fc0ead0a7c
Binary files /dev/null and b/Main/res/drawable-xhdpi/action_settings.png differ
diff --git a/Main/res/drawable-xhdpi/content_remove.png b/Main/res/drawable-xhdpi/content_remove.png
new file mode 100644
index 0000000000000000000000000000000000000000..f391760ef134adb96dcce85abb2c5ab776f8e6bd
Binary files /dev/null and b/Main/res/drawable-xhdpi/content_remove.png differ
diff --git a/Main/res/drawable-xhdpi/grnet_logo.png b/Main/res/drawable-xhdpi/grnet_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc4e4607c1b14ac1b92e637157e735d0bc219a30
Binary files /dev/null and b/Main/res/drawable-xhdpi/grnet_logo.png differ
diff --git a/Main/res/drawable-xhdpi/ic_launcher.png b/Main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..809f8d52ed65794b65d27b5cde577880e0d52709
Binary files /dev/null and b/Main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/Main/res/drawable-xhdpi/rating_important.png b/Main/res/drawable-xhdpi/rating_important.png
new file mode 100644
index 0000000000000000000000000000000000000000..7576cc1e2d53878b62ddad259ed31b3da7215687
Binary files /dev/null and b/Main/res/drawable-xhdpi/rating_important.png differ
diff --git a/Main/res/drawable-xhdpi/rating_not_important.png b/Main/res/drawable-xhdpi/rating_not_important.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c618a129e6096a1ec95b26df4ee0e8a0a2267a3
Binary files /dev/null and b/Main/res/drawable-xhdpi/rating_not_important.png differ
diff --git a/Main/res/layout/change_password.xml b/Main/res/layout/change_password.xml
new file mode 100644
index 0000000000000000000000000000000000000000..02770e6a74cd6102f63718586696c8eb9ef87465
--- /dev/null
+++ b/Main/res/layout/change_password.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent">
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="30dp"
+                android:layout_marginBottom="3dp"
+                android:layout_marginLeft="50dp"
+                android:text="@string/lbl_current_password"/>
+        <EditText
+                android:id="@+id/etxt_current_password"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="40dp"
+                android:layout_marginRight="40dp"
+                android:contentDescription="@null"
+                android:inputType="textPassword"/>
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="40dp"
+                android:layout_marginBottom="3dp"
+                android:layout_marginLeft="50dp"
+                android:text="@string/lbl_new_password"/>
+        <EditText
+                android:id="@+id/etxt_new_password"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="40dp"
+                android:layout_marginRight="40dp"
+                android:contentDescription="@null"
+                android:inputType="textPassword"/>
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginBottom="3dp"
+                android:layout_marginLeft="50dp"
+                android:text="@string/lbl_new_password_confirmation"/>
+        <EditText
+                android:id="@+id/etxt_new_password_confirmation"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="40dp"
+                android:layout_marginRight="40dp"
+                android:contentDescription="@null"
+                android:inputType="textPassword"/>
+        <LinearLayout
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_marginTop="30dp"
+                android:layout_marginLeft="15dp"
+                android:layout_marginRight="15dp">
+            <Button
+                    android:id="@+id/btn_cancel"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:layout_marginRight="3dp"
+                    android:text="@string/lbl_cancel"
+                    android:onClick="cancel"/>
+            <Button
+                    android:id="@+id/btn_confirm"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:layout_marginLeft="3dp"
+                    android:text="@string/lbl_confirm"
+                    android:onClick="confirm"/>
+        </LinearLayout>
+    </LinearLayout>
+</ScrollView>
+
diff --git a/Main/res/layout/main.xml b/Main/res/layout/main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c703e86889a56b1709c60c0cc57c175959bc329f
--- /dev/null
+++ b/Main/res/layout/main.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent">
+        <ImageView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_marginTop="20dp"
+                android:contentDescription="@null"
+                android:src="@drawable/ic_launcher"/>
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="30dp"
+                android:layout_marginBottom="3dp"
+                android:layout_marginLeft="50dp"
+                android:text="@string/lbl_username"/>
+        <EditText
+                android:id="@+id/etxt_username"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="40dp"
+                android:layout_marginRight="40dp"
+                android:inputType="text|textNoSuggestions"/>
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginBottom="3dp"
+                android:layout_marginLeft="50dp"
+                android:text="@string/lbl_password"/>
+        <EditText
+                android:id="@+id/etxt_password"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="40dp"
+                android:layout_marginRight="40dp"
+                android:inputType="textPassword"/>
+        <Button
+                android:id="@+id/btn_sign_in"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_marginTop="10dp"
+                android:text="@string/lbl_sign_in"
+                android:onClick="signIn"/>
+    </LinearLayout>
+</ScrollView>
+
diff --git a/Main/res/layout/offer_list.xml b/Main/res/layout/offer_list.xml
new file mode 100644
index 0000000000000000000000000000000000000000..43f5a5377c441ac66a63637e73a429f31eecc6fd
--- /dev/null
+++ b/Main/res/layout/offer_list.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent">
+    <TextView
+            android:id="@+id/txt_offers_header"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:paddingTop="5dp"
+            android:paddingBottom="5dp"
+            android:textAppearance="@style/header_green"
+            android:text="@string/lbl_active_offers"
+            />
+    <ListView
+            android:id="@android:id/list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+    <TextView
+            android:id="@+id/empty"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:paddingTop="10dp"
+            android:textAppearance="@style/title_smart"
+            android:text="@string/lbl_no_offers"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/Main/res/layout/offer_list_item.xml b/Main/res/layout/offer_list_item.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0431c2fe3f9afeffec61f75c420d8403a788fa35
--- /dev/null
+++ b/Main/res/layout/offer_list_item.xml
@@ -0,0 +1,27 @@
+<?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="wrap_content"
+              android:orientation="vertical"
+              android:padding="10dp"
+              android:paddingLeft="10dp"
+              android:paddingRight="10dp">
+
+    <!-- Title Label -->
+    <TextView
+            android:id="@+id/txtv_offer_item_title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingBottom="2dp"
+            android:paddingTop="6dp"
+            android:textAppearance="@style/list_title"/>
+
+    <!-- Description label -->
+    <TextView
+            android:id="@+id/txtv_offer_item_description"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingBottom="2dp"
+            android:textAppearance="@style/list_item"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/Main/res/layout/single_offer.xml b/Main/res/layout/single_offer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c6263df67450a79b8cd0750918bd7c87b3f198ee
--- /dev/null
+++ b/Main/res/layout/single_offer.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:padding="10dp">
+    <ScrollView
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1">
+        <LinearLayout
+                android:orientation="vertical"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+            <!-- Title Label -->
+            <TextView android:id="@+id/txtv_offer_title"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:paddingBottom="10dp"
+                      android:textSize="25sp"
+                      android:textStyle="bold"
+                      android:textColor="#43bd00"/>
+            <!-- Description Label -->
+            <TextView android:id="@+id/txtv_offer_description"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:textColor="#acacac"/>
+
+            <LinearLayout
+                    android:orientation="horizontal"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:gravity="center_vertical"
+                    android:paddingTop="20dp"
+                    android:paddingBottom="20dp">
+                <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:textAppearance="@style/list_title"
+                        android:paddingRight="5dp"
+                        android:text="@string/lbl_available_from"/>
+                <TextView
+                        android:id="@+id/txtv_offer_startDate"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"/>
+                <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:paddingRight="5dp"
+                        android:paddingLeft="5dp"
+                        android:textAppearance="@style/list_title"
+                        android:text="@string/lbl_available_to"/>
+                <TextView
+                        android:id="@+id/txtv_offer_endDate"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"/>
+            </LinearLayout>
+            <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@style/list_title"
+                    android:text="@string/lbl_eligible_to"/>
+            <TextView
+                    android:id="@+id/txtv_offer_criteria"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+
+            <TextView
+                    android:id="@+id/txtv_offer_inspectionResult"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:layout_marginTop="50dp"
+                    android:visibility="gone"/>
+            <TextView
+                    android:id="@+id/txtv_offer_inspectionResultError"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:visibility="gone"/>
+        </LinearLayout>
+    </ScrollView>
+    <Button
+            android:id="@+id/btn_scan_qr"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:text="@string/lbl_scan_qr"
+            android:onClick="scanQR"/>
+    <RelativeLayout
+            android:id="@+id/rellay_serial_input"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp">
+        <ImageButton
+                android:id="@+id/btn_check_serial"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:contentDescription="@null"
+                android:src="@drawable/action_search"
+                android:onClick="checkSerialNo"/>
+        <EditText
+                android:id="@+id/etxt_serial_number"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_toLeftOf="@id/btn_check_serial"
+                android:layout_toRightOf="@+id/btn_clear_serial"
+                android:layout_alignBottom="@id/btn_check_serial"
+                android:layout_marginTop="4dp"
+                android:imeOptions="actionDone"
+                android:inputType="number"
+                android:maxLength="12"
+                android:hint="@string/lbl_enter_serial"/>
+        <ImageButton
+                android:id="@+id/btn_clear_serial"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentLeft="true"
+                android:contentDescription="@null"
+                android:src="@drawable/content_remove"
+                android:onClick="clearContent"/>
+    </RelativeLayout>
+</LinearLayout>
diff --git a/Main/res/menu/menu_offer_list.xml b/Main/res/menu/menu_offer_list.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4097ec36707fa670326d4346a0cc5073baea5998
--- /dev/null
+++ b/Main/res/menu/menu_offer_list.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+            android:id="@+id/menu_toggle_offers"
+            android:icon="@drawable/rating_not_important"
+            android:title="@string/lbl_inactive_offers"/>
+    <item
+            android:id="@+id/menu_settings"
+            android:icon="@drawable/action_settings"
+            android:title="@string/menu_settings"/>
+</menu>
\ No newline at end of file
diff --git a/Main/res/menu/menu_scan_qr.xml b/Main/res/menu/menu_scan_qr.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8ead7fa6d820cae9c69ebdd3168c97fa7f552c3b
--- /dev/null
+++ b/Main/res/menu/menu_scan_qr.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+            android:id="@+id/menu_settings"
+            android:icon="@drawable/action_settings"
+            android:title="@string/menu_settings"/>
+</menu>
\ No newline at end of file
diff --git a/Main/res/menu/menu_single_offer.xml b/Main/res/menu/menu_single_offer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..74a001f30b602c960c9cc043f8d929b375b2b7f0
--- /dev/null
+++ b/Main/res/menu/menu_single_offer.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+            android:id="@+id/menu_offers"
+            android:icon="@drawable/rating_important"
+            android:title="@string/menu_offers"/>
+    <item
+            android:id="@+id/menu_settings"
+            android:icon="@drawable/action_settings"
+            android:title="@string/menu_settings"/>
+</menu>
\ No newline at end of file
diff --git a/Main/res/values-el/strings.xml b/Main/res/values-el/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9abb1a56f0f85a4351203852df18bc24b59492cb
--- /dev/null
+++ b/Main/res/values-el/strings.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Academic ID Merchant</string>
+
+    <string name="lbl_username">Όνομα ΧρΞ�στη:</string>
+    <string name="lbl_password">ΞšΟ‰Ξ΄ΞΉΞΊΟŒΟ‚ Ξ ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚:</string>
+    <string name="lbl_sign_in">Είσοδος</string>
+
+    <string name="title_no_net_available">Δίκτυο ΞΌΞ· Διαθέσιμο</string>
+    <string name="msg_no_net_available">Για ΡνΡργοποίηση πιέστΡ Ξ•Ο€ΟŒΞΌΞ΅Ξ½ΞΏ</string>
+    <string name="action_next">Ξ•Ο€ΟŒΞΌΞ΅Ξ½ΞΏ</string>
+    <string name="action_close">Ξ€Ξ΅ΟΞΌΞ±Ο„ΞΉΟƒΞΌΟŒΟ‚</string>
+
+    <string name="msg_wait">Παρακαλώ πΡριμένΡτΡ…</string>
+    <string name="msg_incorrect_credentials">΀ο όνομα ΧρΞ�στη Ξ� ΞΏ ΞšΟ‰Ξ΄ΞΉΞΊΟŒΟ‚ Ξ ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚ Ρίναι Ρσφαλμένα</string>
+    <string name="msg_no_camera_available">Ξ— κάμΡρα δΡν Ρίναι διαθέσιμη</string>
+
+    <string name="lbl_active_offers">ΕνΡργές Προσφορές</string>
+    <string name="lbl_inactive_offers">ΑνΡνΡργές Προσφορές</string>
+    <string name="lbl_no_offers">ΔΡν υπάρχουν διαθΡσιμΡς προσφορές</string>
+    <string name="msg_error_retrieving_offers">ΠαρουσιάστηκΡ σφάλμα κατά την ανάκτηση των διαθέσιμων Ο€ΟΞΏΟƒΟ†ΞΏΟΟŽΞ½</string>
+
+    <string name="lbl_available_from">Διαθέσιμη Ξ±Ο€ΟŒ:</string>
+    <string name="lbl_available_to">ΞˆΟ‰Ο‚:</string>
+    <string name="lbl_eligible_to">Δικαιούχοι:</string>
+    <string name="msg_eligible_for_offer">Ξ‘ΟΞΉΞΈΞΌΟŒΟ‚ ακαδημαικΞ�Ο‚ Ο„Ξ±Ο…Ο„ΟŒΟ„Ξ·Ο„Ξ±Ο‚: SERIAL_TAG\nΟ κάτοχος δικαιούται την προσφορά</string>
+    <string name="msg_not_eligible_for_offer">Ξ‘ΟΞΉΞΈΞΌΟŒΟ‚ ακαδημαικΞ�Ο‚ Ο„Ξ±Ο…Ο„ΟŒΟ„Ξ·Ο„Ξ±Ο‚: SERIAL_TAG\nΟ κάτοχος δΡν δικαιούταιτην προσφορά</string>
+    <string name="msg_invalid_input">΀ο στοιχΡίο Ξ΅ΞΉΟƒΟŒΞ΄ΞΏΟ… δΡν αντιστοιχΡί σΡ έγκυρη ακαδημαϊκΞ� Ο„Ξ±Ο…Ο„ΟŒΟ„Ξ·Ο„Ξ±</string>
+    <string name="msg_error_validating_offer">ΠαρουσιάστηκΡ σφάλμα κατά τον έλΡγχο της Ξ΄ΞΉΞ±ΞΈΞ΅ΟƒΞΉΞΌΟŒΟ„Ξ·Ο„Ξ±Ο‚ της προσφοράς</string>
+
+    <string name="lbl_scan_qr">Σάρωση QR</string>
+    <string name="lbl_enter_serial">ΕισαγωγΞ� ΣΡιριακού Αρ.</string>
+    <string name="lbl_exit">ΠιέστΡ ΞΎΞ±Ξ½Ξ¬ Ξ³ΞΉΞ± έξοδο</string>
+
+    <string name="menu_offers">ΕνΡργές Προσφορές</string>
+    <string name="menu_settings">ΑυθμίσΡις</string>
+
+    <string name="title_change_password">ΑλλαγΞ� ΞšΟ‰Ξ΄ΞΉΞΊΞΏΟ Ξ ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚</string>
+    <string name="msg_change_password">ΑλλαγΞ� του κωδικού Ο€ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚ του χρΞ�στη</string>
+
+    <string name="lbl_current_password">΀ρέχων ΞšΟ‰Ξ΄ΞΉΞΊΟŒΟ‚ Ξ ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚:</string>
+    <string name="lbl_new_password">Νέος ΞšΟ‰Ξ΄ΞΉΞΊΟŒΟ‚ Ξ ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚:</string>
+    <string name="lbl_new_password_confirmation">ΕπιβΡβαίωση Νέου ΞšΟ‰Ξ΄ΞΉΞΊΞΏΟ:</string>
+    <string name="lbl_cancel">Ακύρωση</string>
+    <string name="lbl_confirm">ΕπιβΡβαίωση</string>
+
+    <string name="msg_password_change_required">ΑπαιτΡίται αλλαγΞ� του κωδικού Ο€ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚</string>
+    <string name="msg_incorrect_current_password">Ο τρέχων ΞΊΟ‰Ξ΄ΞΉΞΊΟŒΟ‚ Ο€ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚ Ρίναι λάθος</string>
+    <string name="msg_new_passwords_dont_match">Οι Ξ½Ξ­ΞΏΞΉ κωδικοί Ο€ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚ δΡν Ρίναι ίδιοι</string>
+    <string name="msg_password_too_short">Ο ΞΊΟ‰Ξ΄ΞΉΞΊΟŒΟ‚ Ο€ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚ πρέπΡι Ξ½Ξ± πΡριέχΡι τουλάχιστον 4 χαρακτΞ�ρΡς</string>
+    <string name="msg_new_current_password_same">Ο Ξ½Ξ­ΞΏΟ‚ ΞΊΞ±ΞΉ ΞΏ τρέχον ΞΊΟ‰Ξ΄ΞΉΞΊΟŒΟ‚ Ο€ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚ δΡν πρέπΡι Ξ½Ξ± Ρίναι ίδιοι</string>
+    <string name="msg_error_changing_password">ΠαρουσιάστηκΡ σφάλμα κατα την διαδικασία αποθΞ�κΡυσης του Ξ½Ξ­ΞΏΟ… κωδικού Ο€ΟΟŒΟƒΞ²Ξ±ΟƒΞ·Ο‚</string>
+</resources>
diff --git a/Main/res/values/strings.xml b/Main/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..25b8f6f5ecc6023d30ccf58750f5377080726cbf
--- /dev/null
+++ b/Main/res/values/strings.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Academic ID Merchant</string>
+
+    <string name="lbl_username">Username:</string>
+    <string name="lbl_password">Password:</string>
+    <string name="lbl_sign_in">Sign In</string>
+
+    <string name="title_no_net_available">No Network Connection</string>
+    <string name="msg_no_net_available">To enable network connection touch Next</string>
+    <string name="action_next">Next</string>
+    <string name="action_close">Close</string>
+
+    <string name="msg_wait">Please wait…</string>
+    <string name="msg_incorrect_credentials">Incorrect username or password</string>
+    <string name="msg_no_camera_available">Rear Facing Camera Unavailable</string>
+
+    <string name="lbl_active_offers">Active Offers</string>
+    <string name="lbl_inactive_offers">Inactive Offers</string>
+    <string name="lbl_no_offers">No Available Offers</string>
+    <string name="msg_error_retrieving_offers">Error trying to retrieve available offers</string>
+
+    <string name="lbl_available_from">Available from:</string>
+    <string name="lbl_available_to">To:</string>
+    <string name="lbl_eligible_to">Eligible to:</string>
+    <string name="msg_eligible_for_offer">Academic Id: SERIAL_TAG\nEligible for this offer</string>
+    <string name="msg_not_eligible_for_offer">Academic Id: SERIAL_TAG\nNot eligible for this offer</string>
+    <string name="msg_invalid_input">The input is not a valid academic ID</string>
+    <string name="msg_error_validating_offer">Error trying to validate offer</string>
+
+    <string name="lbl_scan_qr">Scan QR Code</string>
+    <string name="lbl_enter_serial">Enter Serial Number</string>
+    <string name="lbl_exit">Press again to exit</string>
+
+    <string name="menu_offers">Active Offers</string>
+    <string name="menu_settings">Settings</string>
+
+    <string name="title_change_password">Change Password</string>
+    <string name="msg_change_password">Change the user password</string>
+
+    <string name="lbl_current_password">Current Password:</string>
+    <string name="lbl_new_password">New Password:</string>
+    <string name="lbl_new_password_confirmation">Confirm New Password:</string>
+    <string name="lbl_cancel">Cancel</string>
+    <string name="lbl_confirm">Confirm</string>
+
+    <string name="msg_password_change_required">Required password change</string>
+    <string name="msg_incorrect_current_password">Current password is incorrect</string>
+    <string name="msg_new_passwords_dont_match">The new passwords don\'t match</string>
+    <string name="msg_password_too_short">Password must contain at least 4 characters</string>
+    <string name="msg_new_current_password_same">New and current password should not be the same</string>
+    <string name="msg_error_changing_password">Error trying to update user password</string>
+</resources>
diff --git a/Main/res/values/styles.xml b/Main/res/values/styles.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ac33aa66902e1016d5095c684277a82b65805073
--- /dev/null
+++ b/Main/res/values/styles.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="header_green">
+        <item name="android:textSize">30sp</item>
+        <item name="android:textColor">#00ff00</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:singleLine">true</item>
+    </style>
+    <style name="header_orange">
+        <item name="android:textSize">30sp</item>
+        <item name="android:textColor">#ee7620</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:singleLine">true</item>
+    </style>
+
+    <style name="list_title">
+        <item name="android:textSize">16sp</item>
+        <item name="android:textColor">#ffffffff</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+    <style name="list_item">
+        <item name="android:textColor">#acacac</item>
+    </style>
+
+    <style name="title_green">
+        <item name="android:textSize">25sp</item>
+        <item name="android:textColor">#00ff00</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:singleLine">true</item>
+    </style>
+    <style name="title_orange">
+        <item name="android:textSize">25sp</item>
+        <item name="android:textColor">#ee7620</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:singleLine">true</item>
+    </style>
+    <style name="title_smart">
+        <item name="android:textSize">20sp</item>
+        <item name="android:textStyle">bold|italic</item>
+    </style>
+
+    <style name="color_green">
+        <item name="android:textColor">#ff008000</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:singleLine">true</item>
+    </style>
+    <style name="color_orange">
+        <item name="android:textColor">#ff800000</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:singleLine">true</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/Main/res/xml/preferences.xml b/Main/res/xml/preferences.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e6ca730e4126cc4b830c9a92ec90de49ebff8ff4
--- /dev/null
+++ b/Main/res/xml/preferences.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    <PreferenceCategory android:title="@string/menu_settings">
+        <PreferenceScreen
+                android:title="@string/title_change_password"
+                android:summary="@string/msg_change_password">
+            <intent android:action="android.intent.action.VIEW"
+                    android:targetPackage="gr.grnet.academicid.merchant"
+                    android:targetClass="gr.grnet.academicid.merchant.ChangePassword"/>
+        </PreferenceScreen>
+    </PreferenceCategory>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/Main/src/gr/grnet/academicid/merchant/ChangePassword.java b/Main/src/gr/grnet/academicid/merchant/ChangePassword.java
new file mode 100644
index 0000000000000000000000000000000000000000..248a0811c53afe18169cf49ab4d0ef27f916b42c
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/ChangePassword.java
@@ -0,0 +1,130 @@
+package gr.grnet.academicid.merchant;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.Toast;
+import gr.grnet.academicid.merchant.domain.Inspector;
+import gr.grnet.academicid.merchant.parser.ChangePasswordResponse;
+import gr.grnet.academicid.merchant.parser.JSONParser;
+import gr.grnet.academicid.merchant.services.ServiceHandler;
+import gr.grnet.academicid.merchant.utilities.Constants;
+import gr.grnet.academicid.merchant.utilities.Tools;
+
+
+public class ChangePassword extends Activity {
+
+    private EditText etxtCurrentPassword;
+    private EditText etxtNewPassword;
+    private EditText etxtNewPasswordConfirmation;
+
+    private ProgressDialog progressDialog;
+    private Inspector inspector;
+    private String newPasswordHash;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.change_password);
+
+        etxtCurrentPassword = (EditText) findViewById(R.id.etxt_current_password);
+        etxtNewPassword = (EditText) findViewById(R.id.etxt_new_password);
+        etxtNewPasswordConfirmation = (EditText) findViewById(R.id.etxt_new_password_confirmation);
+
+        inspector = MerchantApplication.getInspector();
+        if (inspector.shouldChangePswAtLogin())
+            Toast.makeText(getApplicationContext(), getString(R.string.msg_password_change_required), Toast.LENGTH_LONG).show();
+    }
+
+    public void cancel(View view) {
+        finish();
+    }
+
+    public void confirm(View view) {
+        // After 'Sign In' button is pressed, hide soft keyboard
+        InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (getCurrentFocus() != null)
+            inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+
+        String currentPasswordHash = Tools.getHash(etxtCurrentPassword.getText().toString());
+        String newPassword = etxtNewPassword.getText().toString();
+        newPasswordHash = Tools.getHash(newPassword);
+        String newPasswordConfirmationHash = Tools.getHash(etxtNewPasswordConfirmation.getText().toString());
+
+        inspector = MerchantApplication.getInspector();
+
+        // Check if the Current password is the actual password of the user by comparing the hash values.
+        if (!inspector.getPasswordHash().equals(currentPasswordHash)) {
+            Toast.makeText(getApplicationContext(), getString(R.string.msg_incorrect_current_password), Toast.LENGTH_SHORT).show();
+        }
+        // Check if the new password and the new password confirmation match by comparing the hash values.
+        else if (!newPasswordHash.equals(newPasswordConfirmationHash)) {
+            Toast.makeText(getApplicationContext(), getString(R.string.msg_new_passwords_dont_match), Toast.LENGTH_SHORT).show();
+        }
+        // Check if new password is at least 4 chars long.
+        else if (newPassword.length() < 4) {
+            Toast.makeText(getApplicationContext(), getString(R.string.msg_password_too_short), Toast.LENGTH_SHORT).show();
+        }
+        // Check if new password is the same with current password by comparing the hash values.
+        else if (currentPasswordHash.equals(newPasswordHash)) {
+            Toast.makeText(getApplicationContext(), getString(R.string.msg_new_current_password_same), Toast.LENGTH_SHORT).show();
+        } else {
+            new UpdatePassword().execute(inspector.getUsername(), inspector.getPasswordHash(), newPasswordHash);
+        }
+    }
+
+    private class UpdatePassword extends AsyncTask<String, Void, String> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+            // Showing progress dialog
+            progressDialog = new ProgressDialog(ChangePassword.this);
+            progressDialog.setMessage(getString(R.string.msg_wait));
+            progressDialog.setCancelable(false);
+            progressDialog.show();
+        }
+
+        @Override
+        protected String doInBackground(String... variables) {
+            return ServiceHandler.makeChangePswCall(variables[0], variables[1], variables[2]);
+        }
+
+        @Override
+        protected void onPostExecute(String result) {
+            super.onPostExecute(result);
+            // Dismiss the progress dialog
+            if (progressDialog.isShowing())
+                progressDialog.dismiss();
+
+            ChangePasswordResponse changePasswordResponse = JSONParser.getResultOfUpdatePassword(result);
+
+            if (!changePasswordResponse.isSuccessful()) {
+                Toast.makeText(getApplicationContext(), getString(R.string.msg_error_changing_password), Toast.LENGTH_SHORT).show();
+                Log.e(Constants.LOGTAG, "ChangePassword.UpdatePassword.OnPostExecute(): Web service returned unsuccessfully with errorCode: " + changePasswordResponse.getError());
+            } else {
+                Log.i(Constants.LOGTAG, "ChangePassword.UpdatePassword.OnPostExecute(): User " + inspector.getUsername() + " successfully changed his password.");
+
+                inspector = MerchantApplication.getInspector();
+                boolean userChangedPsw = inspector.shouldChangePswAtLogin();
+                inspector.setPasswordHash(newPasswordHash);
+                inspector.setChangePswAtLogin(false);
+                MerchantApplication.setInspector(inspector);
+
+                if (userChangedPsw)
+                    startActivity(new Intent(ChangePassword.this, OfferList.class));
+                else
+                    finish();
+                finish();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/src/gr/grnet/academicid/merchant/MainActivity.java b/Main/src/gr/grnet/academicid/merchant/MainActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..df3a626fc84be0dc407839407c441d1b06d0effd
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/MainActivity.java
@@ -0,0 +1,124 @@
+package gr.grnet.academicid.merchant;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.Toast;
+import gr.grnet.academicid.merchant.domain.Inspector;
+import gr.grnet.academicid.merchant.parser.LoadUserResponse;
+import gr.grnet.academicid.merchant.services.ServiceHandler;
+import gr.grnet.academicid.merchant.parser.JSONParser;
+import gr.grnet.academicid.merchant.utilities.Constants;
+import gr.grnet.academicid.merchant.utilities.Tools;
+
+public class MainActivity extends Activity {
+
+    private EditText etxtUsername;
+    private EditText etxtPassword;
+
+    private ProgressDialog progressDialog;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        etxtUsername = (EditText) findViewById(R.id.etxt_username);
+        etxtPassword = (EditText) findViewById(R.id.etxt_password);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (!Tools.isNetworkAvailable()) {
+            AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
+            alertDialog.setTitle(getString(R.string.title_no_net_available));
+            alertDialog.setMessage(getString(R.string.msg_no_net_available));
+
+            alertDialog.setPositiveButton(getString(R.string.action_next), new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
+                }
+            });
+            alertDialog.setNegativeButton(getString(R.string.action_close), new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    finish();
+                }
+            });
+            alertDialog.show();
+        }
+    }
+
+    // Method called after 'Sign In' button is pressed
+    public void signIn(View view) {
+        // After 'Sign In' button is pressed, hide soft keyboard
+        InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (getCurrentFocus() != null)
+            inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+
+        String username = etxtUsername.getText().toString();
+        String password = etxtPassword.getText().toString();
+
+        // Password is hashed and passed to async task for authorization
+        new Authenticate().execute(username, Tools.getHash(password));
+    }
+
+    // Inner class to perform the network connection asynchronously
+    private class Authenticate extends AsyncTask<String, Void, String> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+            // Showing progress dialog
+            progressDialog = new ProgressDialog(MainActivity.this);
+            progressDialog.setMessage(getString(R.string.msg_wait));
+            progressDialog.setCancelable(false);
+            progressDialog.show();
+        }
+
+        @Override
+        protected String doInBackground(String... credentials) {
+            return ServiceHandler.makeSingInCall(credentials[0], credentials[1]);
+        }
+
+        @Override
+        protected void onPostExecute(String result) {
+            super.onPostExecute(result);
+            // Dismiss the progress dialog
+            if (progressDialog.isShowing())
+                progressDialog.dismiss();
+
+            LoadUserResponse loadUserResponse = JSONParser.getResultOfLoadUser(result);
+
+            if (!loadUserResponse.isSuccessful()) {
+                Toast.makeText(getApplicationContext(), getString(R.string.msg_incorrect_credentials), Toast.LENGTH_SHORT).show();
+                Log.e(Constants.LOGTAG, "MainActivity.Authenticate.OnPostExecute(): Web service returned unsuccessfully with errorCode: " + loadUserResponse.getError());
+            } else {
+                Inspector inspector = loadUserResponse.getInspector();
+                String password = etxtPassword.getText().toString();
+                inspector.setPasswordHash(Tools.getHash(password));
+                MerchantApplication.setInspector(inspector);
+
+                Log.i(Constants.LOGTAG, "User: " + inspector.getUsername() + "successfully logged in");
+
+                //   // Check if user should change his password and redirect him to that view
+                if (inspector.shouldChangePswAtLogin())
+                    startActivity(new Intent(MainActivity.this, ChangePassword.class));
+                else
+                    startActivity(new Intent(MainActivity.this, OfferList.class));
+            }
+        }
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/MerchantApplication.java b/Main/src/gr/grnet/academicid/merchant/MerchantApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..07a5ecfc64275dd57860c920365a99782f69f0a9
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/MerchantApplication.java
@@ -0,0 +1,58 @@
+package gr.grnet.academicid.merchant;
+
+import android.app.Application;
+import android.content.Context;
+import gr.grnet.academicid.merchant.domain.Inspector;
+import gr.grnet.academicid.merchant.domain.Offer;
+import gr.grnet.academicid.merchant.utilities.SharedPrefs;
+
+public class MerchantApplication extends Application {
+
+    private static Context context;
+    private static Inspector inspector;
+    private static Offer selectedOffer;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public MerchantApplication() {
+        super();
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        MerchantApplication.context = getApplicationContext();
+    }
+
+    @Override
+    public void onTerminate() {
+        super.onTerminate();
+        SharedPrefs.ClearInspectorFromPrefs();
+    }
+
+    public static Context getAppContext() {
+        return MerchantApplication.context;
+    }
+
+    public static Inspector getInspector() {
+        // Check if object has been deleted from Android garbage collector and if it has, recall it from Shared Preferences
+        if (inspector == null) {
+            inspector = SharedPrefs.getInspectorFromPrefs();
+        }
+        return inspector;
+    }
+
+    public static void setInspector(Inspector inspector) {
+        MerchantApplication.inspector = inspector;
+        //Save object to Shared Preferences to prevent NPE when app resuming and android garbage collector has cleared this
+        SharedPrefs.setInspectorToPrefs(inspector);
+    }
+
+    public static Offer getSelectedOffer() {
+        return selectedOffer;
+    }
+
+    public static void setSelectedOffer(Offer selectedOffer) {
+        MerchantApplication.selectedOffer = selectedOffer;
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/OfferList.java b/Main/src/gr/grnet/academicid/merchant/OfferList.java
new file mode 100644
index 0000000000000000000000000000000000000000..b08873b596c3ba619bb2a63af1136dd5bc27f63c
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/OfferList.java
@@ -0,0 +1,193 @@
+package gr.grnet.academicid.merchant;
+
+import android.app.ListActivity;
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.*;
+import gr.grnet.academicid.merchant.domain.Inspector;
+import gr.grnet.academicid.merchant.domain.Offer;
+import gr.grnet.academicid.merchant.parser.JSONParser;
+import gr.grnet.academicid.merchant.parser.LoadProviderOffersResponse;
+import gr.grnet.academicid.merchant.services.ServiceHandler;
+import gr.grnet.academicid.merchant.utilities.Constants;
+import gr.grnet.academicid.merchant.utilities.Tools;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class OfferList extends ListActivity {
+
+    private ListView listView;
+    private TextView txtvOffersHeader;
+
+    private ProgressDialog progressDialog;
+    private List<Offer> activeOfferList;
+    private List<Offer> inactiveOfferList;
+    private boolean showingActive;
+    private boolean doubleBackToExitPressedOnce = false;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.offer_list);
+
+        txtvOffersHeader = (TextView) findViewById(R.id.txt_offers_header);
+
+        listView = getListView();
+
+        // Listview on item click listener
+        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+
+                Offer offer = (showingActive ? activeOfferList.get(position) : inactiveOfferList.get(position));
+
+                // Store selected offer for returning to Single Offer when pressing back in camera preview
+                MerchantApplication.setSelectedOffer(offer);
+
+                // Starting single offer activity
+                Intent intent = new Intent(OfferList.this, SingleOffer.class);
+                intent.putExtra(Offer.ID, offer.getId());
+                intent.putExtra(Offer.TITLE, offer.getTitle());
+                intent.putExtra(Offer.DESCRIPTION, offer.getDescription());
+                intent.putExtra(Offer.STATUS, offer.getStatus());
+                intent.putExtra(Offer.START_DATE, offer.getStartDate());
+                intent.putExtra(Offer.END_DATE, offer.getEndDate());
+                intent.putExtra(Offer.BENEFICIARIES, offer.getBeneficiaries());
+                intent.putExtra(Offer.CRITERIA, offer.getCriteria());
+                startActivity(intent);
+            }
+        });
+
+        // Get inspector object from application class
+        Inspector inspector = MerchantApplication.getInspector();
+        new RetrieveOffers().execute(inspector.getUsername(), inspector.getPasswordHash());
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        this.doubleBackToExitPressedOnce = false;
+    }
+
+    private class RetrieveOffers extends AsyncTask<String, Void, String> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+            // Showing progress dialog
+            progressDialog = new ProgressDialog(OfferList.this);
+            progressDialog.setMessage(getString(R.string.msg_wait));
+            progressDialog.setCancelable(false);
+            progressDialog.show();
+        }
+
+        @Override
+        protected String doInBackground(String... credentials) {
+            return ServiceHandler.makeLoadProviderOffersCall(credentials[0], credentials[1]);
+        }
+
+        @Override
+        protected void onPostExecute(String result) {
+            super.onPostExecute(result);
+            // Dismiss the progress dialog
+            if (progressDialog.isShowing())
+                progressDialog.dismiss();
+
+            LoadProviderOffersResponse loadProviderOffersResponse = JSONParser.getResultOfLoadProviderOffers(result);
+
+            if (!loadProviderOffersResponse.isSuccessful()) {
+                Toast.makeText(getApplicationContext(), getString(R.string.msg_error_retrieving_offers), Toast.LENGTH_SHORT).show();
+                Log.e(Constants.LOGTAG, "OfferList.RetrieveOffers.OnPostExecute(): Web service returned unsuccessfully with errorCode: " + loadProviderOffersResponse.getError());
+            } else {
+                List<Offer> offerList = loadProviderOffersResponse.getOffers();
+                activeOfferList = new ArrayList<Offer>();
+                inactiveOfferList = new ArrayList<Offer>();
+
+                // Split the offer list in active and inactive offers
+                Tools.splitOffers(offerList, activeOfferList, inactiveOfferList);
+
+                // Set flag to show the active offers by default
+                showingActive = true;
+
+                // Set the view that should be displayed if no offer exists
+                listView.setEmptyView(findViewById(R.id.empty));
+
+                // Prepare the list with offers that will be displayed
+                List<Map<String, String>> adapterOfferList = Tools.prepareListForAdapter(activeOfferList);
+                ListAdapter adapter = new SimpleAdapter(OfferList.this, adapterOfferList, R.layout.offer_list_item, new String[]{Offer.TITLE, Offer.DESCRIPTION}, new int[]{R.id.txtv_offer_item_title, R.id.txtv_offer_item_description});
+                setListAdapter(adapter);
+            }
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.menu_offer_list, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, @NotNull MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.menu_toggle_offers:
+                if (showingActive) {
+                    showingActive = false;
+
+                    item.setTitle(getString(R.string.lbl_active_offers));
+                    item.setIcon(R.drawable.rating_important);
+
+                    txtvOffersHeader.setText(R.string.lbl_inactive_offers);
+                    txtvOffersHeader.setTextAppearance(this, R.style.header_orange);
+
+                    List<Map<String, String>> adapterOfferList = Tools.prepareListForAdapter(inactiveOfferList);
+                    ListAdapter adapter = new SimpleAdapter(OfferList.this, adapterOfferList, R.layout.offer_list_item, new String[]{Offer.TITLE, Offer.DESCRIPTION}, new int[]{R.id.txtv_offer_item_title, R.id.txtv_offer_item_description});
+                    setListAdapter(adapter);
+                } else {
+                    showingActive = true;
+
+                    item.setTitle(getString(R.string.lbl_inactive_offers));
+                    item.setIcon(R.drawable.rating_not_important);
+
+                    txtvOffersHeader.setText(R.string.lbl_active_offers);
+                    txtvOffersHeader.setTextAppearance(this, R.style.header_green);
+
+                    List<Map<String, String>> adapterOfferList = Tools.prepareListForAdapter(activeOfferList);
+                    ListAdapter adapter = new SimpleAdapter(OfferList.this, adapterOfferList, R.layout.offer_list_item, new String[]{Offer.TITLE, Offer.DESCRIPTION}, new int[]{R.id.txtv_offer_item_title, R.id.txtv_offer_item_description});
+                    setListAdapter(adapter);
+                }
+                return true;
+            case R.id.menu_settings:
+                startActivity(new Intent(this, Preferences.class));
+                return true;
+            default:
+                return super.onMenuItemSelected(featureId, item);
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (doubleBackToExitPressedOnce) {
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.addCategory(Intent.CATEGORY_HOME);
+            startActivity(intent);
+            finish();
+        } else {
+            this.doubleBackToExitPressedOnce = true;
+            Toast.makeText(this, R.string.lbl_exit, Toast.LENGTH_SHORT).show();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/src/gr/grnet/academicid/merchant/Preferences.java b/Main/src/gr/grnet/academicid/merchant/Preferences.java
new file mode 100644
index 0000000000000000000000000000000000000000..75258a6286aef8b480a4dff14520f90fa7168485
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/Preferences.java
@@ -0,0 +1,11 @@
+package gr.grnet.academicid.merchant;
+
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+public class Preferences extends PreferenceActivity {
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.preferences);
+    }
+}
\ No newline at end of file
diff --git a/Main/src/gr/grnet/academicid/merchant/ScanQR.java b/Main/src/gr/grnet/academicid/merchant/ScanQR.java
new file mode 100644
index 0000000000000000000000000000000000000000..734fc9a38969ba54db4016fe150f421c95a3f1ad
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/ScanQR.java
@@ -0,0 +1,60 @@
+package gr.grnet.academicid.merchant;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+import com.dm.zbar.android.scanner.ZBarConstants;
+import com.dm.zbar.android.scanner.ZBarScannerActivity;
+import gr.grnet.academicid.merchant.utilities.Constants;
+import gr.grnet.academicid.merchant.utilities.Tools;
+import net.sourceforge.zbar.Symbol;
+
+public class ScanQR extends Activity {
+
+    private static final int ZBAR_SCANNER_REQUEST = 0;
+    private static final int ZBAR_QR_SCANNER_REQUEST = 1;
+
+    public static final String SCAN_RESULT = "ScanResult";
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (Tools.isCameraAvailable()) {
+            Intent intent = new Intent(this, ZBarScannerActivity.class);
+            intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{Symbol.QRCODE});
+            startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
+        } else {
+            Toast.makeText(this, getString(R.string.msg_no_camera_available), Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+            case ZBAR_SCANNER_REQUEST:
+            case ZBAR_QR_SCANNER_REQUEST:
+                if (resultCode == RESULT_OK) {
+                    String scanResult = data.getStringExtra(ZBarConstants.SCAN_RESULT);
+
+                    Intent intent = new Intent();
+                    intent.putExtra(SCAN_RESULT, scanResult);
+
+                    setResult(Activity.RESULT_OK, intent);
+                    finish();
+                } else if (resultCode == RESULT_CANCELED && data != null) {
+                    String error = data.getStringExtra(ZBarConstants.ERROR_INFO);
+                    if (!TextUtils.isEmpty(error)) {
+                        Toast.makeText(this, error, Toast.LENGTH_SHORT).show();
+                        Log.e(Constants.LOGTAG, "ScanQR.onActivityResult(): " + error);
+                    }
+                }
+                break;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/src/gr/grnet/academicid/merchant/SingleOffer.java b/Main/src/gr/grnet/academicid/merchant/SingleOffer.java
new file mode 100644
index 0000000000000000000000000000000000000000..e2f0112a9e257f714cd8cf35d00c1398b159ad3b
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/SingleOffer.java
@@ -0,0 +1,226 @@
+package gr.grnet.academicid.merchant;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.*;
+import gr.grnet.academicid.merchant.domain.Inspector;
+import gr.grnet.academicid.merchant.domain.Offer;
+import gr.grnet.academicid.merchant.parser.InspectProviderOfferResponse;
+import gr.grnet.academicid.merchant.parser.JSONParser;
+import gr.grnet.academicid.merchant.services.ServiceHandler;
+import gr.grnet.academicid.merchant.utilities.Constants;
+import gr.grnet.academicid.merchant.utilities.Tools;
+import org.jetbrains.annotations.NotNull;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class SingleOffer extends Activity {
+
+    private static final int SCAN_QR = 1;
+    private static final String TAG = "SERIAL_TAG";
+
+    private TextView txtvInspectionResult;
+    private TextView txtvInspectionResultError;
+
+    private ProgressDialog progressDialog;
+    private long offerId;
+    private int offerStatus;
+    private int offerBeneficiaries;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.single_offer);
+
+        // Assign views to variables
+        TextView txtvOfferTitle = (TextView) findViewById(R.id.txtv_offer_title);
+        TextView txtvOfferDescription = (TextView) findViewById(R.id.txtv_offer_description);
+        TextView txtvOfferStartDate = (TextView) findViewById(R.id.txtv_offer_startDate);
+        TextView txtvOfferEndDate = (TextView) findViewById(R.id.txtv_offer_endDate);
+        TextView txtOfferCriteria = (TextView) findViewById(R.id.txtv_offer_criteria);
+
+        txtvInspectionResult = (TextView) findViewById(R.id.txtv_offer_inspectionResult);
+        txtvInspectionResultError = (TextView) findViewById(R.id.txtv_offer_inspectionResultError);
+
+        Button btnScanQR = (Button) findViewById(R.id.btn_scan_qr);
+        RelativeLayout rellaySerialInput = (RelativeLayout) findViewById(R.id.rellay_serial_input);
+
+
+        DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
+
+        // getting intent data
+        Intent intent = getIntent();
+
+        // Get values from intent extras
+        offerId = intent.getLongExtra(Offer.ID, -1L);
+        String offerTitle = intent.getStringExtra(Offer.TITLE);
+        String offerDescription = intent.getStringExtra(Offer.DESCRIPTION);
+        offerStatus = intent.getIntExtra(Offer.STATUS, 0);
+        offerBeneficiaries = intent.getIntExtra(Offer.BENEFICIARIES, 0);
+        Long offerStartDate = intent.getLongExtra(Offer.START_DATE, 0L);
+        Long offerEndDate = intent.getLongExtra(Offer.END_DATE, 0L);
+        String offerCriteria = intent.getStringExtra(Offer.CRITERIA);
+
+        // Format values to display them on screen
+        String offerStartDateStr = format.format(new Date(offerStartDate));
+        String offerEndDateStr = format.format(new Date(offerEndDate));
+        String newOfferCriteria = offerCriteria.replaceAll("<br>", "\n");
+
+        // Displaying offer values on screen
+        txtvOfferTitle.setText(offerTitle);
+        txtvOfferDescription.setText(offerDescription);
+        txtvOfferStartDate.setText(offerStartDateStr);
+        txtvOfferEndDate.setText(offerEndDateStr);
+        txtOfferCriteria.setText(newOfferCriteria);
+
+        // If offer is active then show ScanQR and InputSerial views for validating an offer
+        if (offerStatus == Offer.ACTIVE) {
+            txtvOfferTitle.setTextAppearance(this, R.style.title_green);
+        } else {
+            txtvOfferTitle.setTextAppearance(this, R.style.title_orange);
+
+            btnScanQR.setVisibility(View.GONE);
+            rellaySerialInput.setVisibility(View.GONE);
+        }
+    }
+
+    public void scanQR(View view) {
+        Intent intent = new Intent(this, ScanQR.class);
+        startActivityForResult(intent, SCAN_QR);
+    }
+
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == SCAN_QR) {
+            if (resultCode == RESULT_OK) {
+
+                String scanResult = data.getStringExtra(ScanQR.SCAN_RESULT);
+                validate(scanResult);
+            }
+        }
+    }
+
+    // Method called after 'Check Serial Number' button is pressed
+    public void checkSerialNo(View view) {
+        // After 'Check Id' button is pressed, hide soft keyboard
+        InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (getCurrentFocus() != null)
+            inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+
+        String input = ((EditText) findViewById(R.id.etxt_serial_number)).getText().toString();
+        validate(input);
+    }
+
+    private void validate(String academicId) {
+        // The passed parameter should be a 12 digits numeric value. Otherwise show invalid Academic ID without making an network call
+        if ((academicId.length() == 12) && Tools.isNumericValue(academicId)) {
+            Inspector inspector = MerchantApplication.getInspector();
+            Offer offer = new Offer();
+
+            offer.setId(offerId);
+            offer.setStatus(offerStatus);
+            offer.setBeneficiaries(offerBeneficiaries);
+            offer.setAvailableAllAcademics(true);
+
+            new ValidateOffer().execute(inspector.getUsername(), inspector.getPasswordHash(), offer, academicId);
+        } else {
+            txtvInspectionResult.setVisibility(View.VISIBLE);
+            txtvInspectionResult.setTextAppearance(this, R.style.color_orange);
+            txtvInspectionResult.setText(R.string.msg_invalid_input);
+        }
+    }
+
+    private class ValidateOffer extends AsyncTask<Object, Void, String> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+            // Showing progress dialog
+            progressDialog = new ProgressDialog(SingleOffer.this);
+            progressDialog.setMessage(getString(R.string.msg_wait));
+            progressDialog.setCancelable(false);
+            progressDialog.show();
+        }
+
+        @Override
+        protected String doInBackground(Object... variables) {
+            return ServiceHandler.makeInspectProviderOfferCall((String) variables[0], (String) variables[1], (Offer) variables[2], (String) variables[3]);
+        }
+
+        @Override
+        protected void onPostExecute(String result) {
+            super.onPostExecute(result);
+            // Dismiss the progress dialog
+            if (progressDialog.isShowing())
+                progressDialog.dismiss();
+
+            InspectProviderOfferResponse inspectProviderOfferResponse = JSONParser.getResultsOfInspectProviderOffer(result);
+
+            if (!inspectProviderOfferResponse.isSuccessful()) {
+                Toast.makeText(getApplicationContext(), getString(R.string.msg_error_validating_offer), Toast.LENGTH_SHORT).show();
+                Log.e(Constants.LOGTAG, "SingleOffer.ValidateOffer.OnPostExecute(): Web service returned unsuccessfully with errorCode: " + inspectProviderOfferResponse.getError());
+            } else {
+                String inspectionResultBuilder;
+
+                if (inspectProviderOfferResponse.getOfferValidity()) {
+                    inspectionResultBuilder = getResources().getString(R.string.msg_eligible_for_offer);
+
+                    txtvInspectionResult.setTextAppearance(SingleOffer.this, R.style.color_green);
+                    txtvInspectionResultError.setVisibility(View.GONE);
+                } else {
+                    inspectionResultBuilder = getResources().getString(R.string.msg_not_eligible_for_offer);
+
+                    txtvInspectionResult.setTextAppearance(SingleOffer.this, R.style.color_orange);
+                    txtvInspectionResultError.setVisibility(View.VISIBLE);
+                    txtvInspectionResultError.setText(inspectProviderOfferResponse.getErrorDescription());
+                }
+
+                txtvInspectionResult.setVisibility(View.VISIBLE);
+                inspectionResultBuilder = inspectionResultBuilder.replace(TAG, inspectProviderOfferResponse.getAcademicId().toString());
+                txtvInspectionResult.setText(inspectionResultBuilder);
+            }
+        }
+    }
+
+    // Method called after 'Clear Content' button is pressed
+    public void clearContent(View view) {
+        EditText serialInput = (EditText) findViewById(R.id.etxt_serial_number);
+        serialInput.setText("");
+
+        txtvInspectionResult.setVisibility(View.GONE);
+        txtvInspectionResultError.setVisibility(View.GONE);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.menu_single_offer, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, @NotNull MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.menu_offers:
+                startActivity(new Intent(this, OfferList.class));
+                return true;
+            case R.id.menu_settings:
+                startActivity(new Intent(this, Preferences.class));
+                return true;
+            default:
+                return super.onMenuItemSelected(featureId, item);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/src/gr/grnet/academicid/merchant/domain/Inspector.java b/Main/src/gr/grnet/academicid/merchant/domain/Inspector.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a687cf1ad541524c183559432088c1ede13ec2f
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/domain/Inspector.java
@@ -0,0 +1,92 @@
+package gr.grnet.academicid.merchant.domain;
+
+
+public class Inspector {
+
+    public static final String FIRSTNAME = "firstname";
+    public static final String LASTNAME = "lastname";
+    public static final String USERNAME = "username";
+    public static final String PASSWORD_HASH = "passwordHash";
+    public static final String CHANGE_PSW_AT_LOGIN = "changePassword";
+    public static final String ORG_ID = "orgId";
+    public static final String ORG_NAME = "orgName";
+    public static final String ORG_DESCRIPTION = "orgDescription";
+
+    private String firstname;
+    private String lastname;
+    private String username;
+    private String passwordHash;
+    private boolean changePswAtLogin;
+    private Long orgId;
+    private String orgName;
+    private String orgDescription;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public Inspector() {
+    }
+
+    public String getFirstname() {
+        return firstname;
+    }
+
+    public void setFirstname(String firstname) {
+        this.firstname = firstname;
+    }
+
+    public String getLastname() {
+        return lastname;
+    }
+
+    public void setLastname(String lastname) {
+        this.lastname = lastname;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPasswordHash() {
+        return passwordHash;
+    }
+
+    public void setPasswordHash(String passwordHash) {
+        this.passwordHash = passwordHash;
+    }
+
+    public boolean shouldChangePswAtLogin() {
+        return changePswAtLogin;
+    }
+
+    public void setChangePswAtLogin(boolean changePswAtLogin) {
+        this.changePswAtLogin = changePswAtLogin;
+    }
+
+    public Long getOrgId() {
+        return orgId;
+    }
+
+    public void setOrgId(Long orgId) {
+        this.orgId = orgId;
+    }
+
+    public String getOrgName() {
+        return orgName;
+    }
+
+    public void setOrgName(String orgName) {
+        this.orgName = orgName;
+    }
+
+    public String getOrgDescription() {
+        return orgDescription;
+    }
+
+    public void setOrgDescription(String orgDescription) {
+        this.orgDescription = orgDescription;
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/domain/Offer.java b/Main/src/gr/grnet/academicid/merchant/domain/Offer.java
new file mode 100644
index 0000000000000000000000000000000000000000..336eb0adfb56b260517eb977172c7f84e08b1966
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/domain/Offer.java
@@ -0,0 +1,134 @@
+package gr.grnet.academicid.merchant.domain;
+
+import java.util.List;
+
+@SuppressWarnings("UnusedDeclaration")
+public class Offer {
+
+    public static final String ID = "id";
+    public static final String TITLE = "title";
+    public static final String DESCRIPTION = "description";
+    public static final String STATUS = "status";
+    public static final String START_DATE = "startDate";
+    public static final String END_DATE = "endDate";
+    public static final String BENEFICIARIES = "beneficiaries";
+    public static final String AVAILABLE_ALL_PREFECTURES = "availableAllPrefectures";
+    public static final String AVAILABLE_ALL_ACADEMICS = "availableAllAcademics";
+    public static final String CRITERIA = "criteria";
+
+    public static final int ACTIVE = 3;
+
+    private long id;
+    private String title;
+    private String description;
+    private int status;
+    private long startDate;
+    private Long endDate;
+    private int beneficiaries;
+    private boolean availableAllPrefectures;
+    private List<Integer> prefectures;
+    private boolean availableAllAcademics;
+    private List<Integer> academics;
+    private String criteria;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public Offer() {
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public long getStartDate() {
+        return startDate;
+    }
+
+    public void setStartDate(long startDate) {
+        this.startDate = startDate;
+    }
+
+    public Long getEndDate() {
+        return endDate;
+    }
+
+    public void setEndDate(Long endDate) {
+        this.endDate = endDate;
+    }
+
+    public int getBeneficiaries() {
+        return beneficiaries;
+    }
+
+    public void setBeneficiaries(int beneficiaries) {
+        this.beneficiaries = beneficiaries;
+    }
+
+    public boolean isAvailableAllPrefectures() {
+        return availableAllPrefectures;
+    }
+
+    public void setAvailableAllPrefectures(boolean availableAllPrefectures) {
+        this.availableAllPrefectures = availableAllPrefectures;
+    }
+
+    public List<Integer> getPrefectures() {
+        return prefectures;
+    }
+
+    public void setPrefectures(List<Integer> prefectures) {
+        this.prefectures = prefectures;
+    }
+
+    public boolean isAvailableAllAcademics() {
+        return availableAllAcademics;
+    }
+
+    public void setAvailableAllAcademics(boolean availableAllAcademics) {
+        this.availableAllAcademics = availableAllAcademics;
+    }
+
+    public List<Integer> getAcademics() {
+        return academics;
+    }
+
+    public void setAcademics(List<Integer> academics) {
+        this.academics = academics;
+    }
+
+    public String getCriteria() {
+        return criteria;
+    }
+
+    public void setCriteria(String criteria) {
+        this.criteria = criteria;
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/parser/ChangePasswordResponse.java b/Main/src/gr/grnet/academicid/merchant/parser/ChangePasswordResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f671cc631e6d53ef8f058543e37a7f0b7b27ae3
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/parser/ChangePasswordResponse.java
@@ -0,0 +1,35 @@
+package gr.grnet.academicid.merchant.parser;
+
+@SuppressWarnings("UnusedDeclaration")
+public class ChangePasswordResponse {
+
+    private String response;
+    private String error;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public ChangePasswordResponse(String response, String error) {
+        this.response = response;
+        this.error = error;
+    }
+
+    public String getResponse() {
+        return response;
+    }
+
+    public void setResponse(String response) {
+        this.response = response;
+    }
+
+    public String getError() {
+        return error;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+
+    public boolean isSuccessful() {
+        return (response.equals(JSONParser.RESPONSE_SUCCESSFUL));
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/parser/InspectProviderOfferResponse.java b/Main/src/gr/grnet/academicid/merchant/parser/InspectProviderOfferResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..7baceb2d9b570169659460af4fb51321ab51bd32
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/parser/InspectProviderOfferResponse.java
@@ -0,0 +1,73 @@
+package gr.grnet.academicid.merchant.parser;
+
+@SuppressWarnings("UnusedDeclaration")
+public class InspectProviderOfferResponse {
+
+    private String response;
+    private String error;
+    private Long academicId;
+    private Boolean offerValidity;
+    private String errorDescription;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public InspectProviderOfferResponse(String response, String error) {
+        this.response = response;
+        this.error = error;
+        this.academicId = null;
+        this.offerValidity = null;
+        this.errorDescription = null;
+    }
+
+    public InspectProviderOfferResponse(String response, Long academicId, Boolean offerValidity, String errorDescription) {
+        this.response = response;
+        this.error = null;
+        this.academicId = academicId;
+        this.offerValidity = offerValidity;
+        this.errorDescription = errorDescription;
+    }
+
+    public String getResponse() {
+        return response;
+    }
+
+    public void setResponse(String response) {
+        this.response = response;
+    }
+
+    public String getError() {
+        return error;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+
+    public Long getAcademicId() {
+        return academicId;
+    }
+
+    public void setAcademicId(Long academicId) {
+        this.academicId = academicId;
+    }
+
+    public Boolean getOfferValidity() {
+        return offerValidity;
+    }
+
+    public void setOfferValidity(Boolean offerValidity) {
+        this.offerValidity = offerValidity;
+    }
+
+    public String getErrorDescription() {
+        return errorDescription;
+    }
+
+    public void setErrorDescription(String errorDescription) {
+        this.errorDescription = errorDescription;
+    }
+
+    public boolean isSuccessful() {
+        return (response.equals(JSONParser.RESPONSE_SUCCESSFUL));
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/parser/JSONParser.java b/Main/src/gr/grnet/academicid/merchant/parser/JSONParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..399b8a272991cace0c43bcd0f18e97943ea8de47
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/parser/JSONParser.java
@@ -0,0 +1,163 @@
+package gr.grnet.academicid.merchant.parser;
+
+import android.util.Log;
+import gr.grnet.academicid.merchant.domain.*;
+import gr.grnet.academicid.merchant.utilities.Constants;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JSONParser {
+
+    // JSON Tags
+    private static final String TAG_RESPONSE = "response";
+    private static final String TAG_RESPONSE_ERROR = "errorReason";
+
+    public static final String RESPONSE_SUCCESSFUL = "SUCCESS";
+    public static final String RESPONSE_FAILED = "FAILURE";
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    /**
+     * Prevents this class from being instantiated.
+     */
+    private JSONParser() {
+    }
+
+    /**
+     * This method parses a json string and creates a {@link gr.grnet.academicid.merchant.parser.LoadUserResponse} object.
+     * It is called after {@link gr.grnet.academicid.merchant.services.ServiceHandler#makeSingInCall(String, String)}
+     *
+     * @param jsonString The string that should be parsed.
+     * @return A {@link gr.grnet.academicid.merchant.parser.LoadUserResponse} object.
+     */
+    public static LoadUserResponse getResultOfLoadUser(String jsonString) {
+        try {
+            JSONObject jsonObject = new JSONObject(jsonString);
+            String response = jsonObject.getString(TAG_RESPONSE);
+
+            if (response.equals(RESPONSE_SUCCESSFUL)) {
+                Inspector inspector = new Inspector();
+
+                JSONObject user = jsonObject.getJSONObject("user");
+                inspector.setFirstname(user.getString("firstName"));
+                inspector.setLastname(user.getString("lastName"));
+                inspector.setUsername(user.getString("username"));
+                inspector.setChangePswAtLogin(user.getBoolean("changePassword"));
+
+                JSONObject organization = user.getJSONObject("organization");
+                inspector.setOrgId(organization.getLong("id"));
+                inspector.setOrgName(organization.getString("name"));
+                inspector.setOrgDescription(organization.getString("description"));
+
+                return new LoadUserResponse(RESPONSE_SUCCESSFUL, null, inspector);
+            } else {
+                String error = jsonObject.getString(TAG_RESPONSE_ERROR);
+                return new LoadUserResponse(RESPONSE_FAILED, error, null);
+            }
+        } catch (JSONException e) {
+            Log.e(Constants.LOGTAG, "JSONParser.getResultOfLoadUser(): Error while parsing string: " + jsonString);
+            return null;
+        }
+    }
+
+    /**
+     * This method parses a json string and creates a {@link gr.grnet.academicid.merchant.parser.LoadProviderOffersResponse} object
+     * It is called after {@link gr.grnet.academicid.merchant.services.ServiceHandler#makeLoadProviderOffersCall(String, String)}
+     *
+     * @param jsonString The string that should be parsed.
+     * @return A {@link gr.grnet.academicid.merchant.parser.LoadProviderOffersResponse} object.
+     */
+    public static LoadProviderOffersResponse getResultOfLoadProviderOffers(String jsonString) {
+        try {
+            JSONObject jsonObject = new JSONObject(jsonString);
+            String response = jsonObject.getString(TAG_RESPONSE);
+
+            if (response.equals(RESPONSE_SUCCESSFUL)) {
+                List<Offer> offerList = new ArrayList<Offer>();
+                JSONArray jsonArray = jsonObject.getJSONArray("discountOffers");
+
+                for (int i = 0; i < jsonArray.length(); i++) {
+                    Offer offer = new Offer();
+                    JSONObject jsonOffer = jsonArray.getJSONObject(i);
+
+                    offer.setId(jsonOffer.getLong("offerId"));
+                    offer.setTitle(jsonOffer.getString("title"));
+                    offer.setDescription(jsonOffer.getString("description"));
+                    offer.setStatus(jsonOffer.getInt("offerStatus"));
+                    offer.setStartDate(jsonOffer.getLong("startDate"));
+                    offer.setEndDate(jsonOffer.getLong("endDate"));
+                    offer.setBeneficiaries(jsonOffer.getInt("beneficiaries"));
+                    offer.setAvailableAllPrefectures(jsonOffer.getBoolean("availableToAllPrefectures"));
+                    offer.setAvailableAllAcademics(jsonOffer.getBoolean("availableToAllAcademics"));
+                    offer.setCriteria(jsonOffer.getString("criteria"));
+
+                    offerList.add(offer);
+                }
+
+                return new LoadProviderOffersResponse(RESPONSE_SUCCESSFUL, null, offerList);
+            } else {
+                String error = jsonObject.getString(TAG_RESPONSE_ERROR);
+                return new LoadProviderOffersResponse(RESPONSE_FAILED, error, null);
+            }
+        } catch (JSONException e) {
+            Log.e(Constants.LOGTAG, "JSONParser.LoadProviderOffersResponse(): Error while parsing string: " + jsonString);
+            return null;
+        }
+    }
+
+    /**
+     * This method parses a json string and creates a {@link gr.grnet.academicid.merchant.parser.InspectProviderOfferResponse} object
+     * It is called after {@link gr.grnet.academicid.merchant.services.ServiceHandler#makeInspectProviderOfferCall(String, String, gr.grnet.academicid.merchant.domain.Offer, String)}
+     *
+     * @param jsonString The string that should be parsed.
+     * @return A {@link gr.grnet.academicid.merchant.parser.InspectProviderOfferResponse} object.
+     */
+    public static InspectProviderOfferResponse getResultsOfInspectProviderOffer(String jsonString) {
+        try {
+            JSONObject jsonObject = new JSONObject(jsonString);
+            String response = jsonObject.getString(TAG_RESPONSE);
+
+            if (response.equals(RESPONSE_SUCCESSFUL)) {
+                JSONObject offerInspection = jsonObject.getJSONObject("inspectionResult");
+                Long academicId = Long.valueOf(offerInspection.getString("academicId"));
+                Boolean validOffer = offerInspection.getBoolean("valid");
+                String errorDescription = offerInspection.getString("error");
+
+                return new InspectProviderOfferResponse(RESPONSE_SUCCESSFUL, academicId, validOffer, errorDescription);
+            } else {
+                String error = jsonObject.getString(TAG_RESPONSE_ERROR);
+                return new InspectProviderOfferResponse(RESPONSE_FAILED, error);
+            }
+        } catch (JSONException e) {
+            Log.e(Constants.LOGTAG, "JSONParser.LoadProviderOffersResponse(): Error while parsing string: " + jsonString);
+            return null;
+        }
+    }
+
+    /**
+     * This method parses a json string and creates a {@link gr.grnet.academicid.merchant.parser.ChangePasswordResponse} object.
+     *
+     * @param jsonString The string that should be parsed.
+     * @return A {@link gr.grnet.academicid.merchant.parser.ChangePasswordResponse} object.
+     */
+    public static ChangePasswordResponse getResultOfUpdatePassword(String jsonString) {
+        try {
+            JSONObject jsonObject = new JSONObject(jsonString);
+            String response = jsonObject.getString(TAG_RESPONSE);
+
+            if (response.equals(RESPONSE_SUCCESSFUL)) {
+                return new ChangePasswordResponse(RESPONSE_SUCCESSFUL, null);
+            } else {
+                String error = jsonObject.getString(TAG_RESPONSE_ERROR);
+                return new ChangePasswordResponse(RESPONSE_FAILED, error);
+            }
+        } catch (JSONException e) {
+            Log.e(Constants.LOGTAG, "JSONParser.getResultOfUpdatePassword(): Error while parsing string: " + jsonString);
+            return null;
+        }
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/parser/LoadProviderOffersResponse.java b/Main/src/gr/grnet/academicid/merchant/parser/LoadProviderOffersResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..66a5f06c7198a92bea9eb68edaad17fc48b6e40a
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/parser/LoadProviderOffersResponse.java
@@ -0,0 +1,49 @@
+package gr.grnet.academicid.merchant.parser;
+
+import gr.grnet.academicid.merchant.domain.Offer;
+
+import java.util.List;
+
+@SuppressWarnings("UnusedDeclaration")
+public class LoadProviderOffersResponse {
+
+    private String response;
+    private String error;
+    private List<Offer> offers;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public LoadProviderOffersResponse(String response, String error, List<Offer> offers) {
+        this.response = response;
+        this.error = error;
+        this.offers = offers;
+    }
+
+    public String getResponse() {
+        return response;
+    }
+
+    public void setResponse(String response) {
+        this.response = response;
+    }
+
+    public String getError() {
+        return error;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+
+    public List<Offer> getOffers() {
+        return offers;
+    }
+
+    public void setOffers(List<Offer> offers) {
+        this.offers = offers;
+    }
+
+    public boolean isSuccessful() {
+        return (response.equals(JSONParser.RESPONSE_SUCCESSFUL));
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/parser/LoadUserResponse.java b/Main/src/gr/grnet/academicid/merchant/parser/LoadUserResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b99e3bc20eaad9574dec83c848fc11c43fc116d
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/parser/LoadUserResponse.java
@@ -0,0 +1,47 @@
+package gr.grnet.academicid.merchant.parser;
+
+import gr.grnet.academicid.merchant.domain.Inspector;
+
+@SuppressWarnings("UnusedDeclaration")
+public class LoadUserResponse {
+
+    private String response;
+    private String error;
+    private Inspector inspector;
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    public LoadUserResponse(String response, String error, Inspector inspector) {
+        this.response = response;
+        this.error = error;
+        this.inspector = inspector;
+    }
+
+    public String getResponse() {
+        return response;
+    }
+
+    public void setResponse(String response) {
+        this.response = response;
+    }
+
+    public String getError() {
+        return error;
+    }
+
+    public void setError(String error) {
+        this.error = error;
+    }
+
+    public Inspector getInspector() {
+        return inspector;
+    }
+
+    public void setInspector(Inspector inspector) {
+        this.inspector = inspector;
+    }
+
+    public boolean isSuccessful() {
+        return (response.equals(JSONParser.RESPONSE_SUCCESSFUL));
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/services/ServiceHandler.java b/Main/src/gr/grnet/academicid/merchant/services/ServiceHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..553a2f8ef2079d55bd0d98c1e77501a297cb039d
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/services/ServiceHandler.java
@@ -0,0 +1,178 @@
+package gr.grnet.academicid.merchant.services;
+
+import android.util.Log;
+import gr.grnet.academicid.merchant.domain.Offer;
+import gr.grnet.academicid.merchant.utilities.Constants;
+import gr.grnet.academicid.merchant.utilities.Tools;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+
+public class ServiceHandler {
+
+    // The URL of the server that handles the requests
+    private static final String URL = "http://academicidapp.grnet.gr:8080/";
+//    private static final String URL = "http://academicidappbuilder.grnet.gr:8080/";
+
+    // Path of web services
+    private static final String PATH = "admin/web/ws/users/";
+
+    // Each string represents a different call to a web service
+    private static final String LOAD_USER = "loadUser"; // Get method
+    private static final String LOAD_PROVIDER_OFFERS = "loadProviderOffers"; // Get method
+    private static final String INSPECT_PROVIDER_OFFER = "inspectProviderOffer"; // Post method
+    private static final String CHANGE_PSW = "updatePassword"; // Post method
+
+    // This is the content type dictated by server side.
+    private static final String DEFAULT_CONTENT_TYPE = "application/json";
+
+    // This is the accepted encoding dictated by server side.
+    private static final String ACCEPTED_ENCODING = "application/json";
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
+
+    /**
+     * Prevents this class from being instantiated.
+     */
+    private ServiceHandler() {
+    }
+
+    /**
+     * This method verifies that a user is a valid user.
+     *
+     * @param username     The username of the user.
+     * @param passwordHash The password of the user hashed by {@link Tools#getHash(String)}.
+     * @return A json string.
+     */
+    public static String makeSingInCall(String username, String passwordHash) {
+        try {
+            HttpGet httpMethod = new HttpGet(URL + PATH + LOAD_USER);
+            httpMethod.addHeader("Content-Type", DEFAULT_CONTENT_TYPE);
+            httpMethod.addHeader("Accept-Encoding", ACCEPTED_ENCODING);
+
+            String credentialsEncoded = Tools.encodeBase64(username, passwordHash);
+            httpMethod.addHeader("Authorization", "Basic " + credentialsEncoded);
+
+            DefaultHttpClient client = new DefaultHttpClient();
+            HttpResponse httpResponse = client.execute(httpMethod);
+            HttpEntity httpEntity = httpResponse.getEntity();
+
+            return EntityUtils.toString(httpEntity);
+        } catch (IOException e) {
+            Log.e(Constants.LOGTAG, "ServiceHandler.makeSignInCall(): Error while user: " + username + " trying to sign in ", e);
+            return null;
+        }
+    }
+
+    /**
+     * This method retrieves the offers of the provider that user belongs to.
+     *
+     * @param username     The username of the user.
+     * @param passwordHash The password of the user hashed by {@link Tools#getHash(String)}.
+     * @return a json string.
+     */
+    public static String makeLoadProviderOffersCall(String username, String passwordHash) {
+        try {
+            HttpGet httpMethod = new HttpGet(URL + PATH + LOAD_PROVIDER_OFFERS);
+            httpMethod.addHeader("Content-Type", DEFAULT_CONTENT_TYPE);
+            httpMethod.addHeader("Accept-Encoding", ACCEPTED_ENCODING);
+
+            String credentialsEncoded = Tools.encodeBase64(username, passwordHash);
+            httpMethod.addHeader("Authorization", "Basic " + credentialsEncoded);
+
+            DefaultHttpClient client = new DefaultHttpClient();
+            HttpResponse httpResponse = client.execute(httpMethod);
+            HttpEntity httpEntity = httpResponse.getEntity();
+
+            return EntityUtils.toString(httpEntity);
+        } catch (IOException e) {
+            Log.e(Constants.LOGTAG, "ServiceHandler.makeLoadProviderOffersCall(): Error while user: " + username + " trying to retrieve provider offers", e);
+            return null;
+        }
+    }
+
+    /**
+     * This method verifies if an owner of an academic ID is eligible of an offer.
+     *
+     * @param username     The username of the user.
+     * @param passwordHash The password of the user hashed by {@link Tools#getHash(String)}.
+     * @param offer        The offer for which we enquire if the owner of the academic Id is eligible.
+     * @param academicId   The serial number of the Academic ID card.
+     * @return a json string.
+     */
+    public static String makeInspectProviderOfferCall(String username, String passwordHash, Offer offer, String academicId) {
+        try {
+            HttpPost httpMethod = new HttpPost(URL + PATH + INSPECT_PROVIDER_OFFER);
+            httpMethod.addHeader("Content-Type", DEFAULT_CONTENT_TYPE);
+            httpMethod.addHeader("Accept-Encoding", ACCEPTED_ENCODING);
+
+            String credentialsEncoded = Tools.encodeBase64(username, passwordHash);
+            httpMethod.addHeader("Authorization", "Basic " + credentialsEncoded);
+
+            JSONObject jsonOffer = new JSONObject();
+            jsonOffer.put("offerId", offer.getId());
+            jsonOffer.put("offerStatus", offer.getStatus());
+            jsonOffer.put("beneficiaries", offer.getBeneficiaries());
+            jsonOffer.put("availableToAllAcademics", offer.isAvailableAllAcademics());
+            jsonOffer.put("academicID", academicId);
+
+            httpMethod.setEntity(new StringEntity(jsonOffer.toString()));
+
+            DefaultHttpClient client = new DefaultHttpClient();
+            HttpResponse httpResponse = client.execute(httpMethod);
+            HttpEntity httpEntity = httpResponse.getEntity();
+
+            return EntityUtils.toString(httpEntity);
+        } catch (JSONException e) {
+            Log.e(Constants.LOGTAG, "ServiceHandler.makeInspectProviderOfferCall(): Error while trying to construct JSON Offer", e);
+            return null;
+        } catch (IOException e) {
+            Log.e(Constants.LOGTAG, "ServiceHandler.makeInspectProviderOfferCall(): Error while user: " + username + " trying to validate AcademicID: " + academicId + " with offer: " + offer.getId(), e);
+            return null;
+        }
+    }
+
+    /**
+     * This method performs a password change request.
+     *
+     * @param username        The username of the user.
+     * @param passwordHash    The password of the user hashed by {@link Tools#getHash(String)}.
+     * @param newPasswordHash The new password of the user hashed by {@link Tools#getHash(String)}.
+     * @return A json string.
+     */
+    public static String makeChangePswCall(String username, String passwordHash, String newPasswordHash) {
+        try {
+            HttpPost httpMethod = new HttpPost(URL + PATH + CHANGE_PSW);
+            httpMethod.addHeader("Content-Type", DEFAULT_CONTENT_TYPE);
+            httpMethod.addHeader("Accept-Encoding", ACCEPTED_ENCODING);
+
+            String credentialsEncoded = Tools.encodeBase64(username, passwordHash);
+            httpMethod.addHeader("Authorization", "Basic " + credentialsEncoded);
+
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("newPassword", newPasswordHash);
+
+            httpMethod.setEntity(new StringEntity(jsonObject.toString()));
+
+            DefaultHttpClient client = new DefaultHttpClient();
+            HttpResponse httpResponse = client.execute(httpMethod);
+            HttpEntity httpEntity = httpResponse.getEntity();
+
+            return EntityUtils.toString(httpEntity);
+        } catch (JSONException e) {
+            Log.e(Constants.LOGTAG, "ServiceHandler.makeChangePswCall(): Error while trying to construct JSON string", e);
+            return null;
+        } catch (IOException e) {
+            Log.e(Constants.LOGTAG, "ServiceHandler.makeChangePswCall(): Error while user: " + username + " trying to change password", e);
+            return null;
+        }
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/utilities/Constants.java b/Main/src/gr/grnet/academicid/merchant/utilities/Constants.java
new file mode 100644
index 0000000000000000000000000000000000000000..87f2ca80029fe588f7366823dd7cbdacebc5f865
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/utilities/Constants.java
@@ -0,0 +1,12 @@
+package gr.grnet.academicid.merchant.utilities;
+
+/**
+ * Constant globally available in Inspector application.
+ */
+public class Constants {
+
+    public static final String LOGTAG = "Merchant";
+
+    // The message digest algorithm that is used to hash user password.
+    public static final String DIGEST_ALGORITHM = "MD5";
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/utilities/SharedPrefs.java b/Main/src/gr/grnet/academicid/merchant/utilities/SharedPrefs.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd15f611b159dfe9e59dc4672c30c2aca2c8d8fa
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/utilities/SharedPrefs.java
@@ -0,0 +1,79 @@
+package gr.grnet.academicid.merchant.utilities;
+
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import gr.grnet.academicid.merchant.MerchantApplication;
+import gr.grnet.academicid.merchant.domain.Inspector;
+
+/**
+ * Helper class for handling Preferences.
+ */
+public class SharedPrefs {
+
+    /**
+     * Prevents this class from being instantiated.
+     */
+    private SharedPrefs() {
+    }
+
+    /**
+     * This method retrieves an Inspector object from Shared Preferences.
+     *
+     * @return An Inspector object.
+     */
+    public static Inspector getInspectorFromPrefs() {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MerchantApplication.getAppContext());
+
+        Inspector inspector = new Inspector();
+        inspector.setFirstname(preferences.getString(Inspector.FIRSTNAME, ""));
+        inspector.setLastname(preferences.getString(Inspector.LASTNAME, ""));
+        inspector.setUsername(preferences.getString(Inspector.USERNAME, ""));
+        inspector.setPasswordHash(preferences.getString(Inspector.PASSWORD_HASH, ""));
+        inspector.setChangePswAtLogin(preferences.getBoolean(Inspector.CHANGE_PSW_AT_LOGIN, false));
+        inspector.setOrgId(preferences.getLong(Inspector.ORG_ID, 0));
+        inspector.setOrgName(preferences.getString(Inspector.ORG_NAME, ""));
+        inspector.setOrgDescription(preferences.getString(Inspector.ORG_DESCRIPTION, ""));
+
+        return inspector;
+    }
+
+    /**
+     * This method stores Inspector object in Shared Preferences.
+     *
+     * @param inspector The Inspector object that will be saved in Shared Preferences.
+     */
+    public static void setInspectorToPrefs(Inspector inspector) {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MerchantApplication.getAppContext());
+        SharedPreferences.Editor preferencesEditor = preferences.edit();
+
+        preferencesEditor.putString(Inspector.FIRSTNAME, inspector.getFirstname());
+        preferencesEditor.putString(Inspector.LASTNAME, inspector.getLastname());
+        preferencesEditor.putString(Inspector.USERNAME, inspector.getUsername());
+        preferencesEditor.putString(Inspector.PASSWORD_HASH, inspector.getPasswordHash());
+        preferencesEditor.putBoolean(Inspector.CHANGE_PSW_AT_LOGIN, inspector.shouldChangePswAtLogin());
+        preferencesEditor.putLong(Inspector.ORG_ID, inspector.getOrgId());
+        preferencesEditor.putString(Inspector.ORG_NAME, inspector.getOrgName());
+        preferencesEditor.putString(Inspector.ORG_DESCRIPTION, inspector.getOrgDescription());
+
+        preferencesEditor.commit();
+    }
+
+    /**
+     * This method clear Inspector values from Shared Preferences.
+     */
+    public static void ClearInspectorFromPrefs() {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MerchantApplication.getAppContext());
+        SharedPreferences.Editor preferencesEditor = preferences.edit();
+
+        preferencesEditor.remove(Inspector.FIRSTNAME);
+        preferencesEditor.remove(Inspector.LASTNAME);
+        preferencesEditor.remove(Inspector.USERNAME);
+        preferencesEditor.remove(Inspector.PASSWORD_HASH);
+        preferencesEditor.remove(Inspector.CHANGE_PSW_AT_LOGIN);
+        preferencesEditor.remove(Inspector.ORG_ID);
+        preferencesEditor.remove(Inspector.ORG_NAME);
+        preferencesEditor.remove(Inspector.ORG_DESCRIPTION);
+
+        preferencesEditor.commit();
+    }
+}
diff --git a/Main/src/gr/grnet/academicid/merchant/utilities/Tools.java b/Main/src/gr/grnet/academicid/merchant/utilities/Tools.java
new file mode 100644
index 0000000000000000000000000000000000000000..bac41d3f237e2a71b267b8a8b70d39294a31fe12
--- /dev/null
+++ b/Main/src/gr/grnet/academicid/merchant/utilities/Tools.java
@@ -0,0 +1,133 @@
+package gr.grnet.academicid.merchant.utilities;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.util.Base64;
+import android.util.Log;
+import gr.grnet.academicid.merchant.MerchantApplication;
+import gr.grnet.academicid.merchant.domain.Offer;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper class with utility functionality.
+ */
+public class Tools {
+
+    /**
+     * Prevents this class from being instantiated.
+     */
+    private Tools() {
+    }
+
+    /**
+     * This method verifies that the device has network connectivity.
+     *
+     * @return True if the device has network connectivity.
+     */
+    public static boolean isNetworkAvailable() {
+        ConnectivityManager connectivityManager = (ConnectivityManager) MerchantApplication.getAppContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
+        return (activeNetworkInfo != null && activeNetworkInfo.isConnected());
+    }
+
+    /**
+     * This method verifies that a camera is available.
+     *
+     * @return True if the camera of the device is available.
+     */
+    public static boolean isCameraAvailable() {
+        PackageManager packageManager = MerchantApplication.getAppContext().getPackageManager();
+        return (packageManager != null && packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA));
+    }
+
+    /**
+     * This method verifies that the passed parameter is numeric.
+     *
+     * @param numStr Contains the questioned value.
+     * @return True if numStr is numeric.
+     */
+    public static boolean isNumericValue(String numStr) {
+        try {
+            //noinspection ResultOfMethodCallIgnored
+            Long.parseLong(numStr);
+            return true;
+        } catch (NumberFormatException nfe) {
+            return false;
+        }
+    }
+
+    /**
+     * This method calculates the hash value of the parameter passed based on the DIGEST_ALGORITHM that is used.
+     *
+     * @param message The plain message that will be hashed
+     * @return The hash equivalent of message according to digest algorithm that was used.
+     */
+    public static String getHash(String message) {
+        try {
+            MessageDigest messageDigest = MessageDigest.getInstance(Constants.DIGEST_ALGORITHM);
+            byte[] hashedArray = messageDigest.digest(message.getBytes());
+            BigInteger hashedNumber = new BigInteger(1, hashedArray);
+
+            return hashedNumber.toString(16);
+        } catch (NoSuchAlgorithmException e) {
+            Log.e(Constants.LOGTAG, "Tools.getHash(): The designated algorithm: " + Constants.DIGEST_ALGORITHM + " can't be found.", e);
+            return null;
+        }
+    }
+
+    /**
+     * This method concatenates the two parameters passed and encodes them using Base64 scheme.
+     *
+     * @param str1 This first parameter that needs to be encoded.
+     * @param str2 This second parameter  that needs to be encoded.
+     * @return a encoded with Base64 scheme String.
+     */
+    public static String encodeBase64(String str1, String str2) {
+        byte[] authEncBytes = Base64.encode((str1 + ":" + str2).getBytes(), Base64.NO_WRAP);
+        return new String(authEncBytes);
+    }
+
+    /**
+     * This method splits the offers  provided with offerList param to two lists based on whether the offer is active or not.
+     *
+     * @param offerList         the original list containing both active and inactive offers.
+     * @param activeOfferList   the list containing only active offers.
+     * @param inactiveOfferList the list containing only inactive offers.
+     */
+    public static void splitOffers(List<Offer> offerList, List<Offer> activeOfferList, List<Offer> inactiveOfferList) {
+        for (Offer offer : offerList) {
+            if (offer.getStatus() == 3) //Status code 3 designates Active Offers
+                activeOfferList.add(offer);
+            else
+                inactiveOfferList.add(offer);
+        }
+    }
+
+    /**
+     * This method gets a list with offers and prepares it to be fed in a list adapter.
+     *
+     * @param offerList the original list with offers.
+     * @return a List < Map < String,String>> for the ListAdapter.
+     */
+    public static List<Map<String, String>> prepareListForAdapter(List<Offer> offerList) {
+        List<Map<String, String>> adapterList = new ArrayList<Map<String, String>>();
+
+        for (Offer offer : offerList) {
+            Map<String, String> adapterOffer = new HashMap<String, String>();
+            adapterOffer.put(Offer.TITLE, offer.getTitle());
+            adapterOffer.put(Offer.DESCRIPTION, offer.getDescription());
+
+            adapterList.add(adapterOffer);
+        }
+        return adapterList;
+    }
+}
diff --git a/ZBarScannerLibrary/AndroidManifest.xml b/ZBarScannerLibrary/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5d5925b440dbec519e525d9f6dc5b4b784d8d4e0
--- /dev/null
+++ b/ZBarScannerLibrary/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.dm.zbar.android.scanner"
+      android:versionCode="1"
+      android:versionName="1.0">
+
+    <uses-permission android:name="android.permission.CAMERA"/>
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-sdk android:minSdkVersion="8" />
+
+    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+        <activity android:name="ZBarScannerActivity"
+                  android:screenOrientation="landscape"
+                  android:label="@string/app_name" />
+    </application>
+</manifest>
diff --git a/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/BuildConfig.java b/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/BuildConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..5cdff0b68a4c51e48ed1a40f69c80ba8e4fbdbe3
--- /dev/null
+++ b/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/BuildConfig.java
@@ -0,0 +1,8 @@
+/*___Generated_by_IDEA___*/
+
+package com.dm.zbar.android.scanner;
+
+/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
+public final class BuildConfig {
+  public final static boolean DEBUG = Boolean.parseBoolean(null);
+}
\ No newline at end of file
diff --git a/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/Manifest.java b/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/Manifest.java
new file mode 100644
index 0000000000000000000000000000000000000000..54ea9b1c6ed0fedbcb8e78a83d2739c2f54dc274
--- /dev/null
+++ b/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/Manifest.java
@@ -0,0 +1,7 @@
+/*___Generated_by_IDEA___*/
+
+package com.dm.zbar.android.scanner;
+
+/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
+public final class Manifest {
+}
\ No newline at end of file
diff --git a/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/R.java b/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/R.java
new file mode 100644
index 0000000000000000000000000000000000000000..8eaeca3fa6ac8d1902648e387ffe2901d55ae6c1
--- /dev/null
+++ b/ZBarScannerLibrary/gen/com/dm/zbar/android/scanner/R.java
@@ -0,0 +1,7 @@
+/*___Generated_by_IDEA___*/
+
+package com.dm.zbar.android.scanner;
+
+/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
+public final class R {
+}
\ No newline at end of file
diff --git a/ZBarScannerLibrary/libs/armeabi-v7a/libiconv.so b/ZBarScannerLibrary/libs/armeabi-v7a/libiconv.so
new file mode 100644
index 0000000000000000000000000000000000000000..2bcbb70c3079cdd35455410d069a23f6c8d0832a
Binary files /dev/null and b/ZBarScannerLibrary/libs/armeabi-v7a/libiconv.so differ
diff --git a/ZBarScannerLibrary/libs/armeabi-v7a/libzbarjni.so b/ZBarScannerLibrary/libs/armeabi-v7a/libzbarjni.so
new file mode 100644
index 0000000000000000000000000000000000000000..2693dbb140b58528bc90aa03c2a98c898fdfed05
Binary files /dev/null and b/ZBarScannerLibrary/libs/armeabi-v7a/libzbarjni.so differ
diff --git a/ZBarScannerLibrary/libs/armeabi/libiconv.so b/ZBarScannerLibrary/libs/armeabi/libiconv.so
new file mode 100644
index 0000000000000000000000000000000000000000..9c7150de295ff7a7fded8f00fcdb275a8ec15bf7
Binary files /dev/null and b/ZBarScannerLibrary/libs/armeabi/libiconv.so differ
diff --git a/ZBarScannerLibrary/libs/armeabi/libzbarjni.so b/ZBarScannerLibrary/libs/armeabi/libzbarjni.so
new file mode 100644
index 0000000000000000000000000000000000000000..3d4a8ac3232507703b539320c6262ad0c8aacee7
Binary files /dev/null and b/ZBarScannerLibrary/libs/armeabi/libzbarjni.so differ
diff --git a/ZBarScannerLibrary/libs/x86/libiconv.so b/ZBarScannerLibrary/libs/x86/libiconv.so
new file mode 100644
index 0000000000000000000000000000000000000000..6ab43e51d4793851deb215cfe04dba85a733d759
Binary files /dev/null and b/ZBarScannerLibrary/libs/x86/libiconv.so differ
diff --git a/ZBarScannerLibrary/libs/x86/libzbarjni.so b/ZBarScannerLibrary/libs/x86/libzbarjni.so
new file mode 100644
index 0000000000000000000000000000000000000000..d64f517ad58295affd786686c83667b0b7d0dccb
Binary files /dev/null and b/ZBarScannerLibrary/libs/x86/libzbarjni.so differ
diff --git a/ZBarScannerLibrary/libs/zbar.jar b/ZBarScannerLibrary/libs/zbar.jar
new file mode 100644
index 0000000000000000000000000000000000000000..7d50b957809c65f37e5606988e9fc06410873029
Binary files /dev/null and b/ZBarScannerLibrary/libs/zbar.jar differ
diff --git a/ZBarScannerLibrary/project.properties b/ZBarScannerLibrary/project.properties
new file mode 100644
index 0000000000000000000000000000000000000000..dfa4dd0977fb676f5e209bda13e5a285ecff5c71
--- /dev/null
+++ b/ZBarScannerLibrary/project.properties
@@ -0,0 +1,15 @@
+# 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-16
+android.library=true
diff --git a/ZBarScannerLibrary/res/drawable-hdpi/ic_launcher.png b/ZBarScannerLibrary/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..96a442e5b8e9394ccf50bab9988cb2316026245d
Binary files /dev/null and b/ZBarScannerLibrary/res/drawable-hdpi/ic_launcher.png differ
diff --git a/ZBarScannerLibrary/res/drawable-ldpi/ic_launcher.png b/ZBarScannerLibrary/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..99238729d8753585237a65b91c7cde426c90baef
Binary files /dev/null and b/ZBarScannerLibrary/res/drawable-ldpi/ic_launcher.png differ
diff --git a/ZBarScannerLibrary/res/drawable-mdpi/ic_launcher.png b/ZBarScannerLibrary/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..359047dfa4ed206e41e2354f9c6b307e713efe32
Binary files /dev/null and b/ZBarScannerLibrary/res/drawable-mdpi/ic_launcher.png differ
diff --git a/ZBarScannerLibrary/res/drawable-xhdpi/ic_launcher.png b/ZBarScannerLibrary/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000000000000000000000000000000000..71c6d760f05183ef8a47c614d8d13380c8528499
Binary files /dev/null and b/ZBarScannerLibrary/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/ZBarScannerLibrary/res/values/strings.xml b/ZBarScannerLibrary/res/values/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e73122b930392a0a22ba5640f0171e53ae913f98
--- /dev/null
+++ b/ZBarScannerLibrary/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">ZBar Scanner</string>
+</resources>
diff --git a/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/CameraPreview.java b/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/CameraPreview.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa08c5c9ba61ac5786ecde3ec128e9514d6066ba
--- /dev/null
+++ b/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/CameraPreview.java
@@ -0,0 +1,188 @@
+package com.dm.zbar.android.scanner;
+
+import android.content.Context;
+import android.hardware.Camera;
+import android.hardware.Camera.AutoFocusCallback;
+import android.hardware.Camera.PreviewCallback;
+import android.hardware.Camera.Size;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup;
+import java.io.IOException;
+import java.util.List;
+
+class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {
+    private final String TAG = "CameraPreview";
+
+    SurfaceView mSurfaceView;
+    SurfaceHolder mHolder;
+    Size mPreviewSize;
+    List<Size> mSupportedPreviewSizes;
+    Camera mCamera;
+    PreviewCallback mPreviewCallback;
+    AutoFocusCallback mAutoFocusCallback;
+
+    boolean portrait = false;
+
+    CameraPreview(Context context, PreviewCallback previewCallback, AutoFocusCallback autoFocusCb) {
+        super(context);
+
+        mPreviewCallback = previewCallback;
+        mAutoFocusCallback = autoFocusCb;
+        mSurfaceView = new SurfaceView(context);
+        addView(mSurfaceView);
+
+        // Install a SurfaceHolder.Callback so we get notified when the
+        // underlying surface is created and destroyed.
+        mHolder = mSurfaceView.getHolder();
+        mHolder.addCallback(this);
+        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+    }
+
+    public void setCamera(Camera camera) {
+        mCamera = camera;
+        if (mCamera != null) {
+            mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
+            requestLayout();
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // We purposely disregard child measurements because act as a
+        // wrapper to a SurfaceView that centers the camera preview instead
+        // of stretching it.
+        final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
+        final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
+        setMeasuredDimension(width, height);
+
+        // Check if the device is in portrait mode
+        portrait = (height > width);
+
+        if (mSupportedPreviewSizes != null) {
+            if (portrait)
+                mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, height, width);
+            else
+                mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        if (changed && getChildCount() > 0) {
+            final View child = getChildAt(0);
+
+            final int width = r - l;
+            final int height = b - t;
+
+            int previewWidth = width;
+            int previewHeight = height;
+            if (mPreviewSize != null) {
+                if (portrait) {
+                    previewWidth = mPreviewSize.height;
+                    previewHeight = mPreviewSize.width;
+                } else {
+                    previewWidth = mPreviewSize.width;
+                    previewHeight = mPreviewSize.height;
+                }
+            }
+
+            // Center the child SurfaceView within the parent.
+            if (width * previewHeight > height * previewWidth) {
+                final int scaledChildWidth = previewWidth * height / previewHeight;
+                child.layout((width - scaledChildWidth) / 2, 0,
+                        (width + scaledChildWidth) / 2, height);
+            } else {
+                final int scaledChildHeight = previewHeight * width / previewWidth;
+                child.layout(0, (height - scaledChildHeight) / 2,
+                        width, (height + scaledChildHeight) / 2);
+            }
+        }
+    }
+
+    public void hideSurfaceView() {
+        mSurfaceView.setVisibility(View.INVISIBLE);
+    }
+
+    public void showSurfaceView() {
+        mSurfaceView.setVisibility(View.VISIBLE);
+    }
+
+    public void surfaceCreated(SurfaceHolder holder) {
+        // The Surface has been created, acquire the camera and tell it where
+        // to draw.
+        try {
+            if (mCamera != null) {
+                mCamera.setPreviewDisplay(holder);
+            }
+        } catch (IOException exception) {
+            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
+        }
+    }
+
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        // Surface will be destroyed when we return, so stop the preview.
+        if (mCamera != null) {
+            mCamera.cancelAutoFocus();
+            mCamera.stopPreview();
+        }
+    }
+
+
+    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
+        final double ASPECT_TOLERANCE = 0.1;
+        double targetRatio = (double) w / h;
+        if (sizes == null) return null;
+
+        Size optimalSize = null;
+        double minDiff = Double.MAX_VALUE;
+
+        int targetHeight = h;
+
+        // Try to find an size match aspect ratio and size
+        for (Size size : sizes) {
+            double ratio = (double) size.width / size.height;
+            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
+            if (Math.abs(size.height - targetHeight) < minDiff) {
+                optimalSize = size;
+                minDiff = Math.abs(size.height - targetHeight);
+            }
+        }
+
+        // Cannot find the one match the aspect ratio, ignore the requirement
+        if (optimalSize == null) {
+            minDiff = Double.MAX_VALUE;
+            for (Size size : sizes) {
+                if (Math.abs(size.height - targetHeight) < minDiff) {
+                    optimalSize = size;
+                    minDiff = Math.abs(size.height - targetHeight);
+                }
+            }
+        }
+        return optimalSize;
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        if (holder.getSurface() == null) {
+            // preview surface does not exist
+            return;
+        }
+
+        if (mCamera != null) {
+            // Now that the size is known, set up the camera parameters and begin
+            // the preview.
+            Camera.Parameters parameters = mCamera.getParameters();
+            parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+            requestLayout();
+
+            if (portrait) mCamera.setDisplayOrientation(90);
+            mCamera.setParameters(parameters);
+            mCamera.setPreviewCallback(mPreviewCallback);
+            mCamera.startPreview();
+            mCamera.autoFocus(mAutoFocusCallback);
+        }
+    }
+
+}
diff --git a/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/ZBarConstants.java b/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/ZBarConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..f96037f1b5053b90d20a6280ed3a3eb976559392
--- /dev/null
+++ b/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/ZBarConstants.java
@@ -0,0 +1,8 @@
+package com.dm.zbar.android.scanner;
+
+public interface ZBarConstants {
+    public static final String SCAN_MODES = "SCAN_MODES";
+    public static final String SCAN_RESULT = "SCAN_RESULT";
+    public static final String SCAN_RESULT_TYPE = "SCAN_RESULT_TYPE";
+    public static final String ERROR_INFO = "ERROR_INFO";
+}
diff --git a/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/ZBarScannerActivity.java b/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/ZBarScannerActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6790c6cba9744e0de5540721ffd4bab13995540
--- /dev/null
+++ b/ZBarScannerLibrary/src/com/dm/zbar/android/scanner/ZBarScannerActivity.java
@@ -0,0 +1,188 @@
+package com.dm.zbar.android.scanner;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.os.Handler;
+import android.text.TextUtils;
+import gr.grnet.academicid.merchant.*;
+import gr.grnet.academicid.merchant.domain.Offer;
+import net.sourceforge.zbar.Config;
+import net.sourceforge.zbar.Image;
+import net.sourceforge.zbar.ImageScanner;
+import net.sourceforge.zbar.Symbol;
+import net.sourceforge.zbar.SymbolSet;
+
+public class ZBarScannerActivity extends Activity implements Camera.PreviewCallback, ZBarConstants {
+
+    private CameraPreview mPreview;
+    private Camera mCamera;
+    private ImageScanner mScanner;
+    private Handler mAutoFocusHandler;
+    private boolean mPreviewing = true;
+
+    static {
+        System.loadLibrary("iconv");
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (!isCameraAvailable()) {
+            // Cancel request if there is no rear-facing camera.
+            cancelRequest();
+            return;
+        }
+
+        // Hide the window title.
+//        requestWindowFeature(Window.FEATURE_NO_TITLE);
+//        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+
+        mAutoFocusHandler = new Handler();
+
+        // Create and configure the ImageScanner;
+        setupScanner();
+
+        // Create a RelativeLayout container that will hold a SurfaceView,
+        // and set it as the content of our activity.
+        mPreview = new CameraPreview(this, this, autoFocusCB);
+        setContentView(mPreview);
+    }
+
+    public void setupScanner() {
+        mScanner = new ImageScanner();
+        mScanner.setConfig(0, Config.X_DENSITY, 3);
+        mScanner.setConfig(0, Config.Y_DENSITY, 3);
+
+        int[] symbols = getIntent().getIntArrayExtra(SCAN_MODES);
+        if (symbols != null) {
+            mScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
+            for (int symbol : symbols) {
+                mScanner.setConfig(symbol, Config.ENABLE, 1);
+            }
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        // Open the default i.e. the first rear facing camera.
+        mCamera = Camera.open();
+        if (mCamera == null) {
+            // Cancel request if mCamera is null.
+            cancelRequest();
+            return;
+        }
+
+        mPreview.setCamera(mCamera);
+        mPreview.showSurfaceView();
+
+        mPreviewing = true;
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+        // Because the Camera object is a shared resource, it's very
+        // important to release it when the activity is paused.
+        if (mCamera != null) {
+            mPreview.setCamera(null);
+            mCamera.cancelAutoFocus();
+            mCamera.setPreviewCallback(null);
+            mCamera.stopPreview();
+            mCamera.release();
+
+            // According to Jason Kuang on http://stackoverflow.com/questions/6519120/how-to-recover-camera-preview-from-sleep,
+            // there might be surface recreation problems when the device goes to sleep. So lets just hide it and
+            // recreate on resume
+            mPreview.hideSurfaceView();
+
+            mPreviewing = false;
+            mCamera = null;
+        }
+    }
+
+    public boolean isCameraAvailable() {
+        PackageManager pm = getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
+    }
+
+    public void cancelRequest() {
+        Intent dataIntent = new Intent();
+        dataIntent.putExtra(ERROR_INFO, "Camera unavailable");
+        setResult(Activity.RESULT_CANCELED, dataIntent);
+        finish();
+    }
+
+    public void onPreviewFrame(byte[] data, Camera camera) {
+        Camera.Parameters parameters = camera.getParameters();
+        Camera.Size size = parameters.getPreviewSize();
+
+        Image barcode = new Image(size.width, size.height, "Y800");
+        barcode.setData(data);
+
+        int result = mScanner.scanImage(barcode);
+
+        if (result != 0) {
+            mCamera.cancelAutoFocus();
+            mCamera.setPreviewCallback(null);
+            mCamera.stopPreview();
+            mPreviewing = false;
+            SymbolSet syms = mScanner.getResults();
+            for (Symbol sym : syms) {
+                String symData = sym.getData();
+                if (!TextUtils.isEmpty(symData)) {
+                    Intent dataIntent = new Intent();
+                    dataIntent.putExtra(SCAN_RESULT, symData);
+                    dataIntent.putExtra(SCAN_RESULT_TYPE, sym.getType());
+                    setResult(Activity.RESULT_OK, dataIntent);
+                    finish();
+                    break;
+                }
+            }
+        }
+    }
+
+    private Runnable doAutoFocus = new Runnable() {
+        public void run() {
+            if (mCamera != null && mPreviewing) {
+                mCamera.autoFocus(autoFocusCB);
+            }
+        }
+    };
+
+    // Mimic continuous auto-focusing
+    Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
+        public void onAutoFocus(boolean success, Camera camera) {
+            mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
+        }
+    };
+
+    @Override
+    public void onBackPressed() {
+        Offer offer = MerchantApplication.getSelectedOffer();
+
+        // Starting single offer activity
+        Intent intent = new Intent(this, SingleOffer.class);
+
+        intent.putExtra(Offer.ID, offer.getId());
+        intent.putExtra(Offer.TITLE, offer.getTitle());
+        intent.putExtra(Offer.DESCRIPTION, offer.getDescription());
+        intent.putExtra(Offer.STATUS, offer.getStatus());
+        intent.putExtra(Offer.BENEFICIARIES, offer.getBeneficiaries());
+        intent.putExtra(Offer.START_DATE, offer.getStartDate());
+        intent.putExtra(Offer.END_DATE, offer.getEndDate());
+        intent.putExtra(Offer.CRITERIA, offer.getCriteria());
+
+        // Pop the existing activity instead of creating a new one
+        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+        startActivity(intent);
+    }
+}
+