forked from upstream-mirrors/OpenTracks
App now compiles and runs.
This commit is contained in:
+24
-19
@@ -5,7 +5,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.maps.mytracks"
|
||||
minSdkVersion 14
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 26
|
||||
|
||||
testApplicationId "com.google.android.maps.mytracks.test"
|
||||
@@ -22,33 +22,38 @@ android {
|
||||
|
||||
dependencies {
|
||||
compile project(':myTracksLib')
|
||||
compile files('libs/android-support-v4.jar')
|
||||
//compile files('libs/android-support-v4.jar')
|
||||
compile files('libs/antlib.jar')
|
||||
compile files('libs/gdata-client-1.0.jar')
|
||||
compile files('libs/gdata-client-meta-1.0.jar')
|
||||
compile files('libs/gdata-core-1.0.jar')
|
||||
compile files('libs/gdata-spreadsheet-3.0.jar')
|
||||
compile files('libs/gdata-spreadsheet-meta-3.0.jar')
|
||||
//compile files('libs/gdata-client-1.0.jar')
|
||||
//compile files('libs/gdata-client-meta-1.0.jar')
|
||||
//compile files('libs/gdata-core-1.0.jar')
|
||||
//compile files('libs/gdata-spreadsheet-3.0.jar')
|
||||
//compile files('libs/gdata-spreadsheet-meta-3.0.jar')
|
||||
compile files('libs/google-api-client-1.12.0-beta.jar')
|
||||
compile files('libs/google-api-client-android-1.12.0-beta.jar')
|
||||
compile files('libs/google-api-services-drive-v2-rev30-1.12.0-beta.jar')
|
||||
compile files('libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar')
|
||||
compile files('libs/google-common.jar')
|
||||
//compile files('libs/google-api-services-fusiontables-v1-rev16-1.12.0-beta.jar')
|
||||
//compile files('libs/google-common.jar')
|
||||
compile files('libs/google-http-client-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-android-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-gson-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-jackson-1.12.0-beta.jar')
|
||||
compile files('libs/google-http-client-jackson2-1.12.0-beta.jar')
|
||||
compile files('libs/google-oauth-client-1.12.0-beta.jar')
|
||||
compile files('libs/google-play-services.jar')
|
||||
compile files('libs/gson-2.1.jar')
|
||||
compile files('libs/guava-jdk5-13.0.jar')
|
||||
compile files('libs/jackson-core-2.0.5.jar')
|
||||
compile files('libs/jackson-core-asl-1.9.9.jar')
|
||||
compile files('libs/jsr305.jar')
|
||||
compile files('libs/libGoogleAnalytics.jar')
|
||||
//compile files('libs/google-http-client-jackson-1.12.0-beta.jar')
|
||||
//compile files('libs/google-http-client-jackson2-1.12.0-beta.jar')
|
||||
//compile files('libs/google-oauth-client-1.12.0-beta.jar')
|
||||
//compile files('libs/google-play-services.jar')
|
||||
//compile files('libs/gson-2.1.jar')
|
||||
compile files('libs/guava-jdk5-13.0.jar') //@visiblefortesting
|
||||
//compile files('libs/jackson-core-2.0.5.jar')
|
||||
//compile files('libs/jackson-core-asl-1.9.9.jar')
|
||||
//compile files('libs/jsr305.jar')
|
||||
//compile files('libs/libGoogleAnalytics.jar')
|
||||
androidTestCompile files('libs/AndroidMockGenerator.jar')
|
||||
androidTestCompile files('libs/robotium-solo-5.0.1.jar')
|
||||
|
||||
implementation 'com.google.android.gms:play-services-location:11.8.0'
|
||||
implementation 'com.google.android.gms:play-services:11.8.0'
|
||||
implementation 'com.google.android.gms:play-services-auth:11.8.0'
|
||||
// compile 'com.google.firebase:firebase-core:9.2.0'
|
||||
// compile 'com.google.firebase:firebase-auth:9.2.0'
|
||||
// compile 'com.google.firebase:firebase-messaging:11.8.0'
|
||||
}
|
||||
|
||||
-1
@@ -20,7 +20,6 @@ import com.google.android.apps.mytracks.TrackDetailActivity;
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
|
||||
import com.google.android.apps.mytracks.fragments.ChartFragment;
|
||||
import com.google.android.apps.mytracks.fragments.MyTracksMapFragment;
|
||||
import com.google.android.apps.mytracks.fragments.StatsFragment;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.google.android.apps.mytracks.fragments.ExportDialogFragment.ExportCal
|
||||
import com.google.android.apps.mytracks.fragments.ExportDialogFragment.ExportType;
|
||||
import com.google.android.apps.mytracks.fragments.FrequencyDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.MapLayerDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.MyTracksMapFragment;
|
||||
import com.google.android.apps.mytracks.fragments.PlayMultipleDialogFragment;
|
||||
import com.google.android.apps.mytracks.fragments.PlayMultipleDialogFragment.PlayMultipleCaller;
|
||||
import com.google.android.apps.mytracks.fragments.StatsFragment;
|
||||
@@ -236,11 +235,6 @@ public class TrackDetailActivity extends AbstractSendToGoogleActivity
|
||||
|
||||
tabsAdapter = new TabsAdapter(this, tabHost, viewPager);
|
||||
|
||||
TabSpec mapTabSpec = tabHost.newTabSpec(MyTracksMapFragment.MAP_FRAGMENT_TAG).setIndicator(
|
||||
getString(R.string.track_detail_map_tab),
|
||||
getResources().getDrawable(R.drawable.ic_tab_map));
|
||||
tabsAdapter.addTab(mapTabSpec, MyTracksMapFragment.class, null);
|
||||
|
||||
TabSpec chartTabSpec = tabHost.newTabSpec(ChartFragment.CHART_FRAGMENT_TAG).setIndicator(
|
||||
getString(R.string.track_detail_chart_tab),
|
||||
getResources().getDrawable(R.drawable.ic_tab_chart));
|
||||
|
||||
-764
@@ -1,764 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.android.apps.mytracks.fragments;
|
||||
|
||||
import com.google.android.apps.mytracks.MapOverlay;
|
||||
import com.google.android.apps.mytracks.MarkerDetailActivity;
|
||||
import com.google.android.apps.mytracks.TrackDetailActivity;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
|
||||
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.Factory;
|
||||
import com.google.android.apps.mytracks.content.Track;
|
||||
import com.google.android.apps.mytracks.content.TrackDataHub;
|
||||
import com.google.android.apps.mytracks.content.TrackDataListener;
|
||||
import com.google.android.apps.mytracks.content.TrackDataType;
|
||||
import com.google.android.apps.mytracks.content.Waypoint;
|
||||
import com.google.android.apps.mytracks.services.MyTracksLocationManager;
|
||||
import com.google.android.apps.mytracks.stats.TripStatistics;
|
||||
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
|
||||
import com.google.android.apps.mytracks.util.GoogleLocationUtils;
|
||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||
import com.google.android.apps.mytracks.util.LocationUtils;
|
||||
import com.google.android.apps.mytracks.util.PreferencesUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackIconUtils;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.maps.CameraUpdate;
|
||||
import com.google.android.gms.maps.CameraUpdateFactory;
|
||||
import com.google.android.gms.maps.GoogleMap;
|
||||
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
|
||||
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
|
||||
import com.google.android.gms.maps.LocationSource;
|
||||
import com.google.android.gms.maps.LocationSource.OnLocationChangedListener;
|
||||
import com.google.android.gms.maps.SupportMapFragment;
|
||||
import com.google.android.gms.maps.model.CameraPosition;
|
||||
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.Polyline;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* A fragment to display map to the user.
|
||||
*
|
||||
* @author Leif Hendrik Wilden
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class MyTracksMapFragment extends SupportMapFragment implements TrackDataListener {
|
||||
|
||||
public static final String MAP_FRAGMENT_TAG = "mapFragment";
|
||||
|
||||
private static final String CURRENT_LOCATION_KEY = "current_location_key";
|
||||
private static final String
|
||||
KEEP_CURRENT_LOCATION_VISIBLE_KEY = "keep_current_location_visible_key";
|
||||
|
||||
private static final float DEFAULT_ZOOM_LEVEL = 18f;
|
||||
|
||||
// Google's latitude and longitude
|
||||
private static final double DEFAULT_LATITUDE = 37.423;
|
||||
private static final double DEFAULT_LONGITUDE = -122.084;
|
||||
|
||||
private static final int MAP_VIEW_PADDING = 32;
|
||||
|
||||
// States from TrackDetailActivity, set in onResume
|
||||
private TrackDataHub trackDataHub;
|
||||
|
||||
// Current location
|
||||
private Location currentLocation;
|
||||
private Location lastTrackPoint;
|
||||
private int recordingGpsAccuracy = PreferencesUtils.RECORDING_GPS_ACCURACY_DEFAULT;
|
||||
|
||||
/**
|
||||
* True to continue keeping the current location visible on the screen.
|
||||
* <p>
|
||||
* Set to true when <br>
|
||||
* 1. user clicks on the my location button <br>
|
||||
* 2. first location during a recording <br>
|
||||
* Set to false when <br>
|
||||
* 1. showing a marker <br>
|
||||
* 2. user manually zooms/pans
|
||||
*/
|
||||
private boolean keepCurrentLocationVisible;
|
||||
private MyTracksLocationManager myTracksLocationManager;
|
||||
|
||||
// LocationListener for periodic location request
|
||||
private LocationListener locationListener;
|
||||
|
||||
private OnLocationChangedListener onLocationChangedListener;
|
||||
|
||||
// Current track
|
||||
private Track currentTrack;
|
||||
|
||||
// Current paths
|
||||
private ArrayList<Polyline> paths = new ArrayList<Polyline>();
|
||||
boolean reloadPaths = true;
|
||||
|
||||
// UI elements
|
||||
private GoogleMap googleMap;
|
||||
private MapOverlay mapOverlay;
|
||||
private View mapView;
|
||||
private ImageButton myLocationImageButton;
|
||||
private TextView messageTextView;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
setHasOptionsMenu(true);
|
||||
mapOverlay = new MapOverlay(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
mapView = super.onCreateView(inflater, container, savedInstanceState);
|
||||
View layout = inflater.inflate(R.layout.map, container, false);
|
||||
RelativeLayout mapContainer = (RelativeLayout) layout.findViewById(R.id.map_container);
|
||||
mapContainer.addView(mapView, 0);
|
||||
|
||||
/*
|
||||
* For Froyo (2.2) and Gingerbread (2.3), need a transparent FrameLayout on
|
||||
* top for view pager to work correctly.
|
||||
*/
|
||||
FrameLayout frameLayout = new FrameLayout(getActivity());
|
||||
frameLayout.setBackgroundColor(getResources().getColor(android.R.color.transparent));
|
||||
mapContainer.addView(frameLayout,
|
||||
new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
|
||||
|
||||
myLocationImageButton = (ImageButton) layout.findViewById(R.id.map_my_location);
|
||||
myLocationImageButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!myTracksLocationManager.isGpsProviderEnabled()) {
|
||||
String message = GoogleLocationUtils.getGpsDisabledMyLocationMessage(getActivity());
|
||||
Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
keepCurrentLocationVisible = true;
|
||||
if (locationListener != null) {
|
||||
myTracksLocationManager.removeLocationUpdates(locationListener);
|
||||
locationListener = null;
|
||||
}
|
||||
if (isSelectedTrackRecording()) {
|
||||
myTracksLocationManager.requestLastLocation(new LocationListener() {
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
if (isResumed()) {
|
||||
setCurrentLocation(location);
|
||||
updateCurrentLocation(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
locationListener = new LocationListener() {
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
if (isResumed()) {
|
||||
boolean isFirst = setCurrentLocation(location);
|
||||
updateCurrentLocation(isFirst);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Set currentLocation to null to cause the first requested location
|
||||
* to force zoom to the default level.
|
||||
*/
|
||||
currentLocation = null;
|
||||
myTracksLocationManager.requestLocationUpdates(0, 0f, locationListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
messageTextView = (TextView) layout.findViewById(R.id.map_message);
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
keepCurrentLocationVisible = savedInstanceState.getBoolean(
|
||||
KEEP_CURRENT_LOCATION_VISIBLE_KEY, false);
|
||||
if (keepCurrentLocationVisible) {
|
||||
Location location = (Location) savedInstanceState.getParcelable(CURRENT_LOCATION_KEY);
|
||||
if (location != null) {
|
||||
setCurrentLocation(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, after onCreateView, getMap will not return null and we can
|
||||
* initialize googleMap. However, onActivityCreated can be called multiple
|
||||
* times, e.g., when the user switches tabs. With
|
||||
* GoogleMapOptions.useViewLifecycleInFragment == false, googleMap lifecycle
|
||||
* is tied to the fragment lifecycle and the same googleMap object is
|
||||
* returned in getMap. Thus we only need to initialize googleMap once, when
|
||||
* it is null.
|
||||
*/
|
||||
if (googleMap == null) {
|
||||
googleMap = getMap();
|
||||
googleMap.setMyLocationEnabled(true);
|
||||
|
||||
/*
|
||||
* My Tracks needs to handle the onClick event when the my location button
|
||||
* is clicked. Currently, the API doesn't allow handling onClick event,
|
||||
* thus hiding the default my location button and providing our own.
|
||||
*/
|
||||
googleMap.getUiSettings().setMyLocationButtonEnabled(false);
|
||||
googleMap.setIndoorEnabled(true);
|
||||
googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {
|
||||
|
||||
@Override
|
||||
public boolean onMarkerClick(Marker marker) {
|
||||
if (isResumed()) {
|
||||
String title = marker.getTitle();
|
||||
if (title != null && title.length() > 0) {
|
||||
long id = Long.valueOf(title);
|
||||
Context context = getActivity();
|
||||
Intent intent = IntentUtils.newIntent(context, MarkerDetailActivity.class)
|
||||
.putExtra(MarkerDetailActivity.EXTRA_MARKER_ID, id);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
googleMap.setLocationSource(new LocationSource() {
|
||||
|
||||
@Override
|
||||
public void activate(OnLocationChangedListener listener) {
|
||||
onLocationChangedListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
onLocationChangedListener = null;
|
||||
}
|
||||
});
|
||||
googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onCameraChange(CameraPosition cameraPosition) {
|
||||
if (isResumed() && keepCurrentLocationVisible && currentLocation != null
|
||||
&& !isLocationVisible(currentLocation)) {
|
||||
keepCurrentLocationVisible = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// First obtain the states from TrackDetailActivity
|
||||
long trackId = ((TrackDetailActivity) getActivity()).getTrackId();
|
||||
long markerId = ((TrackDetailActivity) getActivity()).getMarkerId();
|
||||
resumeTrackDataHub();
|
||||
|
||||
myTracksLocationManager = new MyTracksLocationManager(getActivity(), Looper.myLooper(), true);
|
||||
boolean isGpsProviderEnabled = myTracksLocationManager.isGpsProviderEnabled();
|
||||
|
||||
if (googleMap != null) {
|
||||
|
||||
// Disable my location if gps is disabled
|
||||
googleMap.setMyLocationEnabled(isGpsProviderEnabled);
|
||||
}
|
||||
|
||||
// setWarningMessage depends on resumeTrackDataHub being invoked beforehand
|
||||
setWarningMessage(isGpsProviderEnabled);
|
||||
|
||||
currentTrack = MyTracksProviderUtils.Factory.get(getActivity()).getTrack(trackId);
|
||||
mapOverlay.setShowEndMarker(!isSelectedTrackRecording());
|
||||
if (markerId != -1L) {
|
||||
showMarker(markerId);
|
||||
} else {
|
||||
if (keepCurrentLocationVisible && currentLocation != null && isSelectedTrackRecording()) {
|
||||
updateCurrentLocation(true);
|
||||
} else {
|
||||
/*
|
||||
* Clear the current location in case the current location is no longer
|
||||
* being updated continuously.
|
||||
*/
|
||||
if (onLocationChangedListener != null) {
|
||||
onLocationChangedListener.onLocationChanged(new Location(""));
|
||||
}
|
||||
showTrack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putBoolean(KEEP_CURRENT_LOCATION_VISIBLE_KEY, keepCurrentLocationVisible);
|
||||
if (currentLocation != null) {
|
||||
/*
|
||||
* currentLocation is a MyTracksLocation object, which cannot be
|
||||
* unmarshalled. Thus creating a Location object before placing it in the
|
||||
* bundle.
|
||||
*/
|
||||
outState.putParcelable(CURRENT_LOCATION_KEY, new Location(currentLocation));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
pauseTrackDataHub();
|
||||
if (locationListener != null) {
|
||||
myTracksLocationManager.removeLocationUpdates(locationListener);
|
||||
locationListener = null;
|
||||
}
|
||||
myTracksLocationManager.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflator) {
|
||||
menuInflator.inflate(R.menu.map, menu);
|
||||
TrackIconUtils.setMenuIconColor(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||
if (menuItem.getItemId() == R.id.menu_map_layer) {
|
||||
((TrackDetailActivity) getActivity()).showMapLayerDialog();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(menuItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackUpdated(Track track) {
|
||||
currentTrack = track;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTrackPoints() {
|
||||
lastTrackPoint = null;
|
||||
if (isResumed()) {
|
||||
mapOverlay.clearPoints();
|
||||
reloadPaths = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSampledInTrackPoint(final Location location) {
|
||||
lastTrackPoint = location;
|
||||
if (isResumed()) {
|
||||
mapOverlay.addLocation(location);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSampledOutTrackPoint(Location location) {
|
||||
lastTrackPoint = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSegmentSplit(Location location) {
|
||||
if (isResumed()) {
|
||||
mapOverlay.addSegmentSplit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewTrackPointsDone() {
|
||||
if (isResumed()) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (isResumed() && googleMap != null && currentTrack != null) {
|
||||
boolean hasStartMarker = mapOverlay.update(
|
||||
googleMap, paths, currentTrack.getTripStatistics(), reloadPaths);
|
||||
|
||||
/*
|
||||
* If has the start marker, then don't need to reload the paths each
|
||||
* time
|
||||
*/
|
||||
if (hasStartMarker) {
|
||||
reloadPaths = false;
|
||||
}
|
||||
|
||||
if (lastTrackPoint != null && isSelectedTrackRecording()) {
|
||||
boolean firstLocation = setCurrentLocation(lastTrackPoint);
|
||||
if (firstLocation) {
|
||||
keepCurrentLocationVisible = true;
|
||||
}
|
||||
updateCurrentLocation(firstLocation);
|
||||
setWarningMessage(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearWaypoints() {
|
||||
if (isResumed()) {
|
||||
mapOverlay.clearWaypoints();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypoint(Waypoint waypoint) {
|
||||
if (isResumed() && waypoint != null && LocationUtils.isValidLocation(waypoint.getLocation())) {
|
||||
mapOverlay.addWaypoint(waypoint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewWaypointsDone() {
|
||||
if (isResumed()) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (isResumed() && googleMap != null && currentTrack != null) {
|
||||
mapOverlay.update(googleMap, paths, currentTrack.getTripStatistics(), true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMetricUnitsChanged(boolean metric) {
|
||||
// We don't care.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onReportSpeedChanged(boolean reportSpeed) {
|
||||
// We don't care.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onRecordingGpsAccuracy(int newValue) {
|
||||
recordingGpsAccuracy = newValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onRecordingDistanceIntervalChanged(int minRecordingDistance) {
|
||||
// We don't care.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMapTypeChanged(final int mapType) {
|
||||
if (isResumed()) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (isResumed() && googleMap != null) {
|
||||
googleMap.setMapType(mapType);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes the trackDataHub. Needs to be synchronized because the trackDataHub
|
||||
* can be accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void resumeTrackDataHub() {
|
||||
trackDataHub = ((TrackDetailActivity) getActivity()).getTrackDataHub();
|
||||
trackDataHub.registerTrackDataListener(this, EnumSet.of(TrackDataType.TRACKS_TABLE,
|
||||
TrackDataType.WAYPOINTS_TABLE, TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE,
|
||||
TrackDataType.SAMPLED_OUT_TRACK_POINTS_TABLE, TrackDataType.PREFERENCE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the trackDataHub. Needs to be synchronized because the trackDataHub
|
||||
* can be accessed by multiple threads.
|
||||
*/
|
||||
private synchronized void pauseTrackDataHub() {
|
||||
if (trackDataHub != null) {
|
||||
trackDataHub.unregisterTrackDataListener(this);
|
||||
}
|
||||
trackDataHub = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the selected track is recording. Needs to be synchronized
|
||||
* because the trackDataHub can be accessed by multiple threads.
|
||||
*/
|
||||
private synchronized boolean isSelectedTrackRecording() {
|
||||
return trackDataHub != null && trackDataHub.isSelectedTrackRecording();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current location.
|
||||
*
|
||||
* @param location the location
|
||||
* @return true if this is the first location
|
||||
*/
|
||||
private boolean setCurrentLocation(Location location) {
|
||||
boolean isFirst = false;
|
||||
if (currentLocation == null && location != null) {
|
||||
isFirst = true;
|
||||
}
|
||||
currentLocation = location;
|
||||
return isFirst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current location.
|
||||
*
|
||||
* @param forceZoom true to force zoom to the current location regardless of
|
||||
* the keepCurrentLocationVisible policy
|
||||
*/
|
||||
private void updateCurrentLocation(final boolean forceZoom) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (!isResumed() || googleMap == null || onLocationChangedListener == null
|
||||
|| currentLocation == null) {
|
||||
return;
|
||||
}
|
||||
onLocationChangedListener.onLocationChanged(currentLocation);
|
||||
if (forceZoom || (keepCurrentLocationVisible && !isLocationVisible(currentLocation))) {
|
||||
LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
|
||||
CameraUpdate cameraUpdate = forceZoom ? CameraUpdateFactory.newLatLngZoom(
|
||||
latLng, DEFAULT_ZOOM_LEVEL)
|
||||
: CameraUpdateFactory.newLatLng(latLng);
|
||||
googleMap.animateCamera(cameraUpdate);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the current track by moving the camera over the track.
|
||||
*/
|
||||
private void showTrack() {
|
||||
if (googleMap == null || currentTrack == null) {
|
||||
return;
|
||||
}
|
||||
if (currentTrack.getNumberOfPoints() < 2) {
|
||||
googleMap.moveCamera(
|
||||
CameraUpdateFactory.newLatLngZoom(getDefaultLatLng(), googleMap.getMinZoomLevel()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapView.getWidth() == 0 || mapView.getHeight() == 0) {
|
||||
if (mapView.getViewTreeObserver().isAlive()) {
|
||||
mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (!isResumed()) {
|
||||
return;
|
||||
}
|
||||
ApiAdapterFactory.getApiAdapter()
|
||||
.removeGlobalLayoutListener(mapView.getViewTreeObserver(), this);
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isResumed()) {
|
||||
moveCameraOverTrack();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
moveCameraOverTrack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the camera over the current track.
|
||||
*/
|
||||
private void moveCameraOverTrack() {
|
||||
/**
|
||||
* Check all the required variables.
|
||||
*/
|
||||
if (googleMap == null || currentTrack == null || currentTrack.getNumberOfPoints() < 2
|
||||
|| mapView == null || mapView.getWidth() == 0 || mapView.getHeight() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
TripStatistics tripStatistics = currentTrack.getTripStatistics();
|
||||
int latitudeSpanE6 = tripStatistics.getTop() - tripStatistics.getBottom();
|
||||
int longitudeSpanE6 = tripStatistics.getRight() - tripStatistics.getLeft();
|
||||
if (latitudeSpanE6 > 0 && latitudeSpanE6 < 180E6 && longitudeSpanE6 > 0
|
||||
&& longitudeSpanE6 < 360E6) {
|
||||
LatLng southWest = new LatLng(
|
||||
tripStatistics.getBottomDegrees(), tripStatistics.getLeftDegrees());
|
||||
LatLng northEast = new LatLng(
|
||||
tripStatistics.getTopDegrees(), tripStatistics.getRightDegrees());
|
||||
LatLngBounds bounds = LatLngBounds.builder().include(southWest).include(northEast).build();
|
||||
|
||||
/**
|
||||
* Note cannot call CameraUpdateFactory.newLatLngBounds(LatLngBounds
|
||||
* bounds, int padding) if the map view has not undergone layout. Thus
|
||||
* calling CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int
|
||||
* width, int height, int padding) after making sure that mapView is valid
|
||||
* in the above code.
|
||||
*/
|
||||
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(
|
||||
bounds, mapView.getWidth(), mapView.getHeight(), MAP_VIEW_PADDING);
|
||||
googleMap.moveCamera(cameraUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a marker by moving the camera over the marker.
|
||||
*
|
||||
* @param id the marker id
|
||||
*/
|
||||
private void showMarker(final long id) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isResumed() || googleMap == null) {
|
||||
return;
|
||||
}
|
||||
MyTracksProviderUtils MyTracksProviderUtils = Factory.get(getActivity());
|
||||
Waypoint waypoint = MyTracksProviderUtils.getWaypoint(id);
|
||||
if (waypoint == null) {
|
||||
return;
|
||||
}
|
||||
Location location = waypoint.getLocation();
|
||||
if (location == null) {
|
||||
return;
|
||||
}
|
||||
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
|
||||
keepCurrentLocationVisible = false;
|
||||
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM_LEVEL);
|
||||
googleMap.moveCamera(cameraUpdate);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default LatLng.
|
||||
*/
|
||||
private LatLng getDefaultLatLng() {
|
||||
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(getActivity());
|
||||
Location location = myTracksProviderUtils.getLastValidTrackPoint();
|
||||
if (location != null) {
|
||||
return new LatLng(location.getLatitude(), location.getLongitude());
|
||||
}
|
||||
return new LatLng(DEFAULT_LATITUDE, DEFAULT_LONGITUDE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the location is visible. Needs to run on the UI thread.
|
||||
*
|
||||
* @param location the location
|
||||
*/
|
||||
private boolean isLocationVisible(Location location) {
|
||||
if (location == null || googleMap == null) {
|
||||
return false;
|
||||
}
|
||||
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
|
||||
return googleMap.getProjection().getVisibleRegion().latLngBounds.contains(latLng);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the warning message.
|
||||
*
|
||||
* @param isGpsProviderEnabled true if gps provider is enabled
|
||||
*/
|
||||
private void setWarningMessage(boolean isGpsProviderEnabled) {
|
||||
String message = getWarningMessage(isGpsProviderEnabled);
|
||||
|
||||
if (message == null) {
|
||||
messageTextView.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
messageTextView.setText(message);
|
||||
messageTextView.setVisibility(View.VISIBLE);
|
||||
if (isGpsProviderEnabled) {
|
||||
messageTextView.setOnClickListener(null);
|
||||
} else {
|
||||
Toast.makeText(getActivity(), R.string.gps_not_found, Toast.LENGTH_LONG).show();
|
||||
|
||||
// Click to show the location source settings
|
||||
messageTextView.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isResumed()) {
|
||||
startActivity(GoogleLocationUtils.newLocationSettingsIntent(getActivity()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the warning message.
|
||||
*
|
||||
* @param isGpsProviderEnabled true if gps provider is enabled
|
||||
*/
|
||||
private String getWarningMessage(boolean isGpsProviderEnabled) {
|
||||
if (!isSelectedTrackRecording()) {
|
||||
return null;
|
||||
}
|
||||
if (!isGpsProviderEnabled) {
|
||||
return GoogleLocationUtils.getGpsDisabledMessage(getActivity());
|
||||
}
|
||||
|
||||
boolean hasFix;
|
||||
boolean hasGoodFix;
|
||||
if (currentLocation == null) {
|
||||
hasFix = false;
|
||||
hasGoodFix = false;
|
||||
} else {
|
||||
hasFix = !LocationUtils.isLocationOld(currentLocation);
|
||||
hasGoodFix = currentLocation.hasAccuracy()
|
||||
&& currentLocation.getAccuracy() < recordingGpsAccuracy;
|
||||
}
|
||||
if (!hasFix) {
|
||||
return getString(R.string.gps_wait_for_signal);
|
||||
} else if (!hasGoodFix) {
|
||||
return getString(R.string.gps_wait_for_better_signal);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+180
-173
@@ -16,201 +16,208 @@
|
||||
|
||||
package com.google.android.apps.mytracks.services;
|
||||
|
||||
import com.google.android.apps.mytracks.util.GoogleLocationUtils;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
|
||||
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
|
||||
import com.google.android.gms.location.LocationClient;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.google.android.apps.mytracks.util.GoogleLocationUtils;
|
||||
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
|
||||
import com.google.android.gms.location.FusedLocationProviderClient;
|
||||
import com.google.android.gms.location.LocationCallback;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
import com.google.android.gms.tasks.OnSuccessListener;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* My Tracks Location Manager. Applies Google location settings before allowing
|
||||
* access to {@link LocationManager}.
|
||||
*
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
public class MyTracksLocationManager {
|
||||
|
||||
/**
|
||||
* Observer for Google location settings.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private class GoogleSettingsObserver extends ContentObserver {
|
||||
/**
|
||||
* Observer for Google location settings.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
private class GoogleSettingsObserver extends ContentObserver {
|
||||
|
||||
public GoogleSettingsObserver(Handler handler) {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
isAllowed = GoogleLocationUtils.isAllowed(context);
|
||||
}
|
||||
}
|
||||
|
||||
private final ConnectionCallbacks connectionCallbacks = new ConnectionCallbacks() {
|
||||
@Override
|
||||
public void onDisconnected() {}
|
||||
|
||||
@Override
|
||||
public void onConnected(Bundle bunlde) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (requestLastLocation != null && locationClient.isConnected()) {
|
||||
requestLastLocation.onLocationChanged(locationClient.getLastLocation());
|
||||
requestLastLocation = null;
|
||||
}
|
||||
if (requestLocationUpdates != null && locationClient.isConnected()) {
|
||||
LocationRequest locationRequest = new LocationRequest().setPriority(
|
||||
LocationRequest.PRIORITY_HIGH_ACCURACY).setInterval(requestLocationUpdatesTime)
|
||||
.setFastestInterval(requestLocationUpdatesTime)
|
||||
.setSmallestDisplacement(requestLocationUpdatesDistance);
|
||||
locationClient.requestLocationUpdates(
|
||||
locationRequest, requestLocationUpdates, handler.getLooper());
|
||||
}
|
||||
public GoogleSettingsObserver(Handler handler) {
|
||||
super(handler);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private final OnConnectionFailedListener
|
||||
onConnectionFailedListener = new OnConnectionFailedListener() {
|
||||
@Override
|
||||
public void onConnectionFailed(ConnectionResult connectionResult) {}
|
||||
};
|
||||
|
||||
private final Context context;
|
||||
private final Handler handler;
|
||||
private final LocationClient locationClient;
|
||||
private final LocationManager locationManager;
|
||||
private final ContentResolver contentResolver;
|
||||
private final GoogleSettingsObserver observer;
|
||||
|
||||
private boolean isAllowed;
|
||||
private LocationListener requestLastLocation;
|
||||
private LocationListener requestLocationUpdates;
|
||||
private float requestLocationUpdatesDistance;
|
||||
private long requestLocationUpdatesTime;
|
||||
|
||||
public MyTracksLocationManager(Context context, Looper looper, boolean enableLocaitonClient) {
|
||||
this.context = context;
|
||||
this.handler = new Handler(looper);
|
||||
|
||||
if (enableLocaitonClient) {
|
||||
locationClient = new LocationClient(context, connectionCallbacks, onConnectionFailedListener);
|
||||
locationClient.connect();
|
||||
} else {
|
||||
locationClient = null;
|
||||
}
|
||||
|
||||
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
contentResolver = context.getContentResolver();
|
||||
observer = new GoogleSettingsObserver(handler);
|
||||
|
||||
isAllowed = GoogleLocationUtils.isAllowed(context);
|
||||
|
||||
contentResolver.registerContentObserver(
|
||||
GoogleLocationUtils.USE_LOCATION_FOR_SERVICES_URI, false, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the {@link MyTracksLocationManager}.
|
||||
*/
|
||||
public void close() {
|
||||
if (locationClient != null) {
|
||||
locationClient.disconnect();
|
||||
}
|
||||
contentResolver.unregisterContentObserver(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if allowed to access the location manager. Returns true if
|
||||
* there is no enforcement or the Google location settings allows access to
|
||||
* location data.
|
||||
*/
|
||||
public boolean isAllowed() {
|
||||
return isAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if gps provider is enabled.
|
||||
*/
|
||||
public boolean isGpsProviderEnabled() {
|
||||
if (!isAllowed()) {
|
||||
return false;
|
||||
}
|
||||
String provider = LocationManager.GPS_PROVIDER;
|
||||
if (locationManager.getProvider(provider) == null) {
|
||||
return false;
|
||||
}
|
||||
return locationManager.isProviderEnabled(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request last location.
|
||||
*
|
||||
* @param locationListener location listener
|
||||
*/
|
||||
public void requestLastLocation(final LocationListener locationListener) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isAllowed()) {
|
||||
requestLastLocation = null;
|
||||
locationListener.onLocationChanged(null);
|
||||
public void onChange(boolean selfChange) {
|
||||
isAllowed = GoogleLocationUtils.isAllowed(context);
|
||||
}
|
||||
}
|
||||
|
||||
private final ConnectionCallbacks connectionCallbacks = new ConnectionCallbacks() {
|
||||
@Override
|
||||
public void onConnected(@Nullable Bundle bundle) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int i) {
|
||||
handler.post(new Runnable() {
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void run() {
|
||||
if (requestLastLocation != null) {
|
||||
locationClient.getLastLocation().addOnSuccessListener(
|
||||
new OnSuccessListener<Location>() {
|
||||
@Override
|
||||
public void onSuccess(Location location) {
|
||||
// GPS location can be null if GPS is switched off
|
||||
if (location != null) {
|
||||
requestLastLocation.onLocationChanged(location);
|
||||
}
|
||||
requestLastLocation = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (requestLocationUpdates != null) {
|
||||
LocationRequest locationRequest = new LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
|
||||
.setInterval(requestLocationUpdatesTime)
|
||||
.setFastestInterval(requestLocationUpdatesTime)
|
||||
.setSmallestDisplacement(requestLocationUpdatesDistance);
|
||||
|
||||
locationClient.requestLocationUpdates(locationRequest, requestLocationUpdates, handler.getLooper());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
private final Context context;
|
||||
private final Handler handler;
|
||||
private final FusedLocationProviderClient locationClient;
|
||||
private final LocationManager locationManager;
|
||||
private final ContentResolver contentResolver;
|
||||
private final GoogleSettingsObserver observer;
|
||||
|
||||
private boolean isAllowed;
|
||||
private LocationListener requestLastLocation;
|
||||
private LocationCallback requestLocationUpdates;
|
||||
private float requestLocationUpdatesDistance;
|
||||
private long requestLocationUpdatesTime;
|
||||
|
||||
public MyTracksLocationManager(Context context, Looper looper, boolean enableLocationClient) {
|
||||
this.context = context;
|
||||
this.handler = new Handler(looper);
|
||||
|
||||
if (enableLocationClient) {
|
||||
locationClient = LocationServices.getFusedLocationProviderClient(context);
|
||||
} else {
|
||||
requestLastLocation = locationListener;
|
||||
connectionCallbacks.onConnected(null);
|
||||
locationClient = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests location updates. This is an ongoing request, thus the caller
|
||||
* needs to check the status of {@link #isAllowed}.
|
||||
*
|
||||
* @param minTime the minimal time
|
||||
* @param minDistance the minimal distance
|
||||
* @param locationListener the location listener
|
||||
*/
|
||||
public void requestLocationUpdates(
|
||||
final long minTime, final float minDistance, final LocationListener locationListener) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
requestLocationUpdatesTime = minTime;
|
||||
requestLocationUpdatesDistance = minDistance;
|
||||
requestLocationUpdates = locationListener;
|
||||
connectionCallbacks.onConnected(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
contentResolver = context.getContentResolver();
|
||||
observer = new GoogleSettingsObserver(handler);
|
||||
|
||||
/**
|
||||
* Removes location updates.
|
||||
*
|
||||
* @param locationListener the location listener
|
||||
*/
|
||||
public void removeLocationUpdates(final LocationListener locationListener) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
requestLocationUpdates = null;
|
||||
if (locationClient != null && locationClient.isConnected()) {
|
||||
locationClient.removeLocationUpdates(locationListener);
|
||||
isAllowed = GoogleLocationUtils.isAllowed(context);
|
||||
|
||||
contentResolver.registerContentObserver(
|
||||
GoogleLocationUtils.USE_LOCATION_FOR_SERVICES_URI, false, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the {@link MyTracksLocationManager}.
|
||||
*/
|
||||
public void close() {
|
||||
contentResolver.unregisterContentObserver(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if allowed to access the location manager. Returns true if
|
||||
* there is no enforcement or the Google location settings allows access to
|
||||
* location data.
|
||||
*/
|
||||
public boolean isAllowed() {
|
||||
return isAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if gps provider is enabled.
|
||||
*/
|
||||
public boolean isGpsProviderEnabled() {
|
||||
if (!isAllowed()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
String provider = LocationManager.GPS_PROVIDER;
|
||||
if (locationManager.getProvider(provider) == null) {
|
||||
return false;
|
||||
}
|
||||
return locationManager.isProviderEnabled(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request last location.
|
||||
*
|
||||
* @param locationListener location listener
|
||||
*/
|
||||
public void requestLastLocation(final LocationListener locationListener) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isAllowed()) {
|
||||
requestLastLocation = null;
|
||||
locationListener.onLocationChanged(null);
|
||||
} else {
|
||||
requestLastLocation = locationListener;
|
||||
connectionCallbacks.onConnected(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests location updates. This is an ongoing request, thus the caller
|
||||
* needs to check the status of {@link #isAllowed}.
|
||||
*
|
||||
* @param minTime the minimal time
|
||||
* @param minDistance the minimal distance
|
||||
* @param locationListener the location listener
|
||||
*/
|
||||
public void requestLocationUpdates(
|
||||
final long minTime, final float minDistance, final LocationCallback locationListener) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
requestLocationUpdatesTime = minTime;
|
||||
requestLocationUpdatesDistance = minDistance;
|
||||
requestLocationUpdates = locationListener;
|
||||
connectionCallbacks.onConnected(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes location updates.
|
||||
*
|
||||
* @param locationListener the location listener
|
||||
*/
|
||||
public void removeLocationUpdates(final LocationCallback locationListener) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
requestLocationUpdates = null;
|
||||
if (locationClient != null) {
|
||||
locationClient.removeLocationUpdates(locationListener);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+41
-73
@@ -16,6 +16,27 @@
|
||||
|
||||
package com.google.android.apps.mytracks.services;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.os.Process;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.apps.mytracks.Constants;
|
||||
import com.google.android.apps.mytracks.TrackDetailActivity;
|
||||
import com.google.android.apps.mytracks.TrackListActivity;
|
||||
@@ -47,34 +68,15 @@ import com.google.android.apps.mytracks.util.TrackIconUtils;
|
||||
import com.google.android.apps.mytracks.util.TrackNameUtils;
|
||||
import com.google.android.apps.mytracks.util.UnitConversions;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
|
||||
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
|
||||
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
|
||||
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
|
||||
import com.google.android.gms.location.ActivityRecognitionClient;
|
||||
import com.google.android.gms.location.DetectedActivity;
|
||||
import com.google.android.gms.location.LocationListener;
|
||||
import com.google.android.gms.location.LocationCallback;
|
||||
import com.google.android.gms.location.LocationResult;
|
||||
import com.google.android.maps.mytracks.R;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.os.Process;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -119,8 +121,6 @@ public class TrackRecordingService extends Service {
|
||||
private MyTracksProviderUtils myTracksProviderUtils;
|
||||
private Handler handler;
|
||||
private MyTracksLocationManager myTracksLocationManager;
|
||||
private PendingIntent activityRecognitionPendingIntent;
|
||||
private ActivityRecognitionClient activityRecognitionClient;
|
||||
private PeriodicTaskExecutor voiceExecutor;
|
||||
private PeriodicTaskExecutor splitExecutor;
|
||||
private SharedPreferences sharedPreferences;
|
||||
@@ -238,43 +238,25 @@ public class TrackRecordingService extends Service {
|
||||
}
|
||||
};
|
||||
|
||||
private LocationListener locationListener = new LocationListener() {
|
||||
@Override
|
||||
public void onLocationChanged(final Location location) {
|
||||
if (myTracksLocationManager == null || executorService == null
|
||||
|| !myTracksLocationManager.isAllowed() || executorService.isShutdown()
|
||||
|| executorService.isTerminated()) {
|
||||
return;
|
||||
private LocationCallback locationListener = new LocationCallback() {
|
||||
|
||||
public void onLocationResult(final LocationResult locationResult) {
|
||||
if (myTracksLocationManager == null || executorService == null
|
||||
|| !myTracksLocationManager.isAllowed() || executorService.isShutdown()
|
||||
|| executorService.isTerminated()) {
|
||||
return;
|
||||
}
|
||||
executorService.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onLocationChangedAsync(locationResult.getLastLocation());
|
||||
}
|
||||
});
|
||||
}
|
||||
executorService.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onLocationChangedAsync(location);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private final ConnectionCallbacks activityRecognitionCallbacks = new ConnectionCallbacks() {
|
||||
@Override
|
||||
public void onDisconnected() {}
|
||||
|
||||
@Override
|
||||
public void onConnected(Bundle bundle) {
|
||||
activityRecognitionClient.requestActivityUpdates(
|
||||
ONE_MINUTE, activityRecognitionPendingIntent);
|
||||
}
|
||||
};
|
||||
|
||||
private final OnConnectionFailedListener
|
||||
activityRecognitionFailedListener = new OnConnectionFailedListener() {
|
||||
|
||||
@Override
|
||||
public void onConnectionFailed(ConnectionResult connectionResult) {}
|
||||
};
|
||||
|
||||
private final Runnable registerLocationRunnable = new Runnable() {
|
||||
@Override
|
||||
@Override
|
||||
public void run() {
|
||||
if (isRecording() && !isPaused()) {
|
||||
registerLocationListener();
|
||||
@@ -298,12 +280,6 @@ public class TrackRecordingService extends Service {
|
||||
myTracksProviderUtils = MyTracksProviderUtils.Factory.get(this);
|
||||
handler = new Handler();
|
||||
myTracksLocationManager = new MyTracksLocationManager(this, handler.getLooper(), true);
|
||||
activityRecognitionPendingIntent = PendingIntent.getService(context, 0,
|
||||
new Intent(context, ActivityRecognitionIntentService.class),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
activityRecognitionClient = new ActivityRecognitionClient(
|
||||
context, activityRecognitionCallbacks, activityRecognitionFailedListener);
|
||||
activityRecognitionClient.connect();
|
||||
voiceExecutor = new PeriodicTaskExecutor(this, new AnnouncementPeriodicTaskFactory());
|
||||
splitExecutor = new PeriodicTaskExecutor(this, new SplitPeriodicTaskFactory());
|
||||
sharedPreferences = getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
|
||||
@@ -390,12 +366,6 @@ public class TrackRecordingService extends Service {
|
||||
} finally {
|
||||
voiceExecutor = null;
|
||||
}
|
||||
|
||||
if (activityRecognitionClient.isConnected()) {
|
||||
activityRecognitionClient.removeActivityUpdates(activityRecognitionPendingIntent);
|
||||
}
|
||||
activityRecognitionClient.disconnect();
|
||||
activityRecognitionPendingIntent.cancel();
|
||||
|
||||
myTracksLocationManager.close();
|
||||
myTracksLocationManager = null;
|
||||
@@ -621,8 +591,6 @@ public class TrackRecordingService extends Service {
|
||||
// Update shared preferences
|
||||
updateRecordingState(trackId, false);
|
||||
PreferencesUtils.setInt(this, R.string.auto_resume_track_current_retry_key, 0);
|
||||
PreferencesUtils.setInt(this, R.string.activity_recognition_type_key,
|
||||
PreferencesUtils.ACTIVITY_RECOGNITION_TYPE_DEFAULT);
|
||||
|
||||
// Update database
|
||||
track.setId(trackId);
|
||||
@@ -1311,7 +1279,7 @@ public class TrackRecordingService extends Service {
|
||||
if (!canAccess()) {
|
||||
return;
|
||||
}
|
||||
trackRecordingService.locationListener.onLocationChanged(location);
|
||||
//TODO trackRecordingService.locationListener.onLocationChanged(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,7 @@ android {
|
||||
compileSdkVersion 26
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 26
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user