Radek Radek - 1 month ago 23
Android Question

Android GPS not accessible

A novice issue, I have an android app with a service that implements LocationListener. I'm trying to hook up the events in OnCreate and display toaster with my current location when things change. For some reason the app is not seeing my GPS and is complaining that I don't have access to GPS and throws exception when I call requestLocationUpdates function. Any advice would be helpful, am I missing some other entries in my manifest currently I only have (

ACCESS_FINE_LOCATION
,
ACCESS_COARSE_LOCATION
set)

Thank you

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

@Override
public void onCreate() {
super.onCreate();
ctx = this;

if ( Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission( ctx, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission( ctx, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,1, this);
} else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000,1, this);
}
}

// Toast.makeText(this, "MyService Created", Toast.LENGTH_LONG).show();
}

@Override
public void onLocationChanged(Location location) {
double latitude = 0;
double longitude = 0;

latitude = location.getLatitude();
longitude =location.getLongitude();
if (latitude != 0 && longitude != 0){
Toast.makeText(this, "LAT and LON updated", Toast.LENGTH_LONG).show();
}
}

Answer

Not entirely sure what your specific question is, so I'm gonna go with:

How do I request periodic location updates and display a toast when my current location changes?

First things first:

  • Using ACCESS_FINE_LOCATION in the manifest is sufficient if you want to use GPS. There is no need to specify ACCESS_COARSE_LOCATION.
  • For Marshmallow and above you need to request the location permission at runtime. I see you have a ContextCompat.checkSelfPermission() in there, but where do you handle the user decision (see here)?. If the permission is never successfully requested or the response is not properly handled, your app does not actually have permission and you will see the exceptions you experienced.

Now for a bit more detail and a solution to the above question.

Historically, location updates were always retrieved through the LocationManager, which is what you're trying to do. However, for a couple years now, the better (and recommended) way is to use the Google Location API (see here). The Google Location API requires significantly more boilerplate than the LocationManager, though. This is why I wrote the LocationAssistant, a utility class that will do most of the work for you. Using the LocationAssistant, here is how you would go about requesting location updates and displaying the toast:

public class MyActivity extends Activity implements LocationAssistant.Listener {

    private LocationAssistant assistant;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // You can specify a different accuracy and interval here, depending on the needs of your app
        assistant = new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, true);
    }

    @Override
    protected void onResume() {
        super.onResume();
        assistant.start();
    }

    @Override
    protected void onPause() {
        assistant.stop();
        super.onPause();
    }

    @Override
    public void onNewLocationAvailable(Location location) {
        Toast.makeText(this, location != null ?
            "Lat: " + location.getLatitude() + " Lon: " + location.getLongitude() :
            "Null location",
            Toast.LENGTH_LONG).show();        }

    ...
}

onNewLocationAvailable() is invoked as soon as the first valid location is available (and periodically at the requested interval after that). There are some more listener methods you need to implement which deal with situations in which permission is not granted or location providers are switched off. But essentially this is it.

The LocationAssistant also allows you to reliably reject mock locations (in case that's a requirement for your app).