Search code examples
androidgoogle-mapsfusedlocationproviderapi

Wait for GoogleAPIClient to load before trying to connect


I'm building a simple map application using the Google Maps API. When I open the app it will sometimes crash because the GoogleApiClient is not connected yet. I have a few methods that run and need the API to be connected.

How do I prevent the crashes by waiting for the API to connect?

Here is some of my code: onConnected:

@Override
public void onConnected(Bundle connectionHint)
{
    // this callback will be invoked when all specified services are connected
    //Must ask for explicit permission
    //ie: Opening settings action in order to change or give permissions
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        currentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleClient);
        mGoogleClient.connect();

        if (currentLocation != null)
        { 
            currentLatLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15));
        } 

        else
        {
           if (mGoogleClient!=null )
           {
               mGoogleClient.connect();
           }

            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleClient, locationRequest, this);

        }
    }
}

Getting the current location:

private void getLocation() {

    locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(60 * 1000);
    locationRequest.setFastestInterval(30 * 1000);

    mGoogleClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

    if (mGoogleClient != null)
    {
        mGoogleClient.connect();
    }


}

I'm not sure what else is needed. Please let me know if I need to provide more code.

Edit: Crash log

08-15 17:51:54.692 950-950/? E/AndroidRuntime: FATAL EXCEPTION: main
                                           Process: com.hensh.fusedmap, PID: 950
                                           java.lang.IllegalStateException: GoogleApiClient is not connected yet.
                                               at com.google.android.gms.common.api.internal.zzh.zzb(Unknown Source)
                                               at com.google.android.gms.common.api.internal.zzl.zzb(Unknown Source)
                                               at com.google.android.gms.common.api.internal.zzj.zzb(Unknown Source)
                                               at com.google.android.gms.location.internal.zzd.requestLocationUpdates(Unknown Source)
                                               at com.hensh.fusedmap.MapsActivity.onConnected(MapsActivity.java:667)
                                               at com.google.android.gms.common.internal.zzk.zzk(Unknown Source)
                                               at com.google.android.gms.common.api.internal.zzj.zzi(Unknown Source)
                                               at com.google.android.gms.common.api.internal.zzh.zzpx(Unknown Source)
                                               at com.google.android.gms.common.api.internal.zzh.onConnected(Unknown Source)
                                               at com.google.android.gms.common.api.internal.zzl.onConnected(Unknown Source)
                                               at com.google.android.gms.common.api.internal.zzc.onConnected(Unknown Source)
                                               at com.google.android.gms.common.internal.zzj$zzg.zzqL(Unknown Source)
                                               at com.google.android.gms.common.internal.zzj$zza.zzc(Unknown Source)
                                               at com.google.android.gms.common.internal.zzj$zza.zzw(Unknown Source)
                                               at com.google.android.gms.common.internal.zzj$zzc.zzqN(Unknown Source)
                                               at com.google.android.gms.common.internal.zzj$zzb.handleMessage(Unknown Source)
                                               at android.os.Handler.dispatchMessage(Handler.java:102)
                                               at android.os.Looper.loop(Looper.java:135)
                                               at android.app.ActivityThread.main(ActivityThread.java:5294)
                                               at java.lang.reflect.Method.invoke(Native Method)
                                               at java.lang.reflect.Method.invoke(Method.java:372)
                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)

Solution

  • The GoogleAPIClient needs to be connected before you try to use the service. So your call to connect it in the onConnected is wrong. If you're in onConnected it means the client is connected. You need to build the GoogleAPIClient in the onCreate of your activity and ideally connect it in the onStart of your Activity.

    private GoogleApiClient mGoogleApiClient;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.<your-xml>);
    
        mGoogleApiClient = new GoogleApiClient.Builder(context)
                 .addConnectionCallbacks(this)
                 .addOnConnectionFailedListener(this)
                 .addApi(LocationServices.API)
                 .build();
    }
    public void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }
    

    Additionally, when building the GoogleAPIClient you can also set enableAutoManage() for the connect and disconnect to be managed automatically so that you dont have to do it manually, as explained here.

    public class LocationActivity implements GoogleApiClient.OnConnectionFailedListener {
    
        /** Google Services client */
        private GoogleApiClient mGoogleApiClient;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.payment_activity);
            mGoogleApiClient = new GoogleApiClient.Builder(context)
                     .addConnectionCallbacks(this)
                     .enableAutoManage(this, this)
                     .addApi(LocationServices.API)
                     .build();
    }