1 /* 2 * Copyright (C) 2014 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.wearable.speedtracker; 18 19 import com.google.android.gms.maps.CameraUpdateFactory; 20 import com.google.android.gms.maps.GoogleMap; 21 import com.google.android.gms.maps.SupportMapFragment; 22 import com.google.android.gms.maps.OnMapReadyCallback; 23 import com.google.android.gms.maps.model.LatLng; 24 import com.google.android.gms.maps.model.LatLngBounds; 25 import com.google.android.gms.maps.model.PolylineOptions; 26 27 import android.app.DatePickerDialog; 28 import android.os.AsyncTask; 29 import android.os.Bundle; 30 import android.support.v7.app.AppCompatActivity; 31 import android.text.format.DateUtils; 32 import android.util.Log; 33 import android.view.View; 34 import android.widget.DatePicker; 35 import android.widget.TextView; 36 37 import com.example.android.wearable.speedtracker.common.LocationEntry; 38 39 import java.util.ArrayList; 40 import java.util.Calendar; 41 import java.util.List; 42 43 /** 44 * The main activity for the handset application. When a watch device reconnects to the handset 45 * app, the collected GPS data on the watch, if any, is synced up and user can see his/her track on 46 * a map. This data is then saved into an internal database and the corresponding data items are 47 * deleted. 48 */ 49 public class PhoneMainActivity extends AppCompatActivity implements 50 DatePickerDialog.OnDateSetListener, OnMapReadyCallback { 51 52 private static final String TAG = "PhoneMainActivity"; 53 private static final int BOUNDING_BOX_PADDING_PX = 50; 54 private TextView mSelectedDateText; 55 private GoogleMap mMap; 56 private SupportMapFragment mMapFragment; 57 58 @Override onCreate(Bundle savedInstanceState)59 protected void onCreate(Bundle savedInstanceState) { 60 super.onCreate(savedInstanceState); 61 setContentView(R.layout.main_activity); 62 mSelectedDateText = (TextView) findViewById(R.id.selected_date); 63 mMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); 64 mMapFragment.getMapAsync(this); 65 } 66 onClick(View view)67 public void onClick(View view) { 68 Calendar calendar = Calendar.getInstance(); 69 calendar.setTimeInMillis(System.currentTimeMillis()); 70 new DatePickerDialog(PhoneMainActivity.this, PhoneMainActivity.this, 71 calendar.get(Calendar.YEAR), 72 calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)).show(); 73 } 74 75 @Override onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)76 public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { 77 // the following if-clause is to get around a bug that causes this callback to be called 78 // twice 79 if (view.isShown()) { 80 Calendar calendar = Calendar.getInstance(); 81 calendar.setTimeInMillis(System.currentTimeMillis()); 82 calendar.set(Calendar.YEAR, year); 83 calendar.set(Calendar.MONTH, monthOfYear); 84 calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth); 85 String date = DateUtils.formatDateTime(this, calendar.getTimeInMillis(), 86 DateUtils.FORMAT_SHOW_DATE); 87 mSelectedDateText.setText(getString(R.string.showing_for_date, date)); 88 showTrack(calendar); 89 } 90 } 91 92 /** 93 * An {@link android.os.AsyncTask} that is responsible for getting a list of {@link 94 * com.example.android.wearable.speedtracker.common.LocationEntry} objects for a given day and 95 * building a track from those points. In addition, it sets the smallest bounding box for the 96 * map that covers all the points on the track. 97 */ showTrack(Calendar calendar)98 private void showTrack(Calendar calendar) { 99 new AsyncTask<Calendar, Void, Void>() { 100 101 private List<LatLng> coordinates; 102 private LatLngBounds bounds; 103 104 @Override 105 protected Void doInBackground(Calendar... params) { 106 LocationDataManager dataManager = ((PhoneApplication) getApplicationContext()) 107 .getDataManager(); 108 List<LocationEntry> entries = dataManager.getPoints(params[0]); 109 if (entries != null && !entries.isEmpty()) { 110 coordinates = new ArrayList<LatLng>(); 111 LatLngBounds.Builder builder = new LatLngBounds.Builder(); 112 for (LocationEntry entry : entries) { 113 LatLng latLng = new LatLng(entry.latitude, entry.longitude); 114 builder.include(latLng); 115 coordinates.add(latLng); 116 } 117 bounds = builder.build(); 118 } 119 return null; 120 } 121 122 @Override 123 protected void onPostExecute(Void aVoid) { 124 mMap.clear(); 125 if (coordinates == null || coordinates.isEmpty()) { 126 if (Log.isLoggable(TAG, Log.DEBUG)) { 127 Log.d(TAG, "No Entries found for that date"); 128 } 129 } else { 130 mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 131 BOUNDING_BOX_PADDING_PX)); 132 mMap.addPolyline(new PolylineOptions().geodesic(true).addAll(coordinates)); 133 } 134 } 135 136 }.execute(calendar); 137 } 138 139 @Override onMapReady(GoogleMap googleMap)140 public void onMapReady(GoogleMap googleMap) { 141 mMap = googleMap; 142 } 143 } 144