diff --git a/app/build.gradle b/app/build.gradle index 9d862f9..73817ff 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,7 +44,7 @@ dependencies { implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation "io.swagger:swagger-annotations:1.5.15" implementation "org.threeten:threetenbp:1.3.5" - implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:6.4.0' + implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:6.6.5' implementation 'io.reactivex.rxjava2:rxjava:2.2.0' implementation 'com.android.support:recyclerview-v7:27.1.1' implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' diff --git a/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java b/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java index 3c77419..441cbc0 100644 --- a/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java +++ b/app/src/main/java/com/uam/wmi/findmytutor/activity/MapActivity.java @@ -1,12 +1,12 @@ package com.uam.wmi.findmytutor.activity; import android.animation.ObjectAnimator; -import android.animation.TypeEvaluator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.location.Location; import android.os.Bundle; import android.os.Handler; import android.support.design.widget.FloatingActionButton; @@ -15,17 +15,27 @@ import android.util.Log; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; +import com.mapbox.android.core.permissions.PermissionsListener; +import com.mapbox.android.core.permissions.PermissionsManager; import com.mapbox.mapboxsdk.annotations.Icon; import com.mapbox.mapboxsdk.annotations.IconFactory; +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; +import com.mapbox.mapboxsdk.location.LocationComponent; +import com.mapbox.mapboxsdk.location.LocationComponentOptions; +import com.mapbox.mapboxsdk.location.modes.CameraMode; +import com.mapbox.mapboxsdk.location.modes.RenderMode; import com.mapbox.mapboxsdk.style.layers.CircleLayer; import com.mapbox.mapboxsdk.style.layers.Layer; -import com.mapbox.mapboxsdk.style.layers.SymbolLayer; import com.mapbox.mapboxsdk.style.sources.VectorSource; + import static com.mapbox.mapboxsdk.style.layers.Property.NONE; import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor; + import android.graphics.Color; import android.view.View; +import android.view.animation.LinearInterpolator; import android.widget.Button; import android.widget.Toast; @@ -40,34 +50,31 @@ import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; -import com.mapbox.mapboxsdk.style.layers.Layer; import com.uam.wmi.findmytutor.R; import com.uam.wmi.findmytutor.model.Coordinate; import com.uam.wmi.findmytutor.network.ApiClient; -import com.uam.wmi.findmytutor.network.RetrofitClientInstance; import com.uam.wmi.findmytutor.service.CoordinateService; import com.uam.wmi.findmytutor.utils.PrefUtils; import com.uam.wmi.findmytutor.utils.RestApiHelper; import com.uam.wmi.findmytutor.utils.mapUtils; -import java.nio.ByteBuffer; import java.util.HashMap; import java.util.List; -import java.util.Map; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.annotations.NonNull; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.observers.DisposableSingleObserver; import io.reactivex.schedulers.Schedulers; import okhttp3.ResponseBody; +import timber.log.Timber; public class MapActivity extends BaseActivity - implements OnMapReadyCallback { - - String tag = getClass().getName(); + implements PermissionsListener, OnMapReadyCallback { + private String tag = getClass().getName(); + private PermissionsManager permissionsManager; + private LocationComponent locationComponent; private CoordinateService coordinateService; private CompositeDisposable disposable = new CompositeDisposable(); @@ -82,6 +89,9 @@ public class MapActivity extends BaseActivity private HashMap coordsMap = new HashMap<>(); private HashMap markerHash = new HashMap<>(); + private int zoomParam = 17; + private int bearingParam = 180; + private int tiltParam = 30; @Override @@ -115,7 +125,9 @@ public class MapActivity extends BaseActivity @Override public void onMapReady(MapboxMap mapboxMap) { MapActivity.this.mapboxMap = mapboxMap; -// mapboxMap = map; + enableLocationPlugin(); + + // TODO floating marker to remove later final Marker marker = mapboxMap.addMarker(new MarkerViewOptions() .position(new LatLng(52.466782, 16.927549))); mStatusChecker.run(); @@ -131,16 +143,13 @@ public class MapActivity extends BaseActivity }); - // TODO what should happend on click? - mapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() { - @Override - public boolean onMarkerClick(@NonNull Marker marker) { - - // Show a toast with the title of the selected marker - Toast.makeText(MapActivity.this, marker.getTitle(), Toast.LENGTH_SHORT).show(); - return true; - } - }); +// // TODO what should happend on click? +// mapboxMap.setOnMarkerClickListener(marker1 -> { +// +// // Show a toast with the title of the selected marker +//// Toast.makeText(MapActivity.this, marker.getTitle(), Toast.LENGTH_SHORT).show(); +// return true; +// }); setOnMapLongClickListener(); @@ -148,6 +157,7 @@ public class MapActivity extends BaseActivity } private void setOnMapLongClickListener() { + final boolean[] cancel = {false}; Button selectLocationButton = findViewById(R.id.select_location_button); @@ -164,7 +174,7 @@ public class MapActivity extends BaseActivity .title("My Loc") .setSnippet("Snipecik")); - } else if (!cancel[0]){ + } else if (!cancel[0]) { ValueAnimator markerAnimator = ObjectAnimator.ofObject(droppedMarker, "position", new mapUtils.LatLngEvaluator(), droppedMarker.getPosition(), latLng); markerAnimator.setDuration(2000); @@ -173,8 +183,65 @@ public class MapActivity extends BaseActivity selectLocationButton.setOnClickListener((View view) -> { - if (!cancel[0] && droppedMarker != null){ + if (!cancel[0] && droppedMarker != null) { // Toast instructing user to tap on the mapboxMap + + + // TODO PUT MANUAL CORD + + + + + + + try { + Coordinate coordinate = new Coordinate( + latLng.getLatitude(), + latLng.getLongitude(), + latLng.getAltitude(), + PrefUtils.getUserFirstName(getApplicationContext()) + " " + PrefUtils.getUserLastName(getApplicationContext()), + PrefUtils.getUserId(getApplicationContext()) + ); + + disposable.add( + coordinateService + .postCoordinate(coordinate) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeWith(new DisposableSingleObserver() { + @SuppressLint("LongLogTag") + @Override + public void onSuccess(Coordinate coord) { + Log.e(tag+"POST", String.valueOf(coord)); + } + + @SuppressLint("LongLogTag") + @Override + public void onError(Throwable e) { + + Log.e(tag+"onError", e.getMessage()); + + if (e instanceof HttpException) { + ResponseBody responseBody = ((HttpException) e).response().errorBody(); + Log.e(tag+"onError", RestApiHelper.getErrorMessage(responseBody)); + + } + } + })); + } catch (IllegalArgumentException e) { + Timber.e(String.valueOf(e)); + } + + + + + + + + + + + Toast.makeText( MapActivity.this, "Manual Locations selected!" + latLng, @@ -183,10 +250,14 @@ public class MapActivity extends BaseActivity selectLocationButton.setBackgroundColor( ContextCompat.getColor(MapActivity.this, R.color.colorAccent)); - selectLocationButton.setText("Rm my loc"); + selectLocationButton.setText("Remove Manual location"); selectLocationButton.setVisibility(View.VISIBLE); cancel[0] = true; } else { + + // TODO REMOVE Manual Locatio + + mapboxMap.removeMarker(droppedMarker); droppedMarker = null; @@ -202,8 +273,6 @@ public class MapActivity extends BaseActivity selectLocationButton.setBackgroundColor( ContextCompat.getColor(MapActivity.this, R.color.colorPrimary)); } - - }); }); @@ -241,48 +310,57 @@ public class MapActivity extends BaseActivity } private void fetchTopCoords() { + disposable.add( // coordinateService.getTopCoordinates() coordinateService.getOnlineCoordinates() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableSingleObserver>() { + @Override public void onSuccess(List coordsList) { + Log.e(tag, ""); for (Coordinate element : coordsList) { String id = element.getUserId(); Coordinate coordinate = coordsMap.get(id); - Log.e(tag, "hashMapSize: "+ coordsMap.size()); - Log.e(tag, "markerMapSize: "+ coordsMap.size()); + Log.e(tag, "hashMapSize: " + coordsMap.size()); + Log.e(tag, "markerMapSize: " + coordsMap.size()); if (coordinate != null) { - Log.e(tag, "Coordin: " + coordinate.getLatitude()+" | " + coordinate.getLongitude()); + Log.e(tag, "Coordin: " + coordinate.getLatitude() + " | " + coordinate.getLongitude()); // Log.e(tag, "Element: " + element.getLatitude()+" | " + element.getLongitude()); // Log.e(tag, "isEqual: " + coordinate.getLatitude().equals(element.getLatitude())); // Log.e(tag, "isEqual: " + coordinate.getLongitude().equals(element.getLongitude())); - boolean statement = coordinate.getLatitude().equals(element.getLatitude()) || coordinate.getLongitude().equals(element.getLongitude()); + boolean statement = coordinate.getLatitude().equals(element.getLatitude()) || coordinate.getLongitude().equals(element.getLongitude()); Log.e(tag, "diff || diff: " + !statement); if (!statement) { Log.e(tag, "replace and animate"); - ValueAnimator markerAnimator = ObjectAnimator.ofObject(markerHash.get(id), "position", - new mapUtils.LatLngEvaluator(), markerHash.get(id).getPosition(), - new LatLng(element.getLatitude(), element.getLongitude())); + Marker marker = markerHash.get(id); + LatLng toDestination = new LatLng(element.getLatitude(), element.getLongitude()); + + ValueAnimator markerAnimator = ObjectAnimator.ofObject(marker, "position", + new mapUtils.LatLngEvaluator(), + marker.getPosition(), + toDestination); markerAnimator.setDuration(2000); + markerAnimator.setInterpolator(new LinearInterpolator()); markerAnimator.start(); - coordsMap.put(id, element); - markerHash.get(id).setPosition(new LatLng(element.getLatitude(), element.getLongitude())); - } else if(!coordinate.getTimeStamp().equals(element.getTimeStamp())) { - Log.e(tag, "timestamp changed"); + // chba niepotrzbene + mapboxMap.getMarkerViewManager().update(); + + + coordsMap.put(id, element); + marker.setPosition(toDestination); } - } else { Log.e(tag, "Marker Added: " + id); coordsMap.put(id, element); @@ -292,7 +370,22 @@ public class MapActivity extends BaseActivity markerHash.put(id, marker); } } + + for (Coordinate coordinate : coordsMap.values()) { + // 300000 = 5mins + if ((System.currentTimeMillis() - coordinate.getTimeStamp()) > (long) 300000) { + String id = coordinate.getUserId(); + Marker markerToRemove = markerHash.get(id); + markerHash.remove(id); + coordsMap.remove(id); + mapboxMap.removeMarker(markerToRemove); + } + + } + + } + @SuppressLint("LongLogTag") @Override public void onError(Throwable e) { @@ -307,7 +400,6 @@ public class MapActivity extends BaseActivity } }) ); - } private void configureLogoutButton() { @@ -327,33 +419,37 @@ public class MapActivity extends BaseActivity }); } - // Add the mapView lifecycle to the activity's lifecycle methods @Override public void onResume() { super.onResume(); mapView.onResume(); } + @Override protected void onStart() { super.onStart(); mapView.onStart(); } + @Override protected void onStop() { super.onStop(); mapView.onStop(); } + @Override public void onPause() { super.onPause(); mapView.onPause(); } + @Override public void onLowMemory() { super.onLowMemory(); mapView.onLowMemory(); } + @Override protected void onDestroy() { super.onDestroy(); @@ -361,17 +457,94 @@ public class MapActivity extends BaseActivity mHandler.removeCallbacks(mStatusChecker); disposable.dispose(); } + @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } + @Override protected int getContentViewId() { return R.layout.activity_map; } + @Override protected int getNavigationMenuItemId() { return R.id.nav_map; } + + @SuppressWarnings({"MissingPermission"}) + private void enableLocationPlugin() { + // Check if permissions are enabled and if not request + if (PermissionsManager.areLocationPermissionsGranted(this)) { + LocationComponentOptions options = LocationComponentOptions.builder(this) + .trackingGesturesManagement(true) + .accuracyColor(ContextCompat.getColor(this, R.color.mapboxGray)) + .build(); + + // Get an instance of the component + locationComponent = mapboxMap.getLocationComponent(); + + // TODO mieszko tu jest lepsza lokalizacja +// locationComponent.getLastKnownLocation(); +// Log.e(tag + "Last", getLastKnownLocation() + ""); + + // Activate with options + locationComponent.activateLocationComponent(this, options); + // Enable to make component visible + locationComponent.setLocationComponentEnabled(true); + + // Set the component's camera mode + locationComponent.setCameraMode(CameraMode.TRACKING); + locationComponent.setRenderMode(RenderMode.COMPASS); + + + // Button 4 centring + FloatingActionButton myLocFAB = findViewById(R.id.myLocationButton); + myLocFAB.setOnClickListener(v -> { + + Location lastKnownLocation = locationComponent.getLastKnownLocation(); + if (lastKnownLocation != null) { + + CameraPosition position = new CameraPosition.Builder() + .target(new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude())) // Sets the new camera position + .zoom(zoomParam) // Sets the zoom + .bearing(bearingParam) // Rotate the camera + .tilt(tiltParam) // Set the camera tilt + .build(); // Creates a CameraPosition from the builder + + mapboxMap.animateCamera(CameraUpdateFactory + .newCameraPosition(position), 4000); + } + + zoomParam = (zoomParam == 17) ? 19 : 17; + bearingParam += 90; + tiltParam = (tiltParam == 30) ? 0 : 30; + }); + } else { + permissionsManager = new PermissionsManager(this); + permissionsManager.requestLocationPermissions(this); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @android.support.annotation.NonNull String[] permissions, @android.support.annotation.NonNull int[] grantResults) { + permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @Override + public void onExplanationNeeded(List permissionsToExplain) { + Toast.makeText(this, R.string.user_location_permission_explanation, Toast.LENGTH_LONG).show(); + } + + @Override + public void onPermissionResult(boolean granted) { + if (granted) { + enableLocationPlugin(); + } else { + Toast.makeText(this, R.string.user_location_permission_not_granted, Toast.LENGTH_LONG).show(); + finish(); + } + } } diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml index aec74e8..ba8cd8a 100644 --- a/app/src/main/res/layout/activity_map.xml +++ b/app/src/main/res/layout/activity_map.xml @@ -24,7 +24,11 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="bottom" - android:orientation="vertical"> + android:orientation="vertical" + tools:layout_editor_absoluteX="0dp" + tools:layout_editor_absoluteY="1dp"> + + + + +