Compare commits

..

39 Commits

Author SHA1 Message Date
faed9e05b7 Merge branch 'develop' of s416084/find-my-tutor-android into master 2019-01-13 15:09:06 +00:00
1095386659 Merge branch 'fix-battery-prompt-5.1' of s416084/find-my-tutor-android into develop 2019-01-13 15:08:19 +00:00
b7e1e4a984 Fix 5.1 2019-01-13 16:06:58 +01:00
4473834218 Merge branch 'develop' of s416084/find-my-tutor-android into master 2019-01-13 13:39:56 +00:00
5a96d93d37 Merge branch 'fix-info-battery-prompt' of s416084/find-my-tutor-android into develop 2019-01-13 13:38:16 +00:00
33cfa90a28 Update gradle 2019-01-13 14:37:15 +01:00
6fa458d198 show prompt only for tutors 2019-01-13 14:36:51 +01:00
2ca95e0ba0 Merge branch 'develop' of s416084/find-my-tutor-android into master 2019-01-13 13:14:13 +00:00
eb30100183 Merge branch 'presence-wifi-approach' of s416084/find-my-tutor-android into develop 2019-01-13 13:11:38 +00:00
e1c266263a Fix low battery mode 2019-01-13 14:10:50 +01:00
d88525a764 Add presence which works with Wifi 2019-01-13 13:44:10 +01:00
430914bab1 Merge branch 'fix-acra' of s416084/find-my-tutor-android into develop 2019-01-13 10:34:55 +00:00
786a73c963 Fix acra 2019-01-13 11:31:36 +01:00
1f2867cb43 Merge branch 'develop' into fix-acra 2019-01-13 02:09:31 +01:00
5770217c45 Merge branch 'fix-battery-prompt' of s416084/find-my-tutor-android into develop 2019-01-12 20:16:40 +00:00
17b7f4c9a2 fix 2019-01-12 21:15:37 +01:00
f46d9cc60e Merge branch 'add-beta-student-security' of s416084/find-my-tutor-android into develop 2019-01-12 19:23:39 +00:00
325f8a99a2 master version 2019-01-12 20:23:03 +01:00
0ec0e95798 Add logout security 2019-01-12 20:22:30 +01:00
085dc1e4d6 Merge branch 'fix-login-form' of s416084/find-my-tutor-android into develop 2019-01-12 18:37:55 +00:00
9f78eaf688 Fix login form 2019-01-12 19:37:25 +01:00
b528ec68bb Merge branch 'batteryExclusion' of s416084/find-my-tutor-android into develop 2019-01-12 18:27:16 +00:00
7b79a5339a merge develop 2019-01-12 19:26:49 +01:00
6e98eeff16 Merge branch 'fix-last-seen' of s416084/find-my-tutor-android into develop 2019-01-12 18:24:01 +00:00
5fccb72843 fix statuses 2019-01-12 19:15:40 +01:00
377ee3bcbc Change to one get 2019-01-12 18:46:52 +01:00
282f74f5e0 Remove shadow from buttons 2019-01-12 16:42:51 +01:00
b126cbfe31 Fix tutors list 2019-01-12 16:38:28 +01:00
fae7a5f0fe pop up with battery exc + transaltions 2019-01-12 14:56:54 +01:00
e64f5d380c Commit to check out on production 2019-01-11 00:34:27 +01:00
2f25f06d18 On Attach fix 2019-01-11 00:34:04 +01:00
a27c18b468 Merge branch 'fix-acra' of s416084/find-my-tutor-android into develop 2019-01-10 23:26:18 +00:00
311cd7868b Fix acra 2019-01-11 00:25:43 +01:00
be58fba3ad Merge branch 'fix-back-button' of s416084/find-my-tutor-android into develop 2019-01-10 23:00:32 +00:00
2f93dc5d54 Update gradle 2019-01-10 23:59:35 +01:00
c8cdc3aac0 fix return button 2019-01-10 23:58:33 +01:00
f872b08acc Merge branch 'users-list-last-seen' of s416084/find-my-tutor-android into develop 2019-01-10 22:41:47 +00:00
a4c0881300 Merge branch 'develop' of s416084/find-my-tutor-android into master 2019-01-06 18:03:06 +00:00
7e043c9826 Merge branch 'develop' of s416084/find-my-tutor-android into master 2019-01-06 11:02:30 +00:00
25 changed files with 467 additions and 203 deletions

View File

@ -10,7 +10,7 @@ android {
applicationId "com.uam.wmi.findmytutor" applicationId "com.uam.wmi.findmytutor"
minSdkVersion 22 minSdkVersion 22
targetSdkVersion 27 targetSdkVersion 27
versionCode 56 versionCode 66
versionName "1.0.0" versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@ -75,6 +75,6 @@ dependencies {
// spinner loaders library // spinner loaders library
implementation 'com.github.ybq:Android-SpinKit:1.2.0' implementation 'com.github.ybq:Android-SpinKit:1.2.0'
implementation 'com.akexorcist:localizationactivity:1.2.2' // rx binding
implementation 'com.jakewharton.rxbinding:rxbinding:0.3.0'
} }

View File

