I am using google play service for a running app i am making. I am getting the problem that onlocationchanged is not being called. First i though it was the android device that was not working but after testing it with GPS test it seems the device was working as it should. So it must be my code. Onlocationchanged is just not being called by the gps_provider but when i use network_provider it is working but the updates are so slow and in accurate that you can't build a sport runner app with it.
This is my code, what should i do to fix this?
this is in my manifest
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="com.befitdonate.befitdonate.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
This is my fragment i am using to track the users route on the map.
public class WorkoutActivity extends Fragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static String TAG = WorkoutActivity.class.getSimpleName();
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private LocationRequest mLocationRequest;
MapView mapView;
GoogleMap map;
private GoogleApiClient mGoogleApiClient;
private SharedPreferences preferenceSettings;
private SharedPreferences.Editor preferenceEditor;
private static final int PREFERENCE_MODE_PRIVATE = 0;
private static final String PREF_NAME = "UserDetails";
public static final String POST_USEREMAIL = "username";
MainActivity mainactivity;
String emailUser, workoutType;
Button stopWorkout, startWorkout;
TextView speed, info;
ImageView workoutImage;
LinearLayout mapLayout, startWorkoutLayout;
Double currentLat, currentLong;
Double Lat, Longi;
String latLong = "No Location Found!!!";
LocationManager lManager;
final private int REQUEST_CODE_ASK_PERMISSIONS = 123;
//counter that is incremented every time a new position is received, used to calculate average speed
int counter = 0;
//objects to store values for current and average speed
protected double currentSpeed;
protected double kmphSpeed;
protected double avgSpeed;
protected double avgKmph;
protected double totalSpeed;
protected double totalKmph;
ArrayList<LatLng> polylines;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
preferenceSettings = this.getActivity().getSharedPreferences(PREF_NAME, PREFERENCE_MODE_PRIVATE);
preferenceEditor = preferenceSettings.edit();
emailUser = preferenceSettings.getString("Email", null);
Log.d("Saved user email:", "" + emailUser);
Bundle bundle = this.getArguments();
if (bundle != null) {
workoutType = bundle.getString("workoutType");
}
mGoogleApiClient = new GoogleApiClient.Builder(this.getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(1 * 1000) // 5 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_workout, container, false);
mapView = (MapView) view.findViewById(R.id.mapview);
stopWorkout = (Button) view.findViewById(R.id.stopWorkout);
startWorkout = (Button) view.findViewById(R.id.startWorkout);
startWorkoutLayout = (LinearLayout) view.findViewById(R.id.startWorkoutLayout);
mapLayout = (LinearLayout) view.findViewById(R.id.mapLayout);
workoutImage = (ImageView) view.findViewById(R.id.workoutImage);
speed = (TextView) view.findViewById(R.id.speed);
info = (TextView) view.findViewById(R.id.info);
mapView.onCreate(savedInstanceState);
mainactivity = (MainActivity )getActivity();
mainactivity.menuButton.setVisibility(View.GONE);
mainactivity.mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
mainactivity.pageTitle.setText("Workout");
mapLayout.setVisibility(View.GONE);
polylines = new ArrayList<LatLng>();
// Gets to GoogleMap from the MapView and does initialization stuff
map = mapView.getMap();
map.getUiSettings().setMyLocationButtonEnabled(false);
map.setMyLocationEnabled(true);
// Needs to call MapsInitializer before doing any CameraUpdateFactory calls
MapsInitializer.initialize(this.getActivity());
stopWorkout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectOption();
}
});
workoutType = "walking";
startWorkout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mapLayout.setVisibility(View.VISIBLE);
startWorkoutLayout.setVisibility(View.GONE);
}
});
if(workoutType.matches("running")){
Picasso.with(this.getActivity())
.load(R.drawable.newrun)
.fit()
.centerCrop()
.into(workoutImage);
}
if(workoutType.matches("cycling")){
Picasso.with(this.getActivity())
.load(R.drawable.newcycling)
.fit()
.centerCrop()
.into(workoutImage);
}
if(workoutType.matches("walking")){
Picasso.with(this.getActivity())
.load(R.drawable.newwalk)
.fit()
.centerCrop()
.into(workoutImage);
}
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
mainactivity.mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onResume() {
super.onResume();
setUpMapIfNeeded();
mapView.onResume();
mGoogleApiClient.connect();
}
@Override
public void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
//DO WHATEVER YOU WANT WITH GOOGLEMAP
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
map.setMyLocationEnabled(false);
map.setTrafficEnabled(false);
map.setIndoorEnabled(true);
map.setBuildingsEnabled(true);
map.getUiSettings().setZoomControlsEnabled(true);
}
@Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
Log.d(TAG, "Location update running");
handleNewLocation(location);
}
public void selectOption() {
final CharSequence[] items = { "Workout Opslaan", "Afbreken", "Sluiten" };
AlertDialog.Builder builder = new AlertDialog.Builder(WorkoutActivity.this.getActivity());
builder.setTitle("Workout opties");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
if (items[item].equals("Workout Opslaan")) {
} else if (items[item].equals("Afbreken")) {
mapView.onDestroy();
mainactivity.mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
mainactivity.menuButton.setVisibility(View.VISIBLE);
if (mGoogleApiClient.isConnected()) {
onDestroy();
}
Fragment fragment = new HomePage();
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.mainContent, fragment)
.commit();
} else if (items[item].equals("Sluiten")) {
dialog.dismiss();
}
}
});
builder.show();
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.i(TAG, "Location services connected.");
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
else {
handleNewLocation(location);
};
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Location services suspended. Please reconnect.");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this.getActivity(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
}
}
private void handleNewLocation(Location location) {
Log.d(TAG, location.toString());
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
Lat = location.getLatitude();
Longi = location.getLongitude();
LatLng latLng = new LatLng(currentLatitude, currentLongitude);
CameraUpdate zoom=CameraUpdateFactory.zoomTo(17);
map.moveCamera(CameraUpdateFactory.newLatLng(latLng));
map.animateCamera(zoom);
counter++;
//current speed of the gps device
currentSpeed = round(location.getSpeed(),3, BigDecimal.ROUND_HALF_UP);
kmphSpeed = round((currentSpeed*3.6),3,BigDecimal.ROUND_HALF_UP);
//all speeds added together
totalSpeed = totalSpeed + currentSpeed;
totalKmph = totalKmph + kmphSpeed;
//calculates average speed
avgSpeed = round(totalSpeed/counter,3,BigDecimal.ROUND_HALF_UP);
avgKmph = round(totalKmph/counter,3,BigDecimal.ROUND_HALF_UP);
//gets position
currentLatitude = round(((double) (location.getLatitude())),3,BigDecimal.ROUND_HALF_UP);
currentLongitude = round(((double) (location.getLongitude())),3,BigDecimal.ROUND_HALF_UP);
String infoDetails = "Afstand: "+" | Tijd: ";
String updateSpeed = String.valueOf(kmphSpeed);
Log.d(TAG, updateSpeed.toString());
//info.setText();
speed.setText("Snelheid: "+updateSpeed+" km/hr");
buildPolyline();
}
//Method to round the doubles to a max of 3 decimal places
public static double round(double unrounded, int precision, int roundingMode)
{
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(precision, roundingMode);
return rounded.doubleValue();
}
public void buildPolyline(){
Log.d(TAG,"Adding polyline" );
LatLng polyline;
polyline = new LatLng(Lat, Longi);
polylines.add(polyline);
Log.d("Locations Array", ""+polylines);
map.addPolyline(new PolylineOptions().addAll(polylines).width(6.0f).color(Color.BLUE));
//map.moveCamera(CameraUpdateFactory.newLatLngZoom(Start, 14));
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (map == null) {
// Try to obtain the map from the SupportMapFragment.
map = ((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.mapview))
.getMap();
// Check if we were successful in obtaining the map.
if (map != null) {
}
}
}
}
I have spend about a week trying several solution but still stuck with this problem. I need an accurate way to track the route of the runner. I can't find any sport app samples, but enough other location samples but nothing seems to be working. I hope someone can help me with this.
Thanks