From ca20ff24924d8834e6aac44978f1df3228b8991d Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Fri, 24 Nov 2017 19:47:28 -0200
Subject: [PATCH 1/9] AGILE#256: [WIP] Create notification on schedule

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 app/src/main/AndroidManifest.xml              |  11 +-
 .../ScheduleConfirmationActivity.java         | 138 +++++-
 .../agendador/SchedulesHistoryActivity.java   |   9 +-
 .../agendador/SchedulingActivity.java         |   6 +-
 .../agendador/agendador/helpers/Utils.java    |   8 +-
 ...lterListener.java => SpinnerListener.java} |  13 +-
 .../SectorSpinnerListener.java                |   3 +-
 .../ServicePlaceSpinnerListener.java          |   5 +-
 .../ServiceTypeSpinnerListener.java           |   6 +-
 .../agendador/models/Notification.java        |  79 ++++
 .../agendador/network/ApiEndpoints.java       |   5 +-
 .../agendador/agendador/network/ApiUtils.java |   4 +-
 .../ScheduleConfirmationPresenter.java        | 100 +++-
 .../services/ImageUpdateService.java          |   5 +-
 .../services/NotificationCreateService.java   | 104 +++++
 .../views/ScheduleConfirmationView.java       |   6 +-
 .../agendador/views/SpinnerActivity.java      |  10 +
 .../layout/content_schedule_confirmation.xml  | 439 +++++++++++-------
 app/src/main/res/values/integer.xml           |  13 +
 app/src/main/res/values/strings.xml           |  18 +
 20 files changed, 770 insertions(+), 212 deletions(-)
 rename app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/{schedulesHistory/FilterListener.java => SpinnerListener.java} (62%)
 rename app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/{ => scheduling}/SectorSpinnerListener.java (96%)
 rename app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/{ => scheduling}/ServicePlaceSpinnerListener.java (96%)
 rename app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/{ => scheduling}/ServiceTypeSpinnerListener.java (96%)
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/NotificationCreateService.java
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/SpinnerActivity.java

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 070cae3..2497fce 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -47,6 +47,15 @@
             </intent-filter>
         </service>
 
+        <service
+            android:name=".services.NotificationCreateService"
+            android:exported="false"
+            android:permission="android.permission.BIND_JOB_SERVICE">
+            <intent-filter>
+                <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
+            </intent-filter>
+        </service>
+
         <activity android:name=".TermActivity" />
         <activity android:name=".SchedulingActivity"/>
         <activity android:name=".CitizenListActivity" />
@@ -57,7 +66,7 @@
         <activity android:name=".RetrievalFailureActivity" />
         <activity android:name=".RetrievalSuccessActivity" />
         <activity android:name=".SchedulesHistoryActivity" />
-        <activity android:name=".ScheduleInfoActivity"></activity>
+        <activity android:name=".ScheduleInfoActivity" />
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
index ff28cb4..d08497d 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
@@ -6,6 +6,7 @@ import android.app.DialogFragment;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.graphics.Color;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.design.widget.NavigationView;
@@ -19,22 +20,30 @@ import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
+import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.ProgressBar;
+import android.widget.RadioButton;
+import android.widget.Spinner;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.Locale;
 
 import br.ufpr.c3sl.agendador.agendador.helpers.ConnectionErrorDialog;
+import br.ufpr.c3sl.agendador.agendador.helpers.DateValidator;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.UserImgHelper;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.CheckSchedules;
 import br.ufpr.c3sl.agendador.agendador.models.CitizenCompact;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
-import br.ufpr.c3sl.agendador.agendador.models.UserOutput;
 import br.ufpr.c3sl.agendador.agendador.presenters.PresenterManager;
 import br.ufpr.c3sl.agendador.agendador.presenters.ScheduleConfirmationPresenter;
 import br.ufpr.c3sl.agendador.agendador.views.ScheduleConfirmationView;
@@ -58,22 +67,27 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
 
     private ProgressBar pb_scheduleConfirmation;
 
+    private EditText et_email;
+
+    private TextView tv_email_warning;
+
     private Button bt_schedule, bt_back;
 
+    private String[] notificationTime;
+
+    private static String SPINNER_POS = "spinner_position";
+
+    private Spinner sp_notification;
+
     private static final String EXIT_CONFIRMATION_DIALOG_TAG = "exit_dialog";
 
+    private RadioButton rb_yes, rb_no;
+
     private long id;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        if(savedInstanceState == null){
-            scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(getBaseContext());
-        }else{
-            scheduleConfirmationPresenter = PresenterManager.getInstance().restorePresenter(savedInstanceState);
-            if(scheduleConfirmationPresenter == null)
-                scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(this);
-        }
         setContentView(R.layout.activity_schedule_confirmation);
 
         Bundle bundle = getIntent().getBundleExtra(Utils.SCHEDULE_BUNDLE);
@@ -146,6 +160,15 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
 
         navigationView.setNavigationItemSelectedListener(this);
 
+
+        notificationTime = getResources().getStringArray(R.array.notification_time);
+
+        sp_notification = (Spinner) findViewById(R.id.spnr_schedule_time);
+
+        sp_notification.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, notificationTime));
+
+        sp_notification.setSelection(1, true);
+
         pb_scheduleConfirmation = (ProgressBar) findViewById(R.id.pb_schedule_confirmation);
 
         TextView tv_citizen = (TextView) findViewById(R.id.tv_schedule_citizen_content);
@@ -154,7 +177,8 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         TextView tv_type = (TextView) findViewById(R.id.tv_schedule_type_content);
         TextView tv_schedule = (TextView) findViewById(R.id.tv_schedule_date_content);
         TextView tv_street = (TextView) findViewById(R.id.tv_schedule_street_content);
-
+        et_email = (EditText) findViewById(R.id.et_schedule_email);
+        tv_email_warning = (TextView) findViewById(R.id.tv_schedule_email_warning);
 
         tv_sector.setText(sectorName);
         tv_citizen.setText(citizen.getName());
@@ -172,9 +196,58 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         bt_schedule.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                scheduleConfirmationPresenter.onScheduleClicked(scheduleConfirmation, citizen);
-                bt_schedule.setEnabled(false);
-                bt_back.setEnabled(false);
+                boolean schedule = true;
+                if(rb_yes.isChecked()){
+                    if(!DateValidator.isValidEmail(et_email.getText().toString())){
+                        Toast.makeText(getBaseContext(), getResources().getString(R.string.not_valid_email), Toast.LENGTH_SHORT).show();
+                        schedule = false;
+                        tv_email_warning.setVisibility(View.VISIBLE);
+                    }else{
+                        tv_email_warning.setVisibility(View.INVISIBLE);
+                    }
+
+                }
+
+                if(schedule){
+
+                    scheduleConfirmationPresenter.onScheduleClicked(scheduleConfirmation, citizen);
+                    bt_schedule.setEnabled(false);
+                    bt_back.setEnabled(false);
+
+                }
+
+
+            }
+        });
+
+        final TextView tv_email = (TextView) findViewById(R.id.tv_schedule_email);
+
+        rb_yes = (RadioButton) findViewById(R.id.rb_notify_email_yes);
+
+        rb_yes.setChecked(true);
+
+        rb_no = (RadioButton) findViewById(R.id.rb_notify_email_no);
+
+        rb_yes.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                rb_no.setChecked(false);
+                et_email.setEnabled(true);
+                tv_email.setTextColor(Color.BLACK);
+                if(sp_notification.getSelectedItemPosition() == 0){
+                    sp_notification.setSelection(1, true);
+                }
+            }
+        });
+
+        rb_no.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                rb_yes.setChecked(false);
+                et_email.setEnabled(false);
+                et_email.setText("");
+                tv_email.setTextColor(Color.GRAY);
+                tv_email_warning.setVisibility(View.INVISIBLE);
             }
         });
 
@@ -184,6 +257,15 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
                 onBackPressed();
             }
         });
+
+        if(savedInstanceState == null){
+            scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(getBaseContext());
+        }else{
+            sp_notification.setSelection( savedInstanceState.getInt(SPINNER_POS, 1), true);
+            scheduleConfirmationPresenter = PresenterManager.getInstance().restorePresenter(savedInstanceState);
+            if(scheduleConfirmationPresenter == null)
+                scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(this);
+        }
     }
 
     @Override
@@ -202,6 +284,7 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
     @Override
     public void onSaveInstanceState(Bundle outState) {
         PresenterManager.getInstance().savePresenter(scheduleConfirmationPresenter, outState);
+        outState.putInt(SPINNER_POS, sp_notification.getSelectedItemPosition());
         super.onSaveInstanceState(outState);
     }
 
@@ -279,7 +362,36 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         }
     }
 