@ -6,8 +6,9 @@ import android.content.SharedPreferences;
import android.content.res.Configuration; import android.content.res.Configuration;
import com.uam.wmi.findmytutor.utils.Const; import com.uam.wmi.findmytutor.utils.Const;
import com.uam.wmi.findmytutor.utils.MapUtils;
import com.uam.wmi.findmytutor.utils.PrefUtils;
import static org.acra.ReportField.*;
import org.acra.ACRA; import org.acra.ACRA;
import org.acra.annotation.AcraLimiter; import org.acra.annotation.AcraLimiter;
import org.acra.annotation.AcraNotification; import org.acra.annotation.AcraNotification;
@ -16,18 +17,32 @@ import org.acra.config.HttpSenderConfigurationBuilder;
import org.acra.config.ToastConfigurationBuilder; import org.acra.config.ToastConfigurationBuilder;
import org.acra.data.StringFormat; import org.acra.data.StringFormat;
import org.acra.sender.HttpSender; import org.acra.sender.HttpSender;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.acra.ReportField.ANDROID_VERSION;
import static org.acra.ReportField.BUILD_CONFIG;
import static org.acra.ReportField.CUSTOM_DATA;
import static org.acra.ReportField.LOGCAT;
import static org.acra.ReportField.PHONE_MODEL;
import static org.acra.ReportField.REPORT_ID;
import static org.acra.ReportField.SHARED_PREFERENCES;
import static org.acra.ReportField.STACK_TRACE;
import static org.acra.ReportField.USER_APP_START_DATE;
import static org.acra.ReportField.USER_CRASH_DATE;
@AcraNotification(resText = R.string.notification_text, @AcraNotification(resText = R.string.notification_text,
resTitle = R.string.notification_title, resTitle = R.string.notification_title,
resChannelName = R.string.notification_channel) resChannelName = R.string.notification_channel)
@AcraLimiter(failedReportLimit = 2) @AcraLimiter(failedReportLimit = 2)
public class FindMyTutor extends Application { public class FindMyTutor extends Application {
@Override @Override
protected void attachBaseContext(Context base) { protected void attachBaseContext(Context base) {
super.attachBaseContext(base); super.attachBaseContext(base);
//super.attachBaseContext(LocaleHelper.onAttach(base));
// ACRA core // ACRA core
CoreConfigurationBuilder builder = new CoreConfigurationBuilder(this) CoreConfigurationBuilder builder = new CoreConfigurationBuilder(this)
@ -43,16 +58,17 @@ public class FindMyTutor extends Application {
ToastConfigurationBuilder.class ToastConfigurationBuilder.class
).setResText(R.string.acra_toast_text); ).setResText(R.string.acra_toast_text);
SharedPreferences sharedPreferences = base.getSharedPreferences("com.uam.wmi.findmytutor_preferences", Context.MODE_PRIVATE); SharedPreferences sharedPreferences = base.getSharedPreferences("com.uam.wmi.findmytutor_preferences", Context.MODE_PRIVATE);
Map header = new HashMap(); Map header = new HashMap();
String token = sharedPreferences.getString("API_KEY", "KEY_EMPTY"); String token = sharedPreferences.getString("API_KEY", "KEY_EMPTY");
header.put("Authorization","Bearer " + token); header.put("Authorization", "Bearer " + token);
// Api POST // Api POST
builder.getPluginConfigurationBuilder( builder.getPluginConfigurationBuilder(
HttpSenderConfigurationBuilder.class HttpSenderConfigurationBuilder.class
// ).setUri("http://192.168.0.15:3000/api/acra") // ).setUri("http://192.168.0.15:3000/api/acra")
).setUri(Const.BASE_URL +"api/Feedback/autoFeedback") ).setUri(Const.BASE_URL + "api/Feedback/autoFeedback")
.setHttpMethod(HttpSender.Method.POST) .setHttpMethod(HttpSender.Method.POST)
.setHttpHeaders(header) .setHttpHeaders(header)
.setEnabled(true); .setEnabled(true);

View File

@ -24,11 +24,6 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate; private AppCompatDelegate mDelegate;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
getDelegate().installViewFactory(); getDelegate().installViewFactory();

View File

@ -38,6 +38,7 @@ import com.uam.wmi.findmytutor.utils.ActiveFragment;
import com.uam.wmi.findmytutor.utils.FeedbackUtils; import com.uam.wmi.findmytutor.utils.FeedbackUtils;
import com.uam.wmi.findmytutor.utils.LocaleHelper; import com.uam.wmi.findmytutor.utils.LocaleHelper;
import com.uam.wmi.findmytutor.utils.LocaleUtils; import com.uam.wmi.findmytutor.utils.LocaleUtils;
import com.uam.wmi.findmytutor.utils.MapUtils;
import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.RxSearchObservable; import com.uam.wmi.findmytutor.utils.RxSearchObservable;
@ -126,17 +127,9 @@ public abstract class BaseActivity
if(PrefUtils.isBackgroundLocationServiceRunning(getApplicationContext())) { if(PrefUtils.isBackgroundLocationServiceRunning(getApplicationContext())) {
stopBackgroundLocalizationTask(); stopBackgroundLocalizationTask();
} }
logout();
storeBackgroundLocationStatus(getApplication(), false);
PrefUtils.storeIsLoggedIn(getApplicationContext(), false);
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(getBaseContext().getPackageName());
if (i != null) {
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
startActivity(i);
finish();
} else if (itemName.equals(getResources().getString(R.string.navigation_item_feedback))) { } else if (itemName.equals(getResources().getString(R.string.navigation_item_feedback))) {
feedbackUtils.showNoteDialog("FEEDBACK"); feedbackUtils.showNoteDialog("FEEDBACK");
@ -165,6 +158,21 @@ public abstract class BaseActivity
} }
} }
protected void logout(){
storeBackgroundLocationStatus(getApplication(), false);
PrefUtils.storeIsLoggedIn(getApplicationContext(), false);
PrefUtils.setBatteryExlusionInfoStatus(getApplicationContext(), true);
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(getBaseContext().getPackageName());
if (i != null) {
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
startActivity(i);
finish();
}
protected void checkPermissions() { protected void checkPermissions() {
final List<String> missingPermissions = new ArrayList<String>(); final List<String> missingPermissions = new ArrayList<String>();
@ -419,6 +427,7 @@ public abstract class BaseActivity
sharingFragment = SharingFragment.newInstance(); sharingFragment = SharingFragment.newInstance();
FragmentTransaction ft = getFragmentManager().beginTransaction(); FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.activity_content, sharingFragment); ft.replace(R.id.activity_content, sharingFragment);
//ft.addToBackStack(null);
ft.commit(); ft.commit();
} }
@ -428,6 +437,7 @@ public abstract class BaseActivity
userListFragment = UsersListFragment.newInstance(); userListFragment = UsersListFragment.newInstance();
FragmentTransaction ft = getFragmentManager().beginTransaction(); FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.activity_content, userListFragment); ft.replace(R.id.activity_content, userListFragment);
//ft.addToBackStack(null);
ft.commit(); ft.commit();
} }

View File

