Question

According to the sample app that finds the user location it is a good idea to listen for location changes in the activity:

class MyActivity extends Activity implements LocationListener {
    @Inject
    private LocationManager locationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
    }

    @Override
    public void onLocationChanged(Location location) {
        // do something with location
    }

    // ...
}

However, I'm not sure about that. When there is a configuration change, my activity gets destroyed and recreated, registering itself as listener next time. The reference to the old Activity is held in the LocationManager, isn't it?

If I extract the LocationListener to separate object, still I have the problem of how to notify the current activity about new location (not necessarily the same as the requesting activity).

Is there any common pattern to solve this?

Was it helpful?

Solution

In this example you have also another problem: your GPS listener will work always and will drain battery.

The better practice is:

1) register LocationListener into Activity's onStart()

2) remove LocationListener into Activity's onStop()

This will fix both problems.

If you need that your app track user position in background (for example, GPS tracker) use Service (http://developer.android.com/reference/android/app/Service.html)

OTHER TIPS

I had memory leaks using all these suggestions. I got them to stop by applying this method at the point I didn't need the Listener anymore, to onDestroy, and onStop. I also added it to onPause, but you'll have to decide if this is best for your application.

private void stopLocationListener() {
    if (locationManager !=null) locationManager.removeUpdates(locationListener);
    if (locationManager !=null) locationManager =null;
    if (locationListener !=null) locationListener =null;
}

You can make a separate class to do the same and then implement the LocationListenerFinder.onLocationChanged interface to your activity

Now you won't face the leak problem.

public class LocationListenerFinder implements LocationListener {
    onLocationChanged onLocationChanged;

    public LocationListenerFinder(Context context) {
        onLocationChanged = (LocationListenerFinder.onLocationChanged) context;
    }
    @Override
    public void onLocationChanged(Location location) {
        onLocationChanged.onLocationChanged(location);
        onLocationChanged = null;
    }

    public interface onLocationChanged {
        void onLocationChanged(Location location);
    }
}

In my case activity was this... you can refer the same and can convert as per your need.

public class ActivityMapNearByPlace extends FragmentActivity implements OnMapReadyCallback,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, LocationListenerFinder.onLocationChanged {

private GoogleMap mMap;
ArrayList<LatLng> listMarkerPoints;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
private boolean locationPermission;
private ArrayList<NearByPlaces> listNearByFacility;
private int facilityPosition, locationPosition;
private ImageView ivBack, ivMyLocation;
private TextView tvPlaceOriginName, tvPlaceDestinationName, tvPlaceKmDistance, tvPlaceTime;
private TableRow trPlaceTimeKm;
private Marker currentSelectedMarker;
private Map<Integer, Map<String, Object>> mapDistancePathData;
private Polyline polyline;
private boolean flagCalculatingPath = false;
private FetchUrl fetchUrl;
private SupportMapFragment mapFragment;
private LocationListenerFinder locationListenerFinder;
//private WeakLocationListener locationListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map_near_by_place);
    initView();
    initListener();

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        checkLocationPermission();
    } else {
        locationPermission = true;
    }
    // Initializing
    listMarkerPoints = new ArrayList<>();
    getBundleData();
    listNearByFacility.get(0).getNearBy();
    LatLng origin = new LatLng(Double.valueOf(listNearByFacility.get(0).getGeoLocLat()), Double.valueOf(listNearByFacility.get(0).getGeoLocLong()));
    listMarkerPoints.add(origin);
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

@Override
protected void onRestart() {
    super.onRestart();
    //if (mGoogleApiClient != null) mGoogleApiClient.connect();
}

@Override
protected void onStop() {
    super.onStop();
    //if (mGoogleApiClient != null) mGoogleApiClient.disconnect();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, locationListenerFinder);
        mGoogleApiClient.disconnect();
        mGoogleApiClient.unregisterConnectionCallbacks(this);
        mGoogleApiClient.unregisterConnectionFailedListener(this);
        //  locationListener.clearData();
        locationListenerFinder = null;
    }
    mGoogleApiClient = null;
    fetchUrl.cancel(true);
    if (mMap != null) mMap.setMyLocationEnabled(false);
    //if (mapFragment != null) mapFragment.onDestroy();
}

@Override
public void onBackPressed() {
    finish();
}