-    public void onSuccess(){
+    @Override
+    public void onSuccess(ScheduleConfirmation schedule){
+
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ", Locale.getDefault());
+        /*
+        * Position zero is "don't notify"
+        */
+        int reminderTimeArray[] = getResources().getIntArray(R.array.notification_time_int);
+
+        if(sp_notification.getSelectedItemPosition() != 0 ){
+            Notification notification = new Notification();
+            notification.scheduleId = schedule.getId();
+            notification.emailSent = false;
+            notification.description = "a";
+            //reminderTime*1000 to transform milliseconds to minutes.
+            notification.reminderTime = sdf.format(schedule.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]*1000));
+
+            if(rb_yes.isChecked()){
+                notification.emailAddres = et_email.getText().toString();
+            }
+
+            scheduleConfirmationPresenter.createNotification(notification);
+        }else{
+            returnHome();
+        }
+
+    }
+
+    @Override
+    public void returnHome(){
         Intent intent = new Intent(ScheduleConfirmationActivity.this, HomeActivity.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
         Bundle bundle = new Bundle();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
index c580f35..12e6ecb 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
@@ -39,7 +39,7 @@ import br.ufpr.c3sl.agendador.agendador.helpers.UserImgHelper;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.helpers.adapters.HintAdapter;
 import br.ufpr.c3sl.agendador.agendador.helpers.adapters.SchedulesExpandableListAdapter;
-import br.ufpr.c3sl.agendador.agendador.helpers.listeners.schedulesHistory.FilterListener;
+import br.ufpr.c3sl.agendador.agendador.helpers.listeners.SpinnerListener;
 import br.ufpr.c3sl.agendador.agendador.models.CheckSchedules;
 import br.ufpr.c3sl.agendador.agendador.models.FormFilters;
 import br.ufpr.c3sl.agendador.agendador.models.ServicePlace;
@@ -47,10 +47,10 @@ import br.ufpr.c3sl.agendador.agendador.models.ServiceType;
 import br.ufpr.c3sl.agendador.agendador.presenters.PresenterManager;
 import br.ufpr.c3sl.agendador.agendador.presenters.SchedulesHistoryPresenter;
 import br.ufpr.c3sl.agendador.agendador.views.SchedulesHistoryView;
+import br.ufpr.c3sl.agendador.agendador.views.SpinnerActivity;
 
 
-
-public class SchedulesHistoryActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, SchedulesHistoryView {
+public class SchedulesHistoryActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, SchedulesHistoryView, SpinnerActivity {
 
     private NavigationView navigationView;
     private MenuBuilder menuBuilder;
@@ -65,7 +65,6 @@ public class SchedulesHistoryActivity extends AppCompatActivity implements Navig
     private FormFilters filters;
     private long[] sectorsIdArray, serviceTypesIdArray, servicePlacesIdArray, situationIdArray;
     private Button bt_search, bt_clear;
-    private FilterListener filterListener;
     private static final String EXIT_CONFIRMATION_DIALOG_TAG = "exit_dialog";
     private static final String SPINNER_SECTOR = "spinner_setor";
     private static final String SPINNER_TYPE = "spinner_type";
@@ -242,7 +241,7 @@ public class SchedulesHistoryActivity extends AppCompatActivity implements Navig
             }
         });
 
-        filterListener = new FilterListener(this);
+        SpinnerListener filterListener = new SpinnerListener(this);
         sp_sector.setOnItemSelectedListener(filterListener);
         sp_sector.setOnTouchListener(filterListener);
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulingActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulingActivity.java
index 363badc..2df2714 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulingActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulingActivity.java
@@ -49,9 +49,9 @@ import br.ufpr.c3sl.agendador.agendador.helpers.adapters.HintAdapter;
 import br.ufpr.c3sl.agendador.agendador.helpers.adapters.HintEnableAdapter;
 import br.ufpr.c3sl.agendador.agendador.helpers.decorators.NotAvailableDecorator;
 import br.ufpr.c3sl.agendador.agendador.helpers.decorators.SchedulesDecorator;
-import br.ufpr.c3sl.agendador.agendador.helpers.listeners.SectorSpinnerListener;
-import br.ufpr.c3sl.agendador.agendador.helpers.listeners.ServicePlaceSpinnerListener;
-import br.ufpr.c3sl.agendador.agendador.helpers.listeners.ServiceTypeSpinnerListener;
+import br.ufpr.c3sl.agendador.agendador.helpers.listeners.scheduling.SectorSpinnerListener;
+import br.ufpr.c3sl.agendador.agendador.helpers.listeners.scheduling.ServicePlaceSpinnerListener;
+import br.ufpr.c3sl.agendador.agendador.helpers.listeners.scheduling.ServiceTypeSpinnerListener;
 import br.ufpr.c3sl.agendador.agendador.models.CitizenCompact;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
 import br.ufpr.c3sl.agendador.agendador.models.SectorInput;
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
index 9a1db72..5e3f815 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
@@ -108,6 +108,8 @@ public abstract class Utils {
     public static final String REQUEST_FILTER_PLACE = "q[service_place_id]";
     public static final String REQUEST_FILTER_SITUATION = "q[situation_id]";
     public static final String SIZE_LARGE = "large";
+    public static final String NOTIFICATION = "notification";
+    public static final String NOTIFICATION_SERVICE = "br.c3sl.ufpr.notification_service";
 
     public static int getPixelValue(int dp, Context context) {
         Resources resources = context.getResources();
@@ -170,9 +172,9 @@ public abstract class Utils {
 
         String s = calendar.get(Calendar.YEAR) + "";
         tv_calendarHeaderYear.setText(s);
-
-        tv_calendarHeaderDayHour.setText(days_short[calendar.get(Calendar.DAY_OF_WEEK) - 1] + ", " +
-                months_short[calendar.get(Calendar.MONTH)] + " " + calendar.get(Calendar.DAY_OF_MONTH));
+        String text = days_short[calendar.get(Calendar.DAY_OF_WEEK) - 1] + ", " +
+                months_short[calendar.get(Calendar.MONTH)] + " " + calendar.get(Calendar.DAY_OF_MONTH);
+        tv_calendarHeaderDayHour.setText(text);
 
     }
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/schedulesHistory/FilterListener.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerListener.java
similarity index 62%
rename from app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/schedulesHistory/FilterListener.java
rename to app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerListener.java
index c577ea3..f3d9d4e 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/schedulesHistory/FilterListener.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerListener.java
@@ -1,21 +1,21 @@
-package br.ufpr.c3sl.agendador.agendador.helpers.listeners.schedulesHistory;
+package br.ufpr.c3sl.agendador.agendador.helpers.listeners;
 
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.AdapterView;
 
-import br.ufpr.c3sl.agendador.agendador.views.SchedulesHistoryView;
+import br.ufpr.c3sl.agendador.agendador.views.SpinnerActivity;
 
 /**
- * Created by Lucas B. Cunha on 30/10/17.
+ * Created by Lucas Braz Cunha on 22/11/17.
  */
 
-public class FilterListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {
+public class SpinnerListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {
 
     private boolean userSelect;
-    private SchedulesHistoryView activity;
+    private SpinnerActivity activity;
 
-    public FilterListener(SchedulesHistoryView activity) {
+    public SpinnerListener(SpinnerActivity activity) {
         this.activity = activity;
         this.userSelect = false;
     }
@@ -23,6 +23,7 @@ public class FilterListener implements AdapterView.OnItemSelectedListener, View.
     @Override
     public boolean onTouch(View v, MotionEvent event) {
         userSelect = true;
+        v.performClick();
         return false;
     }
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SectorSpinnerListener.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/SectorSpinnerListener.java
similarity index 96%
rename from app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SectorSpinnerListener.java
rename to app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/SectorSpinnerListener.java
index 245aa1f..6132923 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SectorSpinnerListener.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/SectorSpinnerListener.java
@@ -1,4 +1,4 @@
-package br.ufpr.c3sl.agendador.agendador.helpers.listeners;
+package br.ufpr.c3sl.agendador.agendador.helpers.listeners.scheduling;
 
 import android.view.MotionEvent;
 import android.view.View;
@@ -53,6 +53,7 @@ public class SectorSpinnerListener implements AdapterView.OnItemSelectedListener
     @Override
     public boolean onTouch(View v, MotionEvent event) {
         userSelect = true;
+        v.performClick();
         return false;
     }
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/ServicePlaceSpinnerListener.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/ServicePlaceSpinnerListener.java
similarity index 96%
rename from app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/ServicePlaceSpinnerListener.java
rename to app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/ServicePlaceSpinnerListener.java
index 0733222..9252832 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/ServicePlaceSpinnerListener.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/ServicePlaceSpinnerListener.java
@@ -1,4 +1,4 @@
-package br.ufpr.c3sl.agendador.agendador.helpers.listeners;
+package br.ufpr.c3sl.agendador.agendador.helpers.listeners.scheduling;
 
 import android.view.MotionEvent;
 import android.view.View;
@@ -48,12 +48,13 @@ public class ServicePlaceSpinnerListener implements AdapterView.OnItemSelectedLi
     @Override
     public boolean onTouch(View v, MotionEvent event) {
         userSelect = true;
+        v.performClick();
         return false;
     }
 
     @Override
     public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
-        if (userSelect && servicePlaces != null && servicePlaces.size() > 0 ) {
+        if (userSelect && servicePlaces != null && servicePlaces.size() > 0) {
             mcv.setSelectionMode(MaterialCalendarView.SELECTION_MODE_SINGLE);
 
             //if the position is the hint.
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/ServiceTypeSpinnerListener.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/ServiceTypeSpinnerListener.java
similarity index 96%
rename from app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/ServiceTypeSpinnerListener.java
rename to app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/ServiceTypeSpinnerListener.java
index 6d69eee..1601455 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/ServiceTypeSpinnerListener.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/scheduling/ServiceTypeSpinnerListener.java
@@ -1,6 +1,5 @@
-package br.ufpr.c3sl.agendador.agendador.helpers.listeners;
+package br.ufpr.c3sl.agendador.agendador.helpers.listeners.scheduling;
 
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.AdapterView;
@@ -53,12 +52,13 @@ public class ServiceTypeSpinnerListener implements AdapterView.OnItemSelectedLis
     @Override
     public boolean onTouch(View v, MotionEvent event) {
         userSelect = true;
+        v.performClick();
         return false;
     }
 
     @Override
     public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
-        if (userSelect && serviceTypes != null && serviceTypes.size() > 0 ) {
+        if (userSelect && serviceTypes != null && serviceTypes.size() > 0) {
             presenter.requestAvailableSchedules(serviceTypes.get(pos).getId());
 
             Utils.updateCalendarHeaderDate(mcv, tv_calendarHeaderYear, tv_calendarHeaderDayHour, days_short, months_short, null);
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
new file mode 100644
index 0000000..1811b3c
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
@@ -0,0 +1,79 @@
+package br.ufpr.c3sl.agendador.agendador.models;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by Lucas Braz Cunha on 24/11/17.
+ */
+
+public class Notification implements Parcelable{
+
+    @SerializedName("schedule_id")
+    public long scheduleId;
+
+    @SerializedName("reminder_time")
+    public String reminderTime;
+
+    @SerializedName("read")
+    public boolean hasRead;
+
+    @SerializedName("content")
+    public String description;
+
+    @SerializedName("reminder_email")
+    public String emailAddres;
+
+    @SerializedName("email_sent")
+    public boolean emailSent;
+
+
+    public Notification() {
+    }
+
+    /**reads back fields IN THE ORDER they were written */
+    private Notification(Parcel pc){
+        scheduleId         = pc.readLong();
+        reminderTime  = pc.readString();
+        hasRead      = pc.readByte() != 0;
+        description = pc.readString();
+        emailAddres = pc.readString();
+        emailSent = pc.readByte() != 0;
+    }
+
+    /** Static field used to regenerate object, individually or as arrays */
+    public static final Parcelable.Creator<Notification> CREATOR = new Parcelable.Creator<Notification>() {
+        public Notification createFromParcel(Parcel pc) {
+            return new Notification(pc);
+        }
+        public Notification[] newArray(int size) {
+            return new Notification[size];
+        }
+    };
+
+    /**
+     * Flatten this object in to a Parcel.
+     *
+     * @param dest  The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(scheduleId);
+        dest.writeString(reminderTime);
+        dest.writeByte((byte) (hasRead ? 1 : 0));
+        dest.writeString(description);
+        dest.writeString(emailAddres);
+        dest.writeByte((byte) (emailSent ? 1 : 0));
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
index e2a8ed7..1d1aab1 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
@@ -14,6 +14,7 @@ import br.ufpr.c3sl.agendador.agendador.models.Dependent;
 import br.ufpr.c3sl.agendador.agendador.models.DependentCreation;
 import br.ufpr.c3sl.agendador.agendador.models.FormFilters;
 import br.ufpr.c3sl.agendador.agendador.models.FullDependent;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleNote;
 import br.ufpr.c3sl.agendador.agendador.models.SectorInput;
@@ -87,9 +88,11 @@ public interface ApiEndpoints {
     @GET("schedules?permission=citizen")
     Call<CheckSchedules> requestSchedulesHistory(@QueryMap Map<String, String> options);
 
-
     @GET("forms/schedule_history?permission=citizen")
     Call<FormFilters> requestCitizenSectors();
 
+    @POST("notifications?permission=2")
+    Call<ScheduleConfirmation> requestCreateNotification(@Body Notification notification);
+
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
index 3cc8490..14ec54a 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
@@ -14,8 +14,8 @@ import retrofit2.converter.gson.GsonConverterFactory;
  */
 
 public abstract class ApiUtils {
-//     public static final String BASE_URL = "http://10.0.2.2:3000/v1/";
-    public static final String BASE_URL = "http://newcastle.c3sl.ufpr.br/develop/v1/";
+     public static final String BASE_URL = "http://10.0.2.2:3000/v1/";
+//    public static final String BASE_URL = "http://newcastle.c3sl.ufpr.br/develop/v1/";
 
     public static ApiEndpoints request(final Map<String, String> header) {
         OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
index 759f804..9ccd9c2 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
@@ -2,10 +2,17 @@ package br.ufpr.c3sl.agendador.agendador.presenters;
 
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
 import android.util.Log;
 
+import com.firebase.jobdispatcher.Constraint;
 import com.firebase.jobdispatcher.FirebaseJobDispatcher;
 import com.firebase.jobdispatcher.GooglePlayDriver;
+import com.firebase.jobdispatcher.Job;
+import com.firebase.jobdispatcher.Lifetime;
+import com.firebase.jobdispatcher.RetryStrategy;
+import com.firebase.jobdispatcher.Trigger;
+import com.google.gson.Gson;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -15,11 +22,14 @@ import br.ufpr.c3sl.agendador.agendador.ScheduleConfirmationActivity;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.models.CitizenCompact;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleNote;
 import br.ufpr.c3sl.agendador.agendador.models.UserOutput;
 import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
 import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
+import br.ufpr.c3sl.agendador.agendador.services.ImageUpdateService;
+import br.ufpr.c3sl.agendador.agendador.services.NotificationCreateService;
 import okhttp3.Headers;
 import retrofit2.Call;
 import retrofit2.Callback;
@@ -33,10 +43,16 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
 
     private ScheduleConfirmationPresenter scheduleConfirmationPresenter;
 
+    private FirebaseJobDispatcher dispatcher;
+
     public ScheduleConfirmationPresenter(Context context){
         this.context = context;
         this.scheduleConfirmationPresenter = this;
         osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
+
+        dispatcher = new FirebaseJobDispatcher(
+                new GooglePlayDriver(context)
+        );
     }
 
 
@@ -60,14 +76,14 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
             public void onResponse(Call<ScheduleConfirmation> call, Response<ScheduleConfirmation> response) {
                 Headers headers = response.headers();
                 int status = response.code();
-                //ScheduleConfirmation confirmationResponse = response.body();
+                ScheduleConfirmation confirmationResponse = response.body();
                 updateHeaders(headers);
                 switch (status) {
                     case 200:
                         Log.d("Server response", this.getClass().getName() + ": 200 - Sucesso!");
                         scheduleConfirmationPresenter.view().setProgressBar(false);
+                        scheduleConfirmationPresenter.view().onSuccess(confirmationResponse);
 
-                        scheduleConfirmationPresenter.view().onSuccess();
                         break;
                     default:
                         Log.e("Server response", this.getClass().getName() + ": ERRO:" + status);
@@ -87,6 +103,86 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
 
     }
 
+
+    public void createNotification(final Notification notification){
+        Map<String, String> header = new HashMap<>();
+        header.put("Content-Type", "application/json");
+        header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
+        header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
+        header.put(Utils.UID, osb.getString(Utils.UID, null));
+
+        final ApiEndpoints service = ApiUtils.request(header);
+
+
+        // TODO: 24/11/17 arrumar retorno
+        Call<ScheduleConfirmation> listCall = service.requestCreateNotification(notification);
+
+        scheduleConfirmationPresenter.view().setProgressBar(true);
+        listCall.enqueue(new Callback<ScheduleConfirmation>() {
+
+            @Override
+            public void onResponse(Call<ScheduleConfirmation> call, Response<ScheduleConfirmation> response) {
+                Headers headers = response.headers();
+                int status = response.code();
+                //ScheduleConfirmation confirmationResponse = response.body();
+                updateHeaders(headers);
+                switch (status) {
+                    case 200:
+                        Log.d("Server response", this.getClass().getName() + ": 200 - Sucess!");
+                        scheduleConfirmationPresenter.view().setProgressBar(false);
+
+                        scheduleConfirmationPresenter.view().returnHome();
+                        break;
+                    default:
+                        Log.e("Server response", this.getClass().getName() + ": ERRO:" + status + ". Scheduling job");
+                        scheduleNotificationJob(notification);
+                        scheduleConfirmationPresenter.view().setProgressBar(false);
+                        scheduleConfirmationPresenter.view().returnHome();
+                        break;
+                }
+            }
+            @Override
+            public void onFailure(Call<ScheduleConfirmation> call, Throwable t) {
+                Log.e("Server response", this.getClass().getName() +  ": Request Failed, Scheduling job.");
+
+                scheduleNotificationJob(notification);
+
+                scheduleConfirmationPresenter.view().setProgressBar(false);
+                scheduleConfirmationPresenter.view().returnHome();
+            }
+        });
+
+    }
+
+
+
+    private void scheduleNotificationJob(Notification notification){
+        Bundle extras = new Bundle();
+
+        Gson g = new Gson();
+        String json = g.toJson(notification);
+
+        extras.putString(Utils.NOTIFICATION, json);
+
+        Job job = dispatcher.newJobBuilder()
+                .setService(NotificationCreateService.class)
+                .setTag(Utils.NOTIFICATION_SERVICE)
+                //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
+                .setTrigger(Trigger.executionWindow(0, 3600))
+                //will be retried if it fails.
+                .setRecurring(true)
+                .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
+                .setConstraints(
+                        // only run on network
+                        Constraint.ON_ANY_NETWORK
+                )
+                .setExtras(extras)
+                //if device is rebooted the job will be restarted
+                .setLifetime(Lifetime.FOREVER)
+                .build();
+        dispatcher.mustSchedule(job);
+    }
+
     @Override
     protected void updateView() {}
 }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/ImageUpdateService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/ImageUpdateService.java
index 660d53e..4a7d303 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/ImageUpdateService.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/ImageUpdateService.java
@@ -30,7 +30,6 @@ import retrofit2.Response;
 public class ImageUpdateService extends JobService {
 
 
-
     /**
      * The entry point to your Job. Implementations should offload work to another thread of
      * execution as soon as possible.
@@ -88,10 +87,10 @@ public class ImageUpdateService extends JobService {
                         break;
                     case 404:
                         //user has no picture on back-end
-                        Log.d("AGNDDR-ImgService", "Job Foi executado e usuário não possui foto");
+                        Log.d("AGNDDR-ImgService", "Job foi executado e usuário não possui foto");
                         jobFinished(job, false);
                     default:
-                        Log.d("AGNDDR-ImgService", "Job Foi executado mas recebeu retorno " + status);
+                        Log.d("AGNDDR-ImgService", "Job foi executado mas recebeu retorno " + status);
 
                         jobFinished(job, true);
                         break;
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/NotificationCreateService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/NotificationCreateService.java
new file mode 100644
index 0000000..8169038
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/NotificationCreateService.java
@@ -0,0 +1,104 @@
+package br.ufpr.c3sl.agendador.agendador.services;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.firebase.jobdispatcher.JobParameters;
+import com.firebase.jobdispatcher.JobService;
+import com.google.gson.Gson;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
+import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
+import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
+import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
+import okhttp3.Headers;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * Created by Lucas Braz Cunha on 24/11/17.
+ */
+
+public class NotificationCreateService extends JobService {
+
+
+    @Override
+    public boolean onStartJob(final JobParameters job) {
+        Log.v("AGNDDR-NotifiCreate", "Rodando " + NotificationCreateService.class.getName());
+        ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
+        final Bundle extras = job.getExtras();
+        Map<String, String> header = new HashMap<>();
+
+        final String uid = osb.getString(Utils.UID, null);
+        header.put("Content-Type", "application/json");
+        header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
+        header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
+        header.put(Utils.ID, uid);
+
+        Notification notification = null;
+
+        if (extras != null) {
+            notification = new Gson().fromJson(extras.getString(Utils.NOTIFICATION), Notification.class);
+        }else{
+            Log.e("AGNDDR-NotifiCreate", "Job não recebeu os extras.");
+            jobFinished(job, true);
+        }
+
+        ApiEndpoints service = ApiUtils.request(header);
+
+        Call<ScheduleConfirmation> listCall = service.requestCreateNotification(notification);
+
+        listCall.enqueue(new Callback<ScheduleConfirmation>() {
+
+            @Override
+            public void onResponse(Call<ScheduleConfirmation> call, Response<ScheduleConfirmation> response) {
+                int status = response.code();
+                Headers headers = response.headers();
+                ObscuredSharedPreferences  osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
+
+                if(headers.get(Utils.ACCESS_TOKEN) != null)
+                    osb.edit().putString(Utils.ACCESS_TOKEN, headers.get(Utils.ACCESS_TOKEN)).apply();
+                if(headers.get(Utils.CLIENT) != null)
+                    osb.edit().putString(Utils.CLIENT, headers.get(Utils.CLIENT)).apply();
+                if(headers.get(Utils.UID) != null)
+                    osb.edit().putString(Utils.UID, headers.get(Utils.UID)).apply();
+                if(headers.get(Utils.EXPIRY) != null)
+                    osb.edit().putString(Utils.EXPIRY, headers.get(Utils.EXPIRY)).apply();
+
+                switch (status) {
+                    case 200:
+
+                        jobFinished(job, false);
+                        break;
+                    default:
+                        Log.v("AGNDDR-NotifiCreate", "Job foi executado mas recebeu retorno " + status);
+                        jobFinished(job, true);
+                        break;
+                }
+
+            }
+
+            @Override
+            public void onFailure(Call<ScheduleConfirmation> call, Throwable t) {
+                Log.v("AGNDDR-NotifiCreate", "Job falhou e será remarcado!!");
+                jobFinished(job, true);
+            }
+        });
+
+
+        return true;
+    }
+
+
+    @Override
+    public boolean onStopJob(JobParameters job) {
+        return true;
+    }
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleConfirmationView.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleConfirmationView.java
index 930089b..25d0935 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleConfirmationView.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleConfirmationView.java
@@ -1,5 +1,7 @@
 package br.ufpr.c3sl.agendador.agendador.views;
 
+import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
+
 /**
  * Created by Lucas B. Cunha on 25/07/17.
  */
@@ -10,8 +12,10 @@ public interface ScheduleConfirmationView {
 
     void setProgressBar(boolean enabled);
 
-    void onSuccess();
+    void onSuccess(ScheduleConfirmation confirmationResponse);
 
     void setConnectionError(boolean enabled);
 
+    void returnHome();
+
 }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/SpinnerActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/SpinnerActivity.java
new file mode 100644
index 0000000..f8c31cc
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/SpinnerActivity.java
@@ -0,0 +1,10 @@
+package br.ufpr.c3sl.agendador.agendador.views;
+
+/**
+ * Created by Lucas Braz Cunha on 22/11/17.
+ */
+
+public interface SpinnerActivity {
+
+    void updateSpinners(int id);
+}
diff --git a/app/src/main/res/layout/content_schedule_confirmation.xml b/app/src/main/res/layout/content_schedule_confirmation.xml
index 04ccbdb..d5a2107 100644
--- a/app/src/main/res/layout/content_schedule_confirmation.xml
+++ b/app/src/main/res/layout/content_schedule_confirmation.xml
@@ -20,222 +20,329 @@
         android:typeface="normal" />
 
 
-    <LinearLayout
+    <ScrollView
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_below="@+id/tv_scheduling_welcome"
-        android:orientation="vertical"
         android:background="@color/colorWhite">
-
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="24dp"
-            android:layout_marginTop="24dp"
-            android:layout_marginBottom="5dp"
-            android:gravity="center"
-            android:text="@string/schedule_confirmation_description"
-            android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-            android:textSize="16sp"
-            android:textStyle="normal|bold"
-            android:typeface="normal" />
-
-
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="14dp"
-            android:layout_gravity="start"
-            android:text="@string/schedule_confirmation_title"
-            android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-            android:textSize="16sp"
-            android:textStyle="normal|bold"
-            android:typeface="normal"/>
-
-        <RelativeLayout
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginTop="10dp">
+            android:orientation="vertical">
 
             <TextView
-                android:id="@+id/tv_schedule_citizen"
-                android:layout_width="wrap_content"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginStart="14dp"
-                android:layout_gravity="start"
+                android:layout_marginStart="24dp"
+                android:layout_marginTop="24dp"
+                android:layout_marginBottom="5dp"
+                android:gravity="center"
+                android:text="@string/schedule_confirmation_description"
                 android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:text="@string/schedule_confirmation_citizen"
                 android:textSize="16sp"
                 android:textStyle="normal|bold"
-                android:typeface="normal"/>
+                android:typeface="normal" />
 
-            <TextView
-                android:id="@+id/tv_schedule_citizen_content"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="14sp"
-                android:typeface="normal"
-                android:layout_marginStart="3dp"
-                android:layout_alignBaseline="@+id/tv_schedule_citizen"
-                android:layout_alignBottom="@+id/tv_schedule_citizen"
-                android:layout_toEndOf="@+id/tv_schedule_citizen" />
 
             <TextView
-                android:id="@+id/tv_schedule_sector"
-                android:layout_width="wrap_content"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginStart="14dp"
                 android:layout_gravity="start"
-                android:text="@string/schedule_confirmation_sector"
+                android:text="@string/schedule_confirmation_title"
                 android:textAppearance="@style/TextAppearance.AppCompat.Body1"
                 android:textSize="16sp"
                 android:textStyle="normal|bold"
-                android:typeface="normal"
-                android:layout_below="@+id/tv_schedule_citizen_content"
-                android:layout_marginTop="20dp"
-                android:layout_alignStart="@+id/tv_schedule_citizen" />
+                android:typeface="normal"/>
 
-            <TextView
-                android:id="@+id/tv_schedule_sector_content"
-                android:layout_width="wrap_content"
+            <RelativeLayout
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="14sp"
-                android:typeface="normal"
-                android:layout_marginStart="3dp"
-                android:layout_alignBaseline="@+id/tv_schedule_sector"
-                android:layout_alignBottom="@+id/tv_schedule_sector"
-                android:layout_toEndOf="@+id/tv_schedule_sector"/>
+                android:layout_marginTop="10dp">
 
-            <TextView
-                android:id="@+id/tv_schedule_location"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/schedule_confirmation_place"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="16sp"
-                android:textStyle="normal|bold"
-                android:typeface="normal"
-                android:layout_marginTop="15dp"
-                android:layout_below="@id/tv_schedule_sector_content"
-                android:layout_alignStart="@+id/tv_schedule_citizen" />
+                <TextView
+                    android:id="@+id/tv_schedule_citizen"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginStart="14dp"
+                    android:layout_gravity="start"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:text="@string/schedule_confirmation_citizen"
+                    android:textSize="16sp"
+                    android:textStyle="normal|bold"
+                    android:typeface="normal"/>
 
-            <TextView
-                android:id="@+id/tv_schedule_location_content"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="14sp"
-                android:typeface="normal"
-                android:layout_marginStart="3dp"
-                android:layout_alignBaseline="@+id/tv_schedule_location"
-                android:layout_alignBottom="@+id/tv_schedule_location"
-                android:layout_toEndOf="@+id/tv_schedule_location"/>
+                <TextView
+                    android:id="@+id/tv_schedule_citizen_content"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="14sp"
+                    android:typeface="normal"
+                    android:layout_marginStart="3dp"
+                    android:layout_alignBaseline="@+id/tv_schedule_citizen"
+                    android:layout_alignBottom="@+id/tv_schedule_citizen"
+                    android:layout_toEndOf="@+id/tv_schedule_citizen" />
+
+                <TextView
+                    android:id="@+id/tv_schedule_sector"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="start"
+                    android:text="@string/schedule_confirmation_sector"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="16sp"
+                    android:textStyle="normal|bold"
+                    android:typeface="normal"
+                    android:layout_below="@+id/tv_schedule_citizen_content"
+                    android:layout_marginTop="20dp"
+                    android:layout_alignStart="@+id/tv_schedule_citizen" />
+
+                <TextView
+                    android:id="@+id/tv_schedule_sector_content"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="14sp"
+                    android:typeface="normal"
+                    android:layout_marginStart="3dp"
+                    android:layout_alignBaseline="@+id/tv_schedule_sector"
+                    android:layout_alignBottom="@+id/tv_schedule_sector"
+                    android:layout_toEndOf="@+id/tv_schedule_sector"/>
+
+                <TextView
+                    android:id="@+id/tv_schedule_location"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/schedule_confirmation_place"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="16sp"
+                    android:textStyle="normal|bold"
+                    android:typeface="normal"
+                    android:layout_marginTop="15dp"
+                    android:layout_below="@id/tv_schedule_sector_content"
+                    android:layout_alignStart="@+id/tv_schedule_citizen" />
+
+                <TextView
+                    android:id="@+id/tv_schedule_location_content"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="14sp"
+                    android:typeface="normal"
+                    android:layout_marginStart="3dp"
+                    android:layout_alignBaseline="@+id/tv_schedule_location"
+                    android:layout_alignBottom="@+id/tv_schedule_location"
+                    android:layout_toEndOf="@+id/tv_schedule_location"/>
+
+                <TextView
+                    android:id="@+id/tv_schedule_type"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/schedule_confirmation_type"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="16sp"
+                    android:textStyle="normal|bold"
+                    android:typeface="normal"
+                    android:layout_marginTop="15dp"
+                    android:layout_below="@id/tv_schedule_location_content"
+                    android:layout_alignStart="@+id/tv_schedule_citizen" />
+
+                <TextView
+                    android:id="@+id/tv_schedule_type_content"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="14sp"
+                    android:typeface="normal"
+                    android:layout_marginStart="3dp"
+                    android:layout_alignBaseline="@+id/tv_schedule_type"
+                    android:layout_alignBottom="@+id/tv_schedule_type"
+                    android:layout_toEndOf="@+id/tv_schedule_type"/>
+
+                <TextView
+                    android:id="@+id/tv_schedule_date"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/schedule_confirmation_date"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="16sp"
+                    android:textStyle="normal|bold"
+                    android:typeface="normal"
+                    android:layout_marginTop="15dp"
+                    android:layout_below="@id/tv_schedule_type_content"
+                    android:layout_alignStart="@+id/tv_schedule_citizen"/>
+
+                <TextView
+                    android:id="@+id/tv_schedule_date_content"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="14sp"
+                    android:typeface="normal"
+                    android:layout_marginStart="3dp"
+                    android:layout_alignBaseline="@+id/tv_schedule_date"
+                    android:layout_alignBottom="@+id/tv_schedule_date"
+                    android:layout_toEndOf="@+id/tv_schedule_date"/>
+
+                <TextView
+                    android:id="@+id/tv_schedule_street"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/schedule_confirmation_street"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="16sp"
+                    android:textStyle="normal|bold"
+                    android:typeface="normal"
+                    android:layout_marginTop="15dp"
+                    android:layout_below="@id/tv_schedule_date_content"
+                    android:layout_alignStart="@+id/tv_schedule_citizen"/>
+
+                <TextView
+                    android:id="@+id/tv_schedule_street_content"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                    android:textSize="14sp"
+                    android:typeface="normal"
+                    android:layout_marginStart="3dp"
+                    android:layout_alignBaseline="@+id/tv_schedule_street"
+                    android:layout_alignBottom="@+id/tv_schedule_street"
+                    android:layout_toEndOf="@+id/tv_schedule_street"/>
+
+            </RelativeLayout>
 
-            <TextView
-                android:id="@+id/tv_schedule_type"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/schedule_confirmation_type"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="16sp"
-                android:textStyle="normal|bold"
-                android:typeface="normal"
-                android:layout_marginTop="15dp"
-                android:layout_below="@id/tv_schedule_location_content"
-                android:layout_alignStart="@+id/tv_schedule_citizen" />
 
-            <TextView
-                android:id="@+id/tv_schedule_type_content"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="14sp"
-                android:typeface="normal"
-                android:layout_marginStart="3dp"
-                android:layout_alignBaseline="@+id/tv_schedule_type"
-                android:layout_alignBottom="@+id/tv_schedule_type"
-                android:layout_toEndOf="@+id/tv_schedule_type"/>
 
             <TextView
-                android:id="@+id/tv_schedule_date"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="@string/schedule_confirmation_date"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="16sp"
-                android:textStyle="normal|bold"
-                android:typeface="normal"
                 android:layout_marginTop="15dp"
-                android:layout_below="@id/tv_schedule_type_content"
-                android:layout_alignStart="@+id/tv_schedule_citizen"/>
+                android:layout_marginStart="14dp"
+                android:textColor="@color/colorBlack"
+                android:textStyle="normal|bold"
+                android:text="@string/notification_time"/>
 
-            <TextView
-                android:id="@+id/tv_schedule_date_content"
-                android:layout_width="wrap_content"
+
+            <Spinner
+                android:id="@+id/spnr_schedule_time"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="14sp"
-                android:typeface="normal"
+                android:layout_marginTop="2dp"
                 android:layout_marginStart="3dp"
-                android:layout_alignBaseline="@+id/tv_schedule_date"
-                android:layout_alignBottom="@+id/tv_schedule_date"
-                android:layout_toEndOf="@+id/tv_schedule_date"/>
+                android:layout_marginEnd="3dp"/>
+
 
             <TextView
-                android:id="@+id/tv_schedule_street"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="@string/schedule_confirmation_street"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="16sp"
-                android:textStyle="normal|bold"
-                android:typeface="normal"
                 android:layout_marginTop="15dp"
-                android:layout_below="@id/tv_schedule_date_content"
-                android:layout_alignStart="@+id/tv_schedule_citizen"/>
+                android:layout_marginStart="14dp"
+                android:textColor="@color/colorBlack"
+                android:textStyle="normal|bold"
+                android:text="@string/notification_email_question"/>
 
-            <TextView
-                android:id="@+id/tv_schedule_street_content"
+            <RadioGroup
                 android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
-                android:textSize="14sp"
-                android:typeface="normal"
-                android:layout_marginStart="3dp"
-                android:layout_alignBaseline="@+id/tv_schedule_street"
-                android:layout_alignBottom="@+id/tv_schedule_street"
-                android:layout_toEndOf="@+id/tv_schedule_street"/>
+                android:layout_marginStart="14dp"
+                android:layout_height="wrap_content">
 
-        </RelativeLayout>
+                <RadioButton
+                    android:id="@+id/rb_notify_email_yes"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/yes"/>
 
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:gravity="center"
-            android:layout_marginTop="50dp">
+                <RadioButton
+                    android:id="@+id/rb_notify_email_no"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/no"/>
 
-            <Button
-                android:id="@+id/btn_schedule_back"
-                android:layout_width="wrap_content"
+            </RadioGroup>
+
+
+            <LinearLayout
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:background="@drawable/gray_container_shape"
-                android:text="@string/back"
-                />
+                android:layout_marginTop="10dp">
 
-            <Button
-                android:id="@+id/btn_schedule_confirm"
-                android:layout_width="wrap_content"
+                <FrameLayout
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:layout_gravity="center">
+
+                    <TextView
+                        android:id="@+id/tv_schedule_email"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="center_vertical"
+                        android:layout_marginStart="14dp"
+                        android:layout_marginEnd="14dp"
+                        android:text="@string/notification_email_dest"
+                        android:textColor="@color/colorBlack"
+                        android:textStyle="normal|bold"
+                        android:textSize="16sp" />
+
+                    <TextView
+                        android:id="@+id/tv_schedule_email_warning"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="bottom"
+                        android:layout_marginStart="5dp"
+                        android:text="@string/invalid_email"
+                        android:textColor="@color/colorRed"
+                        android:textSize="12sp"
+                        android:visibility="invisible" />
+
+                </FrameLayout>
+
+                <EditText
+                    android:id="@+id/et_schedule_email"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginStart="14dp"
+                    android:layout_marginEnd="14dp"
+                    android:layout_marginTop="5dp"
+                    android:maxLines="1"
+                    android:textColor="@color/colorBlack"
+                    android:textStyle="normal|bold"
+                    android:inputType="textEmailAddress"/>
+
+
+            </LinearLayout>
+
+
+
+            <LinearLayout
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:background="@drawable/green_button_shape"
-                android:text="@string/schedule"
-                android:layout_marginStart="20dp"
-                />
+                android:gravity="center"
+                android:layout_marginTop="30dp"
+                android:layout_marginBottom="30dp">
 
-        </LinearLayout>
+                <Button
+                    android:id="@+id/btn_schedule_back"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/gray_container_shape"
+                    android:text="@string/back"
+                    />
 
+                <Button
+                    android:id="@+id/btn_schedule_confirm"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/green_button_shape"
+                    android:text="@string/schedule"
+                    android:layout_marginStart="20dp"
+                    />
+
+            </LinearLayout>
+
+        </LinearLayout>
+    </ScrollView>
 
-    </LinearLayout>
 
     <ProgressBar
         android:id="@+id/pb_schedule_confirmation"
diff --git a/app/src/main/res/values/integer.xml b/app/src/main/res/values/integer.xml
index d0c1abf..b8d2b0f 100644
--- a/app/src/main/res/values/integer.xml
+++ b/app/src/main/res/values/integer.xml
@@ -3,4 +3,17 @@
 
     <integer name="max_length_name">150</integer>
 
+    <string-array name="notification_time_int">
+        <item>0</item>
+        <item>15</item>
+        <item>30</item>
+        <item>45</item>
+        <item>60</item>
+        <item>120</item>
+        <item>180</item>
+        <item>240</item>
+        <item>300</item>
+        <item>1440</item>
+    </string-array>
+
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 383c0dc..5e1f645 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -203,5 +203,23 @@
     <string name="menu_sign_out">Sair</string>
     <string name="menu_edit">Editar</string>
     <string name="menu_sync">Sincronizar</string>
+    <string name="notification_email_question">Notificar também por e-mail?</string>
+    <string name="notification_time">Notificar sobre o agendamento:</string>
+    <string name="notification_email_dest">Digite o e-mail:</string>
+
+    <string-array name="notification_time">
+        <item>Não notificar</item>
+        <item>15 minutos antes</item>
+        <item>30 minutos antes</item>
+        <item>45 minutos antes</item>
+        <item>1 hora antes</item>
+        <item>2 horas antes</item>
+        <item>3 horas antes</item>
+        <item>4 horas antes</item>
+        <item>5 horas antes</item>
+        <item>1 dia antes</item>
+    </string-array>
+
+    <string name="not_valid_email">Digite um e-mail válido.</string>
 
 </resources>
-- 
GitLab


From 7ca79e1148390a908ef0c9a7220c10d530815e28 Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Tue, 19 Dec 2017 11:16:26 -0200
Subject: [PATCH 2/9] AGILE#271: Re-schedule notifications on device boot

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 app/src/main/AndroidManifest.xml              |  18 ++-
 .../agendador/CitizenListActivity.java        |   4 +-
 .../agendador/agendador/HomeActivity.java     |  16 +++
 .../ScheduleConfirmationActivity.java         | 131 ++++++++++++------
 .../agendador/SchedulesActivity.java          |  25 +++-
 .../agendador/SchedulesHistoryActivity.java   |   6 +-
 .../agendador/SchedulingActivity.java         |   1 +
 .../agendador/agendador/helpers/Utils.java    |  24 +++-
 .../SchedulesExpandableListAdapter.java       |   2 +-
 .../listeners}/SpinnerActivity.java           |   2 +-
 .../helpers/listeners/SpinnerListener.java    |   2 -
 .../agendador/models/CheckSchedules.java      |  65 +++++++--
 .../agendador/models/Notification.java        |  10 ++
 .../agendador/models/NotificationReturn.java  |  45 ++++++
 .../agendador/models/ScheduleNote.java        |   2 +-
 .../agendador/network/ApiEndpoints.java       |   3 +-
 .../agendador/agendador/network/ApiUtils.java |   4 +-
 .../agendador/presenters/LoginPresenter.java  |  17 ++-
 .../ScheduleConfirmationPresenter.java        |  42 +++---
 .../presenters/SchedulesHistoryPresenter.java |   2 +
 .../presenters/SchedulesPresenter.java        |   1 +
 .../agendador/services/BootReceiver.java      |  72 ++++++++++
 .../LocalNotificationManager.java             | 127 +++++++++++++++++
 .../NotificationCreateService.java            |  16 ++-
 .../notification/NotificationReceiver.java    |  67 +++++++++
 .../layout/content_schedule_confirmation.xml  |  25 +++-
 app/src/main/res/values/integer.xml           |  22 +--
 app/src/main/res/values/strings.xml           |   7 +-
 28 files changed, 628 insertions(+), 130 deletions(-)
 rename app/src/main/java/br/ufpr/c3sl/agendador/agendador/{views => helpers/listeners}/SpinnerActivity.java (67%)
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/BootReceiver.java
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
 rename app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/{ => notification}/NotificationCreateService.java (82%)
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2497fce..ef2648c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -16,6 +16,8 @@
         android:maxSdkVersion="18" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+
     <application
         android:allowBackup="false"
         android:icon="@mipmap/ic_launcher"
@@ -48,7 +50,7 @@
         </service>
 
         <service
-            android:name=".services.NotificationCreateService"
+            android:name=".services.notification.NotificationCreateService"
             android:exported="false"
             android:permission="android.permission.BIND_JOB_SERVICE">
             <intent-filter>
@@ -56,6 +58,16 @@
             </intent-filter>
         </service>
 
+
+        <receiver android:name=".services.BootReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED"/>
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name=".services.notification.NotificationReceiver">
+        </receiver>
+
         <activity android:name=".TermActivity" />
         <activity android:name=".SchedulingActivity"/>
         <activity android:name=".CitizenListActivity" />
@@ -67,6 +79,10 @@
         <activity android:name=".RetrievalSuccessActivity" />
         <activity android:name=".SchedulesHistoryActivity" />
         <activity android:name=".ScheduleInfoActivity" />
+
+
+
+
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/CitizenListActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/CitizenListActivity.java
index 5c337c5..055b349 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/CitizenListActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/CitizenListActivity.java
@@ -167,7 +167,9 @@ public class CitizenListActivity extends AppCompatActivity implements CitizenVie
         @Override
         public void onDismiss(DialogInterface dialog) {
             super.onDismiss(dialog);
-            getActivity().onBackPressed();
+            Activity activity = getActivity();
+            if(activity != null)
+                activity.onBackPressed();
         }
     }
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/HomeActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/HomeActivity.java
index d791835..2c42be7 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/HomeActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/HomeActivity.java
@@ -21,6 +21,7 @@ import android.support.v7.widget.ActionMenuView;
 import android.support.v7.widget.Toolbar;
 import android.text.SpannableString;
 import android.text.style.ForegroundColorSpan;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -29,11 +30,18 @@ import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.google.gson.Gson;
+
+import java.util.ArrayList;
+import java.util.List;
+
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.UserImgHelper;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
 import br.ufpr.c3sl.agendador.agendador.presenters.HomePresenter;
 import br.ufpr.c3sl.agendador.agendador.presenters.PresenterManager;
+import br.ufpr.c3sl.agendador.agendador.services.notification.LocalNotificationManager;
 import br.ufpr.c3sl.agendador.agendador.views.HomeView;
 
 /**
@@ -171,6 +179,14 @@ public class HomeActivity extends AppCompatActivity implements HomeView,
         });
         changeTextColor();
         showSnackBar(getIntent());
+
+
+        /*
+        Notification notification = new Notification(1, "2017-12-18T10:10:00.000-0200", false, "Alo Alo", "a@a.c", false);
+        Log.d("Agendador", "Criando notificação");
+        LocalNotificationManager.createLocalNotification(this, notification, osb, new Gson());
+        */
+
     }
 
     @TargetApi(23)
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
index d08497d..885780f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
@@ -16,6 +16,7 @@ import android.support.v7.app.AppCompatActivity;
 import android.support.v7.view.menu.MenuBuilder;
 import android.support.v7.widget.ActionMenuView;
 import android.support.v7.widget.Toolbar;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -32,7 +33,6 @@ import android.widget.Toast;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.Date;
 import java.util.Locale;
 
 import br.ufpr.c3sl.agendador.agendador.helpers.ConnectionErrorDialog;
@@ -40,7 +40,8 @@ import br.ufpr.c3sl.agendador.agendador.helpers.DateValidator;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.UserImgHelper;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
-import br.ufpr.c3sl.agendador.agendador.models.CheckSchedules;
+import br.ufpr.c3sl.agendador.agendador.helpers.listeners.SpinnerActivity;
+import br.ufpr.c3sl.agendador.agendador.helpers.listeners.SpinnerListener;
 import br.ufpr.c3sl.agendador.agendador.models.CitizenCompact;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
@@ -53,7 +54,9 @@ import br.ufpr.c3sl.agendador.agendador.views.ScheduleConfirmationView;
  */
 
 
-public class ScheduleConfirmationActivity extends AppCompatActivity implements ScheduleConfirmationView, NavigationView.OnNavigationItemSelectedListener{
+public class ScheduleConfirmationActivity extends AppCompatActivity implements ScheduleConfirmationView, NavigationView.OnNavigationItemSelectedListener, SpinnerActivity{
+
+    private int[] reminderTimeArray;
 
     private ScheduleConfirmationPresenter scheduleConfirmationPresenter;
 
@@ -69,13 +72,11 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
 
     private EditText et_email;
 
-    private TextView tv_email_warning;
+    private TextView tv_email_warning, tv_email;
 
     private Button bt_schedule, bt_back;
 
-    private String[] notificationTime;
-
-    private static String SPINNER_POS = "spinner_position";
+    private static final String SPINNER_POS = "spinner_position";
 
     private Spinner sp_notification;
 
@@ -93,19 +94,28 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         Bundle bundle = getIntent().getBundleExtra(Utils.SCHEDULE_BUNDLE);
         final CitizenCompact citizen = bundle.getParcelable(Utils.CITIZEN);
         final ScheduleConfirmation scheduleConfirmation = bundle.getParcelable(Utils.SCHEDULE_CONFIRMATION);
-        String sectorName = scheduleConfirmation.getSectorName();
-        String locationName = scheduleConfirmation.getLocationName();
-        String typeName = scheduleConfirmation.getServiceTypeName();
-        String address = scheduleConfirmation.getAddressStreet() + ", " + scheduleConfirmation.getAddressNumber();
+        String sectorName = "";
+        String locationName = "";
+        String typeName = "";
+        String address = "";
+        if (scheduleConfirmation != null) {
+            sectorName = scheduleConfirmation.getSectorName();
+            locationName = scheduleConfirmation.getLocationName();
+            typeName = scheduleConfirmation.getServiceTypeName();
+            address = scheduleConfirmation.getAddressStreet() + ", " + scheduleConfirmation.getAddressNumber();
+        }else{
+            Log.e("Agendador", "Bundle chegou vazio ou Schedule confirmation null " +
+                    "ou citizenCompact null na classe ScheduleConfirmationActivity");
+        }
 
         Toolbar toolbar = (Toolbar) findViewById(R.id.agendador_toolbar);
         toolbar.setTitle(null);
         setSupportActionBar(toolbar);
 
         ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(this, "Agendador", Context.MODE_PRIVATE);
-        String citizenName = osb.getString("name", null);
-        String citizenCity = osb.getString("city.name", null);
-        id = osb.getLong("id", 0);
+        String citizenName = osb.getString(Utils.NAME, null);
+        String citizenCity = osb.getString(Utils.CITY_NAME, null);
+        id = osb.getLong(Utils.ID, 0);
 
         ActionMenuView actionMenuView = (ActionMenuView) toolbar.findViewById(R.id.agendador_toolbar_menu);
         menuBuilder = (MenuBuilder) actionMenuView.getMenu();
@@ -161,14 +171,12 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         navigationView.setNavigationItemSelectedListener(this);
 
 
-        notificationTime = getResources().getStringArray(R.array.notification_time);
+        String[] notificationTime = getResources().getStringArray(R.array.notification_time);
 
         sp_notification = (Spinner) findViewById(R.id.spnr_schedule_time);
 
         sp_notification.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, notificationTime));
 
-        sp_notification.setSelection(1, true);
-
         pb_scheduleConfirmation = (ProgressBar) findViewById(R.id.pb_schedule_confirmation);
 
         TextView tv_citizen = (TextView) findViewById(R.id.tv_schedule_citizen_content);
@@ -179,6 +187,7 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         TextView tv_street = (TextView) findViewById(R.id.tv_schedule_street_content);
         et_email = (EditText) findViewById(R.id.et_schedule_email);
         tv_email_warning = (TextView) findViewById(R.id.tv_schedule_email_warning);
+        final EditText et_scheduleNote = (EditText) findViewById(R.id.et_schedule_note);
 
         tv_sector.setText(sectorName);
         tv_citizen.setText(citizen.getName());
@@ -205,22 +214,18 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
                     }else{
                         tv_email_warning.setVisibility(View.INVISIBLE);
                     }
-
                 }
 
                 if(schedule){
-
-                    scheduleConfirmationPresenter.onScheduleClicked(scheduleConfirmation, citizen);
+                    scheduleConfirmationPresenter.onScheduleClicked(scheduleConfirmation, citizen, et_scheduleNote.getText().toString());
                     bt_schedule.setEnabled(false);
                     bt_back.setEnabled(false);
-
                 }
 
-
             }
         });
 
-        final TextView tv_email = (TextView) findViewById(R.id.tv_schedule_email);
+        tv_email = (TextView) findViewById(R.id.tv_schedule_email);
 
         rb_yes = (RadioButton) findViewById(R.id.rb_notify_email_yes);
 
@@ -231,23 +236,16 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         rb_yes.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                rb_no.setChecked(false);
-                et_email.setEnabled(true);
-                tv_email.setTextColor(Color.BLACK);
-                if(sp_notification.getSelectedItemPosition() == 0){
-                    sp_notification.setSelection(1, true);
-                }
+                //Radio Button already toggled from user click.
+                radioButtonNotificationSelected(R.id.rb_notify_email_yes, false);
             }
         });
 
         rb_no.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                rb_yes.setChecked(false);
-                et_email.setEnabled(false);
-                et_email.setText("");
-                tv_email.setTextColor(Color.GRAY);
-                tv_email_warning.setVisibility(View.INVISIBLE);
+                //Radio Button already toggled from user click.
+                radioButtonNotificationSelected(R.id.rb_notify_email_no, false);
             }
         });
 
@@ -261,11 +259,17 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         if(savedInstanceState == null){
             scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(getBaseContext());
         }else{
-            sp_notification.setSelection( savedInstanceState.getInt(SPINNER_POS, 1), true);
             scheduleConfirmationPresenter = PresenterManager.getInstance().restorePresenter(savedInstanceState);
             if(scheduleConfirmationPresenter == null)
                 scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(this);
         }
+
+
+        SpinnerListener notificationListener = new SpinnerListener(this);
+        sp_notification.setOnItemSelectedListener(notificationListener);
+        sp_notification.setOnTouchListener(notificationListener);
+
+        reminderTimeArray = getResources().getIntArray(R.array.notification_time_milis);
     }
 
     @Override
