Commit efa42aca authored by Lucas Braz Cunha's avatar Lucas Braz Cunha

Merge branch 'email_first_login' into 'develop'

AGILE#295: First login on mobile checks for existence of user's e-mail

See merge request !19
parents ce7aa72c 14a31d8d
......@@ -15,8 +15,7 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="false"
......@@ -48,7 +47,6 @@
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
</intent-filter>
</service>
<service
android:name=".services.notification.NotificationReadService"
android:exported="false"
......@@ -57,7 +55,6 @@
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
</intent-filter>
</service>
<service
android:name=".services.notification.NotificationsListService"
android:exported="false"
......@@ -67,18 +64,15 @@
</intent-filter>
</service>
<receiver android:name=".services.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".services.notification.NotificationReceiver">
</receiver>
<receiver android:name=".services.notification.NotificationReceiver"></receiver>
<activity android:name=".TermActivity" />
<activity android:name=".SchedulingActivity"/>
<activity android:name=".SchedulingActivity" />
<activity android:name=".CitizenListActivity" />
<activity android:name=".SchedulesActivity" />
<activity android:name=".ScheduleConfirmationActivity" />
......@@ -88,10 +82,7 @@
<activity android:name=".RetrievalSuccessActivity" />
<activity android:name=".SchedulesHistoryActivity" />
<activity android:name=".ScheduleInfoActivity" />
<activity android:name=".EmailActivity"></activity>
</application>
</manifest>
\ No newline at end of file
package br.ufpr.c3sl.agendador.agendador;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
import br.ufpr.c3sl.agendador.agendador.helpers.ConnectionErrorDialog;
import br.ufpr.c3sl.agendador.agendador.helpers.DateValidator;
import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
import br.ufpr.c3sl.agendador.agendador.models.AccountUpdate;
import br.ufpr.c3sl.agendador.agendador.models.UserData;
import br.ufpr.c3sl.agendador.agendador.models.UserOutput;
import br.ufpr.c3sl.agendador.agendador.presenters.EmailActPresenter;
import br.ufpr.c3sl.agendador.agendador.presenters.PresenterManager;
import br.ufpr.c3sl.agendador.agendador.views.EmailActView;
public class EmailActivity extends AppCompatActivity implements EmailActView {
private EditText et_email;
private TextView tv_emailAlert;
private EmailActPresenter presenter;
private ProgressBar pb_emailAct;
private ConnectionErrorDialog dg_connection_error;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
presenter = new EmailActPresenter(this);
} else {
presenter = PresenterManager.getInstance().restorePresenter(savedInstanceState);
if (presenter == null)
presenter = new EmailActPresenter(this);
}
setContentView(R.layout.activity_email);
et_email = (EditText) findViewById(R.id.et_emailact_email);
tv_emailAlert = (TextView) findViewById(R.id.tv_emailact_invalid_email);
ImageView bt_confirm = (ImageView) findViewById(R.id.btn_emailact_send);
bt_confirm.setClickable(true);
bt_confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (DateValidator.isValidEmail(et_email.getText().toString())) {
tv_emailAlert.setVisibility(View.INVISIBLE);
UserData usrData = new UserData(et_email.getText().toString());
AccountUpdate update = new AccountUpdate(usrData, null, null, null);
presenter.updateEmail(update);
} else {
tv_emailAlert.setVisibility(View.VISIBLE);
et_email.setError(getString(R.string.invalid_email));
}
}
});
pb_emailAct = (ProgressBar) findViewById(R.id.pb_emailact);
}
@Override
protected void onResume() {
super.onResume();
presenter.bindView(this);
}
@Override
protected void onStop() {
super.onStop();
presenter.unbindView();
}
@Override
public void onSaveInstanceState(Bundle outState) {
PresenterManager.getInstance().savePresenter(presenter, outState);
super.onSaveInstanceState(outState);
}
public void onSuccessfulUpdate() {
Intent data = new Intent();
data.putExtra(Utils.EMAIL, et_email.getText().toString());
setResult(RESULT_OK, data);
finish();
}
public void onRequestFail() {
if (dg_connection_error == null) {
dg_connection_error = new ConnectionErrorDialog();
}
Bundle bundle = new Bundle();
bundle.putString(ConnectionErrorDialog.DIALOG_MESSAGE, getString(R.string.dialog_connection_error_message));
dg_connection_error.setArguments(bundle);
dg_connection_error.show(getFragmentManager(), ConnectionErrorDialog.DIALOG_CONNECTION_ERROR);
}
public void onServerError() {
if (dg_connection_error == null) {
dg_connection_error = new ConnectionErrorDialog();
}
Bundle bundle = new Bundle();
bundle.putString(ConnectionErrorDialog.DIALOG_MESSAGE, getString(R.string.dialog_no_connection_message));
dg_connection_error.setArguments(bundle);
dg_connection_error.show(getFragmentManager(), ConnectionErrorDialog.DIALOG_CONNECTION_ERROR);
}
@Override
public void showProgressBar(boolean show) {
if (show) {
pb_emailAct.setVisibility(View.VISIBLE);
} else {
pb_emailAct.setVisibility(View.INVISIBLE);
}
}
}
......@@ -181,12 +181,6 @@ public class HomeActivity extends AppCompatActivity implements HomeView,
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)
......
......@@ -55,6 +55,8 @@ public class LoginActivity extends AppCompatActivity implements LoginView {
private ConnectionErrorDialog dg_connection_error;
private static final int REQUEST_EMAIL_CODE = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
......@@ -214,16 +216,43 @@ public class LoginActivity extends AppCompatActivity implements LoginView {
}
@Override
public void afterSuccessfulLogin() {
public void afterSuccessfulLogin(boolean needEmail) {
Intent intent;
if(needEmail){
intent = new Intent(LoginActivity.this, EmailActivity.class);
startActivityForResult(intent, REQUEST_EMAIL_CODE);
}else{
presenter.createServiceLocalNotificationsList();
intent = new Intent(LoginActivity.this, HomeActivity.class);
startActivity(intent);
finish();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Intent intent;
if(requestCode == REQUEST_EMAIL_CODE){
if(resultCode == RESULT_OK && data.getStringExtra(Utils.EMAIL) != null){
presenter.updateEmail(data.getStringExtra(Utils.EMAIL));
presenter.createServiceLocalNotificationsList();
intent = new Intent(LoginActivity.this, HomeActivity.class);
startActivity(intent);
finish();
}else if(resultCode == RESULT_CANCELED) {
Toast.makeText(this, getString(R.string.loginact_email_error), Toast.LENGTH_LONG).show();
presenter.cancelLogin();
et_cpf.requestFocus();
et_cpf.setText("");
et_password.setText("");
}
}
presenter.createServiceLocalNotificationsList();
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
startActivity(intent);
finish();
}
@Override
public void afterSuccessfulPhoto(Bitmap bitmap, long id){
public void afterSuccessfulPhoto(Bitmap bitmap, long id, boolean needEmail){
// TODO: 17/04/17 user messages & error warning
UserImgHelper userImgHelper = new UserImgHelper(getBaseContext());
......@@ -233,7 +262,7 @@ public class LoginActivity extends AppCompatActivity implements LoginView {
Toast.makeText(this, "Ocorreu um problema ao atualizar sua foto de perfil", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
afterSuccessfulLogin();
afterSuccessfulLogin(needEmail);
}
private class LoginChangeListener implements TextWatcher {
......
......@@ -156,6 +156,8 @@ public abstract class Utils {
return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
}
*/
// Converting File to Base64.encode String type using Method
public static String getBase64FromFile(String absolutePath) {
InputStream inputStream = null;
......
......@@ -48,6 +48,10 @@ public class UserData {
@SerializedName("image")
private Image mImage;
public UserData(String email){
this.mEmail = email;
}
public UserData(Map<String, String> values) {
this.mAddress_Number = values.get(Utils.ADDRESS_NUMBER);
this.mRg = values.get(Utils.RG);
......
......@@ -317,4 +317,7 @@ public class UserOutput implements Parcelable {
public String getmCep() {
return mCep;
}
}
package br.ufpr.c3sl.agendador.agendador.presenters;
import android.content.Context;
import android.util.Log;
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.AccountOutput;
import br.ufpr.c3sl.agendador.agendador.models.AccountUpdate;
import br.ufpr.c3sl.agendador.agendador.network.ApiEndpoints;
import br.ufpr.c3sl.agendador.agendador.network.ApiUtils;
import br.ufpr.c3sl.agendador.agendador.views.EmailActView;
import okhttp3.Headers;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Created by Lucas Braz Cunha on 29/01/18.
*/
public class EmailActPresenter extends BasePresenter<EmailActView>{
private EmailActPresenter presenter;
@Override
protected void updateView() {
}
public EmailActPresenter(Context context) {
this.context = context;
this.presenter = this;
this.osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
}
public void updateEmail(AccountUpdate accountUpdate){
presenter.view().showProgressBar(true);
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));
ApiEndpoints service = ApiUtils.request(header);
Call<AccountOutput> listCall = service.update(accountUpdate);
listCall.enqueue(new Callback<AccountOutput>() {
@Override
public void onResponse(Call<AccountOutput> call, Response<AccountOutput> response) {
Headers headers = response.headers();
int status = response.code();
presenter.updateHeaders(headers);
presenter.view().showProgressBar(false);
switch (status) {
case 200:
Log.v("Server response", this.getClass().getName() + ": 200 - Sucesso!");
presenter.view().onSuccessfulUpdate();
break;
default:
Log.e("Server response", this.getClass().getName() + ": " + status + " - Falha!");
presenter.view().onServerError();
break;
}
}
@Override
public void onFailure(Call<AccountOutput> call, Throwable t) {
Log.e("Server response", this.getClass().getName() + ": Sem conexão!");
presenter.view().showProgressBar(false);
presenter.view().onRequestFail();
}
});
}
}
......@@ -104,8 +104,16 @@ public class LoginPresenter extends BasePresenter<LoginView> {
break;
case 200:
Log.d("Login Request", "Voltou 200!!!");
boolean needEmail = false;
if(accountOutput.getCitizen().getmEmail() == null){
//cadastrar e-mail para o usuário.
needEmail = true;
}else if(accountOutput.getCitizen().getmEmail().equals("")) {
//cadastrar e-mail para o usuário.
needEmail = true;
}
onSuccessfulLogin(accountOutput, headers);
checkLocalPhoto();
checkLocalPhoto(needEmail);
break;
default:
Log.d("Login Request", "Voltou " + status + "!!!");
......@@ -125,7 +133,7 @@ public class LoginPresenter extends BasePresenter<LoginView> {
}
private void requestImage() {
private void requestImage(final boolean needEmail) {
Map<String, String> header = new HashMap<>();
final String uid = osb.getString(Utils.UID, null);
header.put(Utils.ACCESS_TOKEN, osb.getString(Utils.ACCESS_TOKEN, null));
......@@ -142,26 +150,27 @@ public class LoginPresenter extends BasePresenter<LoginView> {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
int status = response.code();
Log.d("Server response", this.getClass().getName() + ": Retorno da request de imagem: " + status);
Log.d("Server response", this.getClass().getName() + ": Retorno da request de imagem: " + status);
switch (status) {
case 500:
loginPresenter.view().setProgressBar(false);
loginPresenter.view().afterSuccessfulLogin();
loginPresenter.view().afterSuccessfulLogin(needEmail);
break;
case 200:
loginPresenter.view().afterSuccessfulPhoto(BitmapFactory.decodeStream(response.body().byteStream()), osb.getLong(Utils.ID, 0));
loginPresenter.view().afterSuccessfulPhoto(BitmapFactory.decodeStream(response.body().byteStream()), osb.getLong(Utils.ID, 0), needEmail);
loginPresenter.view().setProgressBar(false);
break;
case 404:
//user has no picture on back-end side
loginPresenter.view().setProgressBar(false);
loginPresenter.view().afterSuccessfulLogin();
loginPresenter.view().afterSuccessfulLogin(needEmail);
break;
default:
break;
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Bundle extras = new Bundle();
......@@ -169,7 +178,7 @@ public class LoginPresenter extends BasePresenter<LoginView> {
extras.putString(Utils.JOB_FILE_NAME, Utils.USR_PICT_FILE_NAME);
Job job = dispatcher.newJobBuilder()
Job job = dispatcher.newJobBuilder()
.setService(ImageUpdateService.class)
.setTag(Utils.SERVICE_UPDATE_IMAGE)
//time the function gets is in seconds, 60s = 1 minutes, 1 hour = 3600
......@@ -182,13 +191,13 @@ public class LoginPresenter extends BasePresenter<LoginView> {
Constraint.ON_ANY_NETWORK
)
.setExtras(extras)
//if device is rebooted the job will be restarted
//if device is rebooted the job will be restarted
.setLifetime(Lifetime.FOREVER)
.build();
dispatcher.mustSchedule(job);
dispatcher.mustSchedule(job);
loginPresenter.view().setProgressBar(false);
loginPresenter.view().afterSuccessfulLogin();
loginPresenter.view().afterSuccessfulLogin(needEmail);
}
});
......@@ -196,8 +205,7 @@ public class LoginPresenter extends BasePresenter<LoginView> {
}
public void createServiceLocalNotificationsList(){
public void createServiceLocalNotificationsList() {
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(
new GooglePlayDriver(context)
......@@ -224,7 +232,7 @@ public class LoginPresenter extends BasePresenter<LoginView> {
}
// TODO: 03/05/17 Adapt function to scenario with different file extensions, if needed.
private void checkLocalPhoto(){
private void checkLocalPhoto(boolean needEmail) {
final String uid = osb.getString(Utils.UID, null);
String compare, children[];
......@@ -248,7 +256,7 @@ public class LoginPresenter extends BasePresenter<LoginView> {
File dir = new File(context.getExternalFilesDir(null) + File.separator + Utils.DIR_PICTRS + File.separator);
FilenameFilter filter = new FilenameFilter() {
public boolean accept (File dir, String name) {
public boolean accept(File dir, String name) {
return name.startsWith(Utils.USR_PICT_FILE_NAME + uid);
}
};
......@@ -256,25 +264,32 @@ public class LoginPresenter extends BasePresenter<LoginView> {
children = dir.list(filter);
if (children == null || children.length == 0) {
Log.d("Error", "(Either dir does not exist or is not a directory) or ( File not Found).");
requestImage();
}else{
for (String name: children) {
requestImage(needEmail);
} else {
for (String name : children) {
compare = name.substring(0, name.indexOf("."));
if(compare.equals(Utils.USR_PICT_FILE_NAME + uid) ) {
if (compare.equals(Utils.USR_PICT_FILE_NAME + uid)) {
File f = new File(dir, name);
fileDate = new Date(f.lastModified());
}
}
if(fileDate != null && serverDate.after(fileDate)){
requestImage();
}
else{
if (fileDate != null && serverDate.after(fileDate)) {
requestImage(needEmail);
} else {
loginPresenter.view().setProgressBar(false);
loginPresenter.view().afterSuccessfulLogin();
loginPresenter.view().afterSuccessfulLogin(needEmail);
}
}
}
public void cancelLogin(){
osb.edit().clear().apply();
}
public void updateEmail(String email){
osb.edit().putString(Utils.EMAIL, email).apply();
}
}
\ No newline at end of file
package br.ufpr.c3sl.agendador.agendador.views;
/**
* Created by Lucas Braz Cunha on 30/01/18.
*/
public interface EmailActView {
void onSuccessfulUpdate();
void onRequestFail();
void onServerError();
void showProgressBar(boolean show);
}
......@@ -15,7 +15,7 @@ public interface LoginView {
void setNoConnection(boolean enabled);
void afterSuccessfulLogin();
void afterSuccessfulLogin(boolean needEmail);
void afterSuccessfulPhoto(Bitmap bitmap, long id);
void afterSuccessfulPhoto(Bitmap bitmap, long id, boolean needEmail);
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorGray">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="120.5dp"
android:layout_height="112.5sp"
android:layout_gravity="center"
android:layout_marginTop="40dp"
android:src="@drawable/img_signupact_logo"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorGreen"
android:textSize="16sp"
android:layout_marginTop="56dp"
android:layout_gravity="center"
android:text="@string/register_email"/>
<TextView
android:layout_width="280dp"
android:layout_height="wrap_content"
android:textColor="@color/colorBlack"
android:textSize="14sp"
android:layout_gravity="center"
android:textAlignment="center"
android:text="@string/register_email_description" />
<TextView
android:text="@string/not_valid_email"
android:layout_width="290dp"
android:layout_height="wrap_content"
android:id="@+id/tv_emailact_invalid_email"
android:layout_gravity="center"
android:textSize="15sp"
android:textColor="@color/colorRed"
android:layout_marginTop="18dp"
android:visibility="invisible"/>
<LinearLayout
android:id="@+id/ll_cepact_cep"
android:layout_width="290dp"
android:layout_height="45dp"
android:layout_gravity="center"
android:orientation="horizontal"
android:layout_marginTop="2dp"
android:background="@drawable/white_container_shape">
<EditText
android:id="@+id/et_emailact_email"
android:layout_width="242dp"
android:textSize="16sp"
android:inputType="textEmailAddress"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/btn_emailact_send"
android:layout_width="48dp"
android:layout_height="match_parent"
android:background="@color/colorGreen"
android:scaleType="center"
android:src="@drawable/ic_send_cep"/>
</LinearLayout>
</LinearLayout>
<ProgressBar
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/pb_emailact"
android:layout_centerHorizontal="true"
android:indeterminate="true"
android:layout_centerVertical="true"
android:visibility="invisible"/>
</RelativeLayout>
\ No newline at end of file
......@@ -226,5 +226,8 @@
<string name="notification_note_text">Observações (Máximo de 140 caracteres):</string>
<string name="notification_alert">Atendimento está próximo</string>
<string name="register_email">Cadastre seu e-mail</string>
<string name="register_email_description">Para utilizar o Agendador no seu celular é necessário cadastrar um e-mail.</string>
<string name="loginact_email_error">Para utilizar o Agendador Mobile é necessário cadastrar um e-mail.</string>
</resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment