Commit 2e819f86 authored by Lucas Braz Cunha's avatar Lucas Braz Cunha
Browse files

Merge branch 'background_service' into 'develop'

Background service

See merge request !10
parents 0fe0899a 075e0b36
......@@ -32,4 +32,6 @@ dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support.test.espresso:espresso-core:2.2.2'
compile 'com.firebase:firebase-jobdispatcher:0.6.0'
}
......@@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission 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"/>
<application
android:allowBackup="true"
......@@ -44,6 +45,19 @@
<activity android:name=".ForgotPasswordActivity">
</activity>
<service android:name=".services.ImageUpdateService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
</intent-filter>
</service>
</application>
</manifest>
\ No newline at end of file
......@@ -25,6 +25,7 @@ import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
......@@ -58,7 +59,7 @@ import br.ufpr.c3sl.agendador.agendador.views.AccountView;
* Created by Horstmann on 02/03/17.
*/
// TODO: 23/05/17 test "connection failure" dialogs
public class AccountActivity extends AppCompatActivity implements AccountView {
......@@ -79,7 +80,13 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
tv_phone_warning, tv_password_confirm_warning, tv_email_warning,
tv_account_new_password_warning;
private boolean editable, isChangingPassword, isChangingPhoto, isPhotoDelete;
private MenuItem btn_edit, btn_sync;
private boolean editable;
private boolean isChangingPassword;
private boolean isChangingPhoto;
private boolean isPhotoDelete;
private boolean isUpdated;
private UserPhotoHelper userPhotoHelper;
......@@ -125,7 +132,7 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
osb = ObscuredSharedPreferences.getPrefs(this, "Agendador", Context.MODE_PRIVATE);
String citizenName = osb.getString("name", null);
String citizenName = osb.getString("name", "");
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_acc);
setSupportActionBar(toolbar);
......@@ -247,19 +254,7 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
public void afterTextChanged(Editable s) {}
});
} else {
if(ConnectionChecker.hasConnection(getBaseContext())) {
presenter.onCepNotFocused(Mask.unmask(et_cep.getText().toString()));
}
else{
Bundle bundle = new Bundle();
bundle.putString(ConnectionErrorDialog.DIALOG_MESSAGE_KEY, getString(R.string.dialog_cep_connection_error));
if(dg_connection_error == null){
dg_connection_error = new ConnectionErrorDialog();
}
dg_connection_error.setArguments(bundle);
dg_connection_error.show(getFragmentManager(), ConnectionErrorDialog.DIALOG_CONNECTION_ERROR);
}
presenter.onCepNotFocused(Mask.unmask(et_cep.getText().toString()));
}
}
});
......@@ -278,16 +273,8 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
}
}
else{
if( dg_connection_error == null){
dg_connection_error = new ConnectionErrorDialog();
}
Bundle bundle = new Bundle();
bundle.putString(ConnectionErrorDialog.DIALOG_MESSAGE_KEY, getString(R.string.dialog_no_connection_message));
dg_connection_error.setArguments(bundle);
dg_connection_error.show(getFragmentManager(), ConnectionErrorDialog.DIALOG_CONNECTION_ERROR);
scrollUp();
setNoConnection(true);
}
}
else{
scrollUp();
......@@ -349,13 +336,14 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
isChangingPassword = false;
isChangingPhoto = false;
isPhotoDelete = false;
isUpdated = false;
}
@Override
protected void onResume() {
super.onResume();
presenter.bindView(this);
}
@Override
......@@ -373,6 +361,9 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.account_menu, menu);
btn_edit = menu.findItem(R.id.btn_edit_account);
btn_sync = menu.findItem(R.id.btn_sync_account);
enableButtonEdit(false);
return true;
}
......@@ -419,15 +410,7 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
switch (item.getItemId()) {
case android.R.id.home:
if (editable) {
enableAllFields(false);
setButtonVisible(false);
clearWarnings();
loadData();
scrollUp();
if(userPhotoHelper.existsPhoto())
userPhotoHelper.updateImgView(imgv_profile, userPhotoHelper.getPhotoFileUri());
else
imgv_profile.setImageBitmap(null);
cancelUpdate();
} else {
Intent intent = new Intent(AccountActivity.this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
......@@ -435,9 +418,19 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
finish();
}
return true;
case R.id.edit_account:
enableAllFields(true);
setButtonVisible(true);
case R.id.btn_edit_account:
if(editable){
cancelUpdate();
}
else{
enableAllFields(true);
setButtonVisible(true);
}
return true;
case R.id.btn_sync_account:
Log.d("AccountActivity", "CLIQUEIIIIIIIIIIIIIIIII");
enableButtonSync(false);
presenter.updateCheck();
return true;
default:
return super.onOptionsItemSelected(item);
......@@ -472,15 +465,31 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
enableAllFields(false);
} else {
pb_account.setVisibility(View.INVISIBLE);
enableAllFields(true);
btn_update.setEnabled(true);
btn_cancel.setEnabled(true);
enableAllFields(true);
}
}
private void enableAllFields(boolean enable) {
editable = enable;
public void enableButtonEdit(boolean enable){
btn_edit.setEnabled(enable);
if(enable)
btn_edit.getIcon().setAlpha(255);
else
btn_edit.getIcon().setAlpha(130);
}
public void enableButtonSync(boolean enable){
btn_sync.setEnabled(enable);
if(enable)
btn_sync.getIcon().setAlpha(255);
else
btn_sync.getIcon().setAlpha(130);
}
public void enableAllFields(boolean enable) {
editable = enable;
et_name.setEnabled(enable);
et_rg.setEnabled(enable);
et_sus_number.setEnabled(enable);
......@@ -509,26 +518,27 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
}
}
public void successfulUpdate() {
try{
//has to be done before load data.
userPhotoHelper.confirmUpdate(isPhotoDelete);
if(isChangingPhoto)
userPhotoHelper.confirmUpdate(isPhotoDelete);
}catch (Exception e){
// TODO: 04/05/17 user messages & error warning
Toast.makeText(this, "Ocorreu um erro ao salvar a imagem, tente novamente.", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
enableAllFields(false);
setButtonVisible(false);
enableButtonEdit(true);
enableAllFields(false);
loadData();
}
public void cancelUpdate(){
private void cancelUpdate(){
scrollUp();
enableAllFields(false);
setButtonVisible(false);
clearWarnings();
loadData();
if(userPhotoHelper.existsPhoto())
userPhotoHelper.updateImgView(imgv_profile, userPhotoHelper.getPhotoFileUri());
......@@ -861,7 +871,7 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
}
@Override
public void setNoConnection(boolean enabled){
public void setConnectionError(boolean enabled){
if(enabled){
if(dg_connection_error == null){
dg_connection_error = new ConnectionErrorDialog();
......@@ -874,8 +884,9 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
}
@Override
public void setNoConnectionCep(boolean enabled){
public void setConnectionCepError(boolean enabled){
if(enabled){
Log.d("Aaaa","aaaaaaaa");
if(dg_connection_error == null){
dg_connection_error = new ConnectionErrorDialog();
}
......@@ -887,6 +898,19 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
}
}
public void setNoConnection(boolean enabled){
if(enabled) {
scrollUp();
if (dg_connection_error == null) {
dg_connection_error = new ConnectionErrorDialog();
}
Bundle bundle = new Bundle();
bundle.putString(ConnectionErrorDialog.DIALOG_MESSAGE_KEY, getString(R.string.dialog_no_connection_message));
dg_connection_error.setArguments(bundle);
dg_connection_error.show(getFragmentManager(), ConnectionErrorDialog.DIALOG_CONNECTION_ERROR);
}
}
private void checkBuildVersion(){
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M )
......@@ -1031,5 +1055,13 @@ public class AccountActivity extends AppCompatActivity implements AccountView {
public void setCurrentPassword(String current_password) {
this.current_password = current_password;
}
public void setUpdated(boolean updated) {
isUpdated = updated;
}
}
package br.ufpr.c3sl.agendador.agendador;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
......@@ -20,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;
......@@ -27,9 +29,14 @@ import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
import com.firebase.jobdispatcher.GooglePlayDriver;
import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
import br.ufpr.c3sl.agendador.agendador.helpers.UserPhotoHelper;
import br.ufpr.c3sl.agendador.agendador.helpers.Utils;
import br.ufpr.c3sl.agendador.agendador.presenters.HomePresenter;
import br.ufpr.c3sl.agendador.agendador.services.ImageUpdateService;
import br.ufpr.c3sl.agendador.agendador.views.HomeView;
/**
......@@ -235,4 +242,5 @@ public class HomeActivity extends AppCompatActivity implements HomeView,
}
}
}
......@@ -42,6 +42,8 @@ public class UserPhotoHelper {
//Constructor for LoginActivity use
// TODO: 08/05/17 check usage of getExternalFilesDirs
//https://developer.android.com/guide/topics/data/data-storage.html
public UserPhotoHelper(Context context, String uid){
this.mContext = context;
this.filePath = mContext.getExternalFilesDir(null) + File.separator + Utils.DIR_PICTRS + File.separator + Utils.USR_PICT_FILE_NAME;
......@@ -51,6 +53,10 @@ public class UserPhotoHelper {
//Function to save bitmap received from server on login
public void saveBitmap(Bitmap bmp) throws IOException {
File f2 = new File(mContext.getExternalFilesDir(null) + File.separator + Utils.DIR_PICTRS + File.separator);
f2.mkdirs();
File f = new File(photoFileUri.getPath());
f.createNewFile();
FileOutputStream out = new FileOutputStream(photoFileUri.getPath());
bmp.compress(Bitmap.CompressFormat.PNG, 100, out); //100-best quality
out.close();
......@@ -62,10 +68,10 @@ public class UserPhotoHelper {
this.mContext = context;
osb = ObscuredSharedPreferences.getPrefs(mContext, "Agendador", Context.MODE_PRIVATE);
this.filePath = mContext.getExternalFilesDir(null) + File.separator + Utils.DIR_PICTRS + File.separator + Utils.USR_PICT_FILE_NAME;
createFile();
initVariables();
}
private void createFile() {
private void initVariables() {
this.userUid = osb.getString("uid", null);
this.photo = new File(filePath + userUid + ".bmp");
this.tempPhoto = new File(filePath + "temp_" + userUid);
......
......@@ -24,6 +24,8 @@ public class Utils {
public final static String DIR_PICTRS = "pictures";
public final static String USR_PICT_FILE_NAME = "usr_prof_pic_";
public final static String SERVICE_UPDATE_IMAGE = "br.c3sl.ufpr.image_update";
public static int getPixelValue(int dp, Context context) {
Resources resources = context.getResources();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
......
package br.ufpr.c3sl.agendador.agendador.models;
import android.content.Context;
import com.google.gson.annotations.SerializedName;
import java.util.Map;
import br.ufpr.c3sl.agendador.agendador.helpers.ObscuredSharedPreferences;
/**
* Created by Bruno Freitas Tissei on 2/3/17.
*/
......
......@@ -39,4 +39,7 @@ public interface ApiEndpoints {
@GET("citizens/{id}/picture")
Call<ResponseBody> requestPhoto(@Path("id") int id, @Query("size") String size);
@GET("accounts/self")
Call<AccountOutput> requestSelf();
}
\ No newline at end of file
......@@ -2,7 +2,10 @@ package br.ufpr.c3sl.agendador.agendador.presenters;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
import com.firebase.jobdispatcher.GooglePlayDriver;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
......@@ -11,6 +14,7 @@ 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.models.Address;
......@@ -24,8 +28,6 @@ import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import static android.util.Log.d;
/**
* Created by Horstmann on 02/03/17.
*/
......@@ -35,20 +37,90 @@ public class AccountPresenter extends BasePresenter<AccountView> {
private ObscuredSharedPreferences osb;
private Context context;
private AccountPresenter accountPresenter;
private boolean isPicUpdate;
public AccountPresenter(Context context) {
this.context = context;
accountPresenter = this;
isPicUpdate = false;
osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
}
private void onSuccessfulCheck(AccountOutput accountOutput, Headers headers){
osb.edit().putString("access-token", headers.get("access-token")).apply();
osb.edit().putString("expiry", headers.get("expiry")).apply();
accountOutput.getCitizen().save(context);
}
public void updateCheck(){
accountPresenter.view().setProgressBar(true);
Map<String, String> header = new HashMap<>();
header.put("Content-Type", "application/json");
header.put("access-token", osb.getString("access-token", null));
header.put("client", osb.getString("client", null));
header.put("uid", osb.getString("uid", null));
ApiEndpoints service = ApiUtils.request(header);
Call<AccountOutput> listCall = service.requestSelf();
listCall.enqueue(new Callback<AccountOutput>() {
@Override
public void onResponse(Call<AccountOutput> call, Response<AccountOutput> response) {
Headers headers = response.headers();
int status = response.code();
AccountOutput accountOutput = response.body();
Log.d("SELF Request", "Got " + status + " from server on self request!!!");
switch (status) {
case 200:
//info downloaded
accountPresenter.view().setUpdated(true);
onSuccessfulCheck(accountOutput, headers);
accountPresenter.view().setProgressBar(false);
accountPresenter.view().successfulUpdate();
accountPresenter.view().enableButtonEdit(true);
accountPresenter.view().enableButtonSync(true);
break;
default:
accountPresenter.view().setUpdated(false);
accountPresenter.view().setProgressBar(false);
accountPresenter.view().enableAllFields(false);
accountPresenter.view().enableButtonEdit(false);
accountPresenter.view().enableButtonSync(true);
accountPresenter.view().setConnectionError(true);
break;
}
}
@Override
public void onFailure(Call<AccountOutput> call, Throwable t) {
accountPresenter.view().setUpdated(false);
accountPresenter.view().setProgressBar(false);
accountPresenter.view().enableAllFields(false);
accountPresenter.view().enableButtonEdit(false);
accountPresenter.view().enableButtonSync(true);
accountPresenter.view().setNoConnection(true);
}
});
}
private void onSuccessfulUpdate(AccountOutput accountOutput, Headers headers) {
updateToken(headers);
accountOutput.getCitizen().save(context);
//cancelling job because photo has been updated from app.
if(isPicUpdate){
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
dispatcher.cancel(Utils.SERVICE_UPDATE_IMAGE);
isPicUpdate = false;
}
}
private void updateToken(Headers headers) {
osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
osb.edit().putString("access-token", headers.get("access-token")).apply();
osb.edit().putString("client", headers.get("client")).apply();
osb.edit().putString("uid", headers.get("uid")).apply();
......@@ -58,8 +130,9 @@ public class AccountPresenter extends BasePresenter<AccountView> {
protected void updateView() {
}
public void onUpdateClicked(){
osb = ObscuredSharedPreferences.getPrefs(context, "Agendador", Context.MODE_PRIVATE);
Map<String, String> header = new HashMap<>();
header.put("Content-Type", "application/json");
......@@ -73,9 +146,10 @@ public class AccountPresenter extends BasePresenter<AccountView> {
UserUpdate user = new UserUpdate(body);
final AccountUpdate account;
if(body.get("photo_type") != null)
if(body.get("photo_type") != null) {
user.setImage(body.get("photo_type"), body.get("photo_name"), body.get("photo_content"));
isPicUpdate = true;
}
if (body.get("password") == null || body.get("password_confirmation") == null){
account = new AccountUpdate(user);
} else{
......@@ -97,6 +171,7 @@ public class AccountPresenter extends BasePresenter<AccountView> {
case 404:
Log.d("Server response", "404 - Falha!");
accountPresenter.view().setProgressBar(false);
accountPresenter.view().setConnectionError(true);
break;
case 422:
Log.d("Server response", "422 - Erro na requisição!");
......@@ -117,7 +192,6 @@ public class AccountPresenter extends BasePresenter<AccountView> {
@Override
public void onFailure(Call<AccountOutput> call, Throwable t) {
Log.d("Server response", "Requisição falhou!!");
accountPresenter.view().setProgressBar(false);
accountPresenter.view().setNoConnection(true);
......@@ -125,8 +199,6 @@ public class AccountPresenter extends BasePresenter<AccountView> {
});
}
public void onCepNotFocused(String cep) {
Map<String, String> header = new HashMap<>();
header.put("Content-Type", "application/json");
......@@ -150,7 +222,6 @@ public class AccountPresenter extends BasePresenter<AccountView> {
values.put("cityname_su", address.getCity_name());
values.put("statename_su", address.getState_name());
accountPresenter.view().setProgressBar(false);
break;
case 404:
......@@ -190,7 +261,8 @@ public class AccountPresenter extends BasePresenter<AccountView> {
@Override
public void onFailure(Call<Address> call, Throwable t) {
accountPresenter.view().setProgressBar(false);
accountPresenter.view().setNoConnectionCep(true);
accountPresenter.view().setConnectionCepError(true);
Log.d("Aaaa","aaaaaaaa2222222");