@@ -365,19 +369,25 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
     @Override
     public void onSuccess(ScheduleConfirmation schedule){
 
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ", Locale.getDefault());
+        SimpleDateFormat sdfServer = new SimpleDateFormat(Utils.SERVER_FORMAT, Locale.getDefault());
+        SimpleDateFormat sdfDate = new SimpleDateFormat(Utils.DATE_FORMAT, Locale.getDefault());
+        SimpleDateFormat sdfHour = new SimpleDateFormat(Utils.HOUR_FORMAT, Locale.getDefault());
+
+
         /*
         * Position zero is "don't notify"
         */
-        int reminderTimeArray[] = getResources().getIntArray(R.array.notification_time_int);
 
-        if(sp_notification.getSelectedItemPosition() != 0 ){
+        if(sp_notification.getSelectedItemPosition() != reminderTimeArray.length - 1){
             Notification notification = new Notification();
             notification.scheduleId = schedule.getId();
             notification.emailSent = false;
-            notification.description = "a";
-            //reminderTime*1000 to transform milliseconds to minutes.
-            notification.reminderTime = sdf.format(schedule.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]*1000));
+
+            notification.description = getResources().getString(R.string.notification_content, schedule.getServiceTypeName(),
+                    schedule.getLocationName(), schedule.getAddressStreet(), schedule.getAddressNumber(),
+                        sdfDate.format(schedule.getStartTime()), sdfHour.format(schedule.getStartTime()));
+
+            notification.reminderTime = sdfServer.format(schedule.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]));
 
             if(rb_yes.isChecked()){
                 notification.emailAddres = et_email.getText().toString();
@@ -390,6 +400,28 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
 
     }
 
+
+    private void radioButtonNotificationSelected(int id, boolean toggle){
+        switch (id){
+            case R.id.rb_notify_email_no:
+                if(toggle) {
+                    rb_no.toggle();
+                }
+                et_email.setEnabled(false);
+                et_email.setText("");
+                tv_email.setTextColor(Color.GRAY);
+                tv_email_warning.setVisibility(View.INVISIBLE);
+                break;
+            case R.id.rb_notify_email_yes:
+                if(toggle){
+                    rb_yes.toggle();
+                }
+                et_email.setEnabled(true);
+                tv_email.setTextColor(Color.BLACK);
+                break;
+        }
+    }
+
     @Override
     public void returnHome(){
         Intent intent = new Intent(ScheduleConfirmationActivity.this, HomeActivity.class);
@@ -398,6 +430,7 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         bundle.putInt(HomeActivity.SHOW_SCHEDULE_SNACKBAR, 1);
         intent.putExtra(HomeActivity.SHOW_SCHEDULE_SNACKBAR,bundle);
         startActivity(intent);
+        finish();
     }
 
     @Override
@@ -426,6 +459,22 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         }
     }
 
+    @Override
+    public void updateSpinners(int id) {
+        switch (id){
+            case R.id.spnr_schedule_time:
+                if(sp_notification.getSelectedItemPosition() == reminderTimeArray.length - 1){
+                    radioButtonNotificationSelected(R.id.rb_notify_email_no, true);
+                    rb_no.setEnabled(false);
+                    rb_yes.setEnabled(false);
+                }else{
+                    rb_no.setEnabled(true);
+                    rb_yes.setEnabled(true);
+                }
+                break;
+        }
+    }
+
 
     public static class ConfirmationDialog extends DialogFragment {
         @Override
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesActivity.java
index c07d3ce..904dde0 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesActivity.java
@@ -117,7 +117,17 @@ public class SchedulesActivity extends AppCompatActivity implements NavigationVi
         final DrawerLayout drawer;
         ActionMenuView actionMenuView = (ActionMenuView) toolbar.findViewById(R.id.agendador_toolbar_menu);
         menuBuilder = (MenuBuilder) actionMenuView.getMenu();
+        menuBuilder.setCallback(new MenuBuilder.Callback() {
+            @Override
+            public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+                return onOptionsItemSelected(item);
+            }
 
+            @Override
+            public void onMenuModeChange(MenuBuilder menu) {
+
+            }
+        });
 
         ImageView drawerHamburger = (ImageView) toolbar.findViewById(R.id.img_toolbar_hamburger);
 
@@ -153,6 +163,7 @@ public class SchedulesActivity extends AppCompatActivity implements NavigationVi
         });
 
 
+
         navigationView.setCheckedItem(R.id.nav_check_schedules);
         navigationView.setNavigationItemSelectedListener(this);
 
@@ -239,9 +250,9 @@ public class SchedulesActivity extends AppCompatActivity implements NavigationVi
         maxDate = new Date();
         String date;
 
