OnLocationChanged callback is never called
Asked Answered
U

16

79

I am trying to get the users current location using the LocationManager. I have done a lot of research and can't seem to find anyone with the same problem. The OnLocationChanged callback never seems to be called. Below is my various code and the logcat.

protected LocationListener locationListener;
protected LocationManager locationManager;
protected Context context;

My OnCreate() method

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.v(TAG, "IN ON CREATE");

    this.context = getActivity();

    registerLocationUpdates();
}

My registerLocationUpdates method

void registerLocationUpdates() {
    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_LOW);
    criteria.setPowerRequirement(Criteria.POWER_LOW);
    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(false);

    locationManager = (LocationManager)getActivity().getSystemService(LOCATION_SERVICE);

    provider = locationManager.getBestProvider(criteria, true);

    // Cant get a hold of provider
    if (provider == null) {
        Log.v(TAG, "Provider is null");
        showNoProvider();
        return;
    } else {
        Log.v(TAG, "Provider: " + provider);
    }

    locationListener = new MyLocationListener();

    locationManager.requestLocationUpdates(provider, 1L, 1f, locationListener);

    // connect to the GPS location service
    Location oldLocation = locationManager.getLastKnownLocation(provider);

    if (oldLocation != null)  {
        Log.v(TAG, "Got Old location");
        latitude = Double.toString(oldLocation.getLatitude());
        longitude = Double.toString(oldLocation.getLongitude());
        waitingForLocationUpdate = false;
        getNearbyStores();
    } else {
        Log.v(TAG, "NO Last Location found");
    }
}

My LocationListener

private class MyLocationListener implements LocationListener {

    public void onLocationChanged(Location location) {
        latitude = Double.toString(location.getLatitude());
        longitude = Double.toString(location.getLongitude());

        Log.v(TAG, "IN ON LOCATION CHANGE");

        if (waitingForLocationUpdate) {
            getNearbyStores();
            waitingForLocationUpdate = false;
        }

        locationManager.removeUpdates(this);
    }

    public void onStatusChanged(String s, int i, Bundle bundle) {
        Log.v(TAG, "Status changed: " + s);
    }

    public void onProviderEnabled(String s) {
        Log.e(TAG, "PROVIDER DISABLED: " + s);
    }

    public void onProviderDisabled(String s) {
        Log.e(TAG, "PROVIDER DISABLED: " + s);
    }
}

My permissions in the AndroidManifest

<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" />

And finally the logcat after I run my app

