Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android GPS does not work until restart on new phones

I have posted about this issue before, and found a few other people who have had the same issue with no solutions found.

I am developing an Android app that submits a JSON query to a server with the obtained GPS coordinates and geocoded Zip Code. For brand new users that have never downloaded the app, GPS does not work whatsoever. It is not until rebooting the phone that GPS will work. After installing the app and then rebooting, the GPS will work every time without problem, even if they restart again.

There is precious little information on this issue, and the only issue I have found refers to using Google Play Location Services, with no further details. Has anyone else had this issue? My development is completely halted until this issue can be resolved.


EDIT: Here is the link to the MainActivity.java file that calls the geopositioning functions.

Here is the link to the MyLocation.java file that contains the actual logic for multiple sources of geolocation

I have no doubt that there are much better ways of doing GPS. I'm very new to Android development, so any help on this front is very much appreciated.

EDIT 2: I have wiped my phone with a factory reset, and started from scratch. I still cannot replicate the issue on this device, only on phones using the app for the very first time prior to a restart.

like image 958
mattcoker Avatar asked Feb 23 '14 21:02

mattcoker


2 Answers

Looks like you're registering both the GPS and NETWORK providers to listen for a location for 10 seconds, and when the timer goes off after 10 seconds you try to get the most recent location from both providers.

There are a few things going on here.

First, you seem to be listening for updates in the wrong method. Your two listeners should look like:

    LocationListener locationListenerGps = new LocationListener() {

            // This will never be called, its not part of the LocationListener interface - http://developer.android.com/reference/android/location/LocationListener.html
            /* public void onStatusChanged(Location location) {
                    timer1.cancel();

                    locationResult.gotLocation(location);
                    lm.removeUpdates(this);
                    lm.removeUpdates(locationListenerNetwork);
            } */
            public void onProviderEnabled(String provider) {}
            public void onProviderDisabled(String provider) {}
            public void onLocationChanged(Location location) {
                    // This is the correct method to receive location callbacks
                    timer1.cancel();

                    locationResult.gotLocation(location);
                    lm.removeUpdates(this);
                    lm.removeUpdates(locationListenerNetwork);

            }
            public void onStatusChanged(String provider, int status, Bundle extras) {}
    };

Second, I'd use the ScheduledThreadPoolExecutor or Handler instead of Timer.

From the Timer docs:

Prefer ScheduledThreadPoolExecutor for new code...This class does not offer guarantees about the real-time nature of task scheduling.

If a reboot is required to get the app working, its likely something to do with the Timer not firing after 10 seconds. Note that this doesn't necessarily mean that GPS itself isn't working.

Handler should do the job and it's designed for Android, so I'd suggest using it. It looks like:

Handler handler = new Handler();
handler.postDelayed(getLastLocation, 10000);

...and your GetLastLocation would change to:

Runnable getLastLocation = new Runnable() {
    @Override
    public void run() {
        ...
    }
}

...and your cancel() and other methods would need to reference the Handler.

Also, note that you're declaring the Location object in your MainActivity with a provider type of NETWORK_PROVIDER, and then setting the lat/long in that object.

public Location mUserCoordinates = new Location(LocationManager.NETWORK_PROVIDER);

So, the location type in MainActivity will always appear to be of NETWORK_PROVIDER, no matter the actual source.

Also, doesn't look like your MainActivity needs to implement LocationListener, as its never registered with the LocationManager.

Finally, instead of using two listeners for GPS and NETWORK, I would suggest using the Fused location provider in Google Play Services, as discussed here: http://developer.android.com/training/location/receive-location-updates.html

You'll be limited to devices Android 2.2 and up with Google Play Services installed, but in my opinion its worth it to avoid dealing with some of the eccentricities of location in the platform and managing more than one provider. For more about Fused location provider and how it differs from listening directly to GPS and NETWORK providers, see this 2013 Google I/O presentation - Beyond the Blue Dot: New Features in Android Location

like image 162
Sean Barbeau Avatar answered Oct 26 '22 00:10

Sean Barbeau


Why do you use Google Play Services Location API?

The only new feature provided by Play Services is Geofencing. From your answer i assume that you don't want to use Geofencing but just "usual" location requests.

The Android platform provides a great API for such requests which does not requires Google Play Services. I never had the problem you described when using it.

Note that although Google claims the Play Services to be better than the Android API, this is not true since API 9 (Android 2.3), as long as you use the newer LocationManager.requestLocationUpdates methodes that don't require a provider to be specified.

See: http://developer.android.com/guide/topics/location/strategies.html

like image 32
Marvin W Avatar answered Oct 26 '22 00:10

Marvin W