-        if(schedules.getSchedulesList() != null) {
+        if(schedules.getSchedules().getSchedulesList() != null) {
 
-            for (CheckSchedules.Schedule schedule : schedules.getSchedulesList()) {
+            for (CheckSchedules.Schedule schedule : schedules.getSchedules().getSchedulesList()) {
                 date = dateFormat.format(schedule.getStartTime());
                 if(schedule.getStartTime().after(maxDate)){
                     maxDate = schedule.getStartTime();
@@ -261,7 +272,7 @@ public class SchedulesActivity extends AppCompatActivity implements NavigationVi
 
             for (CheckSchedules.DependentSchedules dependentSchedules : schedules.getDependentSchedulesList()) {
 
-                for (CheckSchedules.Schedule schedule : dependentSchedules.getSchedulesList()){
+                for (CheckSchedules.Schedule schedule : dependentSchedules.getScheduleListModel().getSchedulesList()){
                     date = dateFormat.format(schedule.getStartTime());
                     if(schedule.getStartTime().after(maxDate)){
                         maxDate = schedule.getStartTime();
@@ -403,8 +414,8 @@ public class SchedulesActivity extends AppCompatActivity implements NavigationVi
         long id = 0;
 
         //searching if this schedule belongs to the citizen or the dependents.
-        for(int i = 0; i < schedules.getSchedulesList().size() && id  == 0; ++i){
-            if(schedules.getSchedulesList().get(i).getId() == selectedSchedule.getId())
+        for(int i = 0; i < schedules.getSchedules().getSchedulesList().size() && id  == 0; ++i){
+            if(schedules.getSchedules().getSchedulesList().get(i).getId() == selectedSchedule.getId())
             {
                 id = schedules.getId();
                 name = schedules.getName();
@@ -412,8 +423,8 @@ public class SchedulesActivity extends AppCompatActivity implements NavigationVi
         }
 
         for (int i = 0; i < schedules.getDependentSchedulesList().size() && id  == 0; ++i){
-            for(int j = 0; j < schedules.getDependentSchedulesList().get(i).getSchedulesList().size() && id  == 0; ++j){
-                if(schedules.getDependentSchedulesList().get(i).getSchedulesList().get(j).getId() == selectedSchedule.getId())
+            for(int j = 0; j < schedules.getDependentSchedulesList().get(i).getScheduleListModel().getSchedulesList().size() && id  == 0; ++j){
+                if(schedules.getDependentSchedulesList().get(i).getScheduleListModel().getSchedulesList().get(j).getId() == selectedSchedule.getId())
                 {
                     id = schedules.getDependentSchedulesList().get(i).getId();
                     name = schedules.getDependentSchedulesList().get(i).getName();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
index 12e6ecb..79e0272 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
@@ -47,7 +47,7 @@ import br.ufpr.c3sl.agendador.agendador.models.ServiceType;
 import br.ufpr.c3sl.agendador.agendador.presenters.PresenterManager;
 import br.ufpr.c3sl.agendador.agendador.presenters.SchedulesHistoryPresenter;
 import br.ufpr.c3sl.agendador.agendador.views.SchedulesHistoryView;
-import br.ufpr.c3sl.agendador.agendador.views.SpinnerActivity;
+import br.ufpr.c3sl.agendador.agendador.helpers.listeners.SpinnerActivity;
 
 
 public class SchedulesHistoryActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, SchedulesHistoryView, SpinnerActivity {
@@ -756,11 +756,11 @@ public class SchedulesHistoryActivity extends AppCompatActivity implements Navig
 
         expandableListTitle = new ArrayList<>();
         expandableListTitle.add(new Pair<>(schedules.getName(), schedules.getId()));
-        expandableListDetail.put(schedules.getName(), schedules.getSchedulesList());
+        expandableListDetail.put(schedules.getName(), schedules.getSchedules().getSchedulesList());
 
         for (CheckSchedules.DependentSchedules dependentSchedules : schedules.getDependentSchedulesList()) {
             expandableListTitle.add(new Pair<>(dependentSchedules.getName(), dependentSchedules.getId()));
-            expandableListDetail.put(dependentSchedules.getName(), dependentSchedules.getSchedulesList());
+            expandableListDetail.put(dependentSchedules.getName(), dependentSchedules.getScheduleListModel().getSchedulesList());
         }
 
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulingActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulingActivity.java
index 2df2714..7b996ae 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulingActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulingActivity.java
@@ -328,6 +328,7 @@ public class SchedulingActivity extends AppCompatActivity implements SchedulingV
 
         mcv.setSelectionMode(MaterialCalendarView.SELECTION_MODE_NONE);
 
+        // TODO: 12/12/17 check here
         dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
         hourFormat = new SimpleDateFormat("HH:mm", Locale.getDefault());
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
index 5e3f815..058d842 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
@@ -34,6 +34,14 @@ import br.ufpr.c3sl.agendador.agendador.models.UserOutput;
 
 public abstract class Utils {
 
+    public static final String DATE_HOUR_FORMAT = "dd/MM/yyyy - HH:mm";
+
+    public static final String HOUR_FORMAT = "HH:mm";
+
+    public static final String DATE_FORMAT = "dd/MM/yyyy";
+
+    public static final String SERVER_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
+
     public final static String SERVICE_UPDATE_IMAGE = "br.c3sl.ufpr.image_update";
 
     public static final String SECTORS_LIST = "sectors_list";
@@ -50,10 +58,10 @@ public abstract class Utils {
 
     public static final String SCHEDULE_CONFIRMATION = "selected_schedule";
 
-    public static final String CITIZEN = "citizen_object";
+    public static final String SIZE_LARGE = "large";
 
+    public static final String CITIZEN = "citizen_object";
     public static final String CITIZEN_BUNDLE = "br.ufpr.c3sl.agendador.agendador.citizen_bundle";
-
     public static final String JOB_FILE_NAME = "fileName_tag";
     public static final String ADDRESS_NEIGHBORHOOD = "address.neighborhood";
     public static final String ADDRESS_NUMBER = "address_number";
@@ -99,17 +107,25 @@ public abstract class Utils {
     public static final String CPF_MASK = "###.###.###-##";
     public static final String BIRTH_DAY_MASK = "##/##/####";
     public static final String SCHEDULE = "schedule";
-    public static final String DATE_FORMAT = "MM/dd/yyyy HH:mm";
     public static final String CALLER_ACTIVITY = "from_activity";
+
+
     public static final int HISTORY_ACTIVITY = 1;
     public static final int SCHEDULES_ACTIVITY = 0;
+
+
     public static final String REQUEST_FILTER_SECTOR = "q[sector_id]";
     public static final String REQUEST_FILTER_TYPE = "q[service_type_id]";
     public static final String REQUEST_FILTER_PLACE = "q[service_place_id]";
     public static final String REQUEST_FILTER_SITUATION = "q[situation_id]";
-    public static final String SIZE_LARGE = "large";
+
+
     public static final String NOTIFICATION = "notification";
     public static final String NOTIFICATION_SERVICE = "br.c3sl.ufpr.notification_service";
+    public static final String NOTIFICATION_LIST = "notification_list";
+
+
+    public static final String ACTION_SHOW_NOTIFICATION = "br.ufpr.c3sl.agendador.SHOW_NOTIFICATION";
 
     public static int getPixelValue(int dp, Context context) {
         Resources resources = context.getResources();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/adapters/SchedulesExpandableListAdapter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/adapters/SchedulesExpandableListAdapter.java
index 91db747..624d9a1 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/adapters/SchedulesExpandableListAdapter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/adapters/SchedulesExpandableListAdapter.java
@@ -37,7 +37,7 @@ public class SchedulesExpandableListAdapter extends BaseExpandableListAdapter {
         this.context = context;
         this.expandableListTitle = expandableListTitle;
         this.expandableListDetail = expandableListDetail;
-        dateFormat = new SimpleDateFormat(Utils.DATE_FORMAT, Locale.getDefault());
+        dateFormat = new SimpleDateFormat(Utils.DATE_HOUR_FORMAT, Locale.getDefault());
     }
 
     @Override
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/SpinnerActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerActivity.java
similarity index 67%
rename from app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/SpinnerActivity.java
rename to app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerActivity.java
index f8c31cc..449c737 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/SpinnerActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerActivity.java
@@ -1,4 +1,4 @@
-package br.ufpr.c3sl.agendador.agendador.views;
+package br.ufpr.c3sl.agendador.agendador.helpers.listeners;
 
 /**
  * Created by Lucas Braz Cunha on 22/11/17.
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerListener.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerListener.java
index f3d9d4e..ea90e52 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerListener.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/listeners/SpinnerListener.java
@@ -4,8 +4,6 @@ import android.view.MotionEvent;
 import android.view.View;
 import android.widget.AdapterView;
 
-import br.ufpr.c3sl.agendador.agendador.views.SpinnerActivity;
-
 /**
  * Created by Lucas Braz Cunha on 22/11/17.
  */
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/CheckSchedules.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/CheckSchedules.java
index 5549420..2dc9b0a 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/CheckSchedules.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/CheckSchedules.java
@@ -21,7 +21,7 @@ public class CheckSchedules {
     String name;
 
     @SerializedName("schedules")
-    private List<Schedule> schedulesList;
+    ScheduleListModel schedules;
 
     @SerializedName("dependants")
     private List<DependentSchedules> dependentSchedulesList;
@@ -34,13 +34,17 @@ public class CheckSchedules {
         return name;
     }
 
-    public CheckSchedules(long id, String name, List<Schedule> schedulesList, List<DependentSchedules> dependentSchedulesList) {
+    public CheckSchedules(long id, String name, ScheduleListModel schedules, List<DependentSchedules> dependentSchedulesList) {
         this.id = id;
         this.name = name;
-        this.schedulesList = schedulesList;
+        this.schedules = schedules;
         this.dependentSchedulesList = dependentSchedulesList;
     }
 
+    public ScheduleListModel getSchedules() {
+        return schedules;
+    }
+
     public static class Schedule implements Parcelable{
 
         @SerializedName("id")
@@ -154,6 +158,11 @@ public class CheckSchedules {
 
     }
 
+
+    public List<DependentSchedules> getDependentSchedulesList() {
+        return dependentSchedulesList;
+    }
+
     public static class DependentSchedules{
 
         @SerializedName("id")
@@ -163,11 +172,7 @@ public class CheckSchedules {
         String name;
 
         @SerializedName("schedules")
-        List<Schedule> schedulesList;
-
-        public List<Schedule> getSchedulesList() {
-            return schedulesList;
-        }
+        ScheduleListModel scheduleListModel;
 
         public long getId() {
             return id;
@@ -176,20 +181,50 @@ public class CheckSchedules {
         public String getName() {
             return name;
         }
-
-        public DependentSchedules(long id, String name, List<Schedule> scheduleList) {
+        public DependentSchedules(long id, String name) {
             this.id = id;
             this.name = name;
-            this.schedulesList = scheduleList;
+        }
+
+        public ScheduleListModel getScheduleListModel() {
+            return scheduleListModel;
         }
     }
 
-    public List<Schedule> getSchedulesList() {
-        return schedulesList;
+    public static class ScheduleListModel {
+
+        @SerializedName("num_entries")
+        int listSize;
+
+        @SerializedName("entries")
+        List<Schedule> schedulesList;
+
+        @SerializedName("sectors")
+        List<SectorScheduleModel> sectorScheduleModels;
+
+
+        public List<Schedule> getSchedulesList() {
+            return schedulesList;
+        }
+
+        public int getListSize() {
+            return listSize;
+        }
     }
 
-    public List<DependentSchedules> getDependentSchedulesList() {
-        return dependentSchedulesList;
+    public static class SectorScheduleModel {
+        @SerializedName("id")
+        int sectorId;
+
+        @SerializedName("name")
+        String name;
+
+        @SerializedName("schedules_by_sector")
+        int chedulesbySector;
+
+        @SerializedName("schedules")
+        int schedules;
     }
 
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
index 1811b3c..c43de20 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
@@ -9,6 +9,7 @@ import com.google.gson.annotations.SerializedName;
  * Created by Lucas Braz Cunha on 24/11/17.
  */
 
+
 public class Notification implements Parcelable{
 
     @SerializedName("schedule_id")
@@ -33,6 +34,15 @@ public class Notification implements Parcelable{
     public Notification() {
     }
 
+    public Notification(long scheduleId, String reminderTime, boolean hasRead, String description, String emailAddress, boolean emailSent) {
+        this.scheduleId = scheduleId;
+        this.reminderTime = reminderTime;
+        this.hasRead = hasRead;
+        this.description = description;
+        this.emailAddres = emailAddress;
+        this.emailSent = emailSent;
+    }
+
     /**reads back fields IN THE ORDER they were written */
     private Notification(Parcel pc){
         scheduleId         = pc.readLong();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
new file mode 100644
index 0000000..022bcf3
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
@@ -0,0 +1,45 @@
+package br.ufpr.c3sl.agendador.agendador.models;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by Lucas Braz Cunha on 18/12/17.
+ */
+
+public class NotificationReturn{
+
+    @SerializedName("id")
+    public long notificationId;
+
+    @SerializedName("account_id")
+    public long accountId;
+
+    @SerializedName("schedule_id")
+    public Long scheduleId;
+
+    @SerializedName("resource_schedule_id")
+    public Long resourceScheduleId;
+
+    @SerializedName("reminder_time")
+    public String reminderTime;
+
+    @SerializedName("read")
+    public int hasRead;
+
+    @SerializedName("content")
+    public String description;
+
+    @SerializedName("reminder_email")
+    public String emailAddres;
+
+    @SerializedName("reminder_email_sent")
+    public int emailSent;
+
+    @SerializedName("created_at")
+    public String createdAt;
+
+    @SerializedName("updated_at")
+    public String updatedAt;
+
+
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleNote.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleNote.java
index 3f394cc..8397ca4 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleNote.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleNote.java
@@ -8,7 +8,7 @@ import com.google.gson.annotations.SerializedName;
 
 public class ScheduleNote {
 
-    private Schedule schedule;
+    public Schedule schedule;
 
     public ScheduleNote(String note) {
         this.schedule = new Schedule(note);
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
index 1d1aab1..0683147 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
@@ -15,6 +15,7 @@ import br.ufpr.c3sl.agendador.agendador.models.DependentCreation;
 import br.ufpr.c3sl.agendador.agendador.models.FormFilters;
 import br.ufpr.c3sl.agendador.agendador.models.FullDependent;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleNote;
 import br.ufpr.c3sl.agendador.agendador.models.SectorInput;
@@ -92,7 +93,7 @@ public interface ApiEndpoints {
     Call<FormFilters> requestCitizenSectors();
 
     @POST("notifications?permission=2")
-    Call<ScheduleConfirmation> requestCreateNotification(@Body Notification notification);
+    Call<NotificationReturn> requestCreateNotification(@Body Notification notification);
 
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
index 14ec54a..c4d09fd 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
@@ -14,8 +14,8 @@ import retrofit2.converter.gson.GsonConverterFactory;
  */
 
 public abstract class ApiUtils {
-     public static final String BASE_URL = "http://10.0.2.2:3000/v1/";
-//    public static final String BASE_URL = "http://newcastle.c3sl.ufpr.br/develop/v1/";
+//        public static final String BASE_URL = "http://10.0.2.2:3000/v1/";
+     public static final String BASE_URL = "http://newcastle.c3sl.ufpr.br/develop/v1/";
 
     public static ApiEndpoints request(final Map<String, String> header) {
         OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
index fa5040c..6416763 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
@@ -5,6 +5,7 @@ import android.content.Intent;
 import android.graphics.BitmapFactory;
 import android.os.Bundle;
 import android.util.Log;
+import android.widget.Toast;
 
 import com.firebase.jobdispatcher.Constraint;
 import com.firebase.jobdispatcher.FirebaseJobDispatcher;
@@ -107,6 +108,8 @@ public class LoginPresenter extends BasePresenter<LoginView> {
                         break;
                     default:
                         Log.d("Login Request", "Voltou " + status + "!!!");
+                        loginPresenter.view().setProgressBar(false);
+                        Toast.makeText(context, "Ocorreu um erro ao logar.", Toast.LENGTH_SHORT).show();
                         break;
                 }
             }
@@ -197,19 +200,21 @@ public class LoginPresenter extends BasePresenter<LoginView> {
         final String uid = osb.getString(Utils.UID, null);
         String compare, children[];
 
-        Locale locale = new Locale("pt", "BR");
-        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", locale);
-        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+        DateFormat sdf = new SimpleDateFormat(Utils.SERVER_FORMAT, Locale.getDefault());
         sdf.setLenient(false);
 
 
         Date fileDate = null;
         //in case of parsing exception, it will request image from server and app won't crash.
         Date serverDate = Calendar.getInstance().getTime();
+        Log.d("Agendador", "Data sem parsear:" + osb.getString(Utils.AVATAR_UPDATED_AT, ""));
         try {
             serverDate = sdf.parse(osb.getString(Utils.AVATAR_UPDATED_AT, ""));
-        } catch (ParseException e) {
-            e.printStackTrace();
+            Log.d("Agendador", "Data parseada:" + sdf.format(serverDate));
+        } catch (ParseException ignored) {
+            //in case of parse exception request from server
+            ignored.printStackTrace();
         }
 
         File dir = new File(context.getExternalFilesDir(null) + File.separator + Utils.DIR_PICTRS + File.separator);
@@ -238,8 +243,6 @@ public class LoginPresenter extends BasePresenter<LoginView> {
                 loginPresenter.view().setProgressBar(false);
                 loginPresenter.view().afterSuccessfulLogin();
             }
-
-
         }
 
     }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
index 9ccd9c2..b9f086e 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
@@ -1,7 +1,6 @@
 package br.ufpr.c3sl.agendador.agendador.presenters;
 
 import android.content.Context;
-import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 
@@ -17,19 +16,18 @@ import com.google.gson.Gson;
 import java.util.HashMap;
 import java.util.Map;
 
-import br.ufpr.c3sl.agendador.agendador.LoginActivity;
 import br.ufpr.c3sl.agendador.agendador.ScheduleConfirmationActivity;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.models.CitizenCompact;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleNote;
-import br.ufpr.c3sl.agendador.agendador.models.UserOutput;
 import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
 import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
-import br.ufpr.c3sl.agendador.agendador.services.ImageUpdateService;
-import br.ufpr.c3sl.agendador.agendador.services.NotificationCreateService;
+import br.ufpr.c3sl.agendador.agendador.services.notification.LocalNotificationManager;
+import br.ufpr.c3sl.agendador.agendador.services.notification.NotificationCreateService;
 import okhttp3.Headers;
 import retrofit2.Call;
 import retrofit2.Callback;
@@ -56,7 +54,7 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
     }
 
 
-    public void onScheduleClicked(final ScheduleConfirmation scheduleConfirmation, CitizenCompact citizen){
+    public void onScheduleClicked(final ScheduleConfirmation scheduleConfirmation, CitizenCompact citizen, String note){
         Map<String, String> header = new HashMap<>();
         header.put("Content-Type", "application/json");
         header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
@@ -65,9 +63,9 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
 
         final ApiEndpoints service = ApiUtils.request(header);
 
-        ScheduleNote note = new ScheduleNote("");
+        ScheduleNote scheduleNote = new ScheduleNote(note);
 
-        Call<ScheduleConfirmation> listCall = service.requestPerformScheduling(scheduleConfirmation.getId(), citizen.getId(), note);
+        Call<ScheduleConfirmation> listCall = service.requestPerformScheduling(scheduleConfirmation.getId(), citizen.getId(), scheduleNote);
 
         scheduleConfirmationPresenter.view().setProgressBar(true);
         listCall.enqueue(new Callback<ScheduleConfirmation>() {
@@ -76,13 +74,13 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
             public void onResponse(Call<ScheduleConfirmation> call, Response<ScheduleConfirmation> response) {
                 Headers headers = response.headers();
                 int status = response.code();
-                ScheduleConfirmation confirmationResponse = response.body();
+
                 updateHeaders(headers);
                 switch (status) {
                     case 200:
                         Log.d("Server response", this.getClass().getName() + ": 200 - Sucesso!");
                         scheduleConfirmationPresenter.view().setProgressBar(false);
-                        scheduleConfirmationPresenter.view().onSuccess(confirmationResponse);
+                        scheduleConfirmationPresenter.view().onSuccess(scheduleConfirmation);
 
                         break;
                     default:
@@ -111,30 +109,29 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
         header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
         header.put(Utils.UID, osb.getString(Utils.UID, null));
 
-        final ApiEndpoints service = ApiUtils.request(header);
 
+        final ApiEndpoints service = ApiUtils.request(header);
 
-        // TODO: 24/11/17 arrumar retorno
-        Call<ScheduleConfirmation> listCall = service.requestCreateNotification(notification);
+        final Call<NotificationReturn> listCall = service.requestCreateNotification(notification);
 
         scheduleConfirmationPresenter.view().setProgressBar(true);
-        listCall.enqueue(new Callback<ScheduleConfirmation>() {
+        listCall.enqueue(new Callback<NotificationReturn>() {
 
             @Override
-            public void onResponse(Call<ScheduleConfirmation> call, Response<ScheduleConfirmation> response) {
+            public void onResponse(Call<NotificationReturn> call, Response<NotificationReturn> response) {
                 Headers headers = response.headers();
                 int status = response.code();
-                //ScheduleConfirmation confirmationResponse = response.body();
+                Log.d("Agendador", "Header do create notification:" + headers.get(Utils.ACCESS_TOKEN));
                 updateHeaders(headers);
                 switch (status) {
-                    case 200:
+                    case 201:
                         Log.d("Server response", this.getClass().getName() + ": 200 - Sucess!");
                         scheduleConfirmationPresenter.view().setProgressBar(false);
-
                         scheduleConfirmationPresenter.view().returnHome();
+                        LocalNotificationManager.createLocalNotification(context, notification, osb, new Gson());
                         break;
                     default:
-                        Log.e("Server response", this.getClass().getName() + ": ERRO:" + status + ". Scheduling job");
+                        Log.e("Server response", this.getClass().getName() + ": ERRO:" + status + " na criação de uma notificação.");
                         scheduleNotificationJob(notification);
                         scheduleConfirmationPresenter.view().setProgressBar(false);
                         scheduleConfirmationPresenter.view().returnHome();
@@ -142,11 +139,10 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
                 }
             }
             @Override
-            public void onFailure(Call<ScheduleConfirmation> call, Throwable t) {
+            public void onFailure(Call<NotificationReturn> call, Throwable t) {
                 Log.e("Server response", this.getClass().getName() +  ": Request Failed, Scheduling job.");
-
+                t.printStackTrace();
                 scheduleNotificationJob(notification);
-
                 scheduleConfirmationPresenter.view().setProgressBar(false);
                 scheduleConfirmationPresenter.view().returnHome();
             }
@@ -168,7 +164,7 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
                 .setService(NotificationCreateService.class)
                 .setTag(Utils.NOTIFICATION_SERVICE)
                 //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
-                .setTrigger(Trigger.executionWindow(0, 3600))
+                .setTrigger(Trigger.executionWindow(10, 3600))
                 //will be retried if it fails.
                 .setRecurring(true)
                 .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesHistoryPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesHistoryPresenter.java
index 42a77ce..0055f12 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesHistoryPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesHistoryPresenter.java
@@ -77,6 +77,7 @@ public class SchedulesHistoryPresenter extends BasePresenter<SchedulesHistoryAct
                 presenter.view().setNoConnection(true);
                 presenter.view().enableSpinners(false);
                 presenter.view().enableButtons(false);
+                t.printStackTrace();
             }
         });
 
@@ -124,6 +125,7 @@ public class SchedulesHistoryPresenter extends BasePresenter<SchedulesHistoryAct
                 presenter.view().setNoConnection(true);
                 presenter.view().setProgressBar(false);
                 presenter.view().enableSpinners(true);
+                t.printStackTrace();
             }
         });
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesPresenter.java
index c8197a6..bfdd7a0 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesPresenter.java
@@ -80,6 +80,7 @@ public class SchedulesPresenter extends BasePresenter<SchedulesActivity> {
                 presenter.view().setNoConnection(true);
                 presenter.view().setProgressBar(false);
                 presenter.view().blockCalendar(false);
+                t.printStackTrace();
             }
         });
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/BootReceiver.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/BootReceiver.java
new file mode 100644
index 0000000..1786d10
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/BootReceiver.java
@@ -0,0 +1,72 @@
+package br.ufpr.c3sl.agendador.agendador.services;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
+import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.services.notification.LocalNotificationManager;
+import br.ufpr.c3sl.agendador.agendador.services.notification.NotificationReceiver;
+
+/**
+ * Created by Lucas Braz Cunha on 27/11/17.
+ *
+ * Receiver responsible for re-scheduling notifications on reboot, if it's needed.
+ */
+
+
+public class BootReceiver  extends BroadcastReceiver {
+
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        PendingResult result;
+        if (intent.getAction() != null && context != null && intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
+            // Set the alarm here.
+            result = goAsync();
+            Date date;
+            Calendar calendar;
+            SimpleDateFormat sdfServer = new SimpleDateFormat(Utils.SERVER_FORMAT, Locale.getDefault());
+            ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
+
+            //Retrieve the values
+            Gson gson = new Gson();
+            String jsonText = osb.getString(Utils.NOTIFICATION_LIST, null);
+            List<Notification> notifications = gson.fromJson(jsonText, new TypeToken<List<Notification>>(){}.getType());
+
+
+            if (notifications != null) {
+                Log.d("Agendador", "Tamanho da lista:" + notifications.size());
+                for (Notification notification: notifications) {
+                    calendar = Calendar.getInstance();
+                    try {
+                        date = sdfServer.parse(notification.reminderTime);
+                        calendar.setTime(date);
+                        LocalNotificationManager.setReminder(context, NotificationReceiver.class, calendar, (int) notification.scheduleId);
+                    } catch (ParseException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+
+
+            result.finish();
+        }
+    }
+
+
+
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
new file mode 100644
index 0000000..e463eba
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
@@ -0,0 +1,127 @@
+package br.ufpr.c3sl.agendador.agendador.services.notification;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.util.Log;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+
+import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
+import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
+
+import static android.content.Context.ALARM_SERVICE;
+
+/**
+ * Utility Class to manipulate the local list of notifications.
+ *
+ * Created by Lucas Braz Cunha on 15/12/17.
+ */
+
+
+
+public abstract class LocalNotificationManager {
+
+
+    private static final int NOTIFICATION_REMINDER_REQUEST_CODE = 0x27;
+
+
+    public static void createLocalNotification(Context context, Notification notification, ObscuredSharedPreferences osb, Gson gson){
+        Log.d("Agendador", "Criando notificação local...");
+        addNotification(notification, osb, gson);
+        SimpleDateFormat sdfServer = new SimpleDateFormat(Utils.SERVER_FORMAT, Locale.getDefault());
+        Calendar calendar = Calendar.getInstance();
+
+        try{
+            calendar.setTime(sdfServer.parse(notification.reminderTime));
+            setReminder(context, NotificationReceiver.class, calendar, (int) notification.scheduleId);
+        }catch (ParseException ignored){
+            Log.e("Agendador", "Erro ao parsear data, para criar notificação local.");
+            ignored.printStackTrace();
+        }
+    }
+
+
+    public static void setReminder(Context context, Class<?> cls, Calendar calendar, int scheduleId){
+
+        Intent intent = new Intent(context, cls);
+        intent.setAction(Utils.ACTION_SHOW_NOTIFICATION);
+        intent.putExtra(Utils.ID, scheduleId);
+
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
+                NOTIFICATION_REMINDER_REQUEST_CODE + scheduleId, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+        AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
+        if(am != null){
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
+            }else {
+                am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
+            }
+
+            Log.d("Agendador", "Alarme registrado para o agendamento " + scheduleId + " .");
+        }
+        else{
+            Log.d("Agendador", "Objeto do Alarm Manager NULL.");
+        }
+    }
+
+
+    private static void addNotification(Notification notification, ObscuredSharedPreferences osb, Gson gson){
+
+        //Retrieve the values
+        String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
+        List<Notification> notifications = gson.fromJson(jsonList, new TypeToken<List<Notification>>(){}.getType());
+        if(notifications == null)
+            notifications = new ArrayList<>();
+        notifications.add(notification);
+        jsonList = gson.toJson(notifications);
+
+        Log.d("Agendador", "add notification:" + jsonList);
+
+        osb.edit().putString(Utils.NOTIFICATION_LIST, jsonList).commit();
+
+    }
+
+
+    // TODO: 15/12/17 Testar o retorno da lista.
+    public static List<Notification> getList(ObscuredSharedPreferences osb, Gson gson){
+        String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
+        return gson.fromJson(jsonList, new TypeToken<List<Notification>>(){}.getType());
+    }
+
+    // TODO: 15/12/17 Testar o remove.
+    public static void removeNotification(long scheduleId, ObscuredSharedPreferences osb, Gson gson){
+
+        //Retrieve the values
+        String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
+        List<Notification> notifications = gson.fromJson(jsonList, new TypeToken<List<Notification>>(){}.getType());
+
+        for(Notification n : notifications) {
+            if (n.scheduleId == scheduleId){
+                notifications.remove(n);
+                break;
+            }
+        }
+
+        jsonList = gson.toJson(notifications);
+
+        Log.d("Agendador", "remove notification:" + jsonList);
+
+        osb.edit().putString(Utils.NOTIFICATION_LIST, jsonList).commit();
+
+    }
+
+
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/NotificationCreateService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
similarity index 82%
rename from app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/NotificationCreateService.java
rename to app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
index 8169038..273300a 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/NotificationCreateService.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
@@ -1,4 +1,4 @@
-package br.ufpr.c3sl.agendador.agendador.services;
+package br.ufpr.c3sl.agendador.agendador.services.notification;
 
 import android.content.Context;
 import android.os.Bundle;
@@ -14,7 +14,7 @@ import java.util.Map;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
-import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
 import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
 import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
 import okhttp3.Headers;
@@ -53,12 +53,13 @@ public class NotificationCreateService extends JobService {
 
         ApiEndpoints service = ApiUtils.request(header);
 
-        Call<ScheduleConfirmation> listCall = service.requestCreateNotification(notification);
+        Call<NotificationReturn> listCall = service.requestCreateNotification(notification);
 
-        listCall.enqueue(new Callback<ScheduleConfirmation>() {
+        final Notification finalNotification = notification;
+        listCall.enqueue(new Callback<NotificationReturn>() {
 
             @Override
-            public void onResponse(Call<ScheduleConfirmation> call, Response<ScheduleConfirmation> response) {
+            public void onResponse(Call<NotificationReturn> call, Response<NotificationReturn> response) {
                 int status = response.code();
                 Headers headers = response.headers();
                 ObscuredSharedPreferences  osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
@@ -74,7 +75,7 @@ public class NotificationCreateService extends JobService {
 
                 switch (status) {
                     case 200:
-
+                        LocalNotificationManager.createLocalNotification(getApplicationContext(), finalNotification, osb, new Gson());
                         jobFinished(job, false);
                         break;
                     default:
@@ -86,8 +87,9 @@ public class NotificationCreateService extends JobService {
             }
 
             @Override
-            public void onFailure(Call<ScheduleConfirmation> call, Throwable t) {
+            public void onFailure(Call<NotificationReturn> call, Throwable t) {
                 Log.v("AGNDDR-NotifiCreate", "Job falhou e será remarcado!!");
+                t.printStackTrace();
                 jobFinished(job, true);
             }
         });
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
new file mode 100644
index 0000000..326f2fe
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
@@ -0,0 +1,67 @@
+package br.ufpr.c3sl.agendador.agendador.services.notification;
+
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.support.v7.app.NotificationCompat;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.google.gson.Gson;
+
+import java.util.List;
+
+import br.ufpr.c3sl.agendador.agendador.R;
+import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
+import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
+
+import static android.content.Context.NOTIFICATION_SERVICE;
+
+/**
+ * Created by Lucas Braz Cunha on 27/11/17.
+ */
+
+public class NotificationReceiver extends BroadcastReceiver{
+
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if(intent.getAction() != null && intent.getAction().equals(Utils.ACTION_SHOW_NOTIFICATION)){
+            int id = intent.getIntExtra(Utils.ID, -1);
+            Log.d("Agendador", "Estou no "+ NotificationReceiver.class.getName() +"! Notificação de id "+ id);
+            ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
+            Notification content = null;
+            Gson gson = new Gson();
+            List<Notification> notifications = LocalNotificationManager.getList(osb, gson);
+            for(Notification n : notifications){
+                if(n.scheduleId == id){
+                    content = n;
+                    break;
+                }
+            }
+            LocalNotificationManager.removeNotification(id, osb, gson);
+            NotificationManager notificationManager = (NotificationManager)
+                    context.getSystemService(NOTIFICATION_SERVICE);
+
+            if(content == null || notificationManager == null){
+                Log.e("Agendador", "Erro: notificação não encontrada, ou notification manager null");
+                return;
+            }
+
+            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
+
+            String alert = context.getResources().getString(R.string.notification_alert);
+            android.app.Notification appNotification = mBuilder.setAutoCancel(true).setContentText(content.description).setContentTitle(alert)
+                    .setDefaults(android.app.Notification.DEFAULT_LIGHTS | android.app.Notification.DEFAULT_SOUND)
+                    .setSmallIcon(R.drawable.img_mainact_logo).setTicker(alert)
+                    .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.img_terms_logo)).build();
+
+            // Will display the notification in the notification bar
+            notificationManager.notify(id, appNotification);
+
+        }
+    }
+}
diff --git a/app/src/main/res/layout/content_schedule_confirmation.xml b/app/src/main/res/layout/content_schedule_confirmation.xml
index d5a2107..28553d0 100644
--- a/app/src/main/res/layout/content_schedule_confirmation.xml
+++ b/app/src/main/res/layout/content_schedule_confirmation.xml
@@ -28,6 +28,7 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:focusableInTouchMode="true"
             android:orientation="vertical">
 
             <TextView
@@ -213,6 +214,28 @@
             </RelativeLayout>
 
 
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="15dp"
+                android:layout_marginStart="14dp"
+                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
+                android:textSize="14sp"
+                android:typeface="normal"
+                android:text="@string/notification_note_text"/>
+
+            <EditText
+                android:id="@+id/et_schedule_note"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:layout_marginTop="5dp"
+                android:layout_marginStart="14dp"
+                android:layout_marginEnd="14dp"
+                android:textStyle="normal"
+                android:inputType="textAutoCorrect"
+                android:maxLength="140"/>
+
+
 
             <TextView
                 android:layout_width="wrap_content"
@@ -306,7 +329,7 @@
                     android:layout_marginTop="5dp"
                     android:maxLines="1"
                     android:textColor="@color/colorBlack"
-                    android:textStyle="normal|bold"
+                    android:textStyle="normal"
                     android:inputType="textEmailAddress"/>
 
 
diff --git a/app/src/main/res/values/integer.xml b/app/src/main/res/values/integer.xml
index b8d2b0f..ffee45f 100644
--- a/app/src/main/res/values/integer.xml
+++ b/app/src/main/res/values/integer.xml
@@ -3,17 +3,17 @@
 
     <integer name="max_length_name">150</integer>
 
-    <string-array name="notification_time_int">
+    <integer-array name="notification_time_milis">
+        <item>900000</item>
+        <item>1800000</item>
+        <item>2700000</item>
+        <item>3600000</item>
+        <item>7200000</item>
+        <item>10800000</item>
+        <item>240000</item>
+        <item>14400000</item>
+        <item>86400000</item>
         <item>0</item>
-        <item>15</item>
-        <item>30</item>
-        <item>45</item>
-        <item>60</item>
-        <item>120</item>
-        <item>180</item>
-        <item>240</item>
-        <item>300</item>
-        <item>1440</item>
-    </string-array>
+    </integer-array>
 
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5e1f645..bf0e056 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -208,7 +208,6 @@
     <string name="notification_email_dest">Digite o e-mail:</string>
 
     <string-array name="notification_time">
-        <item>Não notificar</item>
         <item>15 minutos antes</item>
         <item>30 minutos antes</item>
         <item>45 minutos antes</item>
@@ -218,8 +217,14 @@
         <item>4 horas antes</item>
         <item>5 horas antes</item>
         <item>1 dia antes</item>
+        <item>Não notificar</item>
     </string-array>
 
     <string name="not_valid_email">Digite um e-mail válido.</string>
 
+    <string name="notification_content">%s em %s (%s, %d) %s às %s</string>
+    <string name="notification_note_text">Observações (Máximo de 140 caracteres):</string>
+
+    <string name="notification_alert">Atendimento está próximo</string>
+
 </resources>
-- 
GitLab


From 947a48ee6da085bce38114bac19f0a504b3a2132 Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Fri, 22 Dec 2017 11:35:53 -0200
Subject: [PATCH 3/9] AGILE#271: [WP] Cancel notification on logout, Show
 android notification

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 .../agendador/agendador/LoginActivity.java    |  1 +
 .../agendador/ScheduleInfoActivity.java       | 47 ++++++++++++-------
 .../agendador/SchedulesActivity.java          |  8 ++--
 .../agendador/SchedulesHistoryActivity.java   |  2 +-
 .../agendador/agendador/helpers/Utils.java    |  2 +
 .../agendador/models/CheckSchedules.java      |  2 +-
 .../agendador/agendador/network/ApiUtils.java |  4 +-
 .../agendador/presenters/BasePresenter.java   | 46 ++++++++++++++++--
 .../agendador/services/BootReceiver.java      |  2 +-
 .../LocalNotificationManager.java             |  8 ++--
 .../notification/NotificationReceiver.java    |  9 +++-
 11 files changed, 96 insertions(+), 35 deletions(-)

diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
index 1842ca2..a33a5ea 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
@@ -205,6 +205,7 @@ public class LoginActivity extends AppCompatActivity implements LoginView {
 
     @Override
     public void afterSuccessfulLogin() {
+        // TODO 22/12/2017: instanciar job que verifica notificações no back-end.
         Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
         startActivity(intent);
         finish();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
index 5c8a910..61a4a55 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
@@ -43,12 +43,15 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
 
     private long id;
 
-    private CheckSchedules.Schedule schedule;
 
     private static final String EXIT_CONFIRMATION_DIALOG_TAG = "exit_dialog";
 
     private int caller;
 
+    private TextView tv_name, tv_sector, tv_location, tv_type,
+            tv_date, tv_address, tv_situation, tv_situation_content;
+
+
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -114,29 +117,25 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
             }
         });
 
+        tv_name = (TextView) findViewById(R.id.tv_schedule_citizen_content);
+        tv_sector = (TextView) findViewById(R.id.tv_schedule_sector_content);
+        tv_location = (TextView) findViewById(R.id.tv_schedule_location_content);
+        tv_type = (TextView) findViewById(R.id.tv_schedule_type_content);
+        tv_date = (TextView) findViewById(R.id.tv_schedule_date_content);
+        tv_address = (TextView) findViewById(R.id.tv_schedule_street_content);
+        tv_situation = (TextView) findViewById(R.id.tv_schedule_situation);
+        tv_situation_content = (TextView) findViewById(R.id.tv_schedule_situation_content);
+
+        id = getIntent().getIntExtra(Utils.ID, 0);
 
         Bundle bundle = getIntent().getBundleExtra(Utils.SCHEDULE_BUNDLE);
+        CheckSchedules.Schedule schedule = null;
         if(bundle != null){
-            DateFormat df = new SimpleDateFormat("dd/MM/yyyy - HH:mm", Locale.getDefault());
             String name = bundle.getString(Utils.NAME);
             id = bundle.getLong(Utils.ID);
             schedule = bundle.getParcelable(Utils.SCHEDULE);
-            TextView tv_name = (TextView) findViewById(R.id.tv_schedule_citizen_content);
-            TextView tv_sector = (TextView) findViewById(R.id.tv_schedule_sector_content);
-            TextView tv_location = (TextView) findViewById(R.id.tv_schedule_location_content);
-            TextView tv_type = (TextView) findViewById(R.id.tv_schedule_type_content);
-            TextView tv_date = (TextView) findViewById(R.id.tv_schedule_date_content);
-            TextView tv_address = (TextView) findViewById(R.id.tv_schedule_street_content);
-            TextView tv_situation = (TextView) findViewById(R.id.tv_schedule_situation);
-            TextView tv_situation_content = (TextView) findViewById(R.id.tv_schedule_situation_content);
-
             tv_name.setText(name);
-            tv_sector.setText(schedule.getSectorName());
-            tv_location.setText(schedule.getLocationName());
-            tv_type.setText(schedule.getServiceTypeName());
-            tv_date.setText(df.format(schedule.getStartTime()));
-            String address = schedule.getAddressStreet() + ", " + schedule.getAddressNumber();
-            tv_address.setText(address);
+            showScheduleContent(schedule);
             caller = bundle.getInt(Utils.CALLER_ACTIVITY);
 
             if(caller == Utils.SCHEDULES_ACTIVITY){
@@ -147,6 +146,10 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
                 navigationView.setCheckedItem(R.id.nav_schedules_history);
                 tv_situation_content.setText(schedule.getSituation());
             }
+        }else if(id != 0 ){
+            //pega schedule
+            // TODO: caso a intent veio da notificação, realizar requisição para pegar os dados.
+            //showScheduleContent(schedule);
         }
 
 
@@ -163,6 +166,16 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
 
     }
 
+    private void showScheduleContent(CheckSchedules.Schedule schedule){
+        DateFormat df = new SimpleDateFormat("dd/MM/yyyy - HH:mm", Locale.getDefault());
+        tv_sector.setText(schedule.getSectorName());
+        tv_location.setText(schedule.getLocationName());
+        tv_type.setText(schedule.getServiceTypeName());
+        tv_date.setText(df.format(schedule.getStartTime()));
+        String address = schedule.getAddressStreet() + ", " + schedule.getAddressNumber();
+        tv_address.setText(address);
+    }
+
     @Override
     public boolean onNavigationItemSelected(@NonNull MenuItem item) {
         Intent intent;
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesActivity.java
index 904dde0..c101916 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesActivity.java
@@ -250,9 +250,9 @@ public class SchedulesActivity extends AppCompatActivity implements NavigationVi
         maxDate = new Date();
         String date;
 
-        if(schedules.getSchedules().getSchedulesList() != null) {
+        if(schedules.getSchedulesModel().getSchedulesList() != null) {
 
-            for (CheckSchedules.Schedule schedule : schedules.getSchedules().getSchedulesList()) {
+            for (CheckSchedules.Schedule schedule : schedules.getSchedulesModel().getSchedulesList()) {
                 date = dateFormat.format(schedule.getStartTime());
                 if(schedule.getStartTime().after(maxDate)){
                     maxDate = schedule.getStartTime();
@@ -414,8 +414,8 @@ public class SchedulesActivity extends AppCompatActivity implements NavigationVi
         long id = 0;
 
         //searching if this schedule belongs to the citizen or the dependents.
-        for(int i = 0; i < schedules.getSchedules().getSchedulesList().size() && id  == 0; ++i){
-            if(schedules.getSchedules().getSchedulesList().get(i).getId() == selectedSchedule.getId())
+        for(int i = 0; i < schedules.getSchedulesModel().getSchedulesList().size() && id  == 0; ++i){
+            if(schedules.getSchedulesModel().getSchedulesList().get(i).getId() == selectedSchedule.getId())
             {
                 id = schedules.getId();
                 name = schedules.getName();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
index 79e0272..aa2aea8 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/SchedulesHistoryActivity.java
@@ -756,7 +756,7 @@ public class SchedulesHistoryActivity extends AppCompatActivity implements Navig
 
         expandableListTitle = new ArrayList<>();
         expandableListTitle.add(new Pair<>(schedules.getName(), schedules.getId()));
-        expandableListDetail.put(schedules.getName(), schedules.getSchedules().getSchedulesList());
+        expandableListDetail.put(schedules.getName(), schedules.getSchedulesModel().getSchedulesList());
 
         for (CheckSchedules.DependentSchedules dependentSchedules : schedules.getDependentSchedulesList()) {
             expandableListTitle.add(new Pair<>(dependentSchedules.getName(), dependentSchedules.getId()));
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
index 058d842..d5ddd96 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
@@ -127,6 +127,8 @@ public abstract class Utils {
 
     public static final String ACTION_SHOW_NOTIFICATION = "br.ufpr.c3sl.agendador.SHOW_NOTIFICATION";
 
+    public static final int SHOW_SCHEDULE_INFO_ACTION = 0x11;
+
     public static int getPixelValue(int dp, Context context) {
         Resources resources = context.getResources();
         return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/CheckSchedules.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/CheckSchedules.java
index 2dc9b0a..ad994dd 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/CheckSchedules.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/CheckSchedules.java
@@ -41,7 +41,7 @@ public class CheckSchedules {
         this.dependentSchedulesList = dependentSchedulesList;
     }
 
-    public ScheduleListModel getSchedules() {
+    public ScheduleListModel getSchedulesModel() {
         return schedules;
     }
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
index c4d09fd..8e35b85 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiUtils.java
@@ -14,8 +14,8 @@ import retrofit2.converter.gson.GsonConverterFactory;
  */
 
 public abstract class ApiUtils {
-//        public static final String BASE_URL = "http://10.0.2.2:3000/v1/";
-     public static final String BASE_URL = "http://newcastle.c3sl.ufpr.br/develop/v1/";
+        public static final String BASE_URL = "http://10.0.2.2:3000/v1/";
+//     public static final String BASE_URL = "http://newcastle.c3sl.ufpr.br/develop/v1/";
 
     public static ApiEndpoints request(final Map<String, String> header) {
         OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
index 15b6e51..f823665 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
@@ -1,19 +1,31 @@
 package br.ufpr.c3sl.agendador.agendador.presenters;
 
+import android.app.AlarmManager;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Build;
 import android.support.annotation.NonNull;
+import android.util.Log;
 
 import com.firebase.jobdispatcher.FirebaseJobDispatcher;
 import com.firebase.jobdispatcher.GooglePlayDriver;
+import com.google.gson.Gson;
 
 import java.lang.ref.WeakReference;
+import java.util.List;
 
 import br.ufpr.c3sl.agendador.agendador.LoginActivity;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.services.notification.LocalNotificationManager;
+import br.ufpr.c3sl.agendador.agendador.services.notification.NotificationReceiver;
 import okhttp3.Headers;
 
+import static android.content.Context.ALARM_SERVICE;
+
 /**
  * Created by Bruno Freitas Tissei on 2/2/17.
  */
@@ -55,7 +67,7 @@ public abstract class BasePresenter<V> {
 
     protected void updateHeaders(Headers headers) {
         if(osb == null && context != null)
-            osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);;
+            osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
 
         if(headers.get(Utils.ACCESS_TOKEN) != null)
             osb.edit().putString(Utils.ACCESS_TOKEN, headers.get(Utils.ACCESS_TOKEN)).apply();
@@ -73,11 +85,37 @@ public abstract class BasePresenter<V> {
 
         dispatcher.cancel(Utils.SERVICE_UPDATE_IMAGE);
 
+        if(osb == null)
+            osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
+
+        Gson gson = new Gson();
+
+        List<Notification> notificationList = LocalNotificationManager.getList(osb, gson);
+
+        Intent intent = new Intent(context, NotificationReceiver.class);
+        intent.setAction(Utils.ACTION_SHOW_NOTIFICATION);
+
+        PendingIntent pendingIntent;
+        AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
+
+
+        for(Notification n : notificationList){
+
+            pendingIntent = PendingIntent.getBroadcast(context,
+                    LocalNotificationManager.NOTIFICATION_REMINDER_REQUEST_CODE + (int) n.scheduleId, intent,
+                    PendingIntent.FLAG_CANCEL_CURRENT);
+
+            if(am != null){
+                am.cancel(pendingIntent);
+            }
+
+        }
+
         osb.edit().clear().apply();
 
-        Intent intent = new Intent(context, LoginActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
-        context.startActivity(intent);
+        Intent intent2 = new Intent(context, LoginActivity.class);
+        intent2.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(intent2);
 
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/BootReceiver.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/BootReceiver.java
index 1786d10..9262670 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/BootReceiver.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/BootReceiver.java
@@ -55,7 +55,7 @@ public class BootReceiver  extends BroadcastReceiver {
                     try {
                         date = sdfServer.parse(notification.reminderTime);
                         calendar.setTime(date);
-                        LocalNotificationManager.setReminder(context, NotificationReceiver.class, calendar, (int) notification.scheduleId);
+                        LocalNotificationManager.setReminder(context, calendar, (int) notification.scheduleId);
                     } catch (ParseException e) {
                         e.printStackTrace();
                     }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
index e463eba..3d8fc1f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
@@ -34,7 +34,7 @@ import static android.content.Context.ALARM_SERVICE;
 public abstract class LocalNotificationManager {
 
 
-    private static final int NOTIFICATION_REMINDER_REQUEST_CODE = 0x27;
+    public static final int NOTIFICATION_REMINDER_REQUEST_CODE = 0x27;
 
 
     public static void createLocalNotification(Context context, Notification notification, ObscuredSharedPreferences osb, Gson gson){
@@ -45,7 +45,7 @@ public abstract class LocalNotificationManager {
 
         try{
             calendar.setTime(sdfServer.parse(notification.reminderTime));
-            setReminder(context, NotificationReceiver.class, calendar, (int) notification.scheduleId);
+            setReminder(context, calendar, (int) notification.scheduleId);
         }catch (ParseException ignored){
             Log.e("Agendador", "Erro ao parsear data, para criar notificação local.");
             ignored.printStackTrace();
@@ -53,9 +53,9 @@ public abstract class LocalNotificationManager {
     }
 
 
-    public static void setReminder(Context context, Class<?> cls, Calendar calendar, int scheduleId){
+    public static void setReminder(Context context, Calendar calendar, int scheduleId){
 
-        Intent intent = new Intent(context, cls);
+        Intent intent = new Intent(context, NotificationReceiver.class);
         intent.setAction(Utils.ACTION_SHOW_NOTIFICATION);
         intent.putExtra(Utils.ID, scheduleId);
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
index 326f2fe..f5d294f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
@@ -1,6 +1,7 @@
 package br.ufpr.c3sl.agendador.agendador.services.notification;
 
 import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -14,6 +15,7 @@ import com.google.gson.Gson;
 import java.util.List;
 
 import br.ufpr.c3sl.agendador.agendador.R;
+import br.ufpr.c3sl.agendador.agendador.ScheduleInfoActivity;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
@@ -53,10 +55,15 @@ public class NotificationReceiver extends BroadcastReceiver{
 
             NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
 
+            Intent showScheduleIntent = new Intent(context, ScheduleInfoActivity.class);
+            showScheduleIntent.putExtra(Utils.ID, id);
+
+            PendingIntent pendingIntent = PendingIntent.getActivity(context, Utils.SHOW_SCHEDULE_INFO_ACTION, showScheduleIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
             String alert = context.getResources().getString(R.string.notification_alert);
             android.app.Notification appNotification = mBuilder.setAutoCancel(true).setContentText(content.description).setContentTitle(alert)
                     .setDefaults(android.app.Notification.DEFAULT_LIGHTS | android.app.Notification.DEFAULT_SOUND)
-                    .setSmallIcon(R.drawable.img_mainact_logo).setTicker(alert)
+                    .setSmallIcon(R.drawable.img_mainact_logo).setTicker(alert).setContentIntent(pendingIntent)
                     .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.img_terms_logo)).build();
 
             // Will display the notification in the notification bar
-- 
GitLab


From 0f5cdf5884c3c398c78de6708bcc50347145f1f5 Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Wed, 17 Jan 2018 09:28:41 -0200
Subject: [PATCH 4/9] AGILE#301: Issue completed

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 .../ScheduleConfirmationActivity.java         |   6 +-
 .../agendador/ScheduleInfoActivity.java       | 114 ++++++++++++---
 .../agendador/models/ScheduleInfo.java        | 131 ++++++++++++++++++
 .../agendador/models/ShortAddress.java        |  32 +++++
 .../agendador/network/ApiEndpoints.java       |   4 +-
 .../presenters/ScheduleInfoPresenter.java     |  97 +++++++++++++
 .../LocalNotificationManager.java             |   5 +-
 .../agendador/views/ScheduleInfoView.java     |  18 +++
 .../main/res/layout/content_schedule_info.xml |   9 ++
 9 files changed, 393 insertions(+), 23 deletions(-)
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleInfo.java
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ShortAddress.java
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleInfoPresenter.java
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleInfoView.java

diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
index 885780f..dfb421c 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
@@ -257,7 +257,7 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         });
 
         if(savedInstanceState == null){
-            scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(getBaseContext());
+            scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(this);
         }else{
             scheduleConfirmationPresenter = PresenterManager.getInstance().restorePresenter(savedInstanceState);
             if(scheduleConfirmationPresenter == null)
@@ -387,7 +387,8 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
                     schedule.getLocationName(), schedule.getAddressStreet(), schedule.getAddressNumber(),
                         sdfDate.format(schedule.getStartTime()), sdfHour.format(schedule.getStartTime()));
 
-            notification.reminderTime = sdfServer.format(schedule.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]));
+            // TODO: 15/01/18 Apagar aqui o tempo a mais que está sendo usado no calculo da notificaçõa, está em dobro.
+            notification.reminderTime = sdfServer.format(schedule.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]) - (reminderTimeArray[sp_notification.getSelectedItemPosition()]));
 
             if(rb_yes.isChecked()){
                 notification.emailAddres = et_email.getText().toString();
@@ -443,7 +444,6 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
             bt_schedule.setEnabled(true);
             bt_back.setEnabled(true);
         }
-
     }
 
     @Override
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
index 61a4a55..d120503 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
@@ -20,6 +20,7 @@ import android.view.MenuItem;
 import android.view.View;
 import android.widget.Button;
 import android.widget.ImageView;
+import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import org.w3c.dom.Text;
@@ -28,12 +29,17 @@ import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Locale;
 
+import br.ufpr.c3sl.agendador.agendador.helpers.ConnectionErrorDialog;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.UserImgHelper;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.models.CheckSchedules;
+import br.ufpr.c3sl.agendador.agendador.presenters.PresenterManager;
+import br.ufpr.c3sl.agendador.agendador.presenters.ScheduleConfirmationPresenter;
+import br.ufpr.c3sl.agendador.agendador.presenters.ScheduleInfoPresenter;
+import br.ufpr.c3sl.agendador.agendador.views.ScheduleInfoView;
 
-public class ScheduleInfoActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
+public class ScheduleInfoActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, ScheduleInfoView{
 
     private MenuBuilder menuBuilder;
 
@@ -43,7 +49,6 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
 
     private long id;
 
-
     private static final String EXIT_CONFIRMATION_DIALOG_TAG = "exit_dialog";
 
     private int caller;
@@ -51,7 +56,15 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
     private TextView tv_name, tv_sector, tv_location, tv_type,
             tv_date, tv_address, tv_situation, tv_situation_content;
 
+    private ScheduleInfoPresenter presenter;
+
+    private ConnectionErrorDialog connectionErrorDialog;
+
+    private Button bt_back;
 
+    private ProgressBar pb_scheduleInfo;
+
+    private boolean hasToRequest;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -125,17 +138,39 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
         tv_address = (TextView) findViewById(R.id.tv_schedule_street_content);
         tv_situation = (TextView) findViewById(R.id.tv_schedule_situation);
         tv_situation_content = (TextView) findViewById(R.id.tv_schedule_situation_content);
+        pb_scheduleInfo = (ProgressBar) findViewById(R.id.pb_schedule_info);
+        bt_back = (Button) findViewById(R.id.btn_schedule_info_back);
+        bt_back.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                onBackPressed();
+            }
+        });
 
         id = getIntent().getIntExtra(Utils.ID, 0);
 
+
+        if(savedInstanceState == null){
+            presenter = new ScheduleInfoPresenter(this);
+        }else{
+            presenter = PresenterManager.getInstance().restorePresenter(savedInstanceState);
+            if(presenter == null) {
+                presenter = new ScheduleInfoPresenter(this);
+            }
+        }
+
+
+
         Bundle bundle = getIntent().getBundleExtra(Utils.SCHEDULE_BUNDLE);
         CheckSchedules.Schedule schedule = null;
-        if(bundle != null){
+
+        hasToRequest = true;
+        if(bundle != null && bundle.getParcelable(Utils.SCHEDULE) != null){
             String name = bundle.getString(Utils.NAME);
             id = bundle.getLong(Utils.ID);
             schedule = bundle.getParcelable(Utils.SCHEDULE);
             tv_name.setText(name);
-            showScheduleContent(schedule);
+            showScheduleContent(schedule, null);
             caller = bundle.getInt(Utils.CALLER_ACTIVITY);
 
             if(caller == Utils.SCHEDULES_ACTIVITY){
@@ -146,27 +181,32 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
                 navigationView.setCheckedItem(R.id.nav_schedules_history);
                 tv_situation_content.setText(schedule.getSituation());
             }
-        }else if(id != 0 ){
-            //pega schedule
-            // TODO: caso a intent veio da notificação, realizar requisição para pegar os dados.
-            //showScheduleContent(schedule);
+            hasToRequest = false;
         }
 
-
         navigationView.setNavigationItemSelectedListener(this);
 
 
-        Button bt_back = (Button) findViewById(R.id.btn_schedule_info_back);
-        bt_back.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                onBackPressed();
-            }
-        });
 
     }
 
-    private void showScheduleContent(CheckSchedules.Schedule schedule){
+    @Override
+    protected void onPause() {
+        super.onPause();
+        presenter.unbindView();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        presenter.bindView(this);
+        if(hasToRequest && id != 0 ){
+            presenter.requestScheduleInfo(id);
+        }
+    }
+
+    // TODO: 16/01/18 extract date pattern to utils class
+    public void showScheduleContent(CheckSchedules.Schedule schedule, String citizenName){
         DateFormat df = new SimpleDateFormat("dd/MM/yyyy - HH:mm", Locale.getDefault());
         tv_sector.setText(schedule.getSectorName());
         tv_location.setText(schedule.getLocationName());
@@ -174,6 +214,10 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
         tv_date.setText(df.format(schedule.getStartTime()));
         String address = schedule.getAddressStreet() + ", " + schedule.getAddressNumber();
         tv_address.setText(address);
+        tv_situation_content.setText(schedule.getSituation());
+        if(citizenName != null && !citizenName.equals("")){
+            tv_name.setText(citizenName);
+        }
     }
 
     @Override
@@ -232,6 +276,42 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
         }
     }
 
+    @Override
+    public void setProgressBar(boolean enabled) {
+        if (enabled) {
+            pb_scheduleInfo.setVisibility(View.VISIBLE);
+        } else {
+            pb_scheduleInfo.setVisibility(View.INVISIBLE);
+        }
+        bt_back.setEnabled(!enabled);
+    }
+
+    @Override
+    public void setConnectionError(boolean enabled) {
+        if(enabled){
+            if(connectionErrorDialog == null){
+                connectionErrorDialog = new ConnectionErrorDialog();
+            }
+            Bundle bundle = new Bundle();
+            bundle.putString(ConnectionErrorDialog.DIALOG_MESSAGE, getString(R.string.dialog_connection_error_message));
+            connectionErrorDialog.setArguments(bundle);
+            connectionErrorDialog.show(getFragmentManager(), ConnectionErrorDialog.DIALOG_CONNECTION_ERROR);
+        }
+    }
+
+    @Override
+    public void setNoConnection(boolean enabled) {
+        if(enabled){
+            if(connectionErrorDialog == null){
+                connectionErrorDialog = new ConnectionErrorDialog();
+            }
+            Bundle bundle = new Bundle();
+            bundle.putString(ConnectionErrorDialog.DIALOG_MESSAGE, getString(R.string.dialog_connection_error_message));
+            connectionErrorDialog.setArguments(bundle);
+            connectionErrorDialog.show(getFragmentManager(), ConnectionErrorDialog.DIALOG_CONNECTION_ERROR);
+        }
+    }
+
     public static class ConfirmationDialogFragment extends DialogFragment {
         @NonNull
         @Override
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleInfo.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleInfo.java
new file mode 100644
index 0000000..5c114d7
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleInfo.java
@@ -0,0 +1,131 @@
+package br.ufpr.c3sl.agendador.agendador.models;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Date;
+
+/**
+ * Created by Lucas Braz Cunha on 16/01/18.
+ *
+ * model to receive  request schedules/{id_schdule}?permission=citizen
+ *
+ * with complete schedule information.
+ */
+
+public class ScheduleInfo {
+
+    @SerializedName("citizen_data")
+    CitizenSchedule citizen;
+
+    @SerializedName("service_place_data")
+    ServicePlaceSchedule servicePlace;
+
+    @SerializedName("schedule_data")
+    ScheduleData schedule;
+
+
+    public long getId(){
+        return citizen.id;
+    }
+
+    public Date getStartTime(){
+        return schedule.startTime;
+    }
+
+    public String getSectorName(){
+        return schedule.sectorName;
+    }
+
+    public String getServiceTypeName(){
+        return schedule.serviceTypeName;
+    }
+
+    public String getLocationName(){
+        return servicePlace.name;
+    }
+
+    public String getAddressStreet(){
+        return servicePlace.address.address;
+    }
+
+    public String getAddressNumber(){
+        return servicePlace.number;
+    }
+
+    public String getSituation(){
+        return schedule.situation;
+    }
+
+    public String getCitizenName(){
+        return citizen.name;
+    }
+
+
+    public static class CitizenSchedule{
+
+        @SerializedName("id")
+        long id;
+
+        @SerializedName("name")
+        String name;
+
+        @SerializedName("birth_date")
+        String birthDate;
+
+        @SerializedName("rg")
+        String rg;
+
+        @SerializedName("cpf")
+        String cpf;
+
+        @SerializedName("note")
+        String note;
+
+    }
+
+    public static class ServicePlaceSchedule{
+
+
+        @SerializedName("name")
+        String name;
+
+        @SerializedName("complement")
+        String complement;
+
+        @SerializedName("phone1")
+        String phone;
+
+        @SerializedName("address_number")
+        String number;
+
+        @SerializedName("address")
+        ShortAddress address;
+
+    }
+
+    public static class ScheduleData{
+
+        @SerializedName("id")
+        long id;
+
+        @SerializedName("service_type_name")
+        String serviceTypeName;
+
+        @SerializedName("service_start_time")
+        Date startTime;
+
+        @SerializedName("professional_performer")
+        String professionalName;
+
+        @SerializedName("situation")
+        String situation;
+
+        @SerializedName("sector_name")
+        String sectorName;
+
+        @SerializedName("sector_id")
+        long sectorId;
+
+    }
+
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ShortAddress.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ShortAddress.java
new file mode 100644
index 0000000..7542ad0
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ShortAddress.java
@@ -0,0 +1,32 @@
+package br.ufpr.c3sl.agendador.agendador.models;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by Lucas Braz Cunha on 16/01/18.
+ *
+ * model for request: schedules/{id_schedule}?permission=citizen
+ *
+ *
+ */
+
+public class ShortAddress {
+
+    @SerializedName("id")
+    long id;
+
+    @SerializedName("zipcode")
+    String zipcode;
+
+    @SerializedName("address")
+    String address;
+
+    @SerializedName("neighborhood")
+    String neighborhood;
+
+    @SerializedName("complement")
+    String complement;
+
+    @SerializedName("complement2")
+    String complement2;
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
index 0683147..58aea69 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
@@ -17,6 +17,7 @@ import br.ufpr.c3sl.agendador.agendador.models.FullDependent;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
 import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
+import br.ufpr.c3sl.agendador.agendador.models.ScheduleInfo;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleNote;
 import br.ufpr.c3sl.agendador.agendador.models.SectorInput;
 import br.ufpr.c3sl.agendador.agendador.models.ServicePlace;
@@ -95,5 +96,6 @@ public interface ApiEndpoints {
     @POST("notifications?permission=2")
     Call<NotificationReturn> requestCreateNotification(@Body Notification notification);
 
-
+    @GET("schedules/{id_schedule}?permission=citizen")
+    Call<ScheduleInfo> requestScheduleInfo(@Path("id_schedule") long id);
 }
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleInfoPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleInfoPresenter.java
new file mode 100644
index 0000000..44dddc6
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleInfoPresenter.java
@@ -0,0 +1,97 @@
+package br.ufpr.c3sl.agendador.agendador.presenters;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import br.ufpr.c3sl.agendador.agendador.ScheduleInfoActivity;
+import br.ufpr.c3sl.agendador.agendador.SchedulesActivity;
+import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
+import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.CheckSchedules;
+import br.ufpr.c3sl.agendador.agendador.models.ScheduleInfo;
+import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
+import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
+import okhttp3.Headers;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * Created by Lucas Braz Cunha on 15/01/18.
+ */
+
+public class ScheduleInfoPresenter extends BasePresenter<ScheduleInfoActivity> {
+
+    private ScheduleInfoPresenter presenter;
+
+    public ScheduleInfoPresenter(Context context) {
+        this.context = context;
+        presenter = this;
+        osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
+    }
+
+
+
+    public void requestScheduleInfo(long id){
+        Map<String, String> header = new HashMap<>();
+        header.put("Content-Type", "application/json");
+        header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
+        header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
+        header.put(Utils.UID, osb.getString(Utils.UID, null));
+
+        final ApiEndpoints service = ApiUtils.request(header);
+        Call<ScheduleInfo> listCall = service.requestScheduleInfo(id);
+
+        presenter.view().setProgressBar(true);
+        listCall.enqueue(new Callback<ScheduleInfo>() {
+
+            @Override
+            public void onResponse(Call<ScheduleInfo> call, Response<ScheduleInfo> response) {
+                Headers headers = response.headers();
+                int status = response.code();
+                ScheduleInfo scheduleInfo = response.body();
+                updateHeaders(headers);
+                switch (status) {
+                    case 200:
+                        CheckSchedules.Schedule schedule = new CheckSchedules.Schedule(scheduleInfo.getId(), scheduleInfo.getStartTime(),
+                                scheduleInfo.getSectorName(),
+                                scheduleInfo.getServiceTypeName(), scheduleInfo.getLocationName(),
+                                scheduleInfo.getAddressStreet(), scheduleInfo.getAddressNumber(),
+                                scheduleInfo.getSituation());
+                        Log.d("Server response", getClass().getName() + ": 200 - Sucesso!");
+                        presenter.view().showScheduleContent(schedule,scheduleInfo.getCitizenName());
+                        presenter.view().setProgressBar(false);
+                        break;
+                    default:
+                        Log.e("Server response", getClass().getName() + ": ERRO:" + status);
+                        Log.v("Server response", "Redirecionando para tela de visualizar agendamentos.");
+                        Intent i = new Intent(context, SchedulesActivity.class);
+                        i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
+                        presenter.view().finish();
+                        context.startActivity(i);
+                        break;
+                }
+
+            }
+
+            @Override
+            public void onFailure(Call<ScheduleInfo> call, Throwable t) {
+                Log.e("Server response", getClass().getName() + ": Requisição falhou!!");
+                presenter.view().setProgressBar(false);
+                presenter.view().setNoConnection(true);
+                t.printStackTrace();
+            }
+        });
+
+    }
+
+
+    @Override
+    protected void updateView() {
+
+    }
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
index 3d8fc1f..26175cb 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
@@ -30,7 +30,6 @@ import static android.content.Context.ALARM_SERVICE;
  */
 
 
-
 public abstract class LocalNotificationManager {
 
 
@@ -98,7 +97,9 @@ public abstract class LocalNotificationManager {
     // TODO: 15/12/17 Testar o retorno da lista.
     public static List<Notification> getList(ObscuredSharedPreferences osb, Gson gson){
         String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
-        return gson.fromJson(jsonList, new TypeToken<List<Notification>>(){}.getType());
+        List<Notification> notifications = gson.fromJson(jsonList, new TypeToken<List<Notification>>(){}.getType());
+
+        return notifications == null ? new ArrayList<Notification>() : notifications;
     }
 
     // TODO: 15/12/17 Testar o remove.
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleInfoView.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleInfoView.java
new file mode 100644
index 0000000..eaee154
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleInfoView.java
@@ -0,0 +1,18 @@
+package br.ufpr.c3sl.agendador.agendador.views;
+
+import br.ufpr.c3sl.agendador.agendador.models.CheckSchedules;
+
+/**
+ * Created by Lucas B. Cunha on 15/01/18.
+ */
+
+public interface ScheduleInfoView {
+
+    void setProgressBar(boolean enabled);
+
+    void setConnectionError(boolean enabled);
+
+    void setNoConnection(boolean enabled);
+
+    void showScheduleContent(CheckSchedules.Schedule schedule, String citizenName);
+}
diff --git a/app/src/main/res/layout/content_schedule_info.xml b/app/src/main/res/layout/content_schedule_info.xml
index 2d07ab0..d459fc1 100644
--- a/app/src/main/res/layout/content_schedule_info.xml
+++ b/app/src/main/res/layout/content_schedule_info.xml
@@ -242,4 +242,13 @@
 
     </LinearLayout>
 
+    <ProgressBar
+        android:layout_width="80dp"
+        android:id="@+id/pb_schedule_info"
+        android:layout_height="80dp"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:indeterminate="true"
+        android:visibility="invisible" />
+
 </RelativeLayout>
\ No newline at end of file
-- 
GitLab


From ff00deb7796bb6905442140fb5eba7e852ac3cd9 Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Fri, 19 Jan 2018 12:10:31 -0200
Subject: [PATCH 5/9] AGILE#307: [WP] Implementing service to update local list
 of notifications

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 app/src/main/AndroidManifest.xml              |   9 +
 .../agendador/agendador/LoginActivity.java    |  34 +++-
 .../ScheduleConfirmationActivity.java         |   5 +-
 .../agendador/ScheduleInfoActivity.java       |   5 +-
 .../agendador/agendador/helpers/Utils.java    |   1 +
 .../agendador/network/ApiEndpoints.java       |   4 +
 .../agendador/presenters/BasePresenter.java   |   2 +-
 .../ScheduleConfirmationPresenter.java        |   7 +-
 .../NotificationCreateService.java            |  82 +++++----
 .../notification/NotificationReceiver.java    |   1 +
 .../NotificationsListService.java             | 156 ++++++++++++++++++
 app/src/main/res/values/strings.xml           |   2 +-
 12 files changed, 262 insertions(+), 46 deletions(-)
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ef2648c..075728c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -58,6 +58,15 @@
             </intent-filter>
         </service>
 
+        <service
+            android:name=".services.notification.NotificationsListService"
+            android:exported="false"
+            android:permission="android.permission.BIND_JOB_SERVICE">
+            <intent-filter>
+                <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
+            </intent-filter>
+        </service>
+
 
         <receiver android:name=".services.BootReceiver">
             <intent-filter>
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
index a33a5ea..447474a 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
@@ -12,6 +12,7 @@ import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.TextWatcher;
 import android.text.style.StyleSpan;
+import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
@@ -19,6 +20,14 @@ import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.firebase.jobdispatcher.Constraint;
+import com.firebase.jobdispatcher.FirebaseJobDispatcher;
+import com.firebase.jobdispatcher.GooglePlayDriver;
+import com.firebase.jobdispatcher.Job;
+import com.firebase.jobdispatcher.Lifetime;
+import com.firebase.jobdispatcher.RetryStrategy;
+import com.firebase.jobdispatcher.Trigger;
+
 import java.io.IOException;
 
 import br.ufpr.c3sl.agendador.agendador.helpers.ConnectionChecker;
@@ -28,6 +37,7 @@ import br.ufpr.c3sl.agendador.agendador.helpers.UserImgHelper;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.presenters.LoginPresenter;
 import br.ufpr.c3sl.agendador.agendador.presenters.PresenterManager;
+import br.ufpr.c3sl.agendador.agendador.services.notification.NotificationsListService;
 import br.ufpr.c3sl.agendador.agendador.views.LoginView;
 
 /**
@@ -205,7 +215,29 @@ public class LoginActivity extends AppCompatActivity implements LoginView {
 
     @Override
     public void afterSuccessfulLogin() {
-        // TODO 22/12/2017: instanciar job que verifica notificações no back-end.
+        FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(
+                new GooglePlayDriver(this)
+        );
+
+        Job job = dispatcher.newJobBuilder()
+                .setService(NotificationsListService.class)
+                .setTag(Utils.NOTIFICATION_UPDATE_SERVICE)
+                //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
+                //will be repeated every 10 minutes
+                .setTrigger(Trigger.executionWindow(/*600, 720*/1, 29))
+                //will be retried if it fails.
+                .setRecurring(true)
+                .setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
+                .setConstraints(
+                        // only run on network
+                        Constraint.ON_ANY_NETWORK
+                )
+                //if device is rebooted the job will be restarted
+                .setLifetime(Lifetime.FOREVER)
+                .build();
+        dispatcher.mustSchedule(job);
+        Log.d("AGNDDR-NotifiUpdate", "Job agendado para atualizar lista de coisas");
+
         Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
         startActivity(intent);
         finish();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
index dfb421c..7524005 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
@@ -383,9 +383,8 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
             notification.scheduleId = schedule.getId();
             notification.emailSent = false;
 
-            notification.description = getResources().getString(R.string.notification_content, schedule.getServiceTypeName(),
-                    schedule.getLocationName(), schedule.getAddressStreet(), schedule.getAddressNumber(),
-                        sdfDate.format(schedule.getStartTime()), sdfHour.format(schedule.getStartTime()));
+            notification.description = getResources().getString(R.string.notification_content, sdfDate.format(schedule.getStartTime()), sdfHour.format(schedule.getStartTime()), schedule.getServiceTypeName(),
+                    schedule.getLocationName(), schedule.getAddressStreet(), schedule.getAddressNumber());
 
             // TODO: 15/01/18 Apagar aqui o tempo a mais que está sendo usado no calculo da notificaçõa, está em dobro.
             notification.reminderTime = sdfServer.format(schedule.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]) - (reminderTimeArray[sp_notification.getSelectedItemPosition()]));
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
index d120503..5128565 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleInfoActivity.java
@@ -322,9 +322,8 @@ public class ScheduleInfoActivity extends AppCompatActivity implements Navigatio
             builder.setMessage(R.string.signout_confirmation)
                     .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
                         public void onClick(DialogInterface dialog, int id) {
-                            SchedulesActivity activity = (SchedulesActivity) getActivity();
-                            // TODO: 05/10/17 fix here
-                            //activity.presenter.onSignOutClicked();
+                            ScheduleInfoActivity activity = (ScheduleInfoActivity) getActivity();
+                            activity.presenter.onSignOutClicked();
                         }
                     })
                     .setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
index d5ddd96..91608ab 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
@@ -122,6 +122,7 @@ public abstract class Utils {
 
     public static final String NOTIFICATION = "notification";
     public static final String NOTIFICATION_SERVICE = "br.c3sl.ufpr.notification_service";
+    public static final String NOTIFICATION_UPDATE_SERVICE = "br.c3sl.ufpr.notification_update_service";
     public static final String NOTIFICATION_LIST = "notification_list";
 
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
index 58aea69..1c35a04 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
@@ -98,4 +98,8 @@ public interface ApiEndpoints {
 
     @GET("schedules/{id_schedule}?permission=citizen")
     Call<ScheduleInfo> requestScheduleInfo(@Path("id_schedule") long id);
+
+    @GET("notifications?permission=citizen")
+    Call<List<NotificationReturn>> requestNotifications();
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
index f823665..6be7a1d 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
@@ -77,13 +77,13 @@ public abstract class BasePresenter<V> {
             osb.edit().putString(Utils.UID, headers.get(Utils.UID)).apply();
         if(headers.get(Utils.EXPIRY) != null)
             osb.edit().putString(Utils.EXPIRY, headers.get(Utils.EXPIRY)).apply();
-
     }
 
     public void onSignOutClicked() {
         FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
 
         dispatcher.cancel(Utils.SERVICE_UPDATE_IMAGE);
+        dispatcher.cancel(Utils.NOTIFICATION_UPDATE_SERVICE);
 
         if(osb == null)
             osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
index b9f086e..3f9baa2 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
@@ -113,7 +113,7 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
         final ApiEndpoints service = ApiUtils.request(header);
 
         final Call<NotificationReturn> listCall = service.requestCreateNotification(notification);
-
+        scheduleNotificationJob(notification);
         scheduleConfirmationPresenter.view().setProgressBar(true);
         listCall.enqueue(new Callback<NotificationReturn>() {
 
@@ -162,11 +162,10 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
 
         Job job = dispatcher.newJobBuilder()
                 .setService(NotificationCreateService.class)
-                .setTag(Utils.NOTIFICATION_SERVICE)
+                .setTag(Utils.NOTIFICATION_SERVICE + notification.scheduleId)
                 //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
-                .setTrigger(Trigger.executionWindow(10, 3600))
+                .setTrigger(Trigger.NOW)
                 //will be retried if it fails.
-                .setRecurring(true)
                 .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
                 .setConstraints(
                         // only run on network
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
index 273300a..075d8be 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
@@ -9,6 +9,7 @@ import com.firebase.jobdispatcher.JobService;
 import com.google.gson.Gson;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
@@ -32,54 +33,58 @@ public class NotificationCreateService extends JobService {
     @Override
     public boolean onStartJob(final JobParameters job) {
         Log.v("AGNDDR-NotifiCreate", "Rodando " + NotificationCreateService.class.getName());
-        ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
-        final Bundle extras = job.getExtras();
-        Map<String, String> header = new HashMap<>();
 
-        final String uid = osb.getString(Utils.UID, null);
-        header.put("Content-Type", "application/json");
-        header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
-        header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
-        header.put(Utils.ID, uid);
+        new Thread(new Runnable() {
+            public void run() {
 
-        Notification notification = null;
+                final Bundle extras = job.getExtras();
+                Map<String, String> header = new HashMap<>();
+                ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
+                header.put("Content-Type", "application/json");
+                header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
+                header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
+                header.put(Utils.UID, osb.getString(Utils.UID, null));
 
-        if (extras != null) {
-            notification = new Gson().fromJson(extras.getString(Utils.NOTIFICATION), Notification.class);
-        }else{
-            Log.e("AGNDDR-NotifiCreate", "Job não recebeu os extras.");
-            jobFinished(job, true);
-        }
+                Notification notification = null;
 
-        ApiEndpoints service = ApiUtils.request(header);
+                if (extras != null) {
+                    notification = new Gson().fromJson(extras.getString(Utils.NOTIFICATION), Notification.class);
+                } else {
+                    Log.e("AGNDDR-NotifiCreate", "Job não recebeu os extras.");
+                    jobFinished(job, true);
+                }
+
+                requestCreateNotification(header, job, osb, notification);
+
+
+            }}).start();
+
+        return true;
+    }
+
+
+    private void requestCreateNotification(final Map<String, String> header, final JobParameters job, final ObscuredSharedPreferences osb, final Notification notification){
+
+        final ApiEndpoints service = ApiUtils.request(header);
 
         Call<NotificationReturn> listCall = service.requestCreateNotification(notification);
 
-        final Notification finalNotification = notification;
         listCall.enqueue(new Callback<NotificationReturn>() {
 
             @Override
             public void onResponse(Call<NotificationReturn> call, Response<NotificationReturn> response) {
-                int status = response.code();
                 Headers headers = response.headers();
-                ObscuredSharedPreferences  osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
-
-                if(headers.get(Utils.ACCESS_TOKEN) != null)
-                    osb.edit().putString(Utils.ACCESS_TOKEN, headers.get(Utils.ACCESS_TOKEN)).apply();
-                if(headers.get(Utils.CLIENT) != null)
-                    osb.edit().putString(Utils.CLIENT, headers.get(Utils.CLIENT)).apply();
-                if(headers.get(Utils.UID) != null)
-                    osb.edit().putString(Utils.UID, headers.get(Utils.UID)).apply();
-                if(headers.get(Utils.EXPIRY) != null)
-                    osb.edit().putString(Utils.EXPIRY, headers.get(Utils.EXPIRY)).apply();
-
+                int status = response.code();
+                updateHeaders(headers, osb);
                 switch (status) {
                     case 200:
-                        LocalNotificationManager.createLocalNotification(getApplicationContext(), finalNotification, osb, new Gson());
+                    case 201:
+                        Log.d("Server response", getClass().getName() + ": 200 - Sucesso!");
+                        LocalNotificationManager.createLocalNotification(getApplicationContext(), notification, osb, new Gson());
                         jobFinished(job, false);
                         break;
                     default:
-                        Log.v("AGNDDR-NotifiCreate", "Job foi executado mas recebeu retorno " + status);
+                        Log.e("Server response", getClass().getName() + ": ERRO:" + status);
                         jobFinished(job, true);
                         break;
                 }
@@ -88,17 +93,28 @@ public class NotificationCreateService extends JobService {
 
             @Override
             public void onFailure(Call<NotificationReturn> call, Throwable t) {
-                Log.v("AGNDDR-NotifiCreate", "Job falhou e será remarcado!!");
+                Log.e("Server response", getClass().getName() + ": Requisição falhou!!");
                 t.printStackTrace();
                 jobFinished(job, true);
             }
         });
 
+    }
+
+    private void updateHeaders(Headers headers, ObscuredSharedPreferences osb){
+        if (headers.get(Utils.ACCESS_TOKEN) != null)
+            osb.edit().putString(Utils.ACCESS_TOKEN, headers.get(Utils.ACCESS_TOKEN)).apply();
+        if (headers.get(Utils.CLIENT) != null)
+            osb.edit().putString(Utils.CLIENT, headers.get(Utils.CLIENT)).apply();
+        if (headers.get(Utils.UID) != null)
+            osb.edit().putString(Utils.UID, headers.get(Utils.UID)).apply();
+        if (headers.get(Utils.EXPIRY) != null)
+            osb.edit().putString(Utils.EXPIRY, headers.get(Utils.EXPIRY)).apply();
 
-        return true;
     }
 
 
+
     @Override
     public boolean onStopJob(JobParameters job) {
         return true;
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
index f5d294f..14b5d9f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
@@ -44,6 +44,7 @@ public class NotificationReceiver extends BroadcastReceiver{
                     break;
                 }
             }
+            // TODO: 19/01/18 só remover a notificação depois de enviar para o servidor que ela foi mostrada.
             LocalNotificationManager.removeNotification(id, osb, gson);
             NotificationManager notificationManager = (NotificationManager)
                     context.getSystemService(NOTIFICATION_SERVICE);
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java
new file mode 100644
index 0000000..144bf8d
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java
@@ -0,0 +1,156 @@
+package br.ufpr.c3sl.agendador.agendador.services.notification;
+
+import android.content.Context;
+import android.os.Looper;
+import android.util.Log;
+import android.util.LongSparseArray;
+import android.util.SparseArray;
+import android.util.SparseLongArray;
+
+import com.firebase.jobdispatcher.JobParameters;
+import com.firebase.jobdispatcher.JobService;
+import com.google.gson.Gson;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
+import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
+import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
+import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
+import okhttp3.Headers;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * Created by Lucas B. Cunha on 17/01/18.
+ *
+ * Service to keep local list of notifications synchronized.
+ */
+
+public class NotificationsListService  extends JobService {
+    /**
+     * The entry point to your Job. Implementations should offload work to another thread of
+     * execution as soon as possible.
+     *
+     * @param job
+     * @return whether there is more work remaining.
+     */
+    @Override
+    public boolean onStartJob(final JobParameters job) {
+
+        Log.d("AGNDDR-NotifiUpdate", "Estou no Job");
+
+
+       new Thread(new Runnable() {
+            public void run() {
+
+                Log.v("AGNDDR-NotifiUpdate", "Rodando " + NotificationsListService.class.getName());
+                Map<String, String> header = new HashMap<>();
+                ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
+                header.put("Content-Type", "application/json");
+                header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
+                header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
+                header.put(Utils.UID, osb.getString(Utils.UID, null));
+                requestNotificationUpdate(header, job, osb);
+            }
+
+        }).start();
+
+        return true;
+    }
+
+
+    private void requestNotificationUpdate(final Map<String, String> header, final JobParameters job, final ObscuredSharedPreferences osb){
+
+        final ApiEndpoints service = ApiUtils.request(header);
+        Log.v("AGNDDR-NotifiUpdate", Utils.ACCESS_TOKEN + osb.getString(Utils.ACCESS_TOKEN, "NADA"));
+        Log.v("AGNDDR-NotifiUpdate", Utils.CLIENT + osb.getString(Utils.CLIENT, "NADA"));
+        Log.v("AGNDDR-NotifiUpdate", Utils.UID + osb.getString(Utils.UID, "NADA"));
+
+
+
+        Call<List<NotificationReturn>> listCall = service.requestNotifications();
+
+        listCall.enqueue(new Callback<List<NotificationReturn>>() {
+
+            @Override
+            public void onResponse(Call<List<NotificationReturn>> call, Response<List<NotificationReturn>> response) {
+                Headers headers = response.headers();
+                int status = response.code();
+                updateHeaders(headers, osb);
+                final List<NotificationReturn> responseList = response.body();
+                switch (status) {
+                    case 200:
+                    case 201:
+                        Log.d("Server response", getClass().getName() + ": 200 - Sucesso!");
+                        new Thread(new Runnable() {
+                            public void run() {
+                                Gson gson = new Gson();
+                                LongSparseArray<Notification> localNotifications = new LongSparseArray<>();
+                                List<Notification> list = LocalNotificationManager.getList(osb, gson);
+                                for(Notification n  : list)
+                                    localNotifications.append(n.scheduleId, n);
+
+                                for(NotificationReturn nr : responseList){
+                                    if(localNotifications.get(nr.scheduleId) == null){
+                                        LocalNotificationManager.createLocalNotification(getApplicationContext(),
+                                                new Notification(nr.scheduleId, nr.reminderTime, nr.hasRead == 0,
+                                                        nr.description, nr.emailAddres, nr.emailSent == 0),
+                                                osb, gson);
+                                    }
+                                }
+
+                                jobFinished(job, false);
+                            }}).start();
+                        break;
+                    default:
+                        Log.e("Server response", getClass().getName() + ": ERRO:" + status);
+
+                        jobFinished(job, false);
+                        break;
+                }
+
+            }
+
+            @Override
+            public void onFailure(Call<List<NotificationReturn>> call, Throwable t) {
+                Log.e("Server response", getClass().getName() + ": Requisição falhou!!");
+                t.printStackTrace();
+                jobFinished(job, false);
+            }
+        });
+
+    }
+
+    private void updateHeaders(Headers headers, ObscuredSharedPreferences osb){
+        if (headers.get(Utils.ACCESS_TOKEN) != null)
+            osb.edit().putString(Utils.ACCESS_TOKEN, headers.get(Utils.ACCESS_TOKEN)).apply();
+        if (headers.get(Utils.CLIENT) != null)
+            osb.edit().putString(Utils.CLIENT, headers.get(Utils.CLIENT)).apply();
+        if (headers.get(Utils.UID) != null)
+            osb.edit().putString(Utils.UID, headers.get(Utils.UID)).apply();
+        if (headers.get(Utils.EXPIRY) != null)
+            osb.edit().putString(Utils.EXPIRY, headers.get(Utils.EXPIRY)).apply();
+
+    }
+
+
+    /**
+     * Called when the scheduling engine has decided to interrupt the execution of a running job,
+     * most likely because the runtime constraints associated with the job are no longer satisfied.
+     * The job must stop execution.
+     *
+     * @param job
+     * @return true if the job should be retried
+     *
+     */
+    @Override
+    public boolean onStopJob(JobParameters job) {
+        return true;
+    }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bf0e056..4940c74 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -222,7 +222,7 @@
 
     <string name="not_valid_email">Digite um e-mail válido.</string>
 
-    <string name="notification_content">%s em %s (%s, %d) %s às %s</string>
+    <string name="notification_content">%s às %s, %s em %s (%s, %d)</string>
     <string name="notification_note_text">Observações (Máximo de 140 caracteres):</string>
 
     <string name="notification_alert">Atendimento está próximo</string>
-- 
GitLab


From 2632dbdfa7dba8714f74fc72a7842fd8e8ea9e37 Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Thu, 25 Jan 2018 09:34:12 -0200
Subject: [PATCH 6/9] AGILE#307: Done service to update notification's status
 to read.

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 app/src/main/AndroidManifest.xml              |   9 ++
 .../agendador/agendador/LoginActivity.java    |   2 +-
 .../ScheduleConfirmationActivity.java         |   2 +-
 .../agendador/agendador/helpers/Utils.java    |   3 +-
 .../agendador/models/Notification.java        |   8 +-
 .../agendador/models/NotificationReturn.java  |  53 +++++-
 .../agendador/models/NotificationUpdate.java  |  34 ++++
 .../agendador/network/ApiEndpoints.java       |   5 +
 .../agendador/presenters/BasePresenter.java   |   9 +-
 .../ScheduleConfirmationPresenter.java        |   4 +-
 .../LocalNotificationManager.java             |  85 +++++-----
 .../NotificationCreateService.java            |   6 +-
 .../notification/NotificationReadService.java | 141 ++++++++++++++++
 .../notification/NotificationReceiver.java    | 152 +++++++++++++++---
 .../NotificationsListService.java             |  30 ++--
 15 files changed, 441 insertions(+), 102 deletions(-)
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationUpdate.java
 create mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReadService.java

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 075728c..ac0f7c6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -49,6 +49,15 @@
             </intent-filter>
         </service>
 
+        <service
+            android:name=".services.notification.NotificationReadService"
+            android:exported="false"
+            android:permission="android.permission.BIND_JOB_SERVICE">
+            <intent-filter>
+                <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
+            </intent-filter>
+        </service>
+
         <service
             android:name=".services.notification.NotificationCreateService"
             android:exported="false"
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
index 447474a..ebe2a46 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
@@ -221,7 +221,7 @@ public class LoginActivity extends AppCompatActivity implements LoginView {
 
         Job job = dispatcher.newJobBuilder()
                 .setService(NotificationsListService.class)
-                .setTag(Utils.NOTIFICATION_UPDATE_SERVICE)
+                .setTag(Utils.NOTIFICATION_UPDATE_LIST_SERVICE)
                 //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
                 //will be repeated every 10 minutes
                 .setTrigger(Trigger.executionWindow(/*600, 720*/1, 29))
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
index 7524005..a07cf0a 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
@@ -390,7 +390,7 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
             notification.reminderTime = sdfServer.format(schedule.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]) - (reminderTimeArray[sp_notification.getSelectedItemPosition()]));
 
             if(rb_yes.isChecked()){
-                notification.emailAddres = et_email.getText().toString();
+                notification.emailAddress = et_email.getText().toString();
             }
 
             scheduleConfirmationPresenter.createNotification(notification);
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
index 91608ab..dee274f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/helpers/Utils.java
@@ -122,7 +122,8 @@ public abstract class Utils {
 
     public static final String NOTIFICATION = "notification";
     public static final String NOTIFICATION_SERVICE = "br.c3sl.ufpr.notification_service";
-    public static final String NOTIFICATION_UPDATE_SERVICE = "br.c3sl.ufpr.notification_update_service";
+    public static final String NOTIFICATION_UPDATE_LIST_SERVICE = "br.c3sl.ufpr.notification_update_service";
+    public static final String NOTIFICATION_READ_SERVICE = "br.c3sl.ufpr.notification_read_service";
     public static final String NOTIFICATION_LIST = "notification_list";
 
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
index c43de20..be32a0f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/Notification.java
@@ -25,7 +25,7 @@ public class Notification implements Parcelable{
     public String description;
 
     @SerializedName("reminder_email")
-    public String emailAddres;
+    public String emailAddress;
 
     @SerializedName("email_sent")
     public boolean emailSent;
@@ -39,7 +39,7 @@ public class Notification implements Parcelable{
         this.reminderTime = reminderTime;
         this.hasRead = hasRead;
         this.description = description;
-        this.emailAddres = emailAddress;
+        this.emailAddress = emailAddress;
         this.emailSent = emailSent;
     }
 
@@ -49,7 +49,7 @@ public class Notification implements Parcelable{
         reminderTime  = pc.readString();
         hasRead      = pc.readByte() != 0;
         description = pc.readString();
-        emailAddres = pc.readString();
+        emailAddress = pc.readString();
         emailSent = pc.readByte() != 0;
     }
 
@@ -76,7 +76,7 @@ public class Notification implements Parcelable{
         dest.writeString(reminderTime);
         dest.writeByte((byte) (hasRead ? 1 : 0));
         dest.writeString(description);
-        dest.writeString(emailAddres);
+        dest.writeString(emailAddress);
         dest.writeByte((byte) (emailSent ? 1 : 0));
     }
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
index 022bcf3..7887795 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
@@ -1,12 +1,15 @@
 package br.ufpr.c3sl.agendador.agendador.models;
 
+import android.os.Parcel;
+import android.os.Parcelable;
+
 import com.google.gson.annotations.SerializedName;
 
 /**
  * Created by Lucas Braz Cunha on 18/12/17.
  */
 
-public class NotificationReturn{
+public class NotificationReturn implements Parcelable{
 
     @SerializedName("id")
     public long notificationId;
@@ -30,7 +33,7 @@ public class NotificationReturn{
     public String description;
 
     @SerializedName("reminder_email")
-    public String emailAddres;
+    public String emailAddress;
 
     @SerializedName("reminder_email_sent")
     public int emailSent;
@@ -42,4 +45,50 @@ public class NotificationReturn{
     public String updatedAt;
 
 
+
+    /**reads back fields IN THE ORDER they were written */
+    private NotificationReturn(Parcel pc){
+        notificationId = pc.readLong();
+        accountId = pc.readLong();
+        scheduleId         = pc.readLong();
+        resourceScheduleId = pc.readLong();
+        reminderTime  = pc.readString();
+        hasRead      = pc.readInt();
+        description = pc.readString();
+        emailAddress = pc.readString();
+        emailSent = pc.readInt();
+        createdAt = pc.readString();
+        updatedAt = pc.readString();
+    }
+
+    /** Static field used to regenerate object, individually or as arrays */
+    public static final Parcelable.Creator<NotificationReturn> CREATOR = new Parcelable.Creator<NotificationReturn>() {
+        public NotificationReturn createFromParcel(Parcel pc) {
+            return new NotificationReturn(pc);
+        }
+        public NotificationReturn[] newArray(int size) {
+            return new NotificationReturn[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(notificationId);
+        dest.writeLong(accountId);
+        dest.writeLong(scheduleId == null ? 0 : scheduleId);
+        dest.writeLong(resourceScheduleId == null ? 0 : resourceScheduleId);
+        dest.writeString(reminderTime == null ? "" : reminderTime);
+        dest.writeInt(hasRead);
+        dest.writeString(description == null ? "" : description);
+        dest.writeString(emailAddress == null ? "" : emailAddress);
+        dest.writeInt(emailSent);
+        dest.writeString(createdAt == null ? "" : createdAt);
+        dest.writeString(updatedAt == null ? "" : updatedAt);
+    }
 }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationUpdate.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationUpdate.java
new file mode 100644
index 0000000..5283f28
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationUpdate.java
@@ -0,0 +1,34 @@
+package br.ufpr.c3sl.agendador.agendador.models;
+
+import android.content.Context;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Created by Lucas Braz Cunha on 22/01/18.
+ *
+ * Model used to update notification status to "read".
+ *
+ */
+
+public class NotificationUpdate {
+
+    @SerializedName("notification")
+    private NotificationUpdateContent content;
+
+
+    public NotificationUpdate(int hasRead){
+        content = new NotificationUpdateContent();
+        content.hasRead = hasRead;
+    }
+
+
+    private static class NotificationUpdateContent{
+
+        @SerializedName("read")
+        private int hasRead;
+
+    }
+
+}
+
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
index 1c35a04..6d351fc 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
@@ -16,6 +16,7 @@ import br.ufpr.c3sl.agendador.agendador.models.FormFilters;
 import br.ufpr.c3sl.agendador.agendador.models.FullDependent;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
 import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationUpdate;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleInfo;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleNote;
@@ -27,6 +28,7 @@ import okhttp3.ResponseBody;
 import retrofit2.Call;
 import retrofit2.http.Body;
 import retrofit2.http.GET;
+import retrofit2.http.PATCH;
 import retrofit2.http.POST;
 import retrofit2.http.PUT;
 import retrofit2.http.Path;
@@ -102,4 +104,7 @@ public interface ApiEndpoints {
     @GET("notifications?permission=citizen")
     Call<List<NotificationReturn>> requestNotifications();
 
+    @PATCH("notifications/{notification_id}?permission=citizen")
+    Call<NotificationReturn> requestUpdateNotification(@Path("notification_id") long notificationId,@Body NotificationUpdate notification);
+
 }
\ No newline at end of file
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
index 6be7a1d..f93d6a0 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/BasePresenter.java
@@ -20,6 +20,7 @@ import br.ufpr.c3sl.agendador.agendador.LoginActivity;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
 import br.ufpr.c3sl.agendador.agendador.services.notification.LocalNotificationManager;
 import br.ufpr.c3sl.agendador.agendador.services.notification.NotificationReceiver;
 import okhttp3.Headers;
@@ -83,14 +84,14 @@ public abstract class BasePresenter<V> {
         FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
 
         dispatcher.cancel(Utils.SERVICE_UPDATE_IMAGE);
-        dispatcher.cancel(Utils.NOTIFICATION_UPDATE_SERVICE);
+        dispatcher.cancel(Utils.NOTIFICATION_UPDATE_LIST_SERVICE);
 
         if(osb == null)
             osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
 
         Gson gson = new Gson();
 
-        List<Notification> notificationList = LocalNotificationManager.getList(osb, gson);
+        List<NotificationReturn> notificationList = LocalNotificationManager.getList(osb, gson);
 
         Intent intent = new Intent(context, NotificationReceiver.class);
         intent.setAction(Utils.ACTION_SHOW_NOTIFICATION);
@@ -99,10 +100,10 @@ public abstract class BasePresenter<V> {
         AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
 
 
-        for(Notification n : notificationList){
+        for(NotificationReturn n : notificationList){
 
             pendingIntent = PendingIntent.getBroadcast(context,
-                    LocalNotificationManager.NOTIFICATION_REMINDER_REQUEST_CODE + (int) n.scheduleId, intent,
+                    LocalNotificationManager.NOTIFICATION_REMINDER_REQUEST_CODE +  n.scheduleId.intValue(), intent,
                     PendingIntent.FLAG_CANCEL_CURRENT);
 
             if(am != null){
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
index 3f9baa2..88e032b 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
@@ -113,7 +113,6 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
         final ApiEndpoints service = ApiUtils.request(header);
 
         final Call<NotificationReturn> listCall = service.requestCreateNotification(notification);
-        scheduleNotificationJob(notification);
         scheduleConfirmationPresenter.view().setProgressBar(true);
         listCall.enqueue(new Callback<NotificationReturn>() {
 
@@ -121,14 +120,13 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
             public void onResponse(Call<NotificationReturn> call, Response<NotificationReturn> response) {
                 Headers headers = response.headers();
                 int status = response.code();
-                Log.d("Agendador", "Header do create notification:" + headers.get(Utils.ACCESS_TOKEN));
                 updateHeaders(headers);
                 switch (status) {
                     case 201:
                         Log.d("Server response", this.getClass().getName() + ": 200 - Sucess!");
                         scheduleConfirmationPresenter.view().setProgressBar(false);
                         scheduleConfirmationPresenter.view().returnHome();
-                        LocalNotificationManager.createLocalNotification(context, notification, osb, new Gson());
+                        LocalNotificationManager.createLocalNotification(context, response.body(), osb, new Gson());
                         break;
                     default:
                         Log.e("Server response", this.getClass().getName() + ": ERRO:" + status + " na criação de uma notificação.");
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
index 26175cb..6fdf7c1 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/LocalNotificationManager.java
@@ -19,7 +19,7 @@ import java.util.Locale;
 
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
-import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
 
 import static android.content.Context.ALARM_SERVICE;
 
@@ -32,27 +32,25 @@ import static android.content.Context.ALARM_SERVICE;
 
 public abstract class LocalNotificationManager {
 
-
     public static final int NOTIFICATION_REMINDER_REQUEST_CODE = 0x27;
 
 
-    public static void createLocalNotification(Context context, Notification notification, ObscuredSharedPreferences osb, Gson gson){
-        Log.d("Agendador", "Criando notificação local...");
+    public synchronized static void createLocalNotification(Context context, NotificationReturn notification, ObscuredSharedPreferences osb, Gson gson){
         addNotification(notification, osb, gson);
         SimpleDateFormat sdfServer = new SimpleDateFormat(Utils.SERVER_FORMAT, Locale.getDefault());
         Calendar calendar = Calendar.getInstance();
 
         try{
             calendar.setTime(sdfServer.parse(notification.reminderTime));
-            setReminder(context, calendar, (int) notification.scheduleId);
+            setReminder(context, calendar,  notification.scheduleId.intValue());
         }catch (ParseException ignored){
-            Log.e("Agendador", "Erro ao parsear data, para criar notificação local.");
+            Log.e("Notificacao", "Erro ao parsear data, para criar notificação local.");
             ignored.printStackTrace();
         }
     }
 
 
-    public static void setReminder(Context context, Calendar calendar, int scheduleId){
+    public synchronized static void setReminder(Context context, Calendar calendar, int scheduleId){
 
         Intent intent = new Intent(context, NotificationReceiver.class);
         intent.setAction(Utils.ACTION_SHOW_NOTIFICATION);
@@ -69,60 +67,65 @@ public abstract class LocalNotificationManager {
                 am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
             }
 
-            Log.d("Agendador", "Alarme registrado para o agendamento " + scheduleId + " .");
+            Log.d("Notificacao", "Alarme registrado para o agendamento " + scheduleId + " .");
         }
         else{
-            Log.d("Agendador", "Objeto do Alarm Manager NULL.");
+            Log.d("Notificacao", "Objeto do Alarm Manager NULL.");
         }
     }
 
 
-    private static void addNotification(Notification notification, ObscuredSharedPreferences osb, Gson gson){
-
-        //Retrieve the values
-        String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
-        List<Notification> notifications = gson.fromJson(jsonList, new TypeToken<List<Notification>>(){}.getType());
-        if(notifications == null)
-            notifications = new ArrayList<>();
-        notifications.add(notification);
-        jsonList = gson.toJson(notifications);
+    private synchronized static void addNotification(NotificationReturn notification, ObscuredSharedPreferences osb, Gson gson){
 
-        Log.d("Agendador", "add notification:" + jsonList);
+        synchronized (LocalNotificationManager.class) {
+            //Retrieve the values
+            String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
+            List<NotificationReturn> notifications = gson.fromJson(jsonList, new TypeToken<List<NotificationReturn>>() {
+            }.getType());
+            if (notifications == null)
+                notifications = new ArrayList<>();
+            notifications.add(notification);
+            jsonList = gson.toJson(notifications);
 
-        osb.edit().putString(Utils.NOTIFICATION_LIST, jsonList).commit();
 
+            osb.edit().putString(Utils.NOTIFICATION_LIST, jsonList).commit();
+        }
     }
 
-
     // TODO: 15/12/17 Testar o retorno da lista.
-    public static List<Notification> getList(ObscuredSharedPreferences osb, Gson gson){
-        String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
-        List<Notification> notifications = gson.fromJson(jsonList, new TypeToken<List<Notification>>(){}.getType());
-
-        return notifications == null ? new ArrayList<Notification>() : notifications;
+    public synchronized static List<NotificationReturn> getList(ObscuredSharedPreferences osb, Gson gson){
+        synchronized (LocalNotificationManager.class) {
+            String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
+            List<NotificationReturn> notifications = gson.fromJson(jsonList, new TypeToken<List<NotificationReturn>>() {
+            }.getType());
+            return notifications == null ? new ArrayList<NotificationReturn>() : notifications;
+        }
     }
 
     // TODO: 15/12/17 Testar o remove.
-    public static void removeNotification(long scheduleId, ObscuredSharedPreferences osb, Gson gson){
-
-        //Retrieve the values
-        String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
-        List<Notification> notifications = gson.fromJson(jsonList, new TypeToken<List<Notification>>(){}.getType());
-
-        for(Notification n : notifications) {
-            if (n.scheduleId == scheduleId){
-                notifications.remove(n);
-                break;
+    public synchronized static void removeNotification(NotificationReturn notification, ObscuredSharedPreferences osb, Gson gson){
+
+        synchronized (LocalNotificationManager.class) {
+            //Retrieve the values
+            String jsonList = osb.getString(Utils.NOTIFICATION_LIST, "");
+            List<NotificationReturn> notifications = gson.fromJson(jsonList, new TypeToken<List<NotificationReturn>>() {
+            }.getType());
+
+            for (NotificationReturn n : notifications) {
+                if (n.notificationId == notification.notificationId) {
+                    notifications.remove(n);
+                    break;
+                }
             }
-        }
-
-        jsonList = gson.toJson(notifications);
 
-        Log.d("Agendador", "remove notification:" + jsonList);
+            jsonList = gson.toJson(notifications);
 
-        osb.edit().putString(Utils.NOTIFICATION_LIST, jsonList).commit();
 
+            osb.edit().putString(Utils.NOTIFICATION_LIST, jsonList).commit();
+        }
     }
 
 
+
+
 }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
index 075d8be..0620e9f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
@@ -32,7 +32,7 @@ public class NotificationCreateService extends JobService {
 
     @Override
     public boolean onStartJob(final JobParameters job) {
-        Log.v("AGNDDR-NotifiCreate", "Rodando " + NotificationCreateService.class.getName());
+        Log.v("Notificacao", "Rodando " + NotificationCreateService.class.getName());
 
         new Thread(new Runnable() {
             public void run() {
@@ -50,7 +50,7 @@ public class NotificationCreateService extends JobService {
                 if (extras != null) {
                     notification = new Gson().fromJson(extras.getString(Utils.NOTIFICATION), Notification.class);
                 } else {
-                    Log.e("AGNDDR-NotifiCreate", "Job não recebeu os extras.");
+                    Log.e("Notificacao", "Job não recebeu os extras.");
                     jobFinished(job, true);
                 }
 
@@ -80,7 +80,7 @@ public class NotificationCreateService extends JobService {
                     case 200:
                     case 201:
                         Log.d("Server response", getClass().getName() + ": 200 - Sucesso!");
-                        LocalNotificationManager.createLocalNotification(getApplicationContext(), notification, osb, new Gson());
+                        LocalNotificationManager.createLocalNotification(getApplicationContext(), response.body(), osb, new Gson());
                         jobFinished(job, false);
                         break;
                     default:
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReadService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReadService.java
new file mode 100644
index 0000000..4a43b80
--- /dev/null
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReadService.java
@@ -0,0 +1,141 @@
+package br.ufpr.c3sl.agendador.agendador.services.notification;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.firebase.jobdispatcher.JobParameters;
+import com.firebase.jobdispatcher.JobService;
+import com.google.gson.Gson;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
+import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationUpdate;
+import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
+import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
+import okhttp3.Headers;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * Created by Lucas Braz Cunha on 22/01/18.
+ *
+ *
+ * Service to update back-end's notification, now that user has been notified.
+ */
+
+public class NotificationReadService extends JobService {
+    /**
+     * The entry point to your Job. Implementations should offload work to another thread of
+     * execution as soon as possible.
+     *
+     */
+    @Override
+    public boolean onStartJob(final JobParameters job) {
+
+
+        new Thread(new Runnable() {
+            public void run() {
+
+                Log.v("Notificacao", "Rodando " + NotificationReadService.class.getName());
+                Map<String, String> header = new HashMap<>();
+                ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
+                header.put("Content-Type", "application/json");
+                header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
+                header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
+                header.put(Utils.UID, osb.getString(Utils.UID, null));
+                requestNotificationRead(header, job, osb);
+            }
+
+        }).start();
+
+        return true;
+    }
+
+
+    private void requestNotificationRead(final Map<String, String> header, final JobParameters job, final ObscuredSharedPreferences osb){
+
+        final ApiEndpoints service = ApiUtils.request(header);
+
+
+        if(job.getExtras() == null){
+            Log.d("Notificacao", "Job 'extras' está vazio.");
+            jobFinished(job, false);
+            return;
+        }
+
+        String notificationJson =  job.getExtras().getString(Utils.NOTIFICATION);
+        final NotificationReturn notificationReturn = new Gson().fromJson(notificationJson, NotificationReturn.class);
+
+        if(notificationReturn == null){
+            Log.d("Notificacao", "Conteudo para atualizar está vazio.");
+            jobFinished(job, false);
+            return;
+        }
+
+        NotificationUpdate notificationUpdate = new NotificationUpdate(1);
+
+        Call<NotificationReturn> listCall = service.requestUpdateNotification(notificationReturn.notificationId, notificationUpdate);
+
+        listCall.enqueue(new Callback<NotificationReturn>() {
+
+            @Override
+            public void onResponse(Call<NotificationReturn> call, Response<NotificationReturn> response) {
+                Headers headers = response.headers();
+                int status = response.code();
+                updateHeaders(headers, osb);
+                switch (status) {
+                    case 200:
+                    case 201:
+                        Log.d("Server response", getClass().getName() + ": 200 - Sucesso!");
+                        LocalNotificationManager.removeNotification(notificationReturn, osb, new Gson());
+                        jobFinished(job, false);
+                        break;
+                    default:
+                        Log.e("Server response", getClass().getName() + ": ERRO:" + status);
+
+                        jobFinished(job, true);
+                        break;
+                }
+
+            }
+
+            @Override
+            public void onFailure(Call<NotificationReturn> call, Throwable t) {
+                Log.e("Server response", getClass().getName() + ": Requisição falhou!!");
+                t.printStackTrace();
+                jobFinished(job, true);
+            }
+        });
+
+    }
+
+    private void updateHeaders(Headers headers, ObscuredSharedPreferences osb){
+        if (headers.get(Utils.ACCESS_TOKEN) != null)
+            osb.edit().putString(Utils.ACCESS_TOKEN, headers.get(Utils.ACCESS_TOKEN)).apply();
+        if (headers.get(Utils.CLIENT) != null)
+            osb.edit().putString(Utils.CLIENT, headers.get(Utils.CLIENT)).apply();
+        if (headers.get(Utils.UID) != null)
+            osb.edit().putString(Utils.UID, headers.get(Utils.UID)).apply();
+        if (headers.get(Utils.EXPIRY) != null)
+            osb.edit().putString(Utils.EXPIRY, headers.get(Utils.EXPIRY)).apply();
+
+    }
+
+
+
+    /**
+     * Called when the scheduling engine has decided to interrupt the execution of a running job,
+     * most likely because the runtime constraints associated with the job are no longer satisfied.
+     * The job must stop execution.
+     *
+     */
+    @Override
+    public boolean onStopJob(JobParameters job) {
+        return false;
+    }
+}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
index 14b5d9f..a84d08f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationReceiver.java
@@ -6,19 +6,37 @@ import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.BitmapFactory;
+import android.os.Bundle;
 import android.support.v7.app.NotificationCompat;
 import android.util.Log;
 import android.widget.Toast;
 
+import com.firebase.jobdispatcher.Constraint;
+import com.firebase.jobdispatcher.FirebaseJobDispatcher;
+import com.firebase.jobdispatcher.GooglePlayDriver;
+import com.firebase.jobdispatcher.Job;
+import com.firebase.jobdispatcher.Lifetime;
+import com.firebase.jobdispatcher.RetryStrategy;
+import com.firebase.jobdispatcher.Trigger;
 import com.google.gson.Gson;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import br.ufpr.c3sl.agendador.agendador.R;
 import br.ufpr.c3sl.agendador.agendador.ScheduleInfoActivity;
 import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
+import br.ufpr.c3sl.agendador.agendador.models.NotificationUpdate;
+import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
+import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
+import okhttp3.Headers;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
 
 import static android.content.Context.NOTIFICATION_SERVICE;
 
@@ -33,43 +51,135 @@ public class NotificationReceiver extends BroadcastReceiver{
     public void onReceive(Context context, Intent intent) {
         if(intent.getAction() != null && intent.getAction().equals(Utils.ACTION_SHOW_NOTIFICATION)){
             int id = intent.getIntExtra(Utils.ID, -1);
-            Log.d("Agendador", "Estou no "+ NotificationReceiver.class.getName() +"! Notificação de id "+ id);
+            Log.d("Notificacao", "Estou no "+ NotificationReceiver.class.getName() +"! Notificação de id "+ id);
             ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
-            Notification content = null;
+            NotificationReturn content = null;
             Gson gson = new Gson();
-            List<Notification> notifications = LocalNotificationManager.getList(osb, gson);
-            for(Notification n : notifications){
+            List<NotificationReturn> notifications = LocalNotificationManager.getList(osb, gson);
+            for(NotificationReturn n : notifications){
                 if(n.scheduleId == id){
                     content = n;
                     break;
                 }
             }
-            // TODO: 19/01/18 só remover a notificação depois de enviar para o servidor que ela foi mostrada.
-            LocalNotificationManager.removeNotification(id, osb, gson);
+
+
             NotificationManager notificationManager = (NotificationManager)
                     context.getSystemService(NOTIFICATION_SERVICE);
 
-            if(content == null || notificationManager == null){
-                Log.e("Agendador", "Erro: notificação não encontrada, ou notification manager null");
-                return;
-            }
+            if(content == null){
+                Log.e("Notificacao", "Erro: notificação não encontrada");
+            }else if(notificationManager == null){
+                Log.e("Notificacao", "Erro: notification manager null");
+            }else{
+                NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
+
+                Intent showScheduleIntent = new Intent(context, ScheduleInfoActivity.class);
+                showScheduleIntent.putExtra(Utils.ID, id);
 
-            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
+                PendingIntent pendingIntent = PendingIntent.getActivity(context, Utils.SHOW_SCHEDULE_INFO_ACTION, showScheduleIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
-            Intent showScheduleIntent = new Intent(context, ScheduleInfoActivity.class);
-            showScheduleIntent.putExtra(Utils.ID, id);
+                String alert = context.getResources().getString(R.string.notification_alert);
+                android.app.Notification appNotification = mBuilder.setAutoCancel(true).setContentText(content.description).setContentTitle(alert)
+                        .setDefaults(android.app.Notification.DEFAULT_LIGHTS | android.app.Notification.DEFAULT_SOUND)
+                        .setSmallIcon(R.drawable.img_mainact_logo).setTicker(alert).setContentIntent(pendingIntent)
+                        .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.img_terms_logo)).build();
 
-            PendingIntent pendingIntent = PendingIntent.getActivity(context, Utils.SHOW_SCHEDULE_INFO_ACTION, showScheduleIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
-            String alert = context.getResources().getString(R.string.notification_alert);
-            android.app.Notification appNotification = mBuilder.setAutoCancel(true).setContentText(content.description).setContentTitle(alert)
-                    .setDefaults(android.app.Notification.DEFAULT_LIGHTS | android.app.Notification.DEFAULT_SOUND)
-                    .setSmallIcon(R.drawable.img_mainact_logo).setTicker(alert).setContentIntent(pendingIntent)
-                    .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.img_terms_logo)).build();
 
-            // Will display the notification in the notification bar
-            notificationManager.notify(id, appNotification);
+                requestNotificationUpdate(osb, content, context);
 
+                // Will display the notification in the notification bar
+                notificationManager.notify(id, appNotification);
+
+            }
         }
     }
+
+
+
+    private void requestNotificationUpdate(final ObscuredSharedPreferences osb, final NotificationReturn notificationReturn, final Context context){
+        Map<String, String> header = new HashMap<>();
+        header.put("Content-Type", "application/json");
+        header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
+        header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
+        header.put(Utils.UID, osb.getString(Utils.UID, null));
+
+        final ApiEndpoints service = ApiUtils.request(header);
+
+
+        NotificationUpdate notificationUpdate = new NotificationUpdate(1);
+
+        Call<NotificationReturn> listCall = service.requestUpdateNotification(notificationReturn.notificationId, notificationUpdate);
+
+        listCall.enqueue(new Callback<NotificationReturn>() {
+
+            @Override
+            public void onResponse(Call<NotificationReturn> call, Response<NotificationReturn> response) {
+                Headers headers = response.headers();
+                int status = response.code();
+                updateHeaders(headers, osb);
+                switch (status) {
+                    case 200:
+                        Log.d("Server response", getClass().getName() + ": 200 - Sucesso!");
+                        LocalNotificationManager.removeNotification(notificationReturn, osb, new Gson());
+                        break;
+                    default:
+                        Log.e("Server response", getClass().getName() + ": ERRO:" + status);
+                        scheduleJob(context, notificationReturn);
+                        break;
+                }
+
+            }
+
+            @Override
+            public void onFailure(Call<NotificationReturn> call, Throwable t) {
+                Log.e("Server response", getClass().getName() + ": Requisição falhou!!");
+                t.printStackTrace();
+            }
+        });
+
+    }
+
+    private void updateHeaders(Headers headers, ObscuredSharedPreferences osb){
+        if (headers.get(Utils.ACCESS_TOKEN) != null)
+            osb.edit().putString(Utils.ACCESS_TOKEN, headers.get(Utils.ACCESS_TOKEN)).apply();
+        if (headers.get(Utils.CLIENT) != null)
+            osb.edit().putString(Utils.CLIENT, headers.get(Utils.CLIENT)).apply();
+        if (headers.get(Utils.UID) != null)
+            osb.edit().putString(Utils.UID, headers.get(Utils.UID)).apply();
+        if (headers.get(Utils.EXPIRY) != null)
+            osb.edit().putString(Utils.EXPIRY, headers.get(Utils.EXPIRY)).apply();
+
+    }
+
+
+    private void scheduleJob(Context context, NotificationReturn notificationReturn){
+
+        FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(
+                new GooglePlayDriver(context)
+        );
+
+        Bundle extras = new Bundle();
+
+        extras.putString(Utils.NOTIFICATION, new Gson().toJson(notificationReturn));
+
+        Job job = dispatcher.newJobBuilder()
+                .setService(NotificationReadService.class)
+                .setTag(Utils.NOTIFICATION_READ_SERVICE)
+                //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
+                //will be repeated every 10 minutes
+                .setTrigger(Trigger.NOW)
+                //will be retried if it fails.
+                .setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
+                .setExtras(extras)
+                .setConstraints(
+                        // only run on network
+                        Constraint.ON_ANY_NETWORK
+                )
+                //if device is rebooted the job will be restarted
+                .setLifetime(Lifetime.FOREVER)
+                .build();
+        dispatcher.mustSchedule(job);
+    }
 }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java
index 144bf8d..4898109 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java
@@ -1,11 +1,8 @@
 package br.ufpr.c3sl.agendador.agendador.services.notification;
 
 import android.content.Context;
-import android.os.Looper;
 import android.util.Log;
 import android.util.LongSparseArray;
-import android.util.SparseArray;
-import android.util.SparseLongArray;
 
 import com.firebase.jobdispatcher.JobParameters;
 import com.firebase.jobdispatcher.JobService;
@@ -43,13 +40,12 @@ public class NotificationsListService  extends JobService {
     @Override
     public boolean onStartJob(final JobParameters job) {
 
-        Log.d("AGNDDR-NotifiUpdate", "Estou no Job");
 
 
        new Thread(new Runnable() {
             public void run() {
 
-                Log.v("AGNDDR-NotifiUpdate", "Rodando " + NotificationsListService.class.getName());
+                Log.v("Notificacao", "Rodando " + NotificationsListService.class.getName());
                 Map<String, String> header = new HashMap<>();
                 ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
                 header.put("Content-Type", "application/json");
@@ -68,11 +64,6 @@ public class NotificationsListService  extends JobService {
     private void requestNotificationUpdate(final Map<String, String> header, final JobParameters job, final ObscuredSharedPreferences osb){
 
         final ApiEndpoints service = ApiUtils.request(header);
-        Log.v("AGNDDR-NotifiUpdate", Utils.ACCESS_TOKEN + osb.getString(Utils.ACCESS_TOKEN, "NADA"));
-        Log.v("AGNDDR-NotifiUpdate", Utils.CLIENT + osb.getString(Utils.CLIENT, "NADA"));
-        Log.v("AGNDDR-NotifiUpdate", Utils.UID + osb.getString(Utils.UID, "NADA"));
-
-
 
         Call<List<NotificationReturn>> listCall = service.requestNotifications();
 
@@ -87,30 +78,28 @@ public class NotificationsListService  extends JobService {
                 switch (status) {
                     case 200:
                     case 201:
-                        Log.d("Server response", getClass().getName() + ": 200 - Sucesso!");
                         new Thread(new Runnable() {
                             public void run() {
                                 Gson gson = new Gson();
-                                LongSparseArray<Notification> localNotifications = new LongSparseArray<>();
-                                List<Notification> list = LocalNotificationManager.getList(osb, gson);
-                                for(Notification n  : list)
-                                    localNotifications.append(n.scheduleId, n);
+                                LongSparseArray<NotificationReturn> newLocalNotifications = new LongSparseArray<>();
+                                List<NotificationReturn> list = LocalNotificationManager.getList(osb, gson);
+                                for(NotificationReturn n  : list){
+                                    newLocalNotifications.append(n.notificationId, n);
+                                }
 
                                 for(NotificationReturn nr : responseList){
-                                    if(localNotifications.get(nr.scheduleId) == null){
+                                    if(newLocalNotifications.get(nr.notificationId) == null && nr.hasRead == 0){
                                         LocalNotificationManager.createLocalNotification(getApplicationContext(),
-                                                new Notification(nr.scheduleId, nr.reminderTime, nr.hasRead == 0,
-                                                        nr.description, nr.emailAddres, nr.emailSent == 0),
-                                                osb, gson);
+                                               nr, osb, gson);
                                     }
                                 }
 
+
                                 jobFinished(job, false);
                             }}).start();
                         break;
                     default:
                         Log.e("Server response", getClass().getName() + ": ERRO:" + status);
-
                         jobFinished(job, false);
                         break;
                 }
@@ -120,7 +109,6 @@ public class NotificationsListService  extends JobService {
             @Override
             public void onFailure(Call<List<NotificationReturn>> call, Throwable t) {
                 Log.e("Server response", getClass().getName() + ": Requisição falhou!!");
-                t.printStackTrace();
                 jobFinished(job, false);
             }
         });
-- 
GitLab


From ceae49b9a3e85dfd4cdbe65496c940051b130f50 Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Thu, 25 Jan 2018 10:54:21 -0200
Subject: [PATCH 7/9] AGILE#307: Adjusted recurring time of background service.

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 .../agendador/agendador/models/NotificationReturn.java    | 8 +++++---
 .../c3sl/agendador/agendador/network/ApiEndpoints.java    | 2 +-
 .../agendador/agendador/presenters/LoginPresenter.java    | 2 +-
 .../agendador/presenters/SchedulingPresenter.java         | 1 +
 .../services/notification/NotificationsListService.java   | 8 ++++++--
 5 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
index 7887795..c752e4b 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/NotificationReturn.java
@@ -27,7 +27,7 @@ public class NotificationReturn implements Parcelable{
     public String reminderTime;
 
     @SerializedName("read")
-    public int hasRead;
+    public boolean hasRead;
 
     @SerializedName("content")
     public String description;
@@ -35,6 +35,8 @@ public class NotificationReturn implements Parcelable{
     @SerializedName("reminder_email")
     public String emailAddress;
 
+
+    //todo: Mudar para boolean quando o back-end atualizar
     @SerializedName("reminder_email_sent")
     public int emailSent;
 
@@ -53,7 +55,7 @@ public class NotificationReturn implements Parcelable{
         scheduleId         = pc.readLong();
         resourceScheduleId = pc.readLong();
         reminderTime  = pc.readString();
-        hasRead      = pc.readInt();
+        hasRead      = pc.readByte() != 0;
         description = pc.readString();
         emailAddress = pc.readString();
         emailSent = pc.readInt();
@@ -84,7 +86,7 @@ public class NotificationReturn implements Parcelable{
         dest.writeLong(scheduleId == null ? 0 : scheduleId);
         dest.writeLong(resourceScheduleId == null ? 0 : resourceScheduleId);
         dest.writeString(reminderTime == null ? "" : reminderTime);
-        dest.writeInt(hasRead);
+        dest.writeByte((byte) (hasRead ? 1 : 0));
         dest.writeString(description == null ? "" : description);
         dest.writeString(emailAddress == null ? "" : emailAddress);
         dest.writeInt(emailSent);
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
index 6d351fc..99c152a 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
@@ -95,7 +95,7 @@ public interface ApiEndpoints {
     @GET("forms/schedule_history?permission=citizen")
     Call<FormFilters> requestCitizenSectors();
 
-    @POST("notifications?permission=2")
+    @POST("notifications?permission=citizen")
     Call<NotificationReturn> requestCreateNotification(@Body Notification notification);
 
     @GET("schedules/{id_schedule}?permission=citizen")
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
index 6416763..e084fd3 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
@@ -172,7 +172,7 @@ public class LoginPresenter extends BasePresenter<LoginView> {
                         .setService(ImageUpdateService.class)
                         .setTag(Utils.SERVICE_UPDATE_IMAGE)
                         //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
-                        .setTrigger(Trigger.executionWindow(60, 3600))
+                        .setTrigger(Trigger.executionWindow(580, 610))
                         //will be retried if it fails.
                         .setRecurring(true)
                         .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulingPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulingPresenter.java
index 580504a..42b3455 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulingPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulingPresenter.java
@@ -93,6 +93,7 @@ public class SchedulingPresenter extends BasePresenter<SchedulingView> {
         header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
         header.put(Utils.UID, osb.getString(Utils.UID, null));
 
+
         final ApiEndpoints service = ApiUtils.request(header);
 
         Call<ScheduleConfirmation> listCall = service.requestConfirmSchedule(schedule.getmId(), citizen.getId());
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java
index 4898109..8300288 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationsListService.java
@@ -83,12 +83,15 @@ public class NotificationsListService  extends JobService {
                                 Gson gson = new Gson();
                                 LongSparseArray<NotificationReturn> newLocalNotifications = new LongSparseArray<>();
                                 List<NotificationReturn> list = LocalNotificationManager.getList(osb, gson);
+                                Log.d("Notificacao", "NOTIFICACOES LOCAIS!!!!!!!!!");
                                 for(NotificationReturn n  : list){
                                     newLocalNotifications.append(n.notificationId, n);
+                                    Log.d("Notificacao", gson.toJson(n));
                                 }
-
+                                Log.d("Notificacao", "NOTIFICACOES NO SERVIDOR");
                                 for(NotificationReturn nr : responseList){
-                                    if(newLocalNotifications.get(nr.notificationId) == null && nr.hasRead == 0){
+                                    Log.d("Notificacao", gson.toJson(nr));
+                                    if(newLocalNotifications.get(nr.notificationId) == null && nr.hasRead){
                                         LocalNotificationManager.createLocalNotification(getApplicationContext(),
                                                nr, osb, gson);
                                     }
@@ -100,6 +103,7 @@ public class NotificationsListService  extends JobService {
                         break;
                     default:
                         Log.e("Server response", getClass().getName() + ": ERRO:" + status);
+
                         jobFinished(job, false);
                         break;
                 }
-- 
GitLab


From 65b47b50e72dc7f3a2b17573981e606794fb7f69 Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Thu, 25 Jan 2018 11:20:40 -0200
Subject: [PATCH 8/9] AGILE#307: Adjusted recurring time of background service
 (NotificationListService).

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 .../agendador/agendador/LoginActivity.java    | 23 +-------------
 .../agendador/presenters/LoginPresenter.java  | 31 ++++++++++++++++++-
 .../ScheduleConfirmationPresenter.java        |  1 -
 3 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
index ebe2a46..aa5b99e 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/LoginActivity.java
@@ -215,29 +215,8 @@ public class LoginActivity extends AppCompatActivity implements LoginView {
 
     @Override
     public void afterSuccessfulLogin() {
-        FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(
-                new GooglePlayDriver(this)
-        );
-
-        Job job = dispatcher.newJobBuilder()
-                .setService(NotificationsListService.class)
-                .setTag(Utils.NOTIFICATION_UPDATE_LIST_SERVICE)
-                //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
-                //will be repeated every 10 minutes
-                .setTrigger(Trigger.executionWindow(/*600, 720*/1, 29))
-                //will be retried if it fails.
-                .setRecurring(true)
-                .setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
-                .setConstraints(
-                        // only run on network
-                        Constraint.ON_ANY_NETWORK
-                )
-                //if device is rebooted the job will be restarted
-                .setLifetime(Lifetime.FOREVER)
-                .build();
-        dispatcher.mustSchedule(job);
-        Log.d("AGNDDR-NotifiUpdate", "Job agendado para atualizar lista de coisas");
 
+        presenter.createServiceLocalNotificationsList();
         Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
         startActivity(intent);
         finish();
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
index e084fd3..14de8ae 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/LoginPresenter.java
@@ -35,6 +35,7 @@ import br.ufpr.c3sl.agendador.agendador.models.AccountOutput;
 import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
 import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
 import br.ufpr.c3sl.agendador.agendador.services.ImageUpdateService;
+import br.ufpr.c3sl.agendador.agendador.services.notification.NotificationsListService;
 import br.ufpr.c3sl.agendador.agendador.views.LoginView;
 import okhttp3.Headers;
 import okhttp3.ResponseBody;
@@ -172,7 +173,7 @@ public class LoginPresenter extends BasePresenter<LoginView> {
                         .setService(ImageUpdateService.class)
                         .setTag(Utils.SERVICE_UPDATE_IMAGE)
                         //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
-                        .setTrigger(Trigger.executionWindow(580, 610))
+                        .setTrigger(Trigger.executionWindow(60, 3600))
                         //will be retried if it fails.
                         .setRecurring(true)
                         .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
@@ -194,6 +195,34 @@ public class LoginPresenter extends BasePresenter<LoginView> {
 
     }
 
+
+
+    public void createServiceLocalNotificationsList(){
+
+        FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(
+                new GooglePlayDriver(context)
+        );
+
+        Job job = dispatcher.newJobBuilder()
+                .setService(NotificationsListService.class)
+                .setTag(Utils.NOTIFICATION_UPDATE_LIST_SERVICE)
+                //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
+                //will be repeated every 10 minutes
+                .setTrigger(Trigger.executionWindow(570, 610))
+                //will be retried if it fails.
+                .setRecurring(true)
+                .setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
+                .setConstraints(
+                        // only run on network
+                        Constraint.ON_ANY_NETWORK
+                )
+                //if device is rebooted the job will be restarted
+                .setLifetime(Lifetime.FOREVER)
+                .build();
+
+        dispatcher.mustSchedule(job);
+    }
+
     // TODO: 03/05/17 Adapt function to scenario with different file extensions, if needed.
     private void checkLocalPhoto(){
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
index 88e032b..b9d512a 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
@@ -161,7 +161,6 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
         Job job = dispatcher.newJobBuilder()
                 .setService(NotificationCreateService.class)
                 .setTag(Utils.NOTIFICATION_SERVICE + notification.scheduleId)
-                //time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
                 .setTrigger(Trigger.NOW)
                 //will be retried if it fails.
                 .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
-- 
GitLab


From da5258bb2cb64fdddadd41a5032442519546d2f0 Mon Sep 17 00:00:00 2001
From: "Lucas B. Cunha" <lbc16@inf.ufpr.br>
Date: Thu, 25 Jan 2018 11:46:45 -0200
Subject: [PATCH 9/9] AGILE#316: Notification is now created at the same time
 that schedule is confirmed

Signed-off-by: Lucas B. Cunha <lbc16@inf.ufpr.br>
---
 app/src/main/AndroidManifest.xml              |   9 --
 .../ScheduleConfirmationActivity.java         |  60 ++++-----
 .../agendador/models/ScheduleNote.java        |   4 +-
 .../agendador/network/ApiEndpoints.java       |   5 +-
 .../ScheduleConfirmationPresenter.java        |  89 +------------
 .../presenters/SchedulesPresenter.java        |   2 +-
 .../NotificationCreateService.java            | 122 ------------------
 .../views/ScheduleConfirmationView.java       |   4 -
 8 files changed, 39 insertions(+), 256 deletions(-)
 delete mode 100644 app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ac0f7c6..41368bc 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -58,15 +58,6 @@
             </intent-filter>
         </service>
 
-        <service
-            android:name=".services.notification.NotificationCreateService"
-            android:exported="false"
-            android:permission="android.permission.BIND_JOB_SERVICE">
-            <intent-filter>
-                <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
-            </intent-filter>
-        </service>
-
         <service
             android:name=".services.notification.NotificationsListService"
             android:exported="false"
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
index a07cf0a..8907f25 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/ScheduleConfirmationActivity.java
@@ -217,7 +217,33 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
                 }
 
                 if(schedule){
-                    scheduleConfirmationPresenter.onScheduleClicked(scheduleConfirmation, citizen, et_scheduleNote.getText().toString());
+
+                    SimpleDateFormat sdfServer = new SimpleDateFormat(Utils.SERVER_FORMAT, Locale.getDefault());
+                    SimpleDateFormat sdfDate = new SimpleDateFormat(Utils.DATE_FORMAT, Locale.getDefault());
+                    SimpleDateFormat sdfHour = new SimpleDateFormat(Utils.HOUR_FORMAT, Locale.getDefault());
+
+
+                    /*
+                    * Position zero is "don't notify"
+                    */
+                    Notification notification = null;
+                    if(sp_notification.getSelectedItemPosition() != reminderTimeArray.length - 1) {
+                        notification = new Notification();
+                        notification.scheduleId = scheduleConfirmation.getId();
+                        notification.emailSent = false;
+
+                        notification.description = getResources().getString(R.string.notification_content, sdfDate.format(scheduleConfirmation.getStartTime()), sdfHour.format(scheduleConfirmation.getStartTime()), scheduleConfirmation.getServiceTypeName(),
+                                scheduleConfirmation.getLocationName(), scheduleConfirmation.getAddressStreet(), scheduleConfirmation.getAddressNumber());
+
+
+                        notification.reminderTime = sdfServer.format(scheduleConfirmation.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]));
+
+                        if (rb_yes.isChecked()) {
+                            notification.emailAddress = et_email.getText().toString();
+                        }
+                    }
+
+                    scheduleConfirmationPresenter.onScheduleClicked(scheduleConfirmation, citizen, et_scheduleNote.getText().toString(), notification);
                     bt_schedule.setEnabled(false);
                     bt_back.setEnabled(false);
                 }
@@ -366,40 +392,8 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
         }
     }
 
-    @Override
-    public void onSuccess(ScheduleConfirmation schedule){
-
-        SimpleDateFormat sdfServer = new SimpleDateFormat(Utils.SERVER_FORMAT, Locale.getDefault());
-        SimpleDateFormat sdfDate = new SimpleDateFormat(Utils.DATE_FORMAT, Locale.getDefault());
-        SimpleDateFormat sdfHour = new SimpleDateFormat(Utils.HOUR_FORMAT, Locale.getDefault());
 
 
-        /*
-        * Position zero is "don't notify"
-        */
-
-        if(sp_notification.getSelectedItemPosition() != reminderTimeArray.length - 1){
-            Notification notification = new Notification();
-            notification.scheduleId = schedule.getId();
-            notification.emailSent = false;
-
-            notification.description = getResources().getString(R.string.notification_content, sdfDate.format(schedule.getStartTime()), sdfHour.format(schedule.getStartTime()), schedule.getServiceTypeName(),
-                    schedule.getLocationName(), schedule.getAddressStreet(), schedule.getAddressNumber());
-
-            // TODO: 15/01/18 Apagar aqui o tempo a mais que está sendo usado no calculo da notificaçõa, está em dobro.
-            notification.reminderTime = sdfServer.format(schedule.getStartTime().getTime() - (reminderTimeArray[sp_notification.getSelectedItemPosition()]) - (reminderTimeArray[sp_notification.getSelectedItemPosition()]));
-
-            if(rb_yes.isChecked()){
-                notification.emailAddress = et_email.getText().toString();
-            }
-
-            scheduleConfirmationPresenter.createNotification(notification);
-        }else{
-            returnHome();
-        }
-
-    }
-
 
     private void radioButtonNotificationSelected(int id, boolean toggle){
         switch (id){
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleNote.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleNote.java
index 8397ca4..05b6769 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleNote.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/models/ScheduleNote.java
@@ -3,13 +3,15 @@ package br.ufpr.c3sl.agendador.agendador.models;
 import com.google.gson.annotations.SerializedName;
 
 /**
- * Created by lbc16 on 19/09/17.
+ * Created by Lucas Braz Cunha on 19/09/17.
  */
 
 public class ScheduleNote {
 
     public Schedule schedule;
 
+    public Notification notification;
+
     public ScheduleNote(String note) {
         this.schedule = new Schedule(note);
     }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
index 99c152a..268289f 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/network/ApiEndpoints.java
@@ -89,9 +89,12 @@ public interface ApiEndpoints {
     @PUT("citizens/{id_user}/dependants/{id_dependent}?permission=citizen")
     Call<FullDependent> updateDependent(@Path("id_user") long citizenId, @Path("id_dependent") long dependentId, @Body DependentCreation dependent);
 
-    @GET("schedules?permission=citizen")
+    @GET("schedules?permission=citizen&history=true")
     Call<CheckSchedules> requestSchedulesHistory(@QueryMap Map<String, String> options);
 
+    @GET("schedules?permission=citizen&future=true")
+    Call<CheckSchedules> requestFutureSchedules(@QueryMap Map<String, String> options);
+
     @GET("forms/schedule_history?permission=citizen")
     Call<FormFilters> requestCitizenSectors();
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
index b9d512a..0a96900 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/ScheduleConfirmationPresenter.java
@@ -1,17 +1,10 @@
 package br.ufpr.c3sl.agendador.agendador.presenters;
 
 import android.content.Context;
-import android.os.Bundle;
 import android.util.Log;
 
-import com.firebase.jobdispatcher.Constraint;
 import com.firebase.jobdispatcher.FirebaseJobDispatcher;
 import com.firebase.jobdispatcher.GooglePlayDriver;
-import com.firebase.jobdispatcher.Job;
-import com.firebase.jobdispatcher.Lifetime;
-import com.firebase.jobdispatcher.RetryStrategy;
-import com.firebase.jobdispatcher.Trigger;
-import com.google.gson.Gson;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -21,13 +14,10 @@ import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
 import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
 import br.ufpr.c3sl.agendador.agendador.models.CitizenCompact;
 import br.ufpr.c3sl.agendador.agendador.models.Notification;
-import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
 import br.ufpr.c3sl.agendador.agendador.models.ScheduleNote;
 import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
 import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
-import br.ufpr.c3sl.agendador.agendador.services.notification.LocalNotificationManager;
-import br.ufpr.c3sl.agendador.agendador.services.notification.NotificationCreateService;
 import okhttp3.Headers;
 import retrofit2.Call;
 import retrofit2.Callback;
@@ -54,7 +44,7 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
     }
 
 
-    public void onScheduleClicked(final ScheduleConfirmation scheduleConfirmation, CitizenCompact citizen, String note){
+    public void onScheduleClicked(final ScheduleConfirmation scheduleConfirmation, CitizenCompact citizen, String note, Notification notification){
         Map<String, String> header = new HashMap<>();
         header.put("Content-Type", "application/json");
         header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
@@ -65,6 +55,8 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
 
         ScheduleNote scheduleNote = new ScheduleNote(note);
 
+        scheduleNote.notification = notification;
+
         Call<ScheduleConfirmation> listCall = service.requestPerformScheduling(scheduleConfirmation.getId(), citizen.getId(), scheduleNote);
 
         scheduleConfirmationPresenter.view().setProgressBar(true);
@@ -80,7 +72,7 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
                     case 200:
                         Log.d("Server response", this.getClass().getName() + ": 200 - Sucesso!");
                         scheduleConfirmationPresenter.view().setProgressBar(false);
-                        scheduleConfirmationPresenter.view().onSuccess(scheduleConfirmation);
+                        scheduleConfirmationPresenter.view().returnHome();
 
                         break;
                     default:
@@ -102,79 +94,6 @@ public class ScheduleConfirmationPresenter extends BasePresenter<ScheduleConfirm
     }
 
 
-    public void createNotification(final Notification notification){
-        Map<String, String> header = new HashMap<>();
-        header.put("Content-Type", "application/json");
-        header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
-        header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
-        header.put(Utils.UID, osb.getString(Utils.UID, null));
-
-
-        final ApiEndpoints service = ApiUtils.request(header);
-
-        final Call<NotificationReturn> listCall = service.requestCreateNotification(notification);
-        scheduleConfirmationPresenter.view().setProgressBar(true);
-        listCall.enqueue(new Callback<NotificationReturn>() {
-
-            @Override
-            public void onResponse(Call<NotificationReturn> call, Response<NotificationReturn> response) {
-                Headers headers = response.headers();
-                int status = response.code();
-                updateHeaders(headers);
-                switch (status) {
-                    case 201:
-                        Log.d("Server response", this.getClass().getName() + ": 200 - Sucess!");
-                        scheduleConfirmationPresenter.view().setProgressBar(false);
-                        scheduleConfirmationPresenter.view().returnHome();
-                        LocalNotificationManager.createLocalNotification(context, response.body(), osb, new Gson());
-                        break;
-                    default:
-                        Log.e("Server response", this.getClass().getName() + ": ERRO:" + status + " na criação de uma notificação.");
-                        scheduleNotificationJob(notification);
-                        scheduleConfirmationPresenter.view().setProgressBar(false);
-                        scheduleConfirmationPresenter.view().returnHome();
-                        break;
-                }
-            }
-            @Override
-            public void onFailure(Call<NotificationReturn> call, Throwable t) {
-                Log.e("Server response", this.getClass().getName() +  ": Request Failed, Scheduling job.");
-                t.printStackTrace();
-                scheduleNotificationJob(notification);
-                scheduleConfirmationPresenter.view().setProgressBar(false);
-                scheduleConfirmationPresenter.view().returnHome();
-            }
-        });
-
-    }
-
-
-
-    private void scheduleNotificationJob(Notification notification){
-        Bundle extras = new Bundle();
-
-        Gson g = new Gson();
-        String json = g.toJson(notification);
-
-        extras.putString(Utils.NOTIFICATION, json);
-
-        Job job = dispatcher.newJobBuilder()
-                .setService(NotificationCreateService.class)
-                .setTag(Utils.NOTIFICATION_SERVICE + notification.scheduleId)
-                .setTrigger(Trigger.NOW)
-                //will be retried if it fails.
-                .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
-                .setConstraints(
-                        // only run on network
-                        Constraint.ON_ANY_NETWORK
-                )
-                .setExtras(extras)
-                //if device is rebooted the job will be restarted
-                .setLifetime(Lifetime.FOREVER)
-                .build();
-        dispatcher.mustSchedule(job);
-    }
-
     @Override
     protected void updateView() {}
 }
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesPresenter.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesPresenter.java
index bfdd7a0..d17c668 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesPresenter.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/presenters/SchedulesPresenter.java
@@ -51,7 +51,7 @@ public class SchedulesPresenter extends BasePresenter<SchedulesActivity> {
 
         // TODO: 06/10/17 Change to request "active" schedules1
 
-        Call<CheckSchedules> listCall = service.requestSchedulesHistory(new HashMap<String, String>());
+        Call<CheckSchedules> listCall = service.requestFutureSchedules(new HashMap<String, String>());
 
         listCall.enqueue(new Callback<CheckSchedules>() {
 
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
deleted file mode 100644
index 0620e9f..0000000
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/services/notification/NotificationCreateService.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package br.ufpr.c3sl.agendador.agendador.services.notification;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.firebase.jobdispatcher.JobParameters;
-import com.firebase.jobdispatcher.JobService;
-import com.google.gson.Gson;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
-import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
-import br.ufpr.c3sl.agendador.agendador.models.Notification;
-import br.ufpr.c3sl.agendador.agendador.models.NotificationReturn;
-import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
-import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
-import okhttp3.Headers;
-import retrofit2.Call;
-import retrofit2.Callback;
-import retrofit2.Response;
-
-/**
- * Created by Lucas Braz Cunha on 24/11/17.
- */
-
-public class NotificationCreateService extends JobService {
-
-
-    @Override
-    public boolean onStartJob(final JobParameters job) {
-        Log.v("Notificacao", "Rodando " + NotificationCreateService.class.getName());
-
-        new Thread(new Runnable() {
-            public void run() {
-
-                final Bundle extras = job.getExtras();
-                Map<String, String> header = new HashMap<>();
-                ObscuredSharedPreferences osb = ObscuredSharedPreferences.getPrefs(getBaseContext(), "Agendador", Context.MODE_PRIVATE);
-                header.put("Content-Type", "application/json");
-                header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
-                header.put(Utils.CLIENT, osb.getString(Utils.CLIENT, null));
-                header.put(Utils.UID, osb.getString(Utils.UID, null));
-
-                Notification notification = null;
-
-                if (extras != null) {
-                    notification = new Gson().fromJson(extras.getString(Utils.NOTIFICATION), Notification.class);
-                } else {
-                    Log.e("Notificacao", "Job não recebeu os extras.");
-                    jobFinished(job, true);
-                }
-
-                requestCreateNotification(header, job, osb, notification);
-
-
-            }}).start();
-
-        return true;
-    }
-
-
-    private void requestCreateNotification(final Map<String, String> header, final JobParameters job, final ObscuredSharedPreferences osb, final Notification notification){
-
-        final ApiEndpoints service = ApiUtils.request(header);
-
-        Call<NotificationReturn> listCall = service.requestCreateNotification(notification);
-
-        listCall.enqueue(new Callback<NotificationReturn>() {
-
-            @Override
-            public void onResponse(Call<NotificationReturn> call, Response<NotificationReturn> response) {
-                Headers headers = response.headers();
-                int status = response.code();
-                updateHeaders(headers, osb);
-                switch (status) {
-                    case 200:
-                    case 201:
-                        Log.d("Server response", getClass().getName() + ": 200 - Sucesso!");
-                        LocalNotificationManager.createLocalNotification(getApplicationContext(), response.body(), osb, new Gson());
-                        jobFinished(job, false);
-                        break;
-                    default:
-                        Log.e("Server response", getClass().getName() + ": ERRO:" + status);
-                        jobFinished(job, true);
-                        break;
-                }
-
-            }
-
-            @Override
-            public void onFailure(Call<NotificationReturn> call, Throwable t) {
-                Log.e("Server response", getClass().getName() + ": Requisição falhou!!");
-                t.printStackTrace();
-                jobFinished(job, true);
-            }
-        });
-
-    }
-
-    private void updateHeaders(Headers headers, ObscuredSharedPreferences osb){
-        if (headers.get(Utils.ACCESS_TOKEN) != null)
-            osb.edit().putString(Utils.ACCESS_TOKEN, headers.get(Utils.ACCESS_TOKEN)).apply();
-        if (headers.get(Utils.CLIENT) != null)
-            osb.edit().putString(Utils.CLIENT, headers.get(Utils.CLIENT)).apply();
-        if (headers.get(Utils.UID) != null)
-            osb.edit().putString(Utils.UID, headers.get(Utils.UID)).apply();
-        if (headers.get(Utils.EXPIRY) != null)
-            osb.edit().putString(Utils.EXPIRY, headers.get(Utils.EXPIRY)).apply();
-
-    }
-
-
-
-    @Override
-    public boolean onStopJob(JobParameters job) {
-        return true;
-    }
-}
diff --git a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleConfirmationView.java b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleConfirmationView.java
index 25d0935..0c41bba 100644
--- a/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleConfirmationView.java
+++ b/app/src/main/java/br/ufpr/c3sl/agendador/agendador/views/ScheduleConfirmationView.java
@@ -1,7 +1,5 @@
 package br.ufpr.c3sl.agendador.agendador.views;
 
-import br.ufpr.c3sl.agendador.agendador.models.ScheduleConfirmation;
-
 /**
  * Created by Lucas B. Cunha on 25/07/17.
  */
@@ -12,8 +10,6 @@ public interface ScheduleConfirmationView {
 
     void setProgressBar(boolean enabled);
 
-    void onSuccess(ScheduleConfirmation confirmationResponse);
-
     void setConnectionError(boolean enabled);
 
     void returnHome();
-- 
GitLab