private void initListener() {
    ivBack.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            onBackPressed();
        }
    });
    ivMyLocation.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mCurrLocationMarker.getTag() != null && !flagCalculatingPath) {
                locationPosition = (int) mCurrLocationMarker.getTag();
                if (mapDistancePathData.get(locationPosition) != null) {
                    if (polyline != null) {
                        polyline.remove();
                    }
                    Map<String, Object> hashMapDistancePathInfo = mapDistancePathData.get(locationPosition);
                    setPathInfo((String) hashMapDistancePathInfo.get("duration"), (String) hashMapDistancePathInfo.get("distance"), (PolylineOptions) hashMapDistancePathInfo.get("polyLineOptions"), "Current Location");
                    trPlaceTimeKm.setVisibility(View.VISIBLE);
                } else {
                    Locations locations = new Locations();
                    locations.setName("Current Location");
                    locations.setLatitude(String.valueOf(mLastLocation.getLatitude()));
                    locations.setLongitude(String.valueOf(mLastLocation.getLongitude()));
                    findDistanceAndMarkDirection(locations);
                }
            }
            //mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
            //mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
        }
    });
}

private void initView() {
    ivBack = (ImageView) findViewById(R.id.iv_back_btn);
    ivMyLocation = (ImageView) findViewById(R.id.iv_my_location);

    tvPlaceOriginName = (TextView) findViewById(R.id.tv_near_by_place_origin);
    tvPlaceDestinationName = (TextView) findViewById(R.id.tv_near_by_place_destination);
    tvPlaceKmDistance = (TextView) findViewById(R.id.tv_near_by_place_km);
    tvPlaceTime = (TextView) findViewById(R.id.tv_near_by_place_time);
    trPlaceTimeKm = (TableRow) findViewById(R.id.tr_near_by_place_km_time);

}

private void getBundleData() {
    listNearByFacility = (ArrayList<NearByPlaces>) getIntent().getBundleExtra("nearByLocationBundle").getSerializable("nearByLocationData");
    facilityPosition = getIntent().getIntExtra("facilityPosition", 0);
    locationPosition = getIntent().getIntExtra("locationPosition", 0);
}

/**
 * Manipulates the map once available.
 * This callback is triggered when the map is ready to be used.
 * This is where we can add markers or lines, add listeners or move the camera. In this case,
 * we just add a marker near Sydney, Australia.
 * If Google Play services is not installed on the device, the user will be prompted to install
 * it inside the SupportMapFragment. This method will only be triggered once the user has
 * installed Google Play services and returned to the app.
 */
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;

    //Initialize Google Play Services
    if (locationPermission) {
        buildGoogleApiClient();
        checkLocationStatus();
        //mMap.setMyLocationEnabled(true);
        loadMap();
    }
    mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
        @Override
        public boolean onMarkerClick(Marker marker) {
            if (marker.getTag() != null && !flagCalculatingPath) {
                locationPosition = (int) marker.getTag();
                if (mapDistancePathData.get(locationPosition) != null) {
                    if (polyline != null) {
                        polyline.remove();
                    }
                    Map<String, Object> hashMapDistancePathInfo = mapDistancePathData.get(locationPosition);
                    setPathInfo((String) hashMapDistancePathInfo.get("duration"), (String) hashMapDistancePathInfo.get("distance"), (PolylineOptions) hashMapDistancePathInfo.get("polyLineOptions"), listNearByFacility.get(0).getNearBy().get(facilityPosition).getLocations().get(locationPosition).getName());
                    trPlaceTimeKm.setVisibility(View.VISIBLE);
                } else {
                    findDistanceAndMarkDirection(listNearByFacility.get(0).getNearBy().get(facilityPosition).getLocations().get(locationPosition));
                }
            }
            return false;
        }
    });

    mMap.getUiSettings().setMyLocationButtonEnabled(false);
    mMap.getUiSettings().setRotateGesturesEnabled(false);
}

