Tuco Tuco - 2 months ago 19
Android Question

Android: Null location when using GoogleApiClient

Hello I'm currently trying to obtain the latitude and altitude values for my Android device using the GoogleApiClient. I've been following the guide here:

GoogleApiClient: Last Known Location Guide

I'm also trying to do this from my Service and not the Activity, here's a snippet of my code for reference:

public class AppService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

private GoogleApiClient googleApiClient;

@Override
public IBinder onBind(Intent arg0) {
return null;
}

@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
googleApiClient.connect();
try {
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
Log.d("location", String.valueOf(lastLocation.getLatitude()));
Log.d("location", String.valueOf(lastLocation.getLongitude()));
} catch (SecurityException e) {
Log.e("Location error", "Location object is null.");
}

googleApiClient.disconnect();

//Stop service once it finishes its task
stopSelf();
return Service.START_STICKY;
}

@Override
public void onConnected(@Nullable Bundle bundle) {

}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}
}


Every time I try to access the Location variable to obtain latitude and altitude I get a NullPointerException, any idea why?

Also want to include my AndroidManifest file just in case, I have the permissions needed as far as I know:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:label="@string/app_name" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</activity>
<receiver
android:name=".AutoStart"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service android:name=".AppService"/>
</application>
</manifest>

Answer

The call to googleApiClient.connect() is asynchronous according to the documentation:

public abstract void connect ()

Connects the client to Google Play services. This method returns immediately, and connects to the service in the background. If the connection is successful, onConnected(Bundle) is called and enqueued items are executed. On a failure, onConnectionFailed(ConnectionResult) is called.

If the client is already connected or connecting, this method does nothing.

Because of this, you should wait for the onConnected callback to be executed, and place your location retrieve code inside there.

@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
  if (googleApiClient == null) {
     googleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
  }
  googleApiClient.connect();
  return Service.START_STICKY;
}

@Override
public void onConnected(@Nullable Bundle bundle) {
  try {
    Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    Log.d("location", String.valueOf(lastLocation.getLatitude()));
    Log.d("location", String.valueOf(lastLocation.getLongitude()));
  } catch (SecurityException e) {
    Log.e("Location error", "Location object is null.");
  }

  googleApiClient.disconnect();
  stopSelf();
}
Comments