Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LocationListener of NETWORK_PROVIDER is enabled but , onLocationChanged is never called

i have experienced similar issues with Network provider and only solution was force device restart. Though google map was showing always correct location, because it uses other sensors information also apart from Network location provider.

But here is good news, not Long time back Google introduced Fused Location Provider api's via its Google Play Service Framework which is super easy to use than GPS / Network Location providers.

Compatible upto API Level 8, now when i get this weird issue of Network provider, same time Fused Location gives me accurate location(without device restart).

I have commited one working FusedLocation Test Project here, you can clone and test yourself..

Below is snippet of code:-

package com.example.fusedLoctionTest.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationRequest;

public class FusedLocationService extends Service implements GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener{
    private static final LocationRequest REQUEST = LocationRequest.create()
            .setInterval(0)
            .setFastestInterval(0)
            .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    public static final String LOCATION_RECEIVED = "fused.location.received";
    private Long now;

    private LocationClient mLocationClient;
    private final Object locking = new Object();
    private Runnable onFusedLocationProviderTimeout;
    private Handler handler = new Handler();

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        now = Long.valueOf(System.currentTimeMillis());
        mLocationClient = new LocationClient(this, this, this);
        mLocationClient.connect();
        return START_STICKY;
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d("FusedLocationService", "Fused Location Provider got connected successfully");
        mLocationClient.requestLocationUpdates(REQUEST,this);
        onFusedLocationProviderTimeout = new Runnable() {
            public void run() {
                Log.d("FusedLocationService", "location Timeout");

                Location lastbestStaleLocation=getLastBestStaleLocation();
                sendLocationUsingBroadCast(lastbestStaleLocation);

                if(lastbestStaleLocation!=null)
                    Log.d("FusedLocationService", "Last best location returned ["+lastbestStaleLocation.getLatitude()+","+lastbestStaleLocation.getLongitude()+"] in "+(Long.valueOf(System.currentTimeMillis())-now)+" ms");

                if(mLocationClient.isConnected())
                    mLocationClient.disconnect();
            }
        };
        handler.postDelayed(onFusedLocationProviderTimeout, 20000);//20 sec
    }

    private void sendLocationUsingBroadCast(Location location) {
        Intent locationBroadcast = new Intent(FusedLocationService.LOCATION_RECEIVED);
        locationBroadcast.putExtra("LOCATION", location);
        locationBroadcast.putExtra("TIME", Long.valueOf(System.currentTimeMillis()-now) +" ms");
        LocalBroadcastManager.getInstance(this).sendBroadcast(locationBroadcast);
        stopSelf();
    }

    @Override
    public void onDisconnected() {
        Log.d("FusedLocationService","Fused Location Provider got disconnected successfully");
        stopSelf();
    }

    @Override
    public void onLocationChanged(Location location) {
        synchronized (locking){
            Log.d("FusedLocationService", "Location received successfully ["+location.getLatitude()+","+location.getLongitude()+"] in "+(Long.valueOf(System.currentTimeMillis()-now))+" ms");

            handler.removeCallbacks(onFusedLocationProviderTimeout);
            if(mLocationClient.isConnected())
                mLocationClient.removeLocationUpdates(this);

            sendLocationUsingBroadCast(location);

            if(mLocationClient.isConnected())
                mLocationClient.disconnect();
        }
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d("FusedLocationService", "Error connecting to Fused Location Provider");
    }

    public Location getLastBestStaleLocation() {
        Location bestResult = null;
        LocationManager locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Location lastFusedLocation=mLocationClient.getLastLocation();
        Location gpsLocation = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        Location networkLocation = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        if (gpsLocation != null && networkLocation != null) {
            if (gpsLocation.getTime() > networkLocation.getTime())
                bestResult = gpsLocation;
        } else if (gpsLocation != null) {
            bestResult = gpsLocation;
        } else if (networkLocation != null) {
            bestResult = networkLocation;
        }

        //take Fused Location in to consideration while checking for last stale location
        if (bestResult != null && lastFusedLocation != null) {
            if (bestResult.getTime() < lastFusedLocation.getTime())
                bestResult = lastFusedLocation;
        }

        return bestResult;
    }

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

I have exactly the same problem and the only solution for me is to reboot device. What's interesting, that none of the apps has a location information except Google maps.
Google maps app somehow finds a location!..

P.S. using a LocationListener in service, so it definitely not a problem of bad reference, dead object and so on.


I still have this problem. But i'm still looking for an answer, I tried to implement this in the listener of the NETWORK_PROVIDER:

public void onStatusChanged(final String provider, final int status, final Bundle extras) {
    switch( status ) {
    case LocationProvider.AVAILABLE:
                // ...
        break;
    case LocationProvider.OUT_OF_SERVICE:
                // ...
        break;
    case LocationProvider.TEMPORARILY_UNAVAILABLE:
                // ...
        break;
    }
}

Because: OUT_OF_SERVICE if the provider is out of service, and this is not expected to change in the near future; TEMPORARILY_UNAVAILABLE if the provider is temporarily unavailable but is expected to be available shortly; and AVAILABLE if the provider is currently available. onStatusChanged

And I thought the OUT_OF_SERVICE was my problem, and there is no solution at so far, just rebooting the device, then I tried to make some reports when this happens and when this ocurre I ask the user to reebot the device, but few devices recive this status.


Seems an open bug, Network Provider problem reported at Android Open Source Project, Issue Tracker: https://code.google.com/p/android/issues/detail?id=57707. In short: issue reported Jul 17, 2013 - last blog Jan 7, 2015, issue appeared from Android 4.1.x, appears in a wide variety of devices, "Not resolved in latest Play service library", no workarounds suggested in Blog.


I understand some thing in our question; you call requestGPS method and then dicover its location.If gps enabled, got via gps. Othervise gott via NET. When call requestGPS and control provider than get lat-lang but remove updates.(Don't call because you removed updates trigger);

if (gpsComSinal) {
    Log.d(TAG,"PEGO SINAL DE GPS");
    rastreio = "GPS";
    longitude = longitudeGPS;
    latitude = latitudeGPS;

    Log.d(TAG, "Utilizando provedor GPS.");
    // if you remove update don't call onLocationChanged
    localizacao.removeUpdates(locationListenerGPS); 
    localizacao.removeUpdates(locationListenerNET);
} else {
    Log.d(TAG,"Sem GPS... pegar NEt");
    // Setando os valores para usar network
    localizacao.removeUpdates(locationListenerGPS);
    localizacao.removeUpdates(locationListenerNET);
    localizacao.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                                       0, 0, locationListenerNET);
    Log.d(TAG,"EsperaNET");
    requestNET();
}

NETWORK_PROVIDER doesn't update when the phone's GPS is running and receiving a signal. If you switch off GPS and force the phone to get its location from the network, then you will start getting updates again.