Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play Location Services getLastLocation returns null

I am trying to listen to location changes but sometimes onLocationChanged callback is never called and getLastLocation returns null, while Google Maps always working perfectly.

Note

If I reboot my device the location service will work for ~2 days only; after that neither my app nor the SDK example will work while Google Maps still working.

This is my service code:

public class VisitService extends Service implements
        GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener, 
        LocationListener {

    private final IBinder mBinder = new VisitBinder();


    // A request to connect to Location Services
    private LocationRequest mLocationRequest;

    // Stores the current instantiation of the location client in this object
    private LocationClient mLocationClient;


    private boolean mLocationServiceConnected = false;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        initLocation();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        initLocation();
        return mBinder;
    }

    public void startVisit() {
        if (!servicesConnected()) {
            listener.onVisitStartError();
            return;
        }

        if (mLocationServiceConnected) {
            if (isAcceptableLocation(mLocationClient.getLastLocation())) {
                Toast.makeText(this, "You have arrived!", Toast.LENGTH_LONG);
            } else {
                mVisitListener.onVisitStartError();
            }
        }    
    }

    private boolean isAcceptableLocation(Location location) {
        if (location == null) {
            Toast.makeText(this, "Location is null", Toast.LENGTH_LONG).show();
            return false;
        }

        return true;
    }


    private void initLocation() {

        if (mLocationRequest == null) {
            // Create a new global location parameters object
            mLocationRequest = LocationRequest.create();
            /*
             * Set the update interval
             */
            mLocationRequest
                    .setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);

            // Use high accuracy
            mLocationRequest
                    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

            // Set the interval ceiling to one minute
            mLocationRequest
                    .setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);

        }

        if (mLocationClient == null) {
            mLocationClient = new LocationClient(this, this, this);
            mLocationClient.connect();
        }
    }

    /**
     * Verify that Google Play services is available before making a request.
     * 
     * @return true if Google Play services is available, otherwise false
     */
    private boolean servicesConnected() {

        // Check that Google Play services is available
        int resultCode = GooglePlayServicesUtil
                .isGooglePlayServicesAvailable(this);

        // If Google Play services is available
        if (ConnectionResult.SUCCESS == resultCode) {
            // In debug mode, log the status
            Log.d(LocationUtils.APPTAG,
                    getString(R.string.play_services_available));

            return true;
        } else {

            return false;
        }
    }

    public class VisitBinder extends Binder {
        public VisitService getService() {
            return VisitService.this;
        }
    }


    /**
     * In response to a request to start updates, send a request to Location
     * Services
     */
    private void startPeriodicUpdates() {

        mLocationClient.requestLocationUpdates(mLocationRequest, this);
        Toast.makeText(this, "Location Update Requested", Toast.LENGTH_LONG).show();
    }

    /**
     * In response to a request to stop updates, send a request to Location
     * Services
     */
    private void stopPeriodicUpdates() {
        mLocationClient.removeLocationUpdates(this);

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(LocationUtils.APPTAG, "Location Services Connection faild");


    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d(LocationUtils.APPTAG, "Location Services Connected");
        mLocationServiceConnected = true;
        startPeriodicUpdates();
    }

    @Override
    public void onDisconnected() {
        mLocationServiceConnected = false;
    }

    @Override
    public void onLocationChanged(Location location) {
        Toast.makeText(this, "Location has been changed", Toast.LENGTH_LONG).show();
    }
}

Android Manifest

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
like image 1000
Walid Ammar Avatar asked Dec 11 '22 04:12

Walid Ammar


1 Answers

Firstly it is a bug. I also faced this problem.

You can try a simple workaround.

Do a request for location update before you try to get last location, i.e. Request for location updates before you try to find the last location using getLastLocation();

Just like:

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria crta = new Criteria();
crta.setAccuracy(Criteria.ACCURACY_FINE);
crta.setAltitudeRequired(true);
crta.setBearingRequired(true);
crta.setCostAllowed(true);
crta.setPowerRequirement(Criteria.POWER_LOW); 
String provider = locationManager.getBestProvider(crta, true);
Log.d("","provider : "+provider);
// String provider = LocationManager.GPS_PROVIDER; 
locationManager.requestLocationUpdates(provider, 1000, 0, locationListener);
Location location = locationManager.getLastKnownLocation(provider); 

This implementation is based of LocationManager. Please opt Location Client for same.

Hope it helps!

UPDATE

Here you can also go for onLocationChanged() method as it will update you each time location is changed while getLastLocation() method returns best known location which might be NULL.

As per doc, GetLastLocation() method will return NULL in very rare cases. But this happens often with me too.

NEWEST UPDATE

Guys only one update regarding GPS :

Firstly we need to make use of GoogleApiClient instead LocationClient class.

Secondly we need to implement GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener

Third we need to override its onConnected() , onConnectionSuspended() and onConnectionFailed() method.

Rest you are good to go.

CHEERS!

like image 140
AndroidHacker Avatar answered Dec 17 '22 22:12

AndroidHacker