@ -68,6 +68,7 @@ import io.reactivex.Observable;
import io.reactivex.ObservableSource; import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function; import io.reactivex.functions.Function;
import io.reactivex.observers.DisposableObserver; import io.reactivex.observers.DisposableObserver;
import io.reactivex.observers.DisposableSingleObserver; import io.reactivex.observers.DisposableSingleObserver;
@ -153,7 +154,6 @@ public class BlackList extends AppCompatActivity {
})); }));
addToBlackListFab.setOnClickListener(this::showFabDialog); addToBlackListFab.setOnClickListener(this::showFabDialog);
handleSwitch(); handleSwitch();
} }
@ -173,34 +173,29 @@ public class BlackList extends AppCompatActivity {
} }
private void fetchBlackListedUsers() { private void fetchBlackListedUsers() {
prevSize = blacklistedUsers.size();
blacklistedUsers.clear();
disposable.add(getListOfBlacklistedUsers(tutorId) disposable.add(getListOfBlacklistedUsers(tutorId)
.doOnSubscribe(t -> didFetched = false) .doOnSubscribe(this::handleDoOnSubscribe)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.flatMap((Function<List<String>, Observable<String>>) Observable::fromIterable) .flatMap(Observable::fromIterable)
.flatMap((Function<String, ObservableSource<User>>) this::getUserObservable) .flatMap(this::getUserObservable)
.subscribeWith(new DisposableObserver<User>() { .subscribe(user -> blacklistedUsers.add(user), this::handleError,this::handleComplete));
@Override }
public void onNext(User user) {
blacklistedUsers.add(user);
}
@Override private void handleDoOnSubscribe(Disposable disposable) {
public void onError(Throwable e) { prevSize = blacklistedUsers.size();
showError(e); blacklistedUsers.clear();
didFetched = false; didFetched = false;
} }
@Override private void handleComplete() {
public void onComplete() { Collections.sort(blacklistedUsers, this::sortByUserName);
Collections.sort(blacklistedUsers, (a, b) -> sortByUserName(a,b)); didFetched = true;
didFetched = true; refreshUI();
refreshUI(); }
} private void handleError(Throwable e){
})); showError(e);
didFetched = false;
} }
private void refreshUI(){ private void refreshUI(){
@ -262,10 +257,8 @@ public class BlackList extends AppCompatActivity {
); );
} }
private void handleAddUser(User user) { private void handleAddUser(User user) {
Toast.makeText(this, R.string.add_user_to_list, Snackbar.LENGTH_LONG).show(); Toast.makeText(this, R.string.add_user_to_list, Snackbar.LENGTH_LONG).show();
blacklistedUsers.clear(); blacklistedUsers.clear();
fetchBlackListedUsers(); fetchBlackListedUsers();
} }

View File

@ -3,7 +3,6 @@ package com.uam.wmi.findmytutor.activity;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
@ -28,7 +27,7 @@ import com.uam.wmi.findmytutor.model.ValidateUser;
import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.network.ApiClient;
import com.uam.wmi.findmytutor.service.LdapService; import com.uam.wmi.findmytutor.service.LdapService;
import com.uam.wmi.findmytutor.service.UserService; import com.uam.wmi.findmytutor.service.UserService;
import com.uam.wmi.findmytutor.utils.LocaleHelper; import com.uam.wmi.findmytutor.utils.MapUtils;
import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.RestApiHelper; import com.uam.wmi.findmytutor.utils.RestApiHelper;
@ -41,8 +40,7 @@ import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody; import okhttp3.ResponseBody;
public class public class LoginActivity extends AppCompatActivity {
LoginActivity extends AppCompatActivity {
private AutoCompleteTextView mLoginNameView; private AutoCompleteTextView mLoginNameView;
private EditText mPasswordView; private EditText mPasswordView;
@ -52,11 +50,6 @@ LoginActivity extends AppCompatActivity {
private UserService userService; private UserService userService;
private CompositeDisposable disposable = new CompositeDisposable(); private CompositeDisposable disposable = new CompositeDisposable();
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -157,9 +150,9 @@ LoginActivity extends AppCompatActivity {
private void loginProcess(String email, String password) { private void loginProcess(String email, String password) {
ValidateUser user = new ValidateUser(email, password); ValidateUser user = new ValidateUser(email, password);
// LdapUser fakeUser = new LdapUser(email, password,"wmi","tutor",email,"Fałszywy",email); // LdapUser fakeUser = new LdapUser(email, password,"wmi","tutor",email,"Fałszywy",email);
disposable.add(ldapService.validate(user) disposable.add(ldapService.validate(user)
//disposable.add(ldapService.fakeValidate(fakeUser) //disposable.add(ldapService.fakeValidate(fakeUser)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleResponse, this::handleError)); .subscribe(this::handleResponse, this::handleError));
@ -198,6 +191,7 @@ LoginActivity extends AppCompatActivity {
getUserProfile(userId.asString()); getUserProfile(userId.asString());
Intent data = new Intent(); Intent data = new Intent();
String txt = "Main Activity"; String txt = "Main Activity";
data.setData(Uri.parse(txt)); data.setData(Uri.parse(txt));

View File

@ -8,6 +8,7 @@ import android.content.Context;
import android.location.Location; import android.location.Location;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.PowerManager;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.TextUtils; import android.text.TextUtils;
@ -126,6 +127,7 @@ public class MapActivity extends BaseActivity
mStatusChecker = () -> { mStatusChecker = () -> {
try { try {
if (shouldFetchNewCoords) { if (shouldFetchNewCoords) {
checkIfUsesCanBeTutor();
fetchTopCoords(); fetchTopCoords();
} }
} finally { } finally {
@ -134,7 +136,6 @@ public class MapActivity extends BaseActivity
}; };
selectLocationButton = findViewById(R.id.select_location_button); selectLocationButton = findViewById(R.id.select_location_button);
removeLocationButton = findViewById(R.id.remove_location_button); removeLocationButton = findViewById(R.id.remove_location_button);
mapView = findViewById(R.id.mapView); mapView = findViewById(R.id.mapView);
@ -145,6 +146,11 @@ public class MapActivity extends BaseActivity
handleBackgroundTaskLifeCycle(); handleBackgroundTaskLifeCycle();
manualLocationUtils = new ManualLocationUtils(MapActivity.this); manualLocationUtils = new ManualLocationUtils(MapActivity.this);
approximatedLocalization = new ApproximatedLocalization(MapUtils.loadJsonFromAsset(getApplicationContext(), "building.geojson")); approximatedLocalization = new ApproximatedLocalization(MapUtils.loadJsonFromAsset(getApplicationContext(), "building.geojson"));
if(isTutor){
MapUtils.BatteryOptimizationsExceptionCheck(this);
}
} }
@Override @Override
@ -403,6 +409,30 @@ Log.e("LOCALE",PrefUtils.getLocale(getApplicationContext()));
PrefUtils.putCurrentManualLocation(getApplicationContext(), resp.getPredefinedCoordinateId()); PrefUtils.putCurrentManualLocation(getApplicationContext(), resp.getPredefinedCoordinateId());
} }
private void checkIfUsesCanBeTutor(){
disposable.add(
userService.getSelf(myId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<User>() {
@Override
public void onSuccess(User user) {
boolean tutorFromBackend = user.getTitle().equals("tutor");
if(tutorFromBackend != PrefUtils.getIsTutor(getApplicationContext())){
logout();
}
}
@Override
public void onError(Throwable e) {
showError(e);
}
}));
}
private void fetchTopCoords() { private void fetchTopCoords() {
disposable.add( disposable.add(

View File

@ -151,7 +151,6 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere
public void onError(Throwable e) { public void onError(Throwable e) {
Toast.makeText(getApplicationContext(), R.string.error_location_fetch, Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), R.string.error_location_fetch, Toast.LENGTH_SHORT).show();
} }
})); }));
} }
@ -246,7 +245,6 @@ public class SharingFragment extends PreferenceFragment implements SharedPrefere
return true; return true;
}); });
/** Button 'choose from map' button listener **/ /** Button 'choose from map' button listener **/
manualLocationButton.setOnPreferenceChangeListener((preference, o) -> { manualLocationButton.setOnPreferenceChangeListener((preference, o) -> {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();

View File

@ -1,18 +1,29 @@
package com.uam.wmi.findmytutor.activity; package com.uam.wmi.findmytutor.activity;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Settings;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.Toast; import android.widget.Toast;
import com.uam.wmi.findmytutor.R;
import com.uam.wmi.findmytutor.utils.LocaleHelper; import com.uam.wmi.findmytutor.utils.LocaleHelper;
import com.uam.wmi.findmytutor.utils.MapUtils;
import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.PrefUtils;
import java.util.Locale; import java.util.Locale;
@ -38,12 +49,11 @@ public class StartupActivity extends AppCompatActivity {
finish(); finish();
} else { } else {
Intent loginIntent = new Intent(this, LoginActivity.class); Intent loginIntent = new Intent(this, LoginActivity.class);
// Intent loginIntent = new Intent(this, ScrollingActivity.class);
startActivityForResult(loginIntent, AUTHENTICATION_REQUEST_CODE); startActivityForResult(loginIntent, AUTHENTICATION_REQUEST_CODE);
} }
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@Override @Override
@ -56,4 +66,8 @@ public class StartupActivity extends AppCompatActivity {
finish(); finish();
} }
} }