private void loadMap() {
    NearByPlaces originLocation = listNearByFacility.get(0);

    if (listMarkerPoints.size() > 1) {
        mMap.clear();
        listMarkerPoints.remove(1);
    }

    // Adding new item to the ArrayList
    NearBy nearBy = listNearByFacility.get(0).getNearBy().get(facilityPosition);
    tvPlaceOriginName.setText(originLocation.getProjectName());
    //tvPlaceDestinationName.setText(nearBy.getLocations().get(locationPosition).getName());
    if (mapDistancePathData == null) {
        mapDistancePathData = new HashMap<>();
    }
    // .get(locationPosition);
    // LatLng destination = new LatLng(Double.valueOf(location.getLatitude()), Double.valueOf(location.getLongitude()));
    //listMarkerPoints.add(destination);

    MarkerOptions options = new MarkerOptions();
    options.position(listMarkerPoints.get(0));
    options.icon(BitmapDescriptorFactory.fromBitmap(getBitmapMarker(originLocation.getProjectName(), R.drawable.ic_marker_red)));
    //options.title(originLocation.getProjectName());
    mMap.addMarker(options).showInfoWindow();
    for (int position = 0; position < nearBy.getLocations().size(); position++) {
        Locations locations = nearBy.getLocations().get(position);
        // Creating MarkerOptions
        options = new MarkerOptions();
        LatLng markerPosition = new LatLng(Double.valueOf(locations.getLatitude()), Double.valueOf(locations.getLongitude()));
        // Setting the videoPlayPosition of the marker
        options.position(markerPosition);
        /**
         * For the start location, the color of marker is GREEN and
         * for the end location, the color of marker is RED.
         */
        options.icon(BitmapDescriptorFactory.fromBitmap(getBitmapMarker(locations.getName(), 0)));
        //options.title(locationRanges.getName());
        // Add new marker to the Google Map Android API V2
        Marker marker = mMap.addMarker(options);
        // marker.showInfoWindow();
        marker.setTag(position);
    }

    findDistanceAndMarkDirection(nearBy.getLocations().get(locationPosition));

}

public Bitmap getBitmapMarker(String title, int id) {
    View customMarkerView = this.getLayoutInflater().inflate(R.layout.layout_marker_with_title, null);
    customMarkerView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight());

    TextView tvMarkerProjectName = (TextView) customMarkerView.findViewById(R.id.tv_marker_project_name);
    if (id != 0) {
        ImageView ivMarkerImage = (ImageView) customMarkerView.findViewById(R.id.iv_marker_image);
        ivMarkerImage.setImageResource(id);
    }

    tvMarkerProjectName.setText(title);
    customMarkerView.setDrawingCacheEnabled(true);
    customMarkerView.buildDrawingCache();
    Bitmap bm = customMarkerView.getDrawingCache();
    return bm;
}


private void findDistanceAndMarkDirection(Locations destinationLocation) {
    flagCalculatingPath = true;
    if (polyline != null) {
        polyline.remove();
    }
    trPlaceTimeKm.setVisibility(View.INVISIBLE);
    tvPlaceDestinationName.setText(destinationLocation.getName());
    // Checks, whether start and end locationRanges are captured
    LatLng latLngDest = new LatLng(Double.valueOf(destinationLocation.getLatitude()), Double.valueOf(destinationLocation.getLongitude()));
    LatLng origin = listMarkerPoints.get(0);

    // Getting URL to the Google Directions API
    String url = getUrl(origin, latLngDest);
    //Log.d("onMapClick", url.toString());
    fetchUrl = new FetchUrl();

    // Start downloading json data from Google Directions API
    fetchUrl.execute(url);
    //move map camera
    mMap.moveCamera(CameraUpdateFactory.newLatLng(origin));
    mMap.animateCamera(CameraUpdateFactory.zoomTo(12));
}

private void setPathInfo(String duration, String distance, PolylineOptions polylineOptions, String destName) {
    tvPlaceTime.setText(duration);
    tvPlaceKmDistance.setText(distance);
    polyline = mMap.addPolyline(polylineOptions);
    tvPlaceDestinationName.setText(destName);
}

private String getUrl(LatLng origin, LatLng dest) {

    // Origin of route
    String str_origin = "origin=" + origin.latitude + "," + origin.longitude;

    // Destination of route
    String str_dest = "destination=" + dest.latitude + "," + dest.longitude;


    // Sensor enabled
    String sensor = "sensor=false";

    // Building the parameters to the web service
    String parameters = str_origin + "&" + str_dest + "&" + sensor;

    // Output format
    String output = "json";

    // Building the url to the web service
    String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters;


    return url;
}

