OnLocationChanged callback is never called

AndroidGeolocationLocationmanager

Android Problem Overview


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. Thanks in advance.

Android Solutions


Solution 1 - Android

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.

Solution 2 - Android

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

Solution 3 - Android

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.

Solution 4 - Android

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!

Solution 5 - Android

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.

Solution 6 - Android

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).

Solution 7 - Android

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

Solution 8 - Android

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

Solution 9 - Android

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.

Solution 10 - Android

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

Solution 11 - Android

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.

Solution 12 - Android

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://stackoverflow.com/a/27828929/2914140, where it is said about priorities and error recognition (disabling GPS after some time if no coordinsates found).

Solution 13 - Android

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

Solution 14 - Android

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

Solution 15 - Android

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionsmitt04View Question on Stackoverflow
Solution 1 - AndroidSteve BlackwellView Answer on Stackoverflow
Solution 2 - AndroidHitesh SahuView Answer on Stackoverflow
Solution 3 - AndroidLinhView Answer on Stackoverflow
Solution 4 - AndroidLi3roView Answer on Stackoverflow
Solution 5 - AndroidEmil BorconiView Answer on Stackoverflow
Solution 6 - AndroidarenaqView Answer on Stackoverflow
Solution 7 - AndroidRezaView Answer on Stackoverflow
Solution 8 - AndroidNiranjanView Answer on Stackoverflow
Solution 9 - Androidthanhbinh84View Answer on Stackoverflow
Solution 10 - AndroidAndrew GlukhoffView Answer on Stackoverflow
Solution 11 - AndroiddafnahaktanaView Answer on Stackoverflow
Solution 12 - AndroidCoolMindView Answer on Stackoverflow
Solution 13 - AndroidOsura WeerasingheView Answer on Stackoverflow
Solution 14 - AndroidjonView Answer on Stackoverflow
Solution 15 - AndroidSwapnil ChaudhariView Answer on Stackoverflow