01-25 09:43:10.963: VERBOSE/NearbyListFragment(3060): IN ON CREATE
01-25 09:43:10.963: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.963: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.973: VERBOSE/LocationManagerService(1329): getProviders
01-25 09:43:10.983: VERBOSE/NearbyListFragment(3060): Provider: gps
01-25 09:43:10.983: DEBUG/LocationManager(3060): requestLocationUpdates: provider = gps, listener = co.fusionweb.dealsplus.app.NearbyItems$NearbyListFragment$MyLocationListener@46ef4680
01-25 09:43:10.983: DEBUG/GpsLocationProvider(1329): setMinTime 1
01-25 09:43:10.983: VERBOSE/NearbyListFragment(3060): NO Last Location found
01-25 09:43:10.983: VERBOSE/LocationManagerService(1329): _requestLocationUpdates: listener = Receiver{47421e68 Listener android.os.BinderProxy@47421a68}
01-25 09:43:11.003: VERBOSE/countingFragment(3060): IN ON CREATE VIEW
01-25 09:43:11.003: WARN/GpsLocationProvider(1329): Duplicate add listener for co.fusionweb.dealsplus
01-25 09:43:11.013: VERBOSE/ScrollListener(3060): In Constructor
01-25 09:43:11.013: VERBOSE/ScrollListener(3060): Scrolling
01-25 09:43:11.033: DEBUG/GpsLocationProvider(1329): startNavigating
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_qos_time_out(standalone = 60, agps = 89)
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_qos_accuracy(accuracy = 50)
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): persist.radio.agps.mode: []
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_set_position mode, client = 1, interval = 1, mode = 1
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): loc_eng_ioctl called: client = 1, ioctl_type = 2
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): loc_ioctl
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [96]
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet size: [28]
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): loc_api_sync_ioctl: select_id = 0, loc_ioctl returned 0
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.043: VERBOSE/locapi_rpc_glue(1329): Callback received: 80 (cb_id=0x5310000 handle=1)
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [28]
01-25 09:43:11.043: VERBOSE/lib_locapi(1329): loc_eng_ioctl result: client = 1, ioctl_type = 2, SUCCESS
01-25 09:43:11.043: DEBUG/lib_locapi(1329): loc_eng_start
01-25 09:43:11.043: DEBUG/locapi_rpc_glue(1329): loc_start_fix
01-25 09:43:11.043: DEBUG/RPC(1329): written RPC packet size: [44]
01-25 09:43:11.043: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.053: DEBUG/RPC(1329): read RPC packet size: [28]
01-25 09:43:11.103: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.103: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.113: VERBOSE/locapi_rpc_glue(1329): Callback received: 100 (cb_id=0x5310000 handle=1)
01-25 09:43:11.113: VERBOSE/lib_locapi(1329): process_deferred_action: pthread_cond_wait returned
01-25 09:43:11.113: DEBUG/lib_locapi(1329): loc_eng_report_status: GPS_STATUS_SESSION_BEGIN
01-25 09:43:11.113: DEBUG/lib_locapi(1329): loc_eng_report_status: update status
01-25 09:43:11.113: VERBOSE/GpsLocationProvider(1329): reportStatus status: 1
01-25 09:43:11.113: DEBUG/GpsLocationProvider(1329): Acquiring wakelock
01-25 09:43:11.123: DEBUG/RPC(1329): written RPC packet size: [28]
01-25 09:43:11.183: DEBUG/PowerManagerService(1329): New lightsensor value:40, lcdValue:77
01-25 09:43:11.273: DEBUG/RPC(1329): read RPC packet
01-25 09:43:11.273: DEBUG/RPC(1329): read RPC packet size: [80]
01-25 09:43:11.273: VERBOSE/locapi_rpc_glue(1329): Callback received: 100 (cb_id=0x5310000 handle=1)
01-25 09:43:11.273: VERBOSE/lib_locapi(1329): process_deferred_action: pthread_cond_wait returned
01-25 09:43:11.273: DEBUG/lib_locapi(1329): loc_eng_report_status: GPS_STATUS_ENGINE_ON
01-25 09:43:11.273: DEBUG/lib_locapi(1329): loc_eng_report_status: update status
01-25 09:43:11.273: VERBOSE/GpsLocationProvider(1329): reportStatus status: 3

And the android SDK location parts of the logcat keep repeating them selves. I have tried everything that i can think of and have seen on google and stackoverflow. Als just as a side note i have been able to get it to work on a 2.3 device using the requestSingleUpdate which is available in API 9 and by following the guide A Deep Dive into Location but i need it to work on 2.1 or 2.2 and higher using the old SDK. SO if you have any hints or would like to know more please let me know.

Ulrich answered 25/1, 2012 at 17:53 Comment(2)
Although it is very late but I hope this comment can help someone else, look at this link: lengrand.fr/2013/10/…Responsum
My OnLocationChanged() is never called either when I run it on my real phone. However, when I run it in the simulator, it works (gives of course the GPS location of the Google Headquarters in San Francisco). How is that possible? Even if my phone has no GPS reception, OnLocationChanged() should be called upon (every 5000 milliseconds). Doesn't happen. Anyone?Haber
S
78

It looks like you setup should work, since it doesn't, I would make your example as simple as possible in order to troubleshoot. I would make your request look like

requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

This way you get ALL the updates possible. And comment out the part about getting the last known location. It's not needed yet.

Then in onLocationChanged(), just have

Log.v(TAG, "IN ON LOCATION CHANGE, lat=" + latitude + ", lon=" + longitude);

