0

I'm trying to use the user's gps location in my app. The idea is to have a button that will fetch his current location and display it on a map. I don't want to have a real time update of his position. His location will be updated ONLY when he presses the button. Here is a sample of my fragment.

public class HomeFragment extends Fragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, View.OnClickListener {

private static final int MY_PERMISSION_ACCESS_COARSE_LOCATION = 11;
private static final int MY_PERMISSION_ACCESS_FINE_LOCATION = 12;
private GoogleMap mMap;
private GoogleApiClient mGoogleApiClient;
private LocationManager mLocationManager;
private String mLatitudeText;
private String mLongitudeText;
private View view;
private MarkerOptions mMarker = new MarkerOptions();

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null)
            parent.removeView(view);
    }
    try {
        Log.d("debug", "inside TRy");
        view = inflater.inflate(R.layout.fragment_homepage, container, false);


    } catch (Exception e) {
        Log.d("debug", "error inside try:"+e.toString());
    } finally {
        SupportMapFragment mMap = (SupportMapFragment) this.getChildFragmentManager()
                .findFragmentById(R.id.map);
        ImageButton mGpsUpdate = (ImageButton) view.findViewById(R.id.update_gps);
        Log.d("debug", "after inflater");
        mGpsUpdate.setOnClickListener(this);

        createGoogleMapClient(); // <- moi

        mMap.getMapAsync(this);
        return view;
    }
}


public void onStart() {
    mGoogleApiClient.connect();
    super.onStart();
}

public void onStop() {
    mGoogleApiClient.disconnect();
    super.onStop();
}

private void createGoogleMapClient(){

    mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

@Override
public void onMapReady(GoogleMap googleMap) {
    Log.d("debug", "in");
    mMap = googleMap;

    // Add a marker in Sydney and move the camera
    LatLng champlain = new LatLng(45.5164522,-73.52062409999996);

    mMap.addMarker(new MarkerOptions().position(champlain).title("Champlain College"));

    mMap.moveCamera(CameraUpdateFactory.newLatLng(champlain));//Move camera to Champlain
    CameraPosition oldPos = mMap.getCameraPosition();

    CameraPosition pos = CameraPosition.builder(oldPos).bearing(-103).build(); //rotate map
    mMap.moveCamera(CameraUpdateFactory.newCameraPosition(pos));

    //Debug
    updateLocation();

    mMap.setMinZoomPreference((float)17.3);
    mMap.setMaxZoomPreference(20);
    mMap.getUiSettings().setRotateGesturesEnabled(false);
    mMap.getUiSettings().setCompassEnabled(false);
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    updateLocation();

}

private void checkPermission(){
    if (ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions( getActivity(), new String[] {  android.Manifest.permission.ACCESS_COARSE_LOCATION  },
                MY_PERMISSION_ACCESS_COARSE_LOCATION );
        ActivityCompat.requestPermissions( getActivity(), new String[] {  android.Manifest.permission.ACCESS_FINE_LOCATION  },
                MY_PERMISSION_ACCESS_FINE_LOCATION );
    }
}

@Override
public void onConnectionSuspended(int i) {
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

@Override
public void onDestroyView() {

    FragmentManager fm = getFragmentManager();

    Fragment xmlFragment = fm.findFragmentById(R.id.map);
    if (xmlFragment != null) {
        fm.beginTransaction().remove(xmlFragment).commit();
    }

    super.onDestroyView();
}

public void updateLocation(){
    checkPermission();
    Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
        mGoogleApiClient);

    if (mLastLocation != null) {

        mLatitudeText = String.valueOf(mLastLocation.getLatitude());
        mLongitudeText = String.valueOf(mLastLocation.getLongitude());

        Log.d("Coordinates",(mLatitudeText + ", " + mLongitudeText));

        LatLng me = new LatLng(Double.parseDouble(mLatitudeText), Double.parseDouble(mLongitudeText));

        mMap.addMarker(mMarker.position(me).title("me"));

    }
}


@Override
public void onClick(View v) {
    Log.d("debug", "inside Button Listener");
    switch(v.getId()){
        case R.id.update_gps:
            Log.d("debug", "inside good case");
            mMap.clear();
            updateLocation();
            break;
    }
  }
}

Any ideas?

Etienne Berube
  • 547
  • 1
  • 7
  • 21
  • By the way, The methods I tried in the original post does not work. It always gives me the same position even if I move around – Etienne Berube Mar 30 '17 at 16:54

1 Answers1

0

The device doesn't determine its location on its own, but only when some application request the location. So your app is now dependent on other applications requesting location updates. That's why you are stuck with the same location even if moving around.

Also the "last known location" here means exactly that: It may not be up-to-date. Locations do come with a time stamp which could be used to asses if the location might still be relevant.

I don't see a call to requestLocationUpdates() anywhere in your code. You could add that to onConnected(). That would request up-to-date location updates at an interval which you can specify. You could then access this up-to-date "latest location" with getLastLocation() just as you already do.

And you should then call removeLocationUpdates() when you no longer need to track the user.

This approach would keep updating the location all the time and depending on your settings could affect the battery consumption.

But the other option would be to request updates only when the button is pressed and cancel them after the first result and that would have a delay between the button press and receiving the location.

Markus Kauppinen
  • 3,025
  • 4
  • 20
  • 30
  • So basically I would create requestLocationUpdates(), with an extremely high frequency only when the button is created and as soon as a Location is given, I stop the location requests and display the result? – Etienne Berube Mar 30 '17 at 21:10
  • Something like that. It doesn't have to be "extremely high frequency" as the first location comes as soon as it's available anyway. The frequency (update time interval) only affects the location updates after that. Location updates trigger the `onLocationChanged()` callback method where the location is available as a method parameter. You can either store the location to your own variable there or just keep using `getLastLocation()`. Either one will work. – Markus Kauppinen Mar 31 '17 at 06:56