/**
 * A method to download json data from url
 */
private String downloadUrl(String strUrl) throws IOException {
    String data = "";
    InputStream iStream = null;
    HttpURLConnection urlConnection = null;
    try {
        URL url = new URL(strUrl);

        // Creating an http connection to communicate with url
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setReadTimeout(15000 /* milliseconds */);
        urlConnection.setConnectTimeout(15000 /* milliseconds */);
        urlConnection.setDoInput(true);
        // Connecting to url
        urlConnection.connect();

        // Reading data from url
        iStream = urlConnection.getInputStream();

        BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

        StringBuffer sb = new StringBuffer();

        String line = "";
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }

        data = sb.toString();
        //Log.d("downloadUrl", data.toString());
        br.close();

    } catch (Exception e) {
        // Log.d("Exception", e.toString());
    } finally {
        iStream.close();
        urlConnection.disconnect();
    }
    return data;
}


// Fetches data from url passed
private class FetchUrl extends AsyncTask<String, Void, String> {


    @Override
    protected void onCancelled() {
        //super.onCancelled();
    }

    @Override
    protected String doInBackground(String... url) {

        // For storing data from web service
        String data = "";

        try {
            // Fetching the data from web service
            data = downloadUrl(url[0]);
            //Log.d("Background Task data", data.toString());
        } catch (Exception e) {
            //  Log.d("Background Task", e.toString());
        }
        return data;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        if (!TextUtils.isEmpty(result)) {

            ParserTask parserTask = new ParserTask();

            // Invokes the thread for parsing the JSON data
            parserTask.execute(result);
        } else {
            flagCalculatingPath = false;
        }

    }
}

/**
 * A class to parse the Google Places in JSON format
 */
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {

    // Parsing the data in non-ui thread
    @Override
    protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {

        JSONObject jObject;
        List<List<HashMap<String, String>>> routes = null;

        try {
            jObject = new JSONObject(jsonData[0]);
            //Log.d("ParserTask", jsonData[0].toString());
            DataParser parser = new DataParser();
            //Log.d("ParserTask", parser.toString());

            // Starts parsing data
            routes = parser.parse(jObject);
            //Log.d("ParserTask", "Executing routes");
            //Log.d("ParserTask", routes.toString());

        } catch (Exception e) {
            //Log.d("ParserTask", e.toString());
            e.printStackTrace();
        }
        return routes;
    }

    // Executes in UI thread, after the parsing process
    @Override
    protected void onPostExecute(List<List<HashMap<String, String>>> result) {
        ArrayList<LatLng> points;
        PolylineOptions lineOptions = null;
        HashMap<String, Object> hashMapDistancePathInfo = null;

        // Traversing through all the routes
        for (int i = 0; i < result.size(); i++) {
            points = new ArrayList<>();
            lineOptions = new PolylineOptions();


            // Fetching i-th route
            List<HashMap<String, String>> path = result.get(i);

            // Fetching all the points in i-th route
            for (int j = 1; j < path.size(); j++) {
                HashMap<String, String> point = path.get(j);

                double lat = Double.parseDouble(point.get("lat"));
                double lng = Double.parseDouble(point.get("lng"));
                LatLng position = new LatLng(lat, lng);

                points.add(position);
            }

            // Adding all the points in the route to LineOptions
            lineOptions.addAll(points);
            lineOptions.width(5);
            lineOptions.color(Color.RED);
            tvPlaceTime.setText(path.get(0).get("duration"));
            tvPlaceKmDistance.setText(path.get(0).get("distance"));
            trPlaceTimeKm.setVisibility(View.VISIBLE);

            hashMapDistancePathInfo = new HashMap<>();
            hashMapDistancePathInfo.put("duration", path.get(0).get("duration"));
            hashMapDistancePathInfo.put("distance", path.get(0).get("distance"));
            hashMapDistancePathInfo.put("polyLineOptions", lineOptions);
            //Log.d("onPostExecute", "onPostExecute lineoptions decoded");

        }
        // Drawing polyline in the Google Map for the i-th route
        if (lineOptions != null) {
            mapDistancePathData.put(locationPosition, hashMapDistancePathInfo);
            polyline = mMap.addPolyline(lineOptions);
        } else {
            //Log.d("onPostExecute", "without Polylines drawn");
        }
        flagCalculatingPath = false;
    }

}

protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    mGoogleApiClient.connect();
}

@Override
public void onConnected(Bundle bundle) {

    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(1000);
    mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationListenerFinder = new LocationListenerFinder(this);
    if (locationPermission) {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationListenerFinder);
    }
}

@Override
public void onConnectionSuspended(int i) {
    mLocationRequest = null;
}

@Override
public void onLocationChanged(Location location) {

    mLastLocation = location;
    if (mCurrLocationMarker != null) {
        mCurrLocationMarker.remove();
    }
    int size = listNearByFacility.get(0).getNearBy().get(facilityPosition).getLocations().size();
    ivMyLocation.setVisibility(View.VISIBLE);

    //Place current location marker
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions();
    markerOptions.position(latLng);
    markerOptions.icon(BitmapDescriptorFactory.fromBitmap(getBitmapMarker("Current Location", R.drawable.ic_marker_blue)));

    //MarkerOptions markerOptions = new MarkerOptions();
    //markerOptions.videoPlayPosition(latLng);
    //markerOptions.title("Current Location");
    //markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
    mCurrLocationMarker = mMap.addMarker(markerOptions);
    mCurrLocationMarker.setTag(size + 1);

    //move map camera
    // mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    //mMap.animateCamera(CameraUpdateFactory.zoomTo(11));

    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, locationListenerFinder);
        mGoogleApiClient.disconnect();
        mGoogleApiClient.unregisterConnectionCallbacks(this);
        mGoogleApiClient.unregisterConnectionFailedListener(this);
        //locationListener.clearData();
        mLocationRequest = null;
        locationListenerFinder = null;
    }
    mGoogleApiClient = null;
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

public void checkLocationPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Utility.isPermissionAllowed(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
            Utility.showPermissionDialog(this, Manifest.permission.ACCESS_FINE_LOCATION, BookingKARConstants.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
            locationPermission = false;
            return;
        } else {
            locationPermission = true;
            return;
        }
    }
    locationPermission = true;
}

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    //Checking the request code of our request
    if (requestCode == BookingKARConstants.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) {
        // If request is cancelled, the result arrays are empty.
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            // permission was granted. Do the
            locationPermission = true;
            if (mGoogleApiClient == null) {
                buildGoogleApiClient();
                checkLocationStatus();
            }
            loadMap();
            //mMap.setMyLocationEnabled(true);
        } else {

            // Permission denied, Disable the functionality that depends on this permission.
            Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
            finish();
        }
        return;
    }

    // other 'case' lines to check for other permissions this app might request.
    // You can add here other case statements according to your requirement.
}

private void checkLocationStatus() {
    LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    boolean gps_enabled = false;
    boolean network_enabled = false;

    try {
        gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
    } catch (Exception ex) {
    }

    try {
        network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    } catch (Exception ex) {
    }

    if (!gps_enabled && !network_enabled) {
        // notify user
        AlertDialog.Builder dialog = new AlertDialog.Builder(this);
        dialog.setMessage(getResources().getString(R.string.gps_network_not_enabled));
        dialog.setPositiveButton(getResources().getString(R.string.open_location_settings), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                // TODO Auto-generated method stub
                Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(myIntent);
                //get gps
            }
        });
        dialog.setNegativeButton(getString(R.string.Cancel), new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                // TODO Auto-generated method stub

            }
        });
        dialog.show();
    }
}

/*class WeakLocationListener implements LocationListener {

    private final WeakReference<LocationListener> locationListenerRef;

    public WeakLocationListener(@NonNull LocationListener locationListener) {
        locationListenerRef = new WeakReference<>(WeakLocationListener.this);
    }

    @Override
    public void onLocationChanged(android.location.Location location) {
        if (locationListenerRef.get() == null) {
            return;
        }
        locationListenerRef.get().onLocationChanged(location);
    }

    public interface onLocationChanged {
        void onLocationChanged(Location location);
    }

    public void clearData() {
        if (locationListenerRef.get() != null) {
            locationListenerRef.clear();
        }
    }*/

//}

}

@Override
public void onDestroy() {
    super.onDestroy();
    mLocationManager.removeUpdates(locationListener);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top