LocationListener of NETWORK_PROVIDER is enabled but , onLocationChanged is never called
Asked Answered
A

8

42

I am developing an application that gets position of the cell phone all day long in 6 and 6 minutes in a service, it works fine but sometimes the method OnLocationChanged of the Network provider listener stop to being called, and I don't know why.

It for some reason stop being called, but the Provider is enable and the Lister is working, when I Enable or disable the Provider manually, onProviderEnabled and onProviderDisabled is called.

It just happens with NETWORK_PROVIDER, the GPS_PROVIDER works well.

Listener:

LocationListener locationListenerGPS = new LocationListener() {
        // @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO locationListenerGPS onStatusChanged
            Log.d(TAG, "Provedor trocado");
        }

        // @Override
        public void onProviderEnabled(String provider) {
            Log.w(TAG, "PROVEDOR " + provider + " HABILITADO!");
        }

        // @Override
        public void onProviderDisabled(String provider) {
            Log.w(TAG, "PROVEDOR " + provider + " DESABILITADO!");
        }

        // @Override
        public void onLocationChanged(Location location) {

            longitudeGPS = location.getLongitude();
            latitudeGPS = location.getLatitude();
            Log.d(TAG,"LocationChangedGPS LAT: "+latitudeGPS+" longi: "+longitudeGPS);
            gpsComSinal = true;
        }
    };

    LocationListener locationListenerNET = new LocationListener() {

        // @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO locationListenerNET onStatusChanged
            Log.d("Contele", "Provedor foi mudado");
        }

        // @Override
        public void onProviderEnabled(String provider) {
            Log.i(TAG, "PROVEDOR " + provider + " HABILITADO!");
        }

        // @Override
        public void onProviderDisabled(String provider) {
            Log.i(TAG, "PROVEDOR " + provider + " DESABILITADO!");
        }

        @Override
        public void onLocationChanged(Location location) {
            longitudeNET = location.getLongitude();
            latitudeNET = location.getLatitude();
            Log.d(TAG,"LocationChangedNET LAT: "+latitudeNET+" longi: "+longitudeNET);
            netComSinal = true;
        }
    };

Code:

public void initProviders() {

        localizacao = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);


        localizacao.removeUpdates(locationListenerNET);
        localizacao.removeUpdates(locationListenerGPS);

        localizacao.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                locationListenerGPS);

        localizacao.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,
                0, locationListenerNET);

        Log.d(TAG,"EsperaGPS");
        Handler esperaGPS = new Handler() {
            public void handleMessage(Message msg) {

                requestGPS();
            }
        };

        Message msgEsperaGPS = Message.obtain();
        msgEsperaGPS.what = 0;
        esperaGPS.sendMessageDelayed(msgEsperaGPS, 35000);
    }



    public void requestGPS() {
            if (gpsComSinal) {
                Log.d(TAG,"PEGO SINAL DE GPS");
                rastreio = "GPS";
                longitude = longitudeGPS;
                latitude = latitudeGPS;
                Log.d(TAG, "Utilizando provedor GPS.");
                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();
            }
        }

    public void requestNET() {
            if (netComSinal) {
                Log.d(TAG,"PEGO SINAL DE NET");
                rastreio = "NET";
                longitude = longitudeNET;
                latitude = latitudeNET;
                Log.d(TAG, "Utilizando provedor NET.");
                localizacao.removeUpdates(locationListenerNET);

            } else {
                localizacao.removeUpdates(locationListenerGPS);
                localizacao.removeUpdates(locationListenerNET);
                Log.d(TAG,"Sem sinal");
            }
        }

Report in a Samsung Galaxy S3: enter image description here

Still getting "Sem sinal" for 4 days in a row.

This issue have already happened with Galaxy Y and LG Optimus l5

I have made another test to see if other aplications got the NET positions, and I discovered that they are passing for the same problem, they can't get the NET position just the GetLastknowLocation; to test that I used a Galaxy S3 with this problem, and I disabled the GPS Provider. (Tested in Cerberus).

I couldn't find any explanation for why NETWORKSLOCATIONS listener stop giving positions, but it might be because it shouldn't work for 2 or 3 days without stop.

I have done some tests with other aplications to see if this issue is just happening with my aplication, and I discovered that they are passing for same problem, like in Cerberus for example :