Comment out the rest so that you keep your listener active. This should give you a stream of updates on a real device. On the emulator, you'll need to use DDMS, and you'll get one GPS update each time you press send.

Sufflate answered 25/1, 2012 at 18:52 Comment(6)
That almost worked, well i thought it worked because it worked on the MyTouch 4G, i kept on getting update after update. Then i tried on another device (MyTouch 3G) and it no longer worked. I have noticed that on better devices like a Bionic the GPS works very fast, but on lower end phones it seems like i can never get it to work. Are lower end phones really that bad in GPS? or is there something else i am missing?Ulrich
Simplifying helped but it also turned out that on the MyTouch 3G that i couldn't get a position until i connected to a WiFi network firstUlrich
this doesn't make any differenceTarp
Thank you so much !Carce
In order to avoid callback overhead / battery comsumption I recommend to unregister callback when onLocationChanged is called locationManager.removeUpdates(this)Suborder
You save my app mate, much obliged.Isaiasisak
O
16

Replacing

LocationManager.GPS_PROVIDER

with

LocationManager.NETWORK_PROVIDER

solved my problem.

Here is code snippet of my location manager

 LocationManager locationManager = (LocationManager) getActivity().getSystemService(LOCATION_SERVICE);

//Check for Location permissions, Marshmallow and above

        if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.

            Toast.makeText(getActivity(), "Not Enough Permission", Toast.LENGTH_SHORT).show();
            return;
        }

//Get current location to start with

        Location myLocation = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);

        currentLatitude = myLocation.getLatitude();
        currentLongitude = myLocation.getLongitude();

// Request location update using LocationManager.NETWORK_PROVIDER

        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                MIN_TIME_BW_UPDATES,
                MIN_DISTANCE_CHANGE_FOR_UPDATES, MapFragment.this);
Oersted answered 11/1, 2017 at 7:17 Comment(1)
But what if you want the satellite data, and not the data of your provider? After all, it's a GPS app.Haber
B
16

GPS Provider will disable when device in low power or use power save mode then in that case we can not receive onLocationChanged

GPS Provider hardly ever return the location if you stay inside house or building (only work well in outdoor)

Therefore, in my app I will use both GPS_PROVIDER and NETWORK_PROVIDER to receive onLocationChanged() better

https://developer.android.com/guide/topics/location/strategies.html#Updates

To request location updates from the GPS provider, use GPS_PROVIDER instead of NETWORK_PROVIDER. You can also request location updates from both the GPS and the Network Location Provider by calling requestLocationUpdates() twice—once for NETWORK_PROVIDER and once for GPS_PROVIDER.

Bigelow answered 24/3, 2017 at 9:13 Comment(1)
In my case in PRIORITY_HIGH_ACCURACY priority network provider turned off automatically, while in PRIORITY_BALANCED_POWER_ACCURACY it found my coordinates. So, after going outdoor GPS found my device in several minutes.Jalousie
N
5

As Steve Blackwell wrote, your setup is good. What you can try is to understand if you 100% have a GPS fixed signal! I have installed a nice GPS Tester application (from the play store) and it will show you if you have a fix or not and to which satellites you are connected and what is the connection strength. This was the reason my OnLocationChanged() never called.. I tried running it from within a building :\

good luck!

Negrito answered 22/10, 2015 at 8:7 Comment(4)
Thanks for sharing that awesome application, I installed it and came to know that in some places my gps location is not updated automatically(in my application)Claudiaclaudian
Awesome tool, that GPS Test app, so I can see that on my device it shows GPS: NO Fix. I assume this means there's no fixed GPS signal, right?Risky
Yeap. It means "I don't have enough sat connections to calculate triangulation to set your location" basically ..Negrito
Thanks! I understood that my new cheap device couldn't establish a connection with satellites. So, in a building I couldn't see GPS coordinates with PRIORITY_HIGH_ACCURACY (while on Samsung Galaxy S4 it found in seconds). After I walked in a street, it found coordinates, but in several minutes.Jalousie
U
3

