Commit ce7aa72c authored by Lucas Braz Cunha's avatar Lucas Braz Cunha
Browse files

Merge branch 'notification' into 'develop'

Added Notifications

See merge request !18
parents 58306e25 da5258bb
......@@ -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"
......@@ -47,6 +49,34 @@
</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.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>
<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" />
......@@ -57,7 +87,11 @@
<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
......@@ -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();
}
}
......
......@@ -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)
......
......@@ -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,6 +215,8 @@ public class LoginActivity extends AppCompatActivity implements LoginView {
@Override
public void afterSuccessfulLogin() {
presenter.createServiceLocalNotificationsList();
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
startActivity(intent);
finish();
......
......@@ -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;
......@@ -15,26 +16,35 @@ 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;
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.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.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;
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;
......@@ -44,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;
......@@ -58,40 +70,52 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
private ProgressBar pb_scheduleConfirmation;
private EditText et_email;
private TextView tv_email_warning, tv_email;
private Button bt_schedule, bt_back;
private static final 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);
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();
......@@ -146,6 +170,13 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
navigationView.setNavigationItemSelectedListener(this);
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));
pb_scheduleConfirmation = (ProgressBar) findViewById(R.id.pb_schedule_confirmation);
TextView tv_citizen = (TextView) findViewById(R.id.tv_schedule_citizen_content);
......@@ -154,7 +185,9 @@ 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);
final EditText et_scheduleNote = (EditText) findViewById(R.id.et_schedule_note);
tv_sector.setText(sectorName);
tv_citizen.setText(citizen.getName());
......@@ -172,9 +205,73 @@ 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){
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);
}
}
});
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) {
//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) {
//Radio Button already toggled from user click.
radioButtonNotificationSelected(R.id.rb_notify_email_no, false);
}
});
......@@ -184,6 +281,21 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
onBackPressed();
}
});
if(savedInstanceState == null){
scheduleConfirmationPresenter = new ScheduleConfirmationPresenter(this);
}else{
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
......@@ -202,6 +314,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,13 +392,39 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
}
}
public void onSuccess(){
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);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle bundle = new Bundle();
bundle.putInt(HomeActivity.SHOW_SCHEDULE_SNACKBAR, 1);
intent.putExtra(HomeActivity.SHOW_SCHEDULE_SNACKBAR,bundle);
startActivity(intent);
finish();
}
@Override
......@@ -298,7 +437,6 @@ public class ScheduleConfirmationActivity extends AppCompatActivity implements S
bt_schedule.setEnabled(true);
bt_back.setEnabled(true);
}
}
@Override
......@@ -314,6 +452,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
......
......@@ -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,12 +49,22 @@ 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;
private ScheduleInfoPresenter presenter;
private ConnectionErrorDialog connectionErrorDialog;
private Button bt_back;
private ProgressBar pb_scheduleInfo;
private boolean hasToRequest;
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -114,29 +130,47 @@ 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);
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);
if(bundle != null){
DateFormat df = new SimpleDateFormat("dd/MM/yyyy - HH:mm", Locale.getDefault());
CheckSchedules.Schedule schedule = 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);
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();