NullPointerException in getting map fragment

387 Views Asked by At

I have read many other answers regarding the same issue, but this one is different.

My application contains an activity which shows my current location in map. My main activity is not the one which shows the map.

Here is the code for this activity(map showing activity):

public class ActivityShowsNearby extends BaseActivity implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener,
        OnMapReadyCallback {

    private static final String TAG = "ActivityShowsNearby";
    private static GoogleApiClient mGoogleApiClient;
    private Location mCurrentLocation;
    private LocationRequest mLocationRequest;


    private static final int LOCATION_REQUEST_INTERVAL = 1000 * 60; //60 seconds
    private static final int LOCATION_REQUEST_FASTEST_INTERVAL = 1000 * 60; //60 seconds


    // Request codes...


    private GoogleMap mGoogleMap;
    private static final int DEFAULT_ZOOM = 15;
    private final LatLng mDefaultLocation = new LatLng(28.636424, 77.374493);


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        Log.v(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_shows_nearby);

        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

    }


    @Override
    protected void onStart() {
        Log.v(TAG, "onStart");

        mGoogleApiClient.connect();
        super.onStart();


    }

    @Override
    protected void onResume() {
        Log.v(TAG, "onResume");

        if (mGoogleApiClient.isConnected()) {
            Log.v(TAG, "Starting location updates...");

            startLocationUpdates();
        }
        super.onResume();
    }

    @Override
    protected void onPause() {
        Log.v(TAG, "onPause");
        if (mGoogleApiClient.isConnected()) {
            Log.v(TAG, "Removing location updates...");
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
        super.onPause();
    }


    @Override
    protected void onStop() {
        Log.v(TAG, "onStop");

        mGoogleApiClient.disconnect();
        super.onStop();
    }


    @Override
    public void onConnected(Bundle bundle) {
        startLocationUpdates();
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);

        if (mapFragment == null) {
            Log.v(TAG, "mapFragment is null");
        } else {
            Log.v(TAG, "mapFragment is NOT null");

        }
        mapFragment.getMapAsync(this);

    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.v(TAG, "mGoogleApiClient connection suspended");


    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.v(TAG, "mGoogleApiClient connection  failed");


    }

    private void createLocationRequest() {
        if (mLocationRequest == null) {
            mLocationRequest = new LocationRequest();
            mLocationRequest.setInterval(LOCATION_REQUEST_INTERVAL);
            mLocationRequest.setFastestInterval(LOCATION_REQUEST_FASTEST_INTERVAL);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        }

    }

    private void startLocationUpdates() {
        createLocationRequest();
        try {
            LocationServices.FusedLocationApi.requestLocationUpdates(
                    mGoogleApiClient,
                    mLocationRequest,
                    this
            );
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onLocationChanged(Location location) {

        mCurrentLocation = location;
        updateMap();
    }



    //@SuppressWarnings("MissingPermission")
    @Override
    public void onMapReady(GoogleMap googleMap) {


        Log.v(TAG, "onMapReady");
        mGoogleMap = googleMap;

        updateLocationUI();

        if (mCurrentLocation != null) {
            googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                    new LatLng(mCurrentLocation.getLatitude(),
                            mCurrentLocation.getLongitude()), DEFAULT_ZOOM));
        } else {
            googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
        }

    }

    private void updateMap() {
        if (mGoogleMap == null) {
            return;
        }
        mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                new LatLng(mCurrentLocation.getLatitude(),
                        mCurrentLocation.getLongitude()), DEFAULT_ZOOM));
    }


    @SuppressWarnings("MissingPermission")
    private void updateLocationUI() {

        if (mGoogleMap == null) {
            Log.v(TAG, "mGoogleMap is null");
            return;
        }

        mGoogleMap.setMyLocationEnabled(true);
        mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);


    }

}

Clearly, this activity extends from BaseActivity.java which I have created to show navigation drawer. Here is the code of BaseActivity.java

public class BaseActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{

    private static final String TAG = "BaseActivity";
    private Toolbar toolbar;
    private DrawerLayout drawerLayout;
    private ActionBarDrawerToggle actionBarDrawerToggle;
    private NavigationView navigationView;

    //These two values will be used in unison -- see their usage
    private boolean mDrawerItemClicked;
    private int mDrawerItemSelectedId;


    public NavigationView getNavigationView() {
        return navigationView;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate");

        super.onCreate(savedInstanceState);
    }