View File

@ -66,28 +66,6 @@ public class TutorTab extends AppCompatActivity {
private RecyclerView.LayoutManager dutyHoursLayoutManager; private RecyclerView.LayoutManager dutyHoursLayoutManager;
private TutorTabViewModel newTab; private TutorTabViewModel newTab;
public boolean isEmailValid(String email)
{
String regExpn =
"^(([\\w-]+\\.)+[\\w-]+|([a-zA-Z]{1}|[\\w-]{2,}))@"
+"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\.([0-1]?"
+"[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\."
+"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\.([0-1]?"
+"[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|"
+"([a-zA-Z]+[\\w-]+\\.)+[a-zA-Z]{2,4})$";
CharSequence inputStr = email;
Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(inputStr);
if(matcher.matches())
return true;
else
return false;
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -118,8 +96,6 @@ public class TutorTab extends AppCompatActivity {
getTutorTab(); getTutorTab();
// findViewById(R.id.contentTutorTabInfoImageButton).setOnClickListener(v-> InfoHelperUtils.infoPopUp(v,R.layout.info_popup_tutor_tab));
userName.setText(String.format("%s %s", PrefUtils.getUserFirstName(getApplicationContext()), PrefUtils.getUserLastName(getApplicationContext()))); userName.setText(String.format("%s %s", PrefUtils.getUserFirstName(getApplicationContext()), PrefUtils.getUserLastName(getApplicationContext())));
disposable.add( disposable.add(
@ -236,7 +212,6 @@ public class TutorTab extends AppCompatActivity {
}else{ }else{
userEmail.setError(getString(R.string.error_invalid_email)); userEmail.setError(getString(R.string.error_invalid_email));
} }
}); });
} }
@ -286,7 +261,6 @@ public class TutorTab extends AppCompatActivity {
Toast.makeText(getApplicationContext(), Toast.makeText(getApplicationContext(),
"Network error " + error.getMessage(), Toast.LENGTH_SHORT).show(); "Network error " + error.getMessage(), Toast.LENGTH_SHORT).show();
Log.e("WMI SUCC", String.valueOf(error)); Log.e("WMI SUCC", String.valueOf(error));
} }
@ -309,5 +283,21 @@ public class TutorTab extends AppCompatActivity {
super.attachBaseContext(LocaleHelper.onAttach(base)); super.attachBaseContext(LocaleHelper.onAttach(base));
} }
public boolean isEmailValid(String email)
{
String regExpn =
"^(([\\w-]+\\.)+[\\w-]+|([a-zA-Z]{1}|[\\w-]{2,}))@"
+"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\.([0-1]?"
+"[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\."
+"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\\.([0-1]?"
+"[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|"
+"([a-zA-Z]+[\\w-]+\\.)+[a-zA-Z]{2,4})$";
CharSequence inputStr = email;
Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(inputStr);
return matcher.matches();
}
} }

View File

@ -63,6 +63,7 @@ import io.reactivex.Observable;
import io.reactivex.ObservableSource; import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function; import io.reactivex.functions.Function;
import io.reactivex.observers.DisposableObserver; import io.reactivex.observers.DisposableObserver;
import io.reactivex.observers.DisposableSingleObserver; import io.reactivex.observers.DisposableSingleObserver;
@ -316,6 +317,7 @@ public class UsersListFragment extends Fragment {
tutorsList.addAll(users); tutorsList.addAll(users);
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
toggleEmptyNotes(); toggleEmptyNotes();
fetchTopCords();
} }
@Override @Override
@ -425,6 +427,35 @@ public class UsersListFragment extends Fragment {
} }
} }
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
private void fetchTopCords(){
disposable.add(
coordinateService.getTopCoordinates()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::addTimestamps,this::showError));
}
private void addTimestamps(List<Coordinate> coordinates) {
for (Coordinate crd :
coordinates) {
Long ts = crd.getTimeStamp();
tutorsTimeStamps.put(crd.getUserId(), getDate(ts));
}
mAdapter.notifyDataSetChanged();
}
private String getDate(long time) {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTimeInMillis(time);
return DateFormat.format("HH:mm dd/MM", cal).toString();
}
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
@ -447,54 +478,4 @@ public class UsersListFragment extends Fragment {
super.onStop(); super.onStop();
} }
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
private Observable<List<User>> getListOfActiveUsers() {
return userService.getAllActiveTutors()
.toObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
private Observable<Coordinate> getCoordinateObservable(User user) {
return coordinateService
.getTopCoordinateByUserId(user.getId())
.toObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
private void fetchTopCords(){
tutorsTimeStamps.clear();
disposable.add(getListOfActiveUsers()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap((Function<List<User>, Observable<User>>) Observable::fromIterable)
.flatMap((Function<User, ObservableSource<Coordinate>>) this::getCoordinateObservable)
.subscribeWith(new DisposableObserver<Coordinate>() {
@Override
public void onNext(Coordinate coordinate) {
Long ts = coordinate.getTimeStamp();
tutorsTimeStamps.put(coordinate.getUserId(), getDate(ts));
}
@Override
public void onError(Throwable e) {showError(e);}
@Override
public void onComplete() {
Log.e("USERS", String.valueOf(tutorsTimeStamps));
mAdapter.notifyDataSetChanged();
}
}));
}
private String getDate(long time) {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTimeInMillis(time);
String date = DateFormat.format("HH:mm dd/MM", cal).toString();
return date;
}
} }