Sorry for bumping such an old thread, but this might come handy to some others, since this question is ranking relatively high on google search.

I had a similar problem, the onlocationchanged wasn't getting fired, but I could not find anything wrong with my code. After trying all sorts of combination, I realised that the root cause of the problem was the fact that I was registering the listener in a service.

The service WAS a foreground service, so based on Google documentation that should work, it DID NOT!

Wrapping the initialisation in a method, and calling the method from the activity which created or bind to the service solved my problem.

This is my method in my service:

void start_gps_track(int i) {
        if (myCarLocationListener!=null) {
            if (i==1) //if start night
                myCarLocationListener.setNightstart(true);
            else if (i==2) //if start GPS
                myCarLocationListener.setLocationStart(true);
            return;
        }
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if ( locationManager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
            myCarLocationListener=new CarLocationListener(this,adjust_audio);
            if (i==1) //if start night
                myCarLocationListener.setNightstart(true);
            else if (i==2) //if start GPS
                myCarLocationListener.setLocationStart(true);
            try {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0, myCarLocationListener);
                Log.d("HU","Registered location listener");
                Location lastlocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                if (lastlocation == null)
                    lastlocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                if (lastlocation != null)
                    myCarLocationListener.onLocationChanged(lastlocation);
            }
            catch (SecurityException e){
                Log.e("HU-GPS","No permission to access Location");
            }
        }
        else
        {
            Log.e("HU-GPS","No GPS provider or no permission");
        }
    }

If I call this from within the Service itself I won't receive any Location Updates (again note service is a FOREGROUND service and it's actually binded to an activity which is currently running).

However if I call this method from the activity which created/bound to the service like below it works fine:

@Override
public void onServiceConnected(ComponentName className,
                               IBinder service) {
    // We've bound to LocalService, cast the IBinder and get LocalService instance
    TransporterService.LocalBinder binder = (TransporterService.LocalBinder) service;
    mService = binder.getService();
    mService.updatePlayer(player.this);
    try {
        mService.start_gps_track(0);
    }
    catch (Exception e) {            //This should only happen if there is no GPS provider available, but it might happen quickly after boot when the device is not yet ready.
        mService.recheck_gps(0);
    }

    mBound = true;
  }

@Override
public void onServiceDisconnected(ComponentName arg0) {
    mBound = false;

}
};

Hope this helps some others who come across this problem.

Ushaushant answered 21/12, 2018 at 23:46 Comment(1)
This was exactly my issue as well. Same scenario and thx for the clue. Wish Google would fix buggy Android but then again, it wouldn't be Android but iOS.Baalbeer
U
2

I experienced similar issue. I had the permissions, requested for service correctly, but no update came. It turned out that all I had to do was simply wait. While I was searching for the issue on the internet, I had the application running and after few minutes it just started to receiving updates. Then even when I killed the app and run it again, the updates came instantaneously - I guess it is a system thing, some optimization, maybe due to the fact that device wasn't moving at all (btw. it is not some shitty device, it is Pixel).

Unclad answered 4/2, 2017 at 21:39 Comment(0)
K
1
LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (manager != null) {
        List<String> providers = manager.getAllProviders();
        for (String provider : providers) {
           manager.requestLocationUpdates(provider, TIME_BW_UP, DISTANCE_BW_UP, locationListener);
        }
}
Kant answered 20/9, 2018 at 8:59 Comment(0)
C
0

I faced same issue. I was getting getLastKnownLocation as null. Issue is resolved when I restarted both the device and Location service in device.

Canticle answered 13/11, 2015 at 14:47 Comment(1)
I faced same issue but came to know that some devices also take time/movement to fetch location lat-lon... my nexus was not fetching the lat-lon while moto was able to fetchShaina
Z
0

If you are trying with NETWORK_PROVIDER, it is really difficult to test:

  • on Emulator: never work
  • on Real Device: only getLastKnownLocation() works, to receive onLocationChanged(), you have to use mobile data and go outside with the risk of losing phone from robber :P