I disable the GPS Provider in a cellphone (Galaxy S3) with the "Sem sinal" problem, take a look:

My report: enter image description here

And Cerberus(print taken in 14/05/2013) report: enter image description here

But When I opened the Google Maps it seems to work OK, I tried to move to a distance place to see if it going to show the GetLastknowLocation , but no, google maps put me in the right place in the moment, so I realized that Google Maps was using motionevent to move me in the map;

And also print the Log of Google Maps to get NetWorkProvider:

Normal case:

enter image description here

Sem sinal case:

enter image description here

Attu answered 1/4, 2013 at 16:46 Comment(5)
That's because network provider is providing not your location but tower/bts cell location instead. I may be wrong but I think if you'll move enough, you'll probably catch other tower/bts cell and you'll get new location in that network listener.Frugal
Have already tought this, and I tried to move it 2000 meters + but without success, if I reboot the cell phone the aplication works normally for 4 or 3 days, in some device this issue never happened. I got a Galaxy S3 with this problem for 2 days in a row , and it didn't get a single Net position, just GPS.Attu
Seems like device NetworkLocation Provider is broken..i also faced similar kind of issue on some HTC devices, then searched net for HTC GPS issue and found lot of users complaining GPS not working properly..Ruthenious
@Ruthenious I think it is not a devices problem, because it happened with other phones before.Attu
linking related questions #13595432 #15748043 #17735404 #16014101 #17169643Lipoma
R
28

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;
    }
}
Ruthenious answered 1/4, 2013 at 16:46 Comment(5)
I've implemented something similar and can receive Location Updates when my app goes into the background. However, when I destroy my app (service is still running) I no longer receive location updates. The same happens with your app. Any ideas why?Sentimentality
R... restart? What a terrible failure, Google.Ensanguine
google play services library maxes out my dex method number.Justifiable
this answer was been deprecated, LocationClient and GooglePlayServicesClient was changing into GoogleApiClient see this maybe will helpCheckmate
After struggling for hours, the solution for me was to simply stand up, and take a step outside.!Pliable
A
4

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.

Attu answered 1/4, 2013 at 16:46 Comment(0)
M
4

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.

Milligan answered 1/4, 2013 at 16:46 Comment(2)
Yep, it is a kind of mystery but i think Google maps uses the accelerometer to handle this issue.Attu
In my case, my app would not receive any onLocationChanged callbacks on one particular phone, when others received them. I noticed the same thing as m190: somehow Google Maps was getting the current location, and my app was being stuck with only being able to get the last known locations, which were quite old. Rebooting the device ultimately fixed the problem. Would love to know what Google Maps was doing differently...Glorious
T
3

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.

Teat answered 1/4, 2013 at 16:46 Comment(1)
Why did they mark that as obsolete... the problem was never fixed.Arguelles
T
2

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.

Tramway answered 1/4, 2013 at 16:46 Comment(0)
E
2

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();
}
Essence answered 1/4, 2013 at 16:46 Comment(1)
I agree with you that there are some useless removeUpdates, but at this point, if(gpsComSinal) I have already waited 35 seconds to listen to NetProvicer and GPSProvider and saved theirs positions, because i want positions in 6 and 6 minutes and i want to save battery. So this removeUpdates are not the problem because after 6 minutes I request theirs positions again.Attu
G
1

I think it's because your app get's 'killed' in the background. I have faced this problem before and I solved it by moving the creation of the LocationListener in a service. Be sure to keep a reference to the listener too. It just might solve the problem.

Guadalupe answered 1/4, 2013 at 16:46 Comment(1)
I have a service that runs in 6 and 6 minutes in that service, I created the LocationListener for GPS and NET, and there is no errors, the aplication is not getting killed too, because it still gets the GPS position, if I go out the OnlocationChanged of the GPS provider returns me a LAT and LONGITUDE, but the NET stills "dead" even if I have a WIFI connection or 3G.Attu
R
0

I've encountered with this issue and I found that the Network provider not working in some android devices When you disable GPS because they're prevent access location data if GPS not enabled.

I've tried that on many devices 1. lenove k6 note (screen shot1 , screen shot2) 2. Xiomai mi 9t screen shot1 3. Google Pixel 1 & Pixel 2

so some devices need GPS enabled to access location from LocationManager.NETWORK_PROVIDER and you can't get location data without enable GPS

Runkel answered 1/4, 2013 at 16:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.