View File

@ -58,6 +58,7 @@ import io.reactivex.Observable;
import io.reactivex.ObservableSource; import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function; import io.reactivex.functions.Function;
import io.reactivex.observers.DisposableObserver; import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
@ -162,34 +163,29 @@ public class WhiteList extends AppCompatActivity {
} }
private void fetchWhiteListedUsers() { private void fetchWhiteListedUsers() {
prevSize = whitelistedUsers.size();
whitelistedUsers.clear();
disposable.add(getListOfWhitelistedUsers(tutorId) disposable.add(getListOfWhitelistedUsers(tutorId)
.doOnSubscribe(t -> didFetched = false) .doOnSubscribe(this::handleDoOnSubscribe)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.flatMap((Function<List<String>, Observable<String>>) Observable::fromIterable) .flatMap(Observable::fromIterable)
.flatMap((Function<String, ObservableSource<User>>) this::getUserObservable) .flatMap(this::getUserObservable)
.subscribeWith(new DisposableObserver<User>() { .subscribe(user -> whitelistedUsers.add(user), this::handleError,this::handleComplete));
@Override }
public void onNext(User user) {
whitelistedUsers.add(user);
}
@Override private void handleDoOnSubscribe(Disposable disposable) {
public void onError(Throwable e) { prevSize = whitelistedUsers.size();
showError(e); whitelistedUsers.clear();
didFetched = false; didFetched = false;
} }
@Override private void handleComplete() {
public void onComplete() { Collections.sort(whitelistedUsers, this::sortByUserName);
Collections.sort(whitelistedUsers, (a, b) -> sortByUserName(a, b)); didFetched = true;
didFetched = true; refreshUI();
refreshUI(); }
} private void handleError(Throwable e){
})); showError(e);
didFetched = false;
} }
private void refreshUI() { private void refreshUI() {

View File

@ -1,3 +1,4 @@
/*
package com.uam.wmi.findmytutor.adapters; package com.uam.wmi.findmytutor.adapters;
import android.content.Context; import android.content.Context;
@ -46,6 +47,7 @@ public class TutorsListAdapter extends RecyclerView.Adapter<TutorsListAdapter.My
User tutor = tutorsList.get(position); User tutor = tutorsList.get(position);
holder.firstName.setText(String.format("%s %s", tutor.getFirstName(), tutor.getLastName())); holder.firstName.setText(String.format("%s %s", tutor.getFirstName(), tutor.getLastName()));
String ts = tutorsTimeStamps.get(tutor.getId());
if (tutor.isIsOnline()) { if (tutor.isIsOnline()) {
image = context.getResources().getDrawable(R.drawable.user_list_online); image = context.getResources().getDrawable(R.drawable.user_list_online);
@ -53,7 +55,6 @@ public class TutorsListAdapter extends RecyclerView.Adapter<TutorsListAdapter.My
holder.loader.setVisibility(View.GONE); holder.loader.setVisibility(View.GONE);
} else { } else {
image = context.getResources().getDrawable(R.drawable.user_list_offline); image = context.getResources().getDrawable(R.drawable.user_list_offline);
String ts = tutorsTimeStamps.get(tutor.getId());
if (ts != null){ if (ts != null){
holder.lastSeen.setText(R.string.last_sign); holder.lastSeen.setText(R.string.last_sign);
@ -64,7 +65,123 @@ public class TutorsListAdapter extends RecyclerView.Adapter<TutorsListAdapter.My
if (!tutor.isIsActive()) { if (!tutor.isIsActive()) {
image = context.getResources().getDrawable(R.drawable.user_list_off); image = context.getResources().getDrawable(R.drawable.user_list_off);
holder.lastSeen.setText(""); if(ts != null){
holder.lastSeen.setText(R.string.last_sign);
holder.lastSeen.append(String.format(": %s", ts));
}else{
holder.lastSeen.setVisibility(View.GONE);
}
holder.loader.setVisibility(View.GONE);
}
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
holder.isOnline.setCompoundDrawables(image, null, null, null);
}
@Override
public int getItemCount() {
return tutorsList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.firstName)
TextView firstName;
@BindView(R.id.lastSeen)
TextView lastSeen;
@BindView(R.id.isOnline)
TextView isOnline;
@BindView(R.id.loader)
SpinKitView loader;
MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}
*/
package com.uam.wmi.findmytutor.adapters;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.github.ybq.android.spinkit.SpinKitView;
import com.uam.wmi.findmytutor.R;
import com.uam.wmi.findmytutor.model.User;
import java.util.HashMap;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class TutorsListAdapter extends RecyclerView.Adapter<TutorsListAdapter.MyViewHolder> {
private Context context;
private List<User> tutorsList;
private HashMap<String, String> tutorsTimeStamps;
public TutorsListAdapter(Context context, List<User> tutors, HashMap<String,String> tutorsTimeStamps) {
this.context = context;
this.tutorsList = tutors;
this.tutorsTimeStamps = tutorsTimeStamps;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tutor_list_row, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Drawable image = null;
User tutor = tutorsList.get(position);
holder.firstName.setText(String.format("%s %s", tutor.getFirstName(), tutor.getLastName()));
String ts = tutorsTimeStamps.get(tutor.getId());
if (tutor.isIsOnline()) {
image = context.getResources().getDrawable(R.drawable.user_list_online);
holder.lastSeen.setText(R.string.available_now);
holder.lastSeen.setVisibility(View.VISIBLE);
holder.loader.setVisibility(View.GONE);
} else if(tutor.isIsActive()){
image = context.getResources().getDrawable(R.drawable.user_list_offline);
if (ts != null){
holder.lastSeen.setText(R.string.last_sign);
holder.lastSeen.append(String.format(": %s", ts));
holder.loader.setVisibility(View.GONE);
}
} else {
image = context.getResources().getDrawable(R.drawable.user_list_off);
if(ts == null){
holder.lastSeen.setText(R.string.never_logged_in);
}else{
holder.lastSeen.setText(R.string.last_sign);
holder.lastSeen.append(String.format(": %s", ts));
}
holder.loader.setVisibility(View.GONE); holder.loader.setVisibility(View.GONE);
} }

View File

@ -34,9 +34,11 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
import com.uam.wmi.findmytutor.model.Coordinate; import com.uam.wmi.findmytutor.model.Coordinate;
import com.uam.wmi.findmytutor.network.ApiClient; import com.uam.wmi.findmytutor.network.ApiClient;
import com.uam.wmi.findmytutor.utils.ApproximatedLocalization; import com.uam.wmi.findmytutor.utils.ApproximatedLocalization;
import com.uam.wmi.findmytutor.utils.Const;
import com.uam.wmi.findmytutor.utils.MapUtils; import com.uam.wmi.findmytutor.utils.MapUtils;
import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.PrefUtils;
import com.uam.wmi.findmytutor.utils.SharingLevel; import com.uam.wmi.findmytutor.utils.SharingLevel;
import com.uam.wmi.findmytutor.utils.WifiUtils;
import org.apache.commons.collections4.queue.CircularFifoQueue; import org.apache.commons.collections4.queue.CircularFifoQueue;
@ -122,6 +124,12 @@ public class BackgroundLocalizationService extends Service {
mCurrentLocation = locationResult.getLastLocation(); mCurrentLocation = locationResult.getLastLocation();
sendCoordinateToBackend(mCurrentLocation); sendCoordinateToBackend(mCurrentLocation);
changeBackgroundMode(); changeBackgroundMode();
//Restart service when a user started using presence in GPS mode and wmi is currently available
if (WifiUtils.checkIfUserIsInRangeOfWmiWifi(getApplicationContext())
&& PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.PRESENCE.toString())) {
restartService();
}
} }
} }
}; };
@ -140,22 +148,60 @@ public class BackgroundLocalizationService extends Service {
startForeground(1001, notification); startForeground(1001, notification);
} }
if (!stopService && !PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) { if (!stopService) {
createFusedLocationClient(); if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.PRESENCE.toString())) {
} else if (!stopService && if (WifiUtils.checkIfUserIsInRangeOfWmiWifi(getApplicationContext())) {
PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) { Location presenceFakeLoc = new Location("");
mStatusChecker = () -> {
try {
sendCoordinateToBackend(fakeLoc);
} finally {
mHandler.postDelayed(mStatusChecker, notify_interval);
}
};
AsyncTask.execute(mStatusChecker); presenceFakeLoc.setLatitude(Const.presenceLatitude);
presenceFakeLoc.setLongitude(Const.presenceLongitude);
presenceFakeLoc.setAltitude(0);
createPresenceLooper(presenceFakeLoc);
} else {
createFusedLocationClient();
}
} else if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.EXACT.toString())
|| PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.APPROXIMATED.toString())
) {
createFusedLocationClient();
} else if (PrefUtils.getLocationLevel(getApplicationContext()).equals(SharingLevel.MANUAL.toString())) {
Location manualFakeLoc = new Location("");
manualFakeLoc.setLatitude(0);
manualFakeLoc.setLongitude(0);
manualFakeLoc.setAltitude(0);
createLowBatteryLooper(manualFakeLoc);
}
} }
} }
private void createLowBatteryLooper(Location fakeLoc) {
mStatusChecker = () -> {
try {
sendCoordinateToBackend(fakeLoc);
} finally {
mHandler.postDelayed(mStatusChecker, notify_interval);
}
};
AsyncTask.execute(mStatusChecker);
}
private void createPresenceLooper(Location fakeLoc) {
mStatusChecker = () -> {
try {
if (WifiUtils.checkIfUserIsInRangeOfWmiWifi(getApplicationContext())) {
sendCoordinateToBackend(fakeLoc);
} else {
restartService();
}
} finally {
mHandler.postDelayed(mStatusChecker, notify_interval);
}
};
AsyncTask.execute(mStatusChecker);
}
private void createFusedLocationClient() { private void createFusedLocationClient() {
Integer saveMode = Long.valueOf(notify_interval).compareTo(Long.valueOf(offlineBackgroundLocationInterval)); Integer saveMode = Long.valueOf(notify_interval).compareTo(Long.valueOf(offlineBackgroundLocationInterval));
@ -294,7 +340,7 @@ public class BackgroundLocalizationService extends Service {
latitude = location.getLatitude(); latitude = location.getLatitude();
longitude = location.getLongitude(); longitude = location.getLongitude();
altitude = location.getAltitude(); altitude = location.getAltitude();
Log.e(TAG,"TASK" + latitude + " " + longitude); Log.e(TAG, "TASK" + latitude + " " + longitude);
approximatedLocalization = new ApproximatedLocalization(MapUtils.loadJsonFromAsset(getApplicationContext(), "building.geojson")); approximatedLocalization = new ApproximatedLocalization(MapUtils.loadJsonFromAsset(getApplicationContext(), "building.geojson"));
approximatedBuildingPart = approximatedLocalization.getNameOfBuildingPart(Point.fromLngLat(longitude, latitude)); approximatedBuildingPart = approximatedLocalization.getNameOfBuildingPart(Point.fromLngLat(longitude, latitude));
} }
@ -307,6 +353,7 @@ public class BackgroundLocalizationService extends Service {
if (locationLevel.equals(SharingLevel.PRESENCE.toString())) { if (locationLevel.equals(SharingLevel.PRESENCE.toString())) {
if (!MapUtils.checkIfCoordinateIsValid(latitude, longitude)) { if (!MapUtils.checkIfCoordinateIsValid(latitude, longitude)) {
coordinatesHistory.add(fakeLoc);
return null; return null;
} }

View File

@ -39,6 +39,9 @@ public interface UserService {
@GET("api/users/tutors/active") @GET("api/users/tutors/active")
Single <List<User>> getAllActiveTutors(); Single <List<User>> getAllActiveTutors();
@GET("api/users/tutors/offline") @GET("api/users/tutors/offline")
Single <List<User>> getAllOfflineTutors(); Single <List<User>> getAllOfflineTutors();
@ -60,6 +63,9 @@ public interface UserService {
@GET("api/users/{id}") @GET("api/users/{id}")
Single <User> getUserById(@Path("id") String userID); Single <User> getUserById(@Path("id") String userID);
@GET("api/users/self/{id}")
Single <User> getSelf(@Path("id") String userID);
@PUT("api/users/{id}") @PUT("api/users/{id}")
Completable updateUserByID(@Path("id") String userID, @Body User user); Completable updateUserByID(@Path("id") String userID, @Body User user);

View File

@ -20,5 +20,7 @@ public class Const {
public final static Range<Double> outsideLatitudeRange = Range.create(52.4651, 52.468837); public final static Range<Double> outsideLatitudeRange = Range.create(52.4651, 52.468837);
public final static Range<Double> outsideLongitudeRange = Range.create(16.9186, 16.936004); public final static Range<Double> outsideLongitudeRange = Range.create(16.9186, 16.936004);
public final static List<String> validApproximatedLocations = Arrays.asList("Skrzydło B", "Skrzydło A", "Aule", "Łącznik", "Biblioteka", "Hol", "Unknown"); public final static List<String> validApproximatedLocations = Arrays.asList("Skrzydło B", "Skrzydło A", "Aule", "Łącznik", "Biblioteka", "Hol", "Unknown");
public final static String WMI_SSID_NAME = "wmi";
} }

View File

@ -1,8 +1,12 @@
package com.uam.wmi.findmytutor.utils; package com.uam.wmi.findmytutor.utils;
import android.animation.TypeEvaluator; import android.animation.TypeEvaluator;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.location.Location; import android.location.Location;
import android.net.Uri;
import android.provider.Settings;
import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
@ -10,12 +14,15 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds; import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.uam.wmi.findmytutor.R;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import static com.uam.wmi.findmytutor.utils.Const.outsideLongitudeRange; import static com.mapbox.mapboxsdk.Mapbox.getApplicationContext;
import static com.uam.wmi.findmytutor.utils.Const.outsideLatitudeRange; import static com.uam.wmi.findmytutor.utils.Const.outsideLatitudeRange;
import static com.uam.wmi.findmytutor.utils.Const.outsideLongitudeRange;
import static com.uam.wmi.findmytutor.utils.PrefUtils.shouldBatteryExclusionBeShown;
public class MapUtils { public class MapUtils {
@ -41,8 +48,8 @@ public class MapUtils {
// Map Bounds Area // Map Bounds Area
public static void setZoom(MapboxMap mapboxMap, Integer zoom) { public static void setZoom(MapboxMap mapboxMap, Integer zoom) {
makeNewCamera(mapboxMap, 52.466799, 16.927002, zoom, 0, 0, 1000); makeNewCamera(mapboxMap, 52.466799, 16.927002, zoom, 0, 0, 1000);
mapboxMap.setMinZoomPreference(16); // TODO export to map config mapboxMap.setMinZoomPreference(16); // TODO export to map config
} }
public static void makeNewCamera(MapboxMap mapboxMap, double lat, double lon, int zoomParam, int bearingParam, int tiltParam, int duration) { public static void makeNewCamera(MapboxMap mapboxMap, double lat, double lon, int zoomParam, int bearingParam, int tiltParam, int duration) {
@ -73,14 +80,34 @@ public class MapUtils {
} }
} }
public static Boolean checkIfCoordinateIsValid(Location coordinate){ public static Boolean checkIfCoordinateIsValid(Location coordinate) {
return outsideLatitudeRange.contains(coordinate.getLatitude()) && outsideLongitudeRange.contains(coordinate.getLongitude()); return outsideLatitudeRange.contains(coordinate.getLatitude()) && outsideLongitudeRange.contains(coordinate.getLongitude());
} }
public static Boolean checkIfCoordinateIsValid(Double latitude, Double longitude){ public static Boolean checkIfCoordinateIsValid(Double latitude, Double longitude) {
return Const.buildingLatitudeRange.contains(latitude) && Const.buildingLongitudeRange.contains(longitude); return Const.buildingLatitudeRange.contains(latitude) && Const.buildingLongitudeRange.contains(longitude);
} }
public static void BatteryOptimizationsExceptionCheck(Context context) {
if (shouldBatteryExclusionBeShown(getApplicationContext())) {
PrefUtils.setBatteryExlusionInfoStatus(getApplicationContext(), false);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.batter_exclusions_title);
builder.setMessage(R.string.batter_exclusions_message)
.setPositiveButton(R.string.ok, (dialog, id) -> {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getApplicationContext().getPackageName(), null);
intent.setData(uri);
context.startActivity(intent);
})
.setNegativeButton(R.string.cancel, (dialog, id) -> {
}).show();
}
}
// Function for marker animation // Function for marker animation
public static class LatLngEvaluator implements TypeEvaluator<LatLng> { public static class LatLngEvaluator implements TypeEvaluator<LatLng> {
// Method is used to interpolate the marker animation. // Method is used to interpolate the marker animation.

View File

@ -243,4 +243,13 @@ public class PrefUtils {
return getSharedPreferences(context).getBoolean("whitelisting", false); return getSharedPreferences(context).getBoolean("whitelisting", false);
} }
public static Boolean shouldBatteryExclusionBeShown(Context context) {
return getSharedPreferences(context).getBoolean("show_battery_exclusion", false);
}
public static void setBatteryExlusionInfoStatus(Context context, Boolean flag) {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putBoolean("show_battery_exclusion", flag);
editor.apply();
}
} }

View File

@ -0,0 +1,30 @@
package com.uam.wmi.findmytutor.utils;
import android.content.Context;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
import java.util.Objects;
public class WifiUtils {
public static String getWifiName(Context context) {
WifiManager manager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (Objects.requireNonNull(manager).isWifiEnabled()) {
WifiInfo wifiInfo = manager.getConnectionInfo();
if (wifiInfo != null) {
NetworkInfo.DetailedState state = WifiInfo.getDetailedStateOf(wifiInfo.getSupplicantState());
if (state == NetworkInfo.DetailedState.CONNECTED || state == NetworkInfo.DetailedState.OBTAINING_IPADDR) {
return wifiInfo.getSSID();
}
}
}
return null;
}
public static Boolean checkIfUserIsInRangeOfWmiWifi(Context context) {
return Objects.equals(getWifiName(context), Const.WMI_SSID_NAME);
}
}

View File

@ -4,13 +4,13 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fontFamily="@font/lato_regular"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" android:paddingTop="@dimen/activity_vertical_margin"
android:fontFamily="@font/lato_regular" android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".activity.LoginActivity"> tools:context=".activity.LoginActivity">
@ -61,10 +61,7 @@
app:passwordToggleEnabled="true" app:passwordToggleEnabled="true"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<EditText
<android.support.design.widget.TextInputEditText
android:id="@+id/password" android:id="@+id/password"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -78,7 +75,6 @@
</android.support.design.widget.TextInputLayout> </android.support.design.widget.TextInputLayout>
<Button <Button
android:id="@+id/email_sign_in_button" android:id="@+id/email_sign_in_button"
style="?android:textAppearanceSmall" style="?android:textAppearanceSmall"
@ -88,7 +84,6 @@
android:text="@string/action_log_in" android:text="@string/action_log_in"
android:textStyle="bold" /> android:textStyle="bold" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>

View File

@ -77,6 +77,7 @@
android:layout_alignStart="@+id/userRoomLayout" android:layout_alignStart="@+id/userRoomLayout"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_marginTop="30dp" android:layout_marginTop="30dp"
android:layout_marginStart="5dp"
android:text="@string/personalInfoTitle" android:text="@string/personalInfoTitle"
android:textColor="@color/mapboxRedDark" android:textColor="@color/mapboxRedDark"
android:textSize="18sp" android:textSize="18sp"
@ -113,7 +114,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/userRoomLayout" android:layout_below="@+id/userRoomLayout"
android:layout_alignStart="@+id/userRoomLayout" android:layout_alignStart="@+id/userRoomLayout"
android:layout_marginStart="0dp" android:layout_marginStart="5dp"
android:layout_marginEnd="30dp" android:layout_marginEnd="30dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:gravity="center" android:gravity="center"
@ -125,18 +126,18 @@
<android.support.v7.widget.RecyclerView <android.support.v7.widget.RecyclerView
android:id="@+id/dutyHourView" android:id="@+id/dutyHourView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="100dp" android:layout_height="120dp"
android:layout_below="@+id/addDuty" android:layout_below="@+id/addDuty"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_marginStart="30dp" android:layout_marginStart="30dp"
android:layout_marginTop="0dp" android:layout_marginTop="15dp"
android:layout_marginEnd="30dp" android:layout_marginEnd="50dp"
android:scrollbars="vertical" /> android:scrollbars="vertical" />
<TextView <TextView
android:id="@+id/userNoteTitle" android:id="@+id/userNoteTitle"
android:textStyle="bold" android:textStyle="bold"
android:layout_marginStart="5dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/dutyHourView" android:layout_below="@+id/dutyHourView"
@ -153,6 +154,8 @@
app:backgroundTint="@color/colorPrimary" app:backgroundTint="@color/colorPrimary"
android:layout_alignBaseline="@+id/dutyTitle" android:layout_alignBaseline="@+id/dutyTitle"
android:layout_toEndOf="@+id/dutyTitle" android:layout_toEndOf="@+id/dutyTitle"
android:stateListAnimator="@null"
android:text="@string/addDuty" /> android:text="@string/addDuty" />
<android.support.design.widget.TextInputLayout <android.support.design.widget.TextInputLayout
@ -163,12 +166,11 @@
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_marginStart="30dp" android:layout_marginStart="30dp"
android:layout_marginEnd="30dp" android:layout_marginEnd="30dp"
android:layout_marginTop="0dp" android:layout_marginTop="15dp"
app:counterEnabled="true" app:counterEnabled="true"
app:counterMaxLength="1000"> app:counterMaxLength="1000">
<android.support.design.widget.TextInputEditText <android.support.design.widget.TextInputEditText
android:id="@+id/userNote" android:id="@+id/userNote"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="100dp" android:layout_height="100dp"
@ -178,7 +180,7 @@
android:lineSpacingExtra="8sp" android:lineSpacingExtra="8sp"
android:maxLength="1000" android:maxLength="1000"
android:maxLines="7" android:maxLines="7"
android:paddingTop="5dp" android:paddingTop="15dp"
android:requiresFadingEdge="vertical" android:requiresFadingEdge="vertical"
android:scrollbars="vertical" android:scrollbars="vertical"
android:textColor="@color/note_list_text" /> android:textColor="@color/note_list_text" />
@ -192,18 +194,22 @@
android:layout_alignEnd="@+id/userEmailLayout" android:layout_alignEnd="@+id/userEmailLayout"
android:textColor="@color/white" android:textColor="@color/white"
app:backgroundTint="@color/colorPrimary" app:backgroundTint="@color/colorPrimary"
android:stateListAnimator="@null"
android:text="@string/scrap_tutor_tab" /> android:text="@string/scrap_tutor_tab" />
<android.support.v7.widget.AppCompatButton <android.support.v7.widget.AppCompatButton
android:id="@+id/saveButton" android:id="@+id/saveButton"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="-20dp"
android:layout_below="@+id/userNoteLayout" android:layout_below="@+id/userNoteLayout"
android:layout_alignEnd="@+id/dutyHourView" android:layout_alignEnd="@+id/dutyHourView"
android:textColor="@color/white" android:textColor="@color/white"
app:backgroundTint="@color/colorPrimary" app:backgroundTint="@color/colorPrimary"
android:text="@string/saveButton" /> android:stateListAnimator="@null"
android:text="@string/saveButton" />
</RelativeLayout> </RelativeLayout>
</android.support.v4.widget.NestedScrollView> </android.support.v4.widget.NestedScrollView>

View File

@ -7,7 +7,6 @@
android:fontFamily="@font/lato_regular" android:fontFamily="@font/lato_regular"
> >
<android.support.v7.widget.AppCompatButton <android.support.v7.widget.AppCompatButton
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/button_choose_from_map" android:id="@+id/button_choose_from_map"
@ -16,6 +15,8 @@
android:textColor="@color/white" android:textColor="@color/white"
app:backgroundTint="@color/top_user_modal" app:backgroundTint="@color/top_user_modal"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:stateListAnimator="@null"
/> />

View File

@ -288,6 +288,11 @@
<string name="available_now">Dostępny teraz</string> <string name="available_now">Dostępny teraz</string>
<string name="profile_activity_title">Profil użytkownika</string> <string name="profile_activity_title">Profil użytkownika</string>
<string name="batter_exclusions_title">Uwaga</string>
<string name="batter_exclusions_message">Aby aplikacja była w pełni funkcjonalna, dodaj FMT do wyjątków w oszczędzaniu baterii. Po wciśnięciu przycisku \"ok\" zostaniesz przeniesiony do opcji zarządzania baterią. W panelu \"Bateria\" upewnij się, że opcja optymalizacji jest wyłączona.</string>
<string name="never_logged_in">Nigdy</string>
</resources> </resources>

View File

@ -456,4 +456,7 @@
<string name="user_status_label" translatable="false">Status</string> <string name="user_status_label" translatable="false">Status</string>
<string name="available_now">Available now</string> <string name="available_now">Available now</string>
<string name="last_sign">Last seen</string> <string name="last_sign">Last seen</string>
<string name="batter_exclusions_message">To make app fully functional add FMT to battery saving exclusions. You can change battery options in \"Optimise battery usage\". Unfortunately, you have to do it manually. Click \"ok\" to open battery settings and make sure that the application is not optimised.</string>
<string name="batter_exclusions_title">Please note</string>
<string name="never_logged_in">Never</string>
</resources> </resources>

View File

@ -8,7 +8,6 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.2.1' classpath 'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files