LocationListener和内存泄漏

时间:2014-01-23 10:19:24

标签: android memory-leaks location locationlistener

根据找到用户位置的sample app,最好听一下活动中的位置变化:

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
    }

    // ...
}

但是,我不确定。当配置发生更改时,我的活动将被销毁并重新创建,下次将自己注册为侦听器。对旧活动的引用保存在LocationManager中,不是吗?

如果我将LocationListener提取为单独的对象,我仍然遇到如何通知当前活动有关新位置的问题(不一定与请求活动相同)。

有没有可以解决这个问题的常见模式?

5 个答案:

答案 0 :(得分:5)

在这个示例中,您还有另一个问题:您的GPS聆听者将始终工作并且会耗尽电池。

更好的做法是:

1)将LocationListener注册到Activity的onStart()

2)将LocationListener移除到Activity的onStop()

这将解决这两个问题。

如果您的应用需要跟踪用户在后台的位置(例如,GPS跟踪器),请使用Servicehttp://developer.android.com/reference/android/app/Service.html

答案 1 :(得分:3)

使用所有这些建议我有内存泄漏。我让他们停止在我不再需要监听器,onDestroy和onStop的点上应用这个方法。我还将它添加到onPause,但您必须确定这是否适合您的应用。

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

答案 2 :(得分:2)

解决此类问题的方法是使用服务。

服务是一个应用程序组件,可以在后台执行长时间运行的操作,但不提供用户界面。另一个应用程序组件可以启动服务,即使用户切换到另一个应用程序,它也将继续在后台运行。

关于服务还有一件事是无法更新UI。因此,您希望将哪些数据发送到您的活动,您可以通过意图来实现。

服务可以特定于您的应用,或者多个应用可以共享相同的服务。 如果服务特定于您的应用,则您必须关闭此服务;否则它将在后台运行。服务不在单独的线程上运行。

位置监听器的示例代码为服务

public class GPSTracker extends Service implements LocationListener {

    private  Context mContext;
    private final String TAG = "GPSTracker";

    // flag for GPS status
    boolean isGPSEnabled = false;

    // flag for network status
    boolean isNetworkEnabled = false;

    // flag for GPS status
    boolean canGetLocation = false;

    Location location; // location
    double latitude; // latitude
    double longitude; // longitude

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;
    Intent intent = new Intent(MainActivity.LOCATION_CHANGE);

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG,"onStartCommand");
        Log.d(TAG, "flag " + flags + "startId" + startId);
        this.mContext = this;
        getLocation();
        return super.onStartCommand(intent, flags, startId);
    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext
                    .getSystemService(LOCATION_SERVICE);

            // getting GPS status
            isGPSEnabled = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            // getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            Log.d(TAG, "getlocation gpsEnabled " + isGPSEnabled + "networkenabled"
                    + isNetworkEnabled);
           if (!isGPSEnabled && !isNetworkEnabled) {
               Toast.makeText(mContext, "Enable GPS or Network", Toast.LENGTH_LONG).show();
               Log.d(TAG,"No network Provider is enabled");
                // no network provider is enabled
            } else {
                this.canGetLocation = true;
                // First get location from Network Provider
                if (isNetworkEnabled) {

                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                            Log.d(TAG,"LAtitude :" +latitude +"Lngitude:"+longitude);
                            onLocationChanged(location);

                        }
                    }
                }
                // if GPS Enabled get lat/long using GPS Services
                else if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                                onLocationChanged(location);
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }

    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app
     */
    public void stopUsingGPS() {
        if (locationManager != null) {
            locationManager.removeUpdates(GPSTracker.this);
        }
    }
    @Override
    public void onDestroy() {
        Log.d(TAG,"onDestroy Called");
        stopUsingGPS();
        super.onDestroy();
    }
    @Override
    public void onLocationChanged(Location newLocation) {
        Log.d(TAG,"onLocationChanged new Latitude: " + newLocation.getLatitude() +
                "  \nLongitude :" + newLocation.getLongitude());
        intent.putExtra("latitude", newLocation.getLatitude());
        intent.putExtra("longitude", newLocation.getLongitude());
        sendBroadcast(intent);
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

答案 3 :(得分:1)

您可以创建一个单独的类来执行相同操作,然后为您的活动实现LocationListenerFinder.onLocationChanged接口

现在你不会遇到泄漏问题。

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);
    }
}

在我的情况下,活动就是这个......您可以参考相同的内容并根据需要进行转换。

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();
        }
    }*/

//}

}

答案 4 :(得分:0)

@Override
public void onDestroy() {
    super.onDestroy();
    mLocationManager.removeUpdates(locationListener);
}