I guess the reason is that it just the location of network provider only not your device itself, and the network provider never move, so the onLocationChanged() never call. It might happen only when switching between mobile data and wifi and vice versa. Please correct me if I am wrong.

So I suggest to use GPS_PROVIDER to experiment before considering performance and battery usage. It works nicely on both emulators and real devices. For the best practice: https://developer.android.com/guide/topics/location/strategies.html

It took me several hours to test with NETWORK_PROVIDER without any results, so hopefully my suggestion helpful.

Zonnya answered 9/6, 2017 at 3:46 Comment(0)
K
0

I had the same problem (onLocationChanged() never called with NETWORK_PROVIDER) on my real device (M, app's targetSDK 23) until I restarted it.

Ketch answered 3/7, 2017 at 18:34 Comment(0)
O
0

As Phan Van Linh answered , it's probably because you are inside a building. There are explanation here on how to mock GPS for the emulator. Also, there is this app that mocks GPS data.

Optional answered 29/5, 2018 at 14:59 Comment(0)
J
0

I have 2 devices: Samsung Galaxy S4 (Android 5.0.1) and Vertex Win (Android 8.1).

On Samsung everything works right and fast, GPS coordinates are found, and onLocationChanged is called.

On Vertex in prioity PRIORITY_BALANCED_POWER_ACCURACY it probably interacts with network provider first, so it finds coordinates via Wi-Fi. But it can't detect right, whether location service is turned on (after some time the device thinks it is turned on, while it is off, and calls addOnSuccessListener method of LocationServices.getSettingsClient. So I switched to PRIORITY_HIGH_ACCURACY and got another surprise. Network provider turned off, but onLocationChanged wasn't called, so I couldn't get coordinates. I downloaded GPS tester (as @Li3ro advised) from Play Market and saw that sattelites are visible, but without fixed signal. I couldn't receive a signal inside a building.

Even standalone maps couldn't receive coordinates, but outdoor could. So, after I walked away, I could find my coordindinates in an application.

See also https://mcmap.net/q/263127/-onlocationchanged-not-called-on-some-devices, where it is said about priorities and error recognition (disabling GPS after some time if no coordinsates found).

Jalousie answered 24/12, 2018 at 8:3 Comment(0)
L
0

This should be happen due to your phone settings. In phones Location settings, If the Location service Mode set to GPS only, then OnLocationChanged callback calls when there is GPS Fix. By selecting Use GPS, WI-FI And mobile networks options, location will be determine by using those three providers. This will take less time to locate your device location. ***Path to access to location services could be change device to device. Thanks

Lampedusa answered 18/8, 2019 at 4:11 Comment(0)
J
0

This happened to me when the location was turned off. Not the location permission for the app, but the location for the android device itself. Requesting that the user activate the GPS fixed it for me:

protected void onCreate(Bundle savedInstanceState) {
    //...
    final LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );

    if ( !manager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
        buildAlertMessageNoGps();
    }
}

private void buildAlertMessageNoGps() {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Your GPS seems to be disabled, do you want to enable it?")
            .setCancelable(false)
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                    startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                    dialog.cancel();
                }
            });
    final AlertDialog alert = builder.create();
    alert.show();
}

Solution from here.

You may also need to turn the GPS off and then on again to trigger a dialog to improve location accuracy:

Dialog prompting to improve location accuracy

Jagged answered 18/3, 2020 at 17:0 Comment(0)
P
0

In my case even after writing correct code, I did not get location using client.requestLocationUpdates(locationRequest, this, it). In phone gps was enabled as well using

val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)

After spending time in switching emulators, builds, etc, finally figured out that Location mode was "Device Only" and it wasn't providing the result on emulator. Switched to it to "High accuracy" and it started working.

Pushover answered 10/6, 2021 at 9:8 Comment(0)
J
0

In my case the gps was disabled.

So I turned On Location from setting and it worked fine

Jug answered 14/10, 2022 at 12:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.