    @Override
    public void setContentView(int layoutResID) {
        Log.d(TAG, "setContentView");

        super.setContentView(layoutResID);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

    //Other navigation drawer set up codes...
}

When the application is first launched, my main activity shows up. The user can then open navigation drawer and select one of the navigation drawer item to open my map-showing-activity i.e ActivityShowsNearby as shown in the image below.

Here is the screenshot of the same.

Here is the problem.

From my main activity, I open the navigation drawer and select show near me to open ActivityShowsNearby. Then I press back to go to main activity again. Everything works fine upto here.But now, if i open the navigation drawer and select show near me again to re-open ActivityShowsNearby activity, then the application CRASHES.

Here is the logcat the three occasions:

Hitting SHOW NEAR ME first time.

12-29 16:30:53.696 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onCreate
12-29 16:30:54.386 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onStart
12-29 16:30:54.416 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onResume
12-29 16:30:54.416 8585-8585/sumit.example.com.movie D/InputTransport: Input channel constructed: name='d9453f5 sumit.example.com.movie/com.example.sumit.movie.ActivityShowsNearby (client)', fd=56
12-29 16:30:54.596 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: Connected to Google play services.
12-29 16:30:54.636 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: mapFragment is NOT null
12-29 16:30:54.786 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onMapReady

After I press back from my ActivityShowsNearby:

12-29 16:31:02.576 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onPause
12-29 16:31:02.576 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: Removing location updates...
12-29 16:31:02.986 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onStop
12-29 16:31:02.996 8585-8585/sumit.example.com.movie D/InputTransport: Input channel destroyed: name='d9453f5 sumit.example.com.movie/com.example.sumit.movie.ActivityShowsNearby (client)', fd=56

Finally, after I open the navigation drawer again to click show near me

12-29 16:31:07.856 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onCreate
12-29 16:31:07.906 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onStart
12-29 16:31:07.906 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: onResume
12-29 16:31:07.906 8585-8585/sumit.example.com.movie D/InputTransport: Input channel constructed: name='d32ef5a sumit.example.com.movie/com.example.sumit.movie.ActivityShowsNearby (client)', fd=82
12-29 16:31:08.016 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: Connected to Google play services.
12-29 16:31:08.016 8585-8585/sumit.example.com.movie V/ActivityShowsNearby: mapFragment is null
12-29 16:31:08.026 8585-8585/sumit.example.com.movie E/AndroidRuntime: FATAL EXCEPTION: main
                                                                       Process: sumit.example.com.movie, PID: 8585
                                                                       java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.SupportMapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' on a null object reference
                                                                           at com.example.sumit.movie.ActivityShowsNearby.onConnected(ActivityShowsNearby.java:168)
                                                                           at com.google.android.gms.common.internal.zzm.zzq(Unknown Source)
                                                                           at com.google.android.gms.internal.zzaal.zzo(Unknown Source)
                                                                           at com.google.android.gms.internal.zzaaj.zzvE(Unknown Source)
                                                                           at com.google.android.gms.internal.zzaaj.onConnected(Unknown Source)
                                                                           at com.google.android.gms.internal.zzaan.onConnected(Unknown Source)
                                                                           at com.google.android.gms.internal.zzzy.onConnected(Unknown Source)
                                                                           at com.google.android.gms.common.internal.zzl$1.onConnected(Unknown Source)
                                                                           at com.google.android.gms.common.internal.zzf$zzj.zzwZ(Unknown Source)
                                                                           at com.google.android.gms.common.internal.zzf$zza.zzc(Unknown Source)
                                                                           at com.google.android.gms.common.internal.zzf$zza.zzu(Unknown Source)
                                                                           at com.google.android.gms.common.internal.zzf$zze.zzxa(Unknown Source)
                                                                           at com.google.android.gms.common.internal.zzf$zzd.handleMessage(Unknown Source)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                           at android.os.Looper.loop(Looper.java:148)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:7406)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

What is the problem here ?

Please assume I have enabled both location permission and settings.

Here is my activity_show_nearby.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:orientation="vertical"
        tools:context="com.example.sumit.movie.MovieActivity">


        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:elevation="4dp"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <!-- Start of replacement of fragment-container-->


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:id="@+id/activity_shows_nearby_location_layout">

            <fragment
                android:id="@+id/map"
                android:name="com.google.android.gms.maps.SupportMapFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>


        </LinearLayout>

        <!--End of replacement of fragment container-->


    </LinearLayout>


    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_movie"
        app:menu="@menu/activity_movie_drawer" />

</android.support.v4.widget.DrawerLayout>
3

There are 3 best solutions below

0
On

Tried your code except of menu initialization

app:headerLayout="@layout/nav_header_movie"
app:menu="@menu/activity_movie_drawer"

Fragment is not null (LOG record: mapFragment is NOT null) Try to clean and recompile your project

1
On

Add class attribute instead of android:name

<fragment
    android:id="@+id/map"
    class="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Check for more information MapFragment

1
On

Your log shows that the fragment object is null:

V/ActivityShowsNearby: mapFragment is null

So you are trying to invoke a method (getMapAsync) on it, which causes the error.

Also make sure you are overriding all lifecycle methods (noticed onDestroy missing)

@Override
public void onDestroy(){
    super.onDestroy();
}