0

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

carlosx2
  • 1,672
  • 16
  • 23

1 Answers1

0

you have to use Location manager and register for location updates. Try adding this code:

protected LocationManager locationManager;

in onCreate() method call registerLocationUpdates();

void registerLocationUpdates() {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_HIGH);

locationManager = (LocationManager)getActivity().getSystemService(LOCATION_SERVICE);

provider = locationManager.getBestProvider(criteria, true);

// Cant get a hold of provider
if (provider == null) {
    Log.v(TAG, "Provider is null");
    showNoProvider();
    return;
} else {
    Log.v(TAG, "Provider: " + provider);
}

locationManager.requestLocationUpdates(provider, 0, 0, this);

}

rafsanahmad007
  • 23,683
  • 6
  • 47
  • 62
  • I see that i am already asking for requestLocationUpdates, so how come i need to initiate it again, plus it gives me the error cannot resolve method. So seems this is not working for me. – carlosx2 May 21 '16 at 11:05
  • You haven't initialize your Location Manager Object: lManager...try initiating the object and request Location update with that one..take a look at this link:http://stackoverflow.com/questions/9007600/onlocationchanged-callback-is-never-called – rafsanahmad007 May 22 '16 at 04:16