/*
The MIT License (MIT)
Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package io.hypertrack.sendeta.view;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.hypertrack.lib.HyperTrack;
import com.hypertrack.lib.HyperTrackMapFragment;
import com.hypertrack.lib.HyperTrackUtils;
import com.hypertrack.lib.MapFragmentCallback;
import com.hypertrack.lib.callbacks.HyperTrackCallback;
import com.hypertrack.lib.callbacks.HyperTrackEventCallback;
import com.hypertrack.lib.internal.common.models.HTUserVehicleType;
import com.hypertrack.lib.internal.common.util.TextUtils;
import com.hypertrack.lib.internal.transmitter.models.HyperTrackEvent;
import com.hypertrack.lib.models.Action;
import com.hypertrack.lib.models.ErrorResponse;
import com.hypertrack.lib.models.HyperTrackError;
import com.hypertrack.lib.models.Place;
import com.hypertrack.lib.models.ServiceNotificationParams;
import com.hypertrack.lib.models.ServiceNotificationParamsBuilder;
import com.hypertrack.lib.models.SuccessResponse;
import java.util.ArrayList;
import java.util.List;
import io.hypertrack.sendeta.R;
import io.hypertrack.sendeta.callback.ActionManagerListener;
import io.hypertrack.sendeta.model.ETAResponse;
import io.hypertrack.sendeta.presenter.HomePresenter;
import io.hypertrack.sendeta.presenter.IHomePresenter;
import io.hypertrack.sendeta.receiver.GpsLocationReceiver;
import io.hypertrack.sendeta.receiver.NetworkChangeReceiver;
import io.hypertrack.sendeta.service.FetchLocationIntentService;
import io.hypertrack.sendeta.store.ActionManager;
import io.hypertrack.sendeta.store.OnboardingManager;
import io.hypertrack.sendeta.store.SharedPreferenceManager;
import io.hypertrack.sendeta.util.AnimationUtils;
import io.hypertrack.sendeta.util.Constants;
import io.hypertrack.sendeta.util.ErrorMessages;
import io.hypertrack.sendeta.util.ImageUtils;
import io.hypertrack.sendeta.util.PermissionUtils;
import io.hypertrack.sendeta.util.Utils;
public class Home extends BaseActivity implements HomeView {
private static final String TAG = Home.class.getSimpleName();
private GoogleMap mMap;
private Marker expectedPlaceMarker;
private String lookupId = null;
private Location defaultLocation = new Location("default");
private TabLayout vehicleTypeTabLayout;
private TextView infoMessageViewText;
private LinearLayout infoMessageView;
private FrameLayout bottomButtonLayout;
private Button shareLiveLocationButton, retryButton, stopSharingButton;
private ImageButton shareButton, navigateButton;
private Place expectedPlace;
private ProgressDialog mProgressDialog;
private boolean isMapLoaded = false, isvehicleTypeTabLayoutVisible = false;
private float zoomLevel = 15.0f;
private HTUserVehicleType selectedVehicleType = SharedPreferenceManager.getLastSelectedVehicleType(this);
private IHomePresenter<HomeView> presenter = new HomePresenter();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// Initialize UI Views
initializeUIViews();
// Initialize Map Fragment added in Activity Layout to getMapAsync
HyperTrackMapFragment htMapFragment = (HyperTrackMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.htMapfragment);
HomeMapAdapter adapter = new HomeMapAdapter(this, getToolbar());
htMapFragment.setHTMapAdapter(adapter);
htMapFragment.setMapFragmentCallback(callback);
// Get Default User Location from his CountryCode
// SKIP: if Location Permission is Granted and Location is Enabled
if (!HyperTrack.checkLocationServices(this) || !HyperTrack.checkLocationPermission(this)) {
geocodeUserCountryName();
}
// Check & Prompt User if Internet is Not Connected
if (!HyperTrackUtils.isInternetConnected(this)) {
Toast.makeText(this, R.string.network_issue, Toast.LENGTH_SHORT).show();
}
// Set callback for HyperTrackEvent updates
setCallbackForHyperTrackEvents();
// Ask for tracking permission
checkForBackgroundTrackingPermission();
// Check if location is being shared currently
restoreLocationSharingIfNeeded();
// Handles Tracking Url deeplink
handleTrackingUrlDeeplink();
}
private void initializeUIViews() {
// Initialize Toolbar without Home Button
initToolbar();
// Initialize Retry button
retryButton = (Button) findViewById(R.id.retryButton);
// Initialize Share button and its click listener
shareButton = (ImageButton) findViewById(R.id.shareButton);
shareButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenter.shareTrackingUrl(ActionManager.getSharedManager(Home.this));
}
});
// Initialize ShareLiveLocation button and its click listener
shareLiveLocationButton = (Button) findViewById(R.id.shareLiveLocation);
bottomButtonLayout = (FrameLayout) findViewById(R.id.home_bottomButtonLayout);
shareLiveLocationButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
shareLiveLocation();
}
});
// Initialize StopSharing button and its click listener
stopSharingButton = (Button) findViewById(R.id.stopSharingButton);
stopSharingButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Check if Location Permission has been granted & Location has been enabled
if (HyperTrack.checkLocationPermission(Home.this) && HyperTrack.checkLocationServices(Home.this)) {
presenter.stopSharing(ActionManager.getSharedManager(Home.this));
}
}
});
// Initialize Navigate button and its click listener
navigateButton = (ImageButton) findViewById(R.id.navigateButton);
navigateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenter.openNavigationForExpectedPlace(ActionManager.getSharedManager(Home.this));
}
});
// Setup Info message view layouts
infoMessageView = (LinearLayout) findViewById(R.id.home_info_message_view);
infoMessageViewText = (TextView) findViewById(R.id.home_info_message_text);
// Initializing the vehicleTypeTabLayout and its tabs using addTab() method
vehicleTypeTabLayout = (TabLayout) findViewById(R.id.tabLayout);
vehicleTypeTabLayout.addTab(vehicleTypeTabLayout.newTab().setIcon(R.drawable.ic_vehicle_type_car));
vehicleTypeTabLayout.addTab(vehicleTypeTabLayout.newTab().setIcon(R.drawable.ic_vehicle_type_bus));
vehicleTypeTabLayout.addTab(vehicleTypeTabLayout.newTab().setIcon(R.drawable.ic_vehicle_type_motorbike));
vehicleTypeTabLayout.addTab(vehicleTypeTabLayout.newTab().setIcon(R.drawable.ic_vehicle_type_walk));
}
public MapFragmentCallback callback = new MapFragmentCallback() {
@Override
public void onMapReadyCallback(HyperTrackMapFragment hyperTrackMapFragment, GoogleMap map) {
onMapReady(map);
}
@Override
public void onExpectedPlaceSelected(Place expectedPlace) {
// Check if expected place was selected
if (expectedPlace != null) {
Home.this.expectedPlace = expectedPlace;
onSelectPlace(Home.this.expectedPlace);
}
}
@Override
public void onMapLoadedCallback(HyperTrackMapFragment hyperTrackMapFragment, GoogleMap map) {
isMapLoaded = true;
updateMapView();
}
@Override
public void onActionRefreshed(List<String> refreshedActionIds, List<Action> refreshedActions) {
if (shareLiveLocationButton != null && shareLiveLocationButton.isShown()
&& HyperTrack.getConsumerClient().getActiveActionIDList() == null) {
shareLiveLocationButton.setVisibility(View.GONE);
}
}
};
private void shareLiveLocation() {
//Check if Location Permission has been granted & Location has been enabled
if (HyperTrack.checkLocationPermission(this) && HyperTrack.checkLocationServices(this)) {
if (!ActionManager.getSharedManager(Home.this).isActionLive()) {
// Start the Task
startAction();
} else {
// Reset Current State when user chooses to edit destination
ActionManager.getSharedManager(Home.this).clearState();
OnStopSharing();
}
} else {
checkForLocationSettings();
}
}
private void checkForLocationSettings() {
// Check If LOCATION Permission is available & then if Location is enabled
if (!HyperTrack.checkLocationPermission(this)) {
HyperTrack.requestLocationServices(this, null);
return;
}
if (!HyperTrack.checkLocationServices(this)) {
HyperTrack.requestLocationServices(this, null);
}
}
/**
* Method to set callback for HyperTrackEvents to update notification with relevant information.
* Note: Show share tracking url message on Stop_Ended/Trip_Started event and reset it in other cases.
*/
private void setCallbackForHyperTrackEvents() {
HyperTrack.setCallback(new HyperTrackEventCallback() {
@Override
public void onEvent(@NonNull final HyperTrackEvent event) {
switch (event.getEventType()) {
case HyperTrackEvent.EventType.STOP_ENDED_EVENT:
//Check if user has shared his tracking link
if (ActionManager.getSharedManager(Home.this).isActionLive()) {
return;
}
Home.this.runOnUiThread(new Runnable() {
@Override
public void run() {
ServiceNotificationParamsBuilder builder = new ServiceNotificationParamsBuilder();
ArrayList<String> action = new ArrayList<>();
action.add("Set Destination Address");
ServiceNotificationParams notificationParams = builder
.setSmallIcon(R.drawable.ic_ht_service_notification_small)
.setSmallIconBGColor(ContextCompat.getColor(Home.this, R.color.colorAccent))
.setContentTitle(getString(R.string.notification_share_tracking_link))
.setContextText(getString(R.string.notification_set_expected_place))
.setContentIntentActivityClass(SplashScreen.class)
.setContentIntentExtras(action)
.build();
HyperTrack.setServiceNotificationParams(notificationParams);
}
});
break;
case HyperTrackEvent.EventType.TRACKING_STOPPED_EVENT:
case HyperTrackEvent.EventType.ACTION_ASSIGNED_EVENT:
case HyperTrackEvent.EventType.ACTION_COMPLETED_EVENT:
case HyperTrackEvent.EventType.STOP_STARTED_EVENT:
HyperTrack.clearServiceNotificationParams();
break;
}
}
@Override
public void onError(@NonNull final ErrorResponse errorResponse) {
// do nothing
}
});
}
/**
* Method to request user to be tracked in background. This enables the app to give user better
* suggestions for tracking links when he/she is on the move.
*/
private void checkForBackgroundTrackingPermission() {
// Check if a valid user exists
if (HyperTrack.getUserId() == null)
return;
// Check if the user has denied for Background tracking
if (!SharedPreferenceManager.hasRequestedForBackgroundTracking()) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.background_tracking_permission_msg)
.setPositiveButton("Enable", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startHyperTrackTracking(true);
}
})
.setNegativeButton("Disable", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
SharedPreferenceManager.setRequestedForBackgroundTracking();
}
}
/*
* Method to restore app's state in case of ongoing location sharing for current user.
*/
private void restoreLocationSharingIfNeeded() {
final ActionManager actionManager = ActionManager.getSharedManager(this);
//Check if there is any existing task to be restored
if (actionManager.shouldRestoreState()) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(getString(R.string.fetching_details_msg));
mProgressDialog.setCancelable(false);
mProgressDialog.show();
onShareLiveLocation();
} else {
// Initialize VehicleTabLayout
initializeVehicleTypeTab();
}
}
/**
* Method to handle Tracking url deeplinks to enable live location sharing amongst friends
*/
private void handleTrackingUrlDeeplink() {
Intent intent = getIntent();
if (intent != null && intent.getBooleanExtra(Track.KEY_TRACK_DEEPLINK, false)) {
// Add ProgressDialog
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(getString(R.string.fetching_details_msg));
mProgressDialog.show();
// Get required parameters for tracking Actions on map
lookupId = intent.getStringExtra(Track.KEY_LOOKUP_ID);
List<String> actionIDs = intent.getStringArrayListExtra(Track.KEY_ACTION_ID_LIST);
// Call trackActionsOnMap method
presenter.trackActionsOnMap(lookupId, actionIDs, ActionManager.getSharedManager(this));
}
}
@Override
public void showTrackActionsOnMapSuccess(List<Action> actions) {
if (mProgressDialog != null)
mProgressDialog.dismiss();
expectedPlace = ActionManager.getSharedManager(Home.this).getPlace();
showShareLiveLocationButton();
}
@Override
public void showTrackActionsOnMapError(ErrorResponse errorResponse) {
if (mProgressDialog != null)
mProgressDialog.dismiss();
Toast.makeText(this, errorResponse.getErrorMessage(), Toast.LENGTH_SHORT).show();
}
/**
* Method to be called when user selects an expected place to be used for sharing his live location
* via the tracking url.
* @param place Expected place for the user
*/
private void onSelectPlace(final Place place) {
if (place == null || this.isFinishing()) {
return;
}
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(getString(R.string.calculating_eta_message));
mProgressDialog.setCancelable(false);
mProgressDialog.show();
presenter.getETAForExpectedPlace(place, selectedVehicleType.toString(), ActionManager.getSharedManager(this));
}
@Override
public void showGetETAForExpectedPlaceSuccess(ETAResponse etaResponse, Place expectedPlace) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
// Hide Retry Button
showRetryButton(false, null);
onETASuccess(etaResponse, expectedPlace);
}
@Override
public void showGetETAForExpectedPlaceError(ErrorResponse errorResponse, Place expectedPlace) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
// Show Retry button to fetch eta again
showRetryButton(true, expectedPlace);
if (expectedPlaceMarker != null) {
expectedPlaceMarker.remove();
expectedPlaceMarker = null;
}
Toast.makeText(this, getString(R.string.eta_fetching_error), Toast.LENGTH_SHORT).show();
}
private void showRetryButton(boolean showRetryButton, final Place place) {
if (showRetryButton) {
// Initialize RetryButton on getETAForDestination failure
bottomButtonLayout.setVisibility(View.VISIBLE);
retryButton.setVisibility(View.VISIBLE);
retryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Fetch ETA for selected place
onSelectPlace(place);
}
});
} else {
// Reset Retry button
bottomButtonLayout.setVisibility(View.GONE);
retryButton.setVisibility(View.GONE);
retryButton.setOnClickListener(null);
}
}
private void onETASuccess(ETAResponse response, Place place) {
// Make the VehicleTabLayout visible onETASuccess
AnimationUtils.expand(vehicleTypeTabLayout);
isvehicleTypeTabLayoutVisible = true;
LatLng latLng = new LatLng(place.getLocation().getLatitude(), place.getLocation().getLongitude());
updateViewForETASuccess((int) response.getDuration() / 60, latLng);
expectedPlace = place;
ActionManager.getSharedManager(this).setPlace(expectedPlace);
}
private void updateViewForETASuccess(Integer etaInMinutes, LatLng latLng) {
showShareLiveLocationButton();
updateExpectedPlaceMarker(latLng, etaInMinutes);
updateMapView();
}
private void updateExpectedPlaceMarker(LatLng expectedPlaceLocation, Integer etaInMinutes) {
if (mMap == null) {
return;
}
if (expectedPlaceMarker != null) {
expectedPlaceMarker.remove();
expectedPlaceMarker = null;
}
View markerView = getExpectedPlaceMarkerView(etaInMinutes);
Bitmap bitmap = ImageUtils.getBitMapForView(this, markerView);
if (bitmap != null) {
expectedPlaceMarker = mMap.addMarker(new MarkerOptions()
.position(expectedPlaceLocation)
.icon(BitmapDescriptorFactory.fromBitmap(bitmap)));
bitmap.recycle();
}
}
private View getExpectedPlaceMarkerView(Integer etaInMinutes) {
View marker = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.custom_destination_marker_layout, null);
TextView etaTimeTextView = (TextView) marker.findViewById(R.id.eta_time);
TextView etaTimeTypeTextView = (TextView) marker.findViewById(R.id.eta_time_type_text);
updateTextViewForMinutes(etaTimeTextView, etaTimeTypeTextView, etaInMinutes);
return marker;
}
private void updateTextViewForMinutes(TextView etaTimeTextView, TextView etaTimeTypeTextView, Integer etaInMinutes) {
// Set empty view if etaInMinutes is null
if (etaInMinutes == null) {
etaTimeTextView.setText("");
etaTimeTypeTextView.setText("");
// Set ETA to 0 if etaInMinutes is 0 or below
} else if (etaInMinutes <= 0) {
etaInMinutes = 0;
etaTimeTextView.setText(String.valueOf(etaInMinutes));
etaTimeTypeTextView.setText(this.getResources().getQuantityString(R.plurals.eta_in_minute_text, etaInMinutes));
} else {
// Set ETA in minutes if etaInMinutes is equal or below MINUTES_ON_ETA_MARKER_LIMIT
if (etaInMinutes <= Constants.MINUTES_ON_ETA_MARKER_LIMIT) {
etaTimeTextView.setText(String.valueOf(etaInMinutes));
etaTimeTypeTextView.setText(this.getResources().getQuantityString(R.plurals.eta_in_minute_text, etaInMinutes));
// Set ETA in hours if etaInMinutes is above MINUTES_ON_ETA_MARKER_LIMIT
} else {
int hours = etaInMinutes / Constants.MINUTES_IN_AN_HOUR;
// Round off ETA to nearest hour
if (etaInMinutes % Constants.MINUTES_IN_AN_HOUR < Constants.MINUTES_TO_ROUND_OFF_TO_HOUR) {
etaTimeTextView.setText(String.valueOf(hours));
} else {
hours = hours + 1;
etaTimeTextView.setText(String.valueOf(hours));
}
etaTimeTypeTextView.setText(this.getResources().getQuantityString(R.plurals.eta_in_hour_text, hours));
}
}
}
private void showShareLiveLocationButton() {
// Set SendETA Button Text
shareLiveLocationButton.setText(getString(R.string.action_share_live_location));
shareLiveLocationButton.setVisibility(View.VISIBLE);
bottomButtonLayout.setVisibility(View.VISIBLE);
}
private void initializeVehicleTypeTab() {
// Remove onTabSelectedListener
vehicleTypeTabLayout.setOnTabSelectedListener(null);
for (int i = 0; i < vehicleTypeTabLayout.getTabCount(); i++) {
TabLayout.Tab tab = vehicleTypeTabLayout.getTabAt(i);
if (tab != null) {
if (selectedVehicleType.equals(getVehicleTypeForTabPosition(tab.getPosition()))) {
int tabIconColor = ContextCompat.getColor(Home.this, R.color.tab_layout_selected_item);
if (tab.getIcon() != null)
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
tab.select();
continue;
}
tab.setCustomView(R.layout.vehicle_type_tab_layout);
if (tab.getIcon() == null)
return;
int tabIconColor = ContextCompat.getColor(Home.this, R.color.tab_layout_unselected_item);
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
}
}
// Set onTabSelectedListener
vehicleTypeTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
// VehicleType tab has been changed
onVehicleTypeTabChanged(tab);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
if (tab == null || tab.getIcon() == null)
return;
int tabIconColor = ContextCompat.getColor(Home.this, R.color.tab_layout_unselected_item);
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void onVehicleTypeTabChanged(TabLayout.Tab tab) {
if (tab == null || tab.getIcon() == null)
return;
int tabIconColor = ContextCompat.getColor(Home.this, R.color.tab_layout_selected_item);
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
selectedVehicleType = getVehicleTypeForTabPosition(tab.getPosition());
// Check if a place has been selected or
Place place = ActionManager.getSharedManager(Home.this).getPlace();
if (place == null)
return;
// Call getETAForDestination with selected vehicleType
Home.this.onSelectPlace(place);
}
private HTUserVehicleType getVehicleTypeForTabPosition(int tabPosition) {
switch (tabPosition) {
case 1:
return HTUserVehicleType.VAN;
case 2:
return HTUserVehicleType.MOTORCYCLE;
case 3:
return HTUserVehicleType.WALK;
case 0:
default:
return HTUserVehicleType.CAR;
}
}
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
LatLng latLng;
if (SharedPreferenceManager.getActionID(Home.this) == null) {
if (googleMap != null && googleMap.isMyLocationEnabled() && googleMap.getMyLocation() != null) {
SharedPreferenceManager.setLastKnownLocation(googleMap.getMyLocation());
latLng = new LatLng(googleMap.getMyLocation().getLatitude(), googleMap.getMyLocation().getLongitude());
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoomLevel));
} else {
// Set Default View for map according to User's LastKnownLocation
if (SharedPreferenceManager.getLastKnownLocation() != null) {
defaultLocation = SharedPreferenceManager.getLastKnownLocation();
}
// Else Set Default View for map according to either User's Default Location
// (If Country Info was available) or (0.0, 0.0)
if (defaultLocation != null && defaultLocation.getLatitude() != 0.0
&& defaultLocation.getLongitude() != 0.0) {
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(defaultLocation.getLatitude(), defaultLocation.getLongitude()), zoomLevel));
}
}
}
mMap.getUiSettings().setMapToolbarEnabled(false);
mMap.getUiSettings().setZoomControlsEnabled(false);
mMap.getUiSettings().setCompassEnabled(false);
checkForLocationSettings();
}
private void updateMapPadding() {
if (mMap != null) {
int top = isvehicleTypeTabLayoutVisible ? getResources().getDimensionPixelSize(R.dimen.map_top_padding_with_vehicle_type_layout) :
getResources().getDimensionPixelSize(R.dimen.map_top_padding);
int left = getResources().getDimensionPixelSize(R.dimen.map_side_padding);
int bottom = getResources().getDimensionPixelSize(R.dimen.map_side_padding);
if (stopSharingButton.isShown())
bottom = getResources().getDimensionPixelSize(R.dimen.map_bottom_padding);
if (lookupId == null)
bottom = getResources().getDimensionPixelSize(R.dimen.home_map_bottom_padding);
mMap.setPadding(left, top, 0, bottom);
}
}
/**
* Method to Initiate START TASK
*/
private void startAction() {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(getString(R.string.sharing_live_location_message));
mProgressDialog.show();
presenter.shareLiveLocation(ActionManager.getSharedManager(this), lookupId, expectedPlace);
}
@Override
public void showShareLiveLocationError(ErrorResponse errorResponse) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
switch (errorResponse.getErrorCode()) {
case HyperTrackError.Code.PUBLISHABLE_KEY_NOT_CONFIGURED:
case HyperTrackError.Code.SDK_NOT_INITIALIZED:
case HyperTrackError.Code.USER_ID_NOT_CONFIGURED:
case HyperTrackError.Code.PLAY_SERVICES_UNAVAILABLE:
case HyperTrackError.Code.PERMISSIONS_NOT_REQUESTED:
case HyperTrackError.Code.LOCATION_SETTINGS_DISABLED:
case HyperTrackError.Code.LOCATION_SETTINGS_LOW_ACCURACY:
case HyperTrackError.Code.NETWORK_CONNECTIVITY_ERROR:
case HyperTrackError.Code.LOCATION_SETTINGS_CHANGE_UNAVAILABLE:
Toast.makeText(this, errorResponse.getErrorMessage(), Toast.LENGTH_SHORT).show();
return;
default:
Toast.makeText(this, ErrorMessages.SHARE_LIVE_LOCATION_FAILED, Toast.LENGTH_SHORT).show();
}
}
@Override
public void showShareLiveLocationSuccess(Action action) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
// Show ShareCard
presenter.shareTrackingUrl(ActionManager.getSharedManager(this));
onShareLiveLocation();
}
/**
* Method to update State Variables & UI to reflect Task Started
*/
private void onShareLiveLocation() {
if (ActionManager.getSharedManager(Home.this).getHyperTrackAction() == null)
return;
ActionManager.getSharedManager(this).setActionComletedListener(actionCompletedListener);
lookupId = ActionManager.getSharedManager(this).getHyperTrackAction().getLookupId();
HyperTrack.trackActionByLookupId(lookupId, new HyperTrackCallback() {
@Override
public void onSuccess(@NonNull SuccessResponse response) {
// do nothing
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
}
@Override
public void onError(@NonNull ErrorResponse errorResponse) {
Toast.makeText(Home.this, errorResponse.getErrorMessage(), Toast.LENGTH_SHORT).show();
}
});
expectedPlaceMarker = null;
// Hide VehicleType TabLayout onShareLiveLocation success
AnimationUtils.collapse(vehicleTypeTabLayout);
isvehicleTypeTabLayoutVisible = false;
shareLiveLocationButton.setVisibility(View.GONE);
stopSharingButton.setVisibility(View.VISIBLE);
stopSharingButton.setText(R.string.action_stop_sharing);
shareButton.setVisibility(View.VISIBLE);
navigateButton.setVisibility(View.VISIBLE);
// Update SelectedVehicleType in persistentStorage
SharedPreferenceManager.setLastSelectedVehicleType(selectedVehicleType);
supportInvalidateOptionsMenu();
}
private ActionManagerListener actionCompletedListener = new ActionManagerListener() {
@Override
public void OnCallback() {
// Initiate Stop Sharing on UI thread
runOnUiThread(new Runnable() {
@Override
public void run() {
presenter.stopSharing(ActionManager.getSharedManager(Home.this));
}
});
}
};
@Override
public void showStopSharingError() {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
Toast.makeText(this, getString(R.string.stop_sharing_failed), Toast.LENGTH_SHORT).show();
}
@Override
public void showStopSharingSuccess() {
OnStopSharing();
}
/**
* Method to update State Variables & UI to reflect Task Ended
*/
private void OnStopSharing() {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
// Reset lookupId variable
lookupId = null;
// Hide VehicleType TabLayout onShareLiveLocation success
AnimationUtils.collapse(vehicleTypeTabLayout);
isvehicleTypeTabLayoutVisible = false;
shareLiveLocationButton.setVisibility(View.GONE);
stopSharingButton.setVisibility(View.GONE);
bottomButtonLayout.setVisibility(View.GONE);
shareButton.setVisibility(View.GONE);
navigateButton.setVisibility(View.GONE);
if (SharedPreferenceManager.isTrackingON()) {
startHyperTrackTracking(true);
} else {
stopHyperTrackTracking();
}
supportInvalidateOptionsMenu();
updateMapView();
}
private void updateMapView() {
if (mMap == null || !isMapLoaded || lookupId != null) {
return;
}
LatLng currentLocation = null;
if (HyperTrack.checkLocationPermission(this) && mMap.isMyLocationEnabled() && mMap.getMyLocation() != null) {
currentLocation = new LatLng(mMap.getMyLocation().getLatitude(),
mMap.getMyLocation().getLongitude());
SharedPreferenceManager.setLastKnownLocation(mMap.getMyLocation());
}
try {
int count = 0;
LatLngBounds.Builder builder = new LatLngBounds.Builder();
if (currentLocation != null) {
builder.include(currentLocation);
count++;
}
if (expectedPlaceMarker != null) {
builder.include(expectedPlaceMarker.getPosition());
count++;
}
if (count == 1 && currentLocation != null) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLocation, zoomLevel));
} else if (count >= 1) {
mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 100));
}
updateMapPadding();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void showShareTrackingUrlError() {
Toast.makeText(Home.this, R.string.share_message_error, Toast.LENGTH_SHORT).show();
}
@Override
public void showShareTrackingUrlSuccess(String shareMessage) {
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareMessage);
startActivityForResult(Intent.createChooser(sharingIntent, "Share via"), Constants.SHARE_REQUEST_CODE);
}
@Override
public void showOpenNavigationError() {
Toast.makeText(Home.this, R.string.navigate_to_expected_place_error, Toast.LENGTH_SHORT).show();
}
@Override
public void showOpenNavigationSuccess(double latitude, double longitude) {
String navigationString = Double.toString(latitude) + "," + Double.toString(longitude) + "&mode=d";
Uri gmmIntentUri = Uri.parse("google.navigation:q=" + navigationString);
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
//Check if map application is installed or not.
try {
startActivity(mapIntent);
} catch (ActivityNotFoundException ex) {
try {
Intent unrestrictedIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
startActivity(unrestrictedIntent);
} catch (ActivityNotFoundException innerEx) {
Toast.makeText(this, "Please install a map application", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (ActionManager.getSharedManager(this).getHyperTrackAction() != null)
return false;
getMenuInflater().inflate(R.menu.menu_home, menu);
MenuItem menuItem = menu.findItem(R.id.tracking_toogle);
if (SharedPreferenceManager.isTrackingON()) {
menuItem.setTitle("Pause Tracking");
} else {
menuItem.setTitle("Resume Tracking");
}
// Hide menu items if user is on an Action
return true;
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.tracking_toogle:
// Check if clicked item is Resume tracking
if (getString(R.string.action_resume_tracking).equalsIgnoreCase(item.getTitle().toString())) {
// Start Tracking the user
startHyperTrackTracking(true);
item.setTitle(R.string.action_pause_tracking);
} else {
// Stop Tracking the user
stopHyperTrackTracking();
item.setTitle(R.string.action_resume_tracking);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void startHyperTrackTracking(final boolean byUser) {
// HACK: Check if user is tracking currently or not
// Only for exisitng users because Permission and Location Settings have been checked here
if (!HyperTrack.isTracking()) {
HyperTrack.startTracking();
if (byUser) {
SharedPreferenceManager.setTrackingON();
supportInvalidateOptionsMenu();
}
} else if (byUser) {
SharedPreferenceManager.setTrackingON();
supportInvalidateOptionsMenu();
}
}
private void stopHyperTrackTracking() {
HyperTrack.stopTracking();
SharedPreferenceManager.setTrackingOFF();
supportInvalidateOptionsMenu();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
if (requestCode == HyperTrack.REQUEST_CODE_LOCATION_PERMISSION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
checkForLocationSettings();
} else if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
PermissionUtils.showPermissionDeclineDialog(this, Manifest.permission.ACCESS_FINE_LOCATION,
getString(R.string.location_permission_never_allow));
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == HyperTrack.REQUEST_CODE_LOCATION_SERVICES) {
if (resultCode == Activity.RESULT_OK) {
checkForLocationSettings();
} else {
// Handle Location services request denied error
Snackbar.make(findViewById(R.id.parent_layout), R.string.location_services_snackbar_msg,
Snackbar.LENGTH_INDEFINITE).setAction("Enable Location", new View.OnClickListener() {
@Override
public void onClick(View v) {
checkForLocationSettings();
}
}).show();
}
}
}
private void geocodeUserCountryName() {
// Fetch Country Level Location only if no cached location is available
Location lastKnownCachedLocation = SharedPreferenceManager.getLastKnownLocation();
if (lastKnownCachedLocation == null || lastKnownCachedLocation.getLatitude() == 0.0
|| lastKnownCachedLocation.getLongitude() == 0.0) {
OnboardingManager onboardingManager = OnboardingManager.sharedManager();
String countryName = Utils.getCountryName(onboardingManager.getUser().getCountryCode());
if (!TextUtils.isEmpty(countryName)) {
Intent intent = new Intent(this, FetchLocationIntentService.class);
intent.putExtra(FetchLocationIntentService.RECEIVER, new GeocodingResultReceiver(new Handler()));
intent.putExtra(FetchLocationIntentService.ADDRESS_DATA_EXTRA, countryName);
startService(intent);
}
}
}
@SuppressLint("ParcelCreator")
private class GeocodingResultReceiver extends ResultReceiver {
GeocodingResultReceiver(Handler handler) {
super(handler);
}
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == FetchLocationIntentService.SUCCESS_RESULT) {
LatLng latLng = resultData.getParcelable(FetchLocationIntentService.RESULT_DATA_KEY);
if (latLng == null)
return;
defaultLocation.setLatitude(latLng.latitude);
defaultLocation.setLongitude(latLng.longitude);
Log.d(TAG, "Geocoding for Country Name Successful: " + latLng.toString());
if (mMap != null) {
if (defaultLocation.getLatitude() != 0.0 || defaultLocation.getLongitude() != 0.0)
zoomLevel = 4.0f;
// Check if any Location Data is available, meaning Country zoom level need not be used
Location lastKnownCachedLocation = SharedPreferenceManager.getLastKnownLocation();
if (lastKnownCachedLocation != null && lastKnownCachedLocation.getLatitude() != 0.0
&& lastKnownCachedLocation.getLongitude() != 0.0) {
return;
}
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoomLevel));
}
}
}
}
@Override
protected void onResume() {
super.onResume();
// Attach View Presenter to View
presenter.attachView(this);
ActionManager actionManager = ActionManager.getSharedManager(Home.this);
if (actionManager.getHyperTrackAction() != null && !actionManager.getHyperTrackAction().isCompleted()) {
actionManager.setActionComletedListener(actionCompletedListener);
lookupId = actionManager.getHyperTrackAction().getLookupId();
HyperTrack.trackActionByLookupId(lookupId, null);
}
// Check if Location & Network are Enabled
updateInfoMessageView();
// Re-register BroadcastReceiver for Location_Change, Network_Change & GCM
LocalBroadcastManager.getInstance(this).registerReceiver(mLocationChangeReceiver,
new IntentFilter(GpsLocationReceiver.LOCATION_CHANGED));
LocalBroadcastManager.getInstance(this).registerReceiver(mConnectivityChangeReceiver,
new IntentFilter(NetworkChangeReceiver.NETWORK_CHANGED));
}
BroadcastReceiver mLocationChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateInfoMessageView();
}
};
BroadcastReceiver mConnectivityChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateInfoMessageView();
}
};
private void updateInfoMessageView() {
if (!HyperTrackUtils.isLocationEnabled(Home.this)) {
infoMessageView.setVisibility(View.VISIBLE);
if (!HyperTrackUtils.isInternetConnected(this)) {
infoMessageViewText.setText(R.string.location_off_info_message);
} else {
infoMessageViewText.setText(R.string.location_off_info_message);
}
} else {
infoMessageView.setVisibility(View.VISIBLE);
if (!HyperTrackUtils.isInternetConnected(this)) {
infoMessageViewText.setText(R.string.internet_off_info_message);
} else {
// Both Location & Network Enabled, Hide the Info Message View
infoMessageView.setVisibility(View.GONE);
}
}
}
@Override
protected void onPause() {
super.onPause();
// Attach View Presenter to View
presenter.detachView();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mConnectivityChangeReceiver);
LocalBroadcastManager.getInstance(this).unregisterReceiver(mLocationChangeReceiver);
}
@Override
public void onBackPressed() {
if (!isvehicleTypeTabLayoutVisible) {
HyperTrack.removeActions(null);
super.onBackPressed();
} else {
OnStopSharing();
}
}
@Override
protected void onStop() {
super.onStop();
HyperTrack.removeActions(null);
if (mProgressDialog != null)
mProgressDialog.dismiss();
}
}