package it.bz.its.angelhack.threedudes.hikingbuddy.activities; import android.app.Activity; import android.app.PendingIntent; import android.app.ProgressDialog; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.os.AsyncTask; import android.os.Handler; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.PolylineOptions; import java.util.Date; import java.util.List; import it.bz.its.angelhack.threedudes.hikingbuddy.Constants; import it.bz.its.angelhack.threedudes.hikingbuddy.R; import it.bz.its.angelhack.threedudes.hikingbuddy.Utils; import it.bz.its.angelhack.threedudes.hikingbuddy.models.HeightGraph; import it.bz.its.angelhack.threedudes.hikingbuddy.models.Location; import it.bz.its.angelhack.threedudes.hikingbuddy.models.Mission; import it.bz.its.angelhack.threedudes.hikingbuddy.models.MissionSessionResponse; import it.bz.its.angelhack.threedudes.hikingbuddy.models.Route; import it.bz.its.angelhack.threedudes.hikingbuddy.models.RoutePoint; import it.bz.its.angelhack.threedudes.hikingbuddy.services.MissionService; import it.bz.its.angelhack.threedudes.hikingbuddy.services.MissionSessionService; import retrofit.Callback; import retrofit.RestAdapter; import retrofit.RetrofitError; import retrofit.client.Response; public class RouteMapActivity extends AppCompatActivity { private static final String TAG = "RouteMapActivity"; public static final String MISSION_HOLDER_ID = "RouteMapActivity.Mission"; private GoogleMap mMap; // Might be null if Google Play services APK is not available. private Mission currentMission; private Route currentRoute; private Date missionStartTime; private NfcAdapter nfcAdapter; private PendingIntent pendingIntent; private String displayedCounterVal; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_route_map); // Load the route RestAdapter restAdapter = Utils.getRestAdapter(RouteMapActivity.this); final MissionSessionService msr = restAdapter.create(MissionSessionService.class); final MissionService ms = restAdapter.create(MissionService.class); // Prepare the NFC listener nfcAdapter = NfcAdapter.getDefaultAdapter(this); pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); // Process the starting intent Intent starterIntent = getIntent(); if (starterIntent != null && starterIntent.hasExtra(MISSION_HOLDER_ID)) { currentMission = starterIntent.getParcelableExtra(MISSION_HOLDER_ID); starterIntent.removeExtra(MISSION_HOLDER_ID); } // Create the timer update logic final TextView tvTimer = (TextView) this.findViewById(R.id.tv_mission_counter); missionStartTime = new Date(); Handler counterHandler = new Handler(); counterHandler.post(new Runnable() { @Override public void run() { Activity ctx = RouteMapActivity.this; ctx.runOnUiThread(new Runnable() { @Override public void run() { Date now = new Date(); long dateDiff = now.getTime() - missionStartTime.getTime(); long minutesElapsed = dateDiff / (60 * 1000); long secondsElapsed = (dateDiff - minutesElapsed * 60 * 1000) / 1000; long millisecondsElapsed = (dateDiff % 1000) / 10; displayedCounterVal = String.format("%02d:%02d:%02d", minutesElapsed, secondsElapsed, millisecondsElapsed); tvTimer.setText(displayedCounterVal); } }); Handler mainHandler = new Handler(ctx.getMainLooper()); mainHandler.postDelayed(this, Constants.TIMER_INCREMENT_VAL_MS); } }); // Handle the "Cancel Mission" logic Button btCancelMission = (Button) this.findViewById(R.id.bt_cancel_mission); btCancelMission.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Utils.showYesNoAlertDialog(RouteMapActivity.this, "Are you sure?", "Do you really want to cancel this current mission?", new Runnable() { @Override public void run() { final ProgressDialog progDialog = Utils.newLoadingDialog(RouteMapActivity.this, "Cancelling mission ..."); progDialog.show(); msr.abortMission(new Callback<Response>() { @Override public void success(Response response, Response response2) { Intent mainMissionIntentActivity = new Intent(RouteMapActivity.this, MainActivity.class); startActivity(mainMissionIntentActivity); progDialog.dismiss(); finish(); } @Override public void failure(RetrofitError error) { Utils.showOkAlertDialog(RouteMapActivity.this, "Problem", error.getMessage(), null); progDialog.dismiss(); } }); } }, null // No clicked ); } }); if (currentMission != null) { final ProgressDialog progDialog = Utils.newLoadingDialog(RouteMapActivity.this, "Downloading route ..."); progDialog.show(); ms.getRoute(currentMission.getId(), new Callback<Route>() { @Override public void success(Route route, Response response2) { Log.d(TAG, "Received a route with " + route.getRoute().size() + " geo points."); currentRoute = route; setUpMapIfNeeded(); progDialog.dismiss(); } @Override public void failure(RetrofitError error) { Utils.showOkAlertDialog(RouteMapActivity.this, "Problem", error.getMessage(), null); progDialog.dismiss(); } }); } } @Override protected void onResume() { super.onResume(); nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null); setUpMapIfNeeded(); } @Override protected void onPause() { super.onPause(); nfcAdapter.disableForegroundDispatch(this); } @Override protected void onNewIntent(Intent intent) { Log.d(TAG, "New intent received: " + intent.getAction()); Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); RestAdapter restAdapter = Utils.getRestAdapter(RouteMapActivity.this); MissionSessionService msr = restAdapter.create(MissionSessionService.class); final ProgressDialog progDialog = Utils.newLoadingDialog(RouteMapActivity.this, "Ending mission ..."); progDialog.show(); msr.checkTag(Utils.bytesToHex(tag.getId()), new Callback<MissionSessionResponse>() { @Override public void success(MissionSessionResponse response, Response response2) { Intent endMissionIntentActivity = new Intent(RouteMapActivity.this, EndMissionActivity.class); endMissionIntentActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); if (currentMission != null) { endMissionIntentActivity.putExtra(EndMissionActivity.MISSION_ID, currentMission.getId()); } else { SharedPreferences prefs = getSharedPreferences("infos", MODE_PRIVATE); endMissionIntentActivity.putExtra(EndMissionActivity.MISSION_ID, prefs.getInt("mission_id", 1)); } endMissionIntentActivity.putExtra(EndMissionActivity.MISSION_TIME_ELAPSED, displayedCounterVal); startActivity(endMissionIntentActivity); progDialog.dismiss(); finish(); } @Override public void failure(RetrofitError error) { Utils.showOkAlertDialog(RouteMapActivity.this, "Problem", error.getMessage(), null); progDialog.dismiss(); } }); } /** * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly * installed) and the map has not already been instantiated.. This will ensure that we only ever * call {@link #setUpMap()} once when {@link #mMap} is not null. * <p/> * If it isn't installed {@link SupportMapFragment} (and * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to * install/update the Google Play services APK on their device. * <p/> * A user can return to this FragmentActivity after following the prompt and correctly * installing/updating/enabling the Google Play services. Since the FragmentActivity may not * have been completely destroyed during this process (it is likely that it would only be * stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this * method in {@link #onResume()} to guarantee that it will be called. */ private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) .getMap(); // Check if we were successful in obtaining the map. if (mMap != null) { setUpMap(); } } } private void setUpMap() { if (mMap != null) { // Add the important markers if (currentMission != null) { for (Location missLoc: currentMission.getImportantPoints()) { mMap.addMarker(new MarkerOptions().position(missLoc.getGoogleMapCoord())); } // Reposition the camera to see the whole rute mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { @Override public void onMapLoaded() { // Draw the route new AsyncRouteRenderer().execute(currentRoute); mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(currentMission.getLatLngBounds(), 40)); } }); } } } private class AsyncRouteRenderer extends AsyncTask<Route, PolylineOptions, Long> { ProgressDialog pgd; protected void onPreExecute() { pgd = Utils.newLoadingDialog(RouteMapActivity.this, "Loading route ..."); pgd.show(); } protected Long doInBackground(Route... rs) { if (rs != null && rs.length != 0 && rs[0] != null) { Route route = rs[0]; List<RoutePoint> routePoints = route.getRoute(); if (routePoints.size() > 1) { for (int i = 0; i < routePoints.size() - 1; i++) { PolylineOptions segmOptions = new PolylineOptions() .add(routePoints.get(i).getGoogleMapCoord(), routePoints.get(i + 1).getGoogleMapCoord()) .width(4) .color(Color.RED); publishProgress(segmOptions); } } } return 0L; } protected void onProgressUpdate(PolylineOptions... lineOpt) { if (lineOpt != null) { mMap.addPolyline(lineOpt[0]); } } protected void onPostExecute(Long result) { pgd.dismiss(); } } }