Search code examples
androidandroid-studiogoogle-mapsandroid-fragmentsandroid-viewpager

whenever i run my fragment this line of code mapFragment.setRetainInstance(true); is crashing my app?


So i had a maps activity that i changed to a fragment so I can display It on my viewpager but after changing the Activity to a fragment this line of code mapFragment.setRetainInstance(true); is crashing the app. Did i miss anything when changing the MapsActivity to a Fragment, ill put the old MapsActivity class and the one i changed to fragment below so you guys can take a look at.

MapsActivity.java that i changed to a fragment so i can display it on viewpager:

 public class MapsActivity extends Fragment
      implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, LocationListener, 
 com.google.android.gms.location.LocationListener {
View view;
Context context;
public static boolean SAVE_LOCATION,SAVE_LOCATION_ADDRESS;
private static final String TAG = "Current Location";
  GoogleMap mGoogleMap;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
Location mLastLocation;
private LatLng mDefaultLocation;
private static final int DEFAULT_ZOOM = 15;
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private static final int PERMISSION_DATA_ACCESS_CODE = 2;
private boolean mLocationPermissionGranted;
String lat,long_;
SwitchCompat current_loction_switch,selected_location_switch;
ExpandableRelativeLayout expandable_layout;
TextView my_current_location;
TextView new_location_txt;
boolean isMaptouched=false;
private GeoDataClient mGeoDataClient;
private PlaceDetectionClient mPlaceDetectionClient;
// The entry point to the Fused Location Provider.
private FusedLocationProviderClient mFusedLocationProviderClient;
// A default location (Sydney, Australia) and default zoom to use when location permission is
// not granted.
private Location mLastKnownLocation;
private SupportMapFragment mapFragment;
private MapView mapView;
private SharedPreferences sPredMap;
private GoogleMap.OnCameraIdleListener onCameraIdleListener;
ImageView close_country;
TextView current_text_tv;
RelativeLayout current_address_div;
       Button save_loc_div;
ImageButton arrow_down;

public MapsActivity() {
    // Required empty public constructor
}

@SuppressWarnings("deprecation")
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    context = getContext();
    view = inflater.inflate(R.layout.activity_main_maps, container, false);
   SharedPreferences sPredMap = this.getActivity().getSharedPreferences(Variables.pref_name,MODE_PRIVATE);
    lat = sPredMap.getString(Variables.seleted_Lat,"");
    long_ = sPredMap.getString(Variables.selected_Lon,"");
    if(lat.isEmpty()&&long_.isEmpty()){
        lat =  sPredMap.getString(Variables.current_Lat,"");
        long_ =sPredMap.getString(Variables.current_Lon,"");
    }


    mDefaultLocation = new LatLng(Double.parseDouble(lat), Double.parseDouble(long_));     
    current_text_tv = view.findViewById(R.id.current_text_tv);
    close_country = view.findViewById(R.id.close_country);
    current_address_div = view.findViewById(R.id.current_address_div);
    save_loc_div = view.findViewById(R.id.save_loc_div);


    save_loc_div.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            SAVE_LOCATION = true;
            SAVE_LOCATION_ADDRESS = true;
            Intent data = new Intent();
            data.putExtra("lat", String.valueOf(lat));
            data.putExtra("lng", String.valueOf(long_));
            data.putExtra("location_string",current_text_tv.getText());
            getActivity().setResult(Activity.RESULT_OK, data);
            //(RESULT_OK, data);
            String latSearch = data.getStringExtra("lat");
            String longSearch = data.getStringExtra("lng");
            String location_string = data.getStringExtra("location_string");
            new_location_txt.setText(location_string);
            new_location_txt.setText(location_string);
            selected_location_switch.setClickable(true);
            current_loction_switch.setClickable(true);
            selected_location_switch.setChecked(true);

            MainMenuActivity.sharedPreferences.edit().putString(Variables.seleted_Lat,latSearch).commit();
            MainMenuActivity.sharedPreferences.edit().putString(Variables.selected_Lon,longSearch).commit();

            MainMenuActivity.sharedPreferences.edit().putString(Variables.selected_location_string,location_string).commit();


        }
    });

    current_address_div.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent i = new Intent(getActivity(), SearchPlaces.class);
            startActivityForResult(i, PERMISSION_DATA_ACCESS_CODE);

        }
    });
    close_country.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            getActivity().finish();
        }
    });

     mGeoDataClient = Places.getGeoDataClient(this.getActivity(), null);

    // Construct a PlaceDetectionClient.
    mPlaceDetectionClient = Places.getPlaceDetectionClient(this.getActivity(), null);

    // Construct a FusedLocationProviderClient.
    mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this.getActivity());


    setupMapIfNeeded();

    configureCameraIdle();

    mapFragment.setRetainInstance(true);

    current_loction_switch = view.findViewById(R.id.current_loction_switch);
    selected_location_switch=view.findViewById(R.id.selected_location_switch);

    if(MainMenuActivity.sharedPreferences.getBoolean(Variables.is_seleted_location_selected,false)){
        selected_location_switch.setChecked(true);
    }else {
        current_loction_switch.setChecked(true);
    }



    current_loction_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            Variables.is_reload_users=true;

            if(isChecked){
                MainMenuActivity.sharedPreferences.edit().putBoolean(Variables.is_seleted_location_selected,false).commit();
                selected_location_switch.setChecked(false);
             
            }else {

                MainMenuActivity.sharedPreferences.edit().putBoolean(Variables.is_seleted_location_selected,true).commit();
                selected_location_switch.setChecked(true);
                // my_current_location.setText(MainMenuActivity.sharedPreferences.getString(Variables.selected_location_string,""));
            }

        }
    });



    selected_location_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            Variables.is_reload_users=true;

            if(isChecked){
                MainMenuActivity.sharedPreferences.edit().putBoolean(Variables.is_seleted_location_selected,true).commit();
                current_loction_switch.setChecked(false);
                my_current_location.setText(MainMenuActivity.sharedPreferences.getString(Variables.selected_location_string,""));
            }else {
                MainMenuActivity.sharedPreferences.edit().putBoolean(Variables.is_seleted_location_selected,false).commit();
                current_loction_switch.setChecked(true);
           
            }


        }
    });

    new_location_txt=view.findViewById(R.id.new_location_txt);


    if(!MainMenuActivity.sharedPreferences.getString(Variables.selected_location_string,"").equals("")){
        new_location_txt.setText(MainMenuActivity.sharedPreferences.getString(Variables.selected_location_string,""));
    }else {
        selected_location_switch.setClickable(false);
        current_loction_switch.setClickable(false);
    }

    //below code is to collapse expanble view when arrow is clicked

    expandable_layout=view.findViewById(R.id.expandable_layout);
    arrow_down =view.findViewById(R.id.arrow_down);
    arrow_down.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){

            if(expandable_layout.isExpanded()){
                arrow_down.setRotation(90);
                expandable_layout.collapse();


            }
            else
                arrow_down.setRotation(270);
                expandable_layout.expand();


        }
    });
    return view;

}



