Roman Pozdnyakov
Roman Pozdnyakov

Reputation: 408

GoogleApiClient null pointer exception

I try to learn android development and now i developing an app with fused location service.

I got a RunFragment.java class when i want to put the GoogleMap fragment, Textviews with latitude and longitude and some other widgets. First of all i want to connect to GoogleApiClient and i created new class that will do all this job and leave RunFragment.java clear. (Is that a good idea??) When i try to run my app i got this error:

     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Looper android.content.Context.getMainLooper()' on a null object reference
        at com.google.android.gms.common.api.GoogleApiClient$Builder.<init>(Unknown Source)
        at com.runtheworld.roman.runtheworld.GoogleAPI.buildGoogleApiClient(GoogleAPI.java:28)
        at com.runtheworld.roman.runtheworld.RunFragment.onCreate(RunFragment.java:39)
        at android.app.Fragment.performCreate(Fragment.java:2031)

There is the relevant classes:

RunFragment.java

package com.runtheworld.roman.runtheworld;

import android.app.Fragment;
import android.os.Bundle;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;



public class RunFragment extends Fragment  {

private static View view;

// TextViews
TextView lat,lon;

// GoogleApi
private GoogleAPI mGoogleApiClient = new GoogleAPI(getActivity());



// Default Constructor
public RunFragment() {
}


@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    mGoogleApiClient.buildGoogleApiClient();
}
@Override
public void onStart(){
    super.onStart();
    mGoogleApiClient.Connect();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (view != null) {
        ViewGroup parent = (ViewGroup) view.getParent();
        if (parent != null)
            parent.removeView(view);
    }
    try {
        view = inflater.inflate(R.layout.run_fragment, container, false);
    } catch (InflateException e) {
        // Map already created
    }

    lat = (TextView)view.findViewById(R.id.lat);
    lon = (TextView)view.findViewById(R.id.lon);
    lat.setText(String.valueOf(mGoogleApiClient.getLat()));
    lon.setText(String.valueOf(mGoogleApiClient.getLon()));


    return view;
}




}

GoogleAPI.java

package com.runtheworld.roman.runtheworld;


import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;

public class GoogleAPI  implements GoogleApiClient.ConnectionCallbacks,    GoogleApiClient.OnConnectionFailedListener {

private Context context;
private GoogleApiClient mGoogleApiClient;
private boolean isConnected;
// Location
Location mLastLocation;

public GoogleAPI(Context c) {
    context = c;
}


protected synchronized void buildGoogleApiClient() {
    Log.d("MYTAG", "BUILDING GOOGLE API");
    mGoogleApiClient = new GoogleApiClient.Builder(context)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

public boolean Connect(){
    if (!mGoogleApiClient.isConnected())
        mGoogleApiClient.connect();
    else
    Log.d("MYTAG","GoogleApiClient is already connected!");
    return isConnected;
}

@Override
public void onConnected(Bundle bundle) {
    Log.d("MYTAG", "GOOGLE API CONNECTED!");
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
            mGoogleApiClient);
    if (mLastLocation != null) {
    }
}

public double getLat(){
    return mLastLocation.getLatitude();
}
public double getLon(){
    return mLastLocation.getLongitude();
}
@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

}

Can anyone help ?

Upvotes: 3

Views: 11255

Answers (1)

Daniel Nugent
Daniel Nugent

Reputation: 43322

It sounds like your initial problem was fixed in the comments, here is how you can complete the functionality.

First, to fix the NPE, make sure that mLocation is not null before you reference it:

public double getLat(){
    double retVal = 0d;
    if (mLastLocation != null){
       retVal = mLastLocation.getLatitude();
    }
    return retVal;
}
public double getLon(){
    double retVal = 0d;
    if (mLastLocation != null){
       retVal = mLastLocation.getLongitude();
    }
    return retVal;
}

The next problem is that getLastLocation() has a high tendency to return null.

The best way to get around that is to register a location listener.

Declare GoogleAPI as a location listener:

public class GoogleAPI  implements GoogleApiClient.ConnectionCallbacks,    GoogleApiClient.OnConnectionFailedListener, LocationListener{

private Context context;
private GoogleApiClient mGoogleApiClient;
private boolean isConnected;

Then register a listener in onConnected() (see documentation: for how to set up the values for minTime, fastestTime, and distanceThreshold):

        @Override
        public void onConnected(Bundle bundle) {
            Log.d("MYTAG", "GOOGLE API CONNECTED!");
            mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                    mGoogleApiClient);
            if (mLastLocation == null) {
               mLocationRequest = new LocationRequest();
               mLocationRequest.setInterval(minTime);
               mLocationRequest.setFastestInterval(fastestTime);
                                 mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
              mLocationRequest.setSmallestDisplacement(distanceThreshold);
              LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            }

        }

Then add the location changed callback:

 @Override
    public void onLocationChanged(Location location) {

             mLastLocation = location;

     }

Upvotes: 2

Related Questions