@Override
public void onResume(){
    super.onResume();

    setupMapIfNeeded();

}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

}
@Override
public void onMapReady(GoogleMap googleMap) {
    mGoogleMap = googleMap;
    updateLocationUI();
    getDeviceLocation();

    mGoogleMap.getUiSettings().setCompassEnabled(false);
    MapStateManager mgr = new MapStateManager(this.getActivity());
    CameraPosition position = mgr.getSavedCameraPosition();
    if (position != null) {
        CameraUpdate update = CameraUpdateFactory.newCameraPosition(position);
        mGoogleMap.moveCamera(update);

        mGoogleMap.setMapType(mgr.getSavedMapType());
    }

    if (mGoogleMap != null) {
        mGoogleMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
        if (ActivityCompat.checkSelfPermission(getApplicationContext()
                , Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getApplicationContext()
                , Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
          
            return;
        }
        mGoogleMap.setMyLocationEnabled(true);
        mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);

    }
    mGoogleMap.setOnCameraIdleListener(onCameraIdleListener);
}


@Override
public void onStart() {
    super.onStart();
}
private void updateLocationUI() {
    if (mGoogleMap == null) {
        return;
    }
    try {
        if (mLocationPermissionGranted) {
            mGoogleMap.setMyLocationEnabled(true);
            mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
        } else {
            mGoogleMap.setMyLocationEnabled(false);
             mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
            mLastKnownLocation = null;
            getLocationPermission();
        }
    } catch (SecurityException e)  {
        Log.e("Exception: %s", e.getMessage());
    }
}
private void getDeviceLocation() {

    try {
        if (mLocationPermissionGranted) {
            Task locationResult = mFusedLocationProviderClient.getLastLocation();
            locationResult.addOnCompleteListener(this.getActivity(), new OnCompleteListener() {
                @Override
                public void onComplete(@NonNull Task task) {
                    if (task.isSuccessful()) {
                        // Set the map's camera position to the current location of the device.
                        mLastKnownLocation = (Location) task.getResult();
                        mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                                new LatLng(Double.parseDouble(lat), Double.parseDouble(long_)), DEFAULT_ZOOM));
                        mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);

                        SharedPreferences.Editor editor = sPredMap.edit();
                        editor.putString(Variables.current_Lat, String.valueOf(lat));
                        editor.putString(Variables.current_Lon, String.valueOf(long_));
                        editor.apply();

                    } else {
                        Log.d(TAG, "Current location is null. Using defaults.");
                        Log.e(TAG, "Exception: %s", task.getException());
                        mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
                        mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
                         }
                }
            });
        }
    } catch(SecurityException e)  {
        Log.e("Exception: %s", e.getMessage());
    }

   }
private void configureCameraIdle() {
    onCameraIdleListener = new GoogleMap.OnCameraIdleListener() {
        @Override
        public void onCameraIdle() {

            LatLng latLng = mGoogleMap.getCameraPosition().target;
            Geocoder geocoder = new Geocoder(getActivity(), Locale.getDefault());

            try {
                List<Address> addressList = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1);
                if (addressList != null && addressList.size() > 0) {
                   
                    String country = addressList.get(0).getCountryName();
                   
                        lat = ""+latLng.latitude;
                        long_ = ""+latLng.longitude;
                     
                        current_text_tv.setText(country);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
}
private void setupMapIfNeeded(){
    // Build the map.
    if(mGoogleMap==null) {
        SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
    }
}
@Override
public void onPause() {
    super.onPause();
    MapStateManager mgr = new MapStateManager(this.getActivity());
    mgr.saveMapState(mGoogleMap);

}


private void getLocationPermission() {
/*
 * Request location permission, so that we can get the location of the
 * device. The result of the permission request is handled by a callback,
 * onRequestPermissionsResult.
 */
    if (ContextCompat.checkSelfPermission(this.getActivity().getApplicationContext(),
            android.Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {
        mLocationPermissionGranted = true;
    } else {
        try {
            ActivityCompat.requestPermissions(getActivity(),
                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
        }
        catch (Exception e){
            e.getMessage();
        }

    }
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PERMISSION_DATA_ACCESS_CODE) {
        if(resultCode == RESULT_OK) {
            String latSearch = data.getStringExtra("lat");
            String longSearch = data.getStringExtra("lng");
            lat = latSearch;
            long_ = longSearch;
            mDefaultLocation = new LatLng(Double.parseDouble(latSearch), Double.parseDouble(longSearch));
            mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
        }
    }

    if (requestCode == 111) {
        if(resultCode == RESULT_OK) {
            String latSearch = data.getStringExtra("lat");
            String longSearch = data.getStringExtra("lng");
            String location_string = data.getStringExtra("location_string");
            new_location_txt.setText(location_string);
            new_location_txt.setText(location_string);
            selected_location_switch.setClickable(true);
            current_loction_switch.setClickable(true);
            selected_location_switch.setChecked(true);

            MainMenuActivity.sharedPreferences.edit().putString(Variables.seleted_Lat,latSearch).commit();
            MainMenuActivity.sharedPreferences.edit().putString(Variables.selected_Lon,longSearch).commit();

            MainMenuActivity.sharedPreferences.edit().putString(Variables.selected_location_string,location_string).commit();

        }
    }
}
@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String permissions[],
                                       @NonNull int[] grantResults) {
    mLocationPermissionGranted = false;
    switch (requestCode) {
        case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                mLocationPermissionGranted = true;
                updateLocationUI();
            }
        }
    }

}
protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this.getActivity())
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API).build();

    if (mGoogleApiClient != null) {
        mGoogleApiClient.connect();
    }
}
@Override
public void onLocationChanged(Location location) {
    mLastLocation = location;
      }
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
@Override
public void onConnected(@Nullable Bundle bundle) {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(0);
    mLocationRequest.setFastestInterval(0);
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
@Override
public void onConnectionSuspended(int i) {
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
private void getDriversAround(){
    DatabaseReference driversLocation = FirebaseDatabase.getInstance().getReference().child(("availableUsers"));
 }
 }

Solution

  • mapFragment is null. Kindly verify that your layout file contains

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

    And you are inflating the correct layout file. Secondly, your function setupMapIfNeeded is having wrong condition. Your condition should be on fragment and it must be assigned to global variable mapFragment

    setupMapIfNeeded

    private void setupMapIfNeeded(){
        // Build the map.
        if(mapFragment==null) {
            mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
        }
    }