I'm developing an app that has a app feature for displaying teams on Google maps as markers.
I'm able to display myself as marker that updates when I move & others as markers on a fragment.
The issue is markers are displayed ONLY THE 1st TIME that I go to MapFragment. When I navigate away to another fragment and come back to the map, I see an EMPTY map with no markers & no zoom buttons.
Attempt #3, please see history for previous implementations which are slightly different:
My fragment layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/incident_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        />
    <ProgressBar
        android:id="@+id/incident_map_progress_bar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="visible"/>
    <!--<com.google.android.gms.maps.MapView
        android:id="@+id/incident_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />-->
</RelativeLayout>
My IncidentMapFragment code, which is now updated based on user feedback. The updates are minimal. Instead on onResume() im using onActivityCreated() and instead of onPause() Im using onSaveInstanceState(), see updated code below
    package com.xyz.fragments;
//i did not include imports 
//Based  on https://developers.google.com/maps/documentation/android-sdk/map-with-marker
public class IncidentMapFragment extends Fragment implements OnMapReadyCallback {
    public static final String TAG = "IncidentMapFragment";
    private static  IncidentMapFragment incidentMapFragment = null;
    public static IncidentMapFragment instance() {
        if (incidentMapFragment==null)
        {
            incidentMapFragment =   new IncidentMapFragment();
        }
        return incidentMapFragment;
    }
    private MapView mapView;
    private static GoogleMap map;
    private ProgressBar progressBar;
    private SupportMapFragment mapFragment;
    public static final int UPDATE_MY_CURRENT_LOCATION = 0;
    public static final int UPDATE_MY_TEAMS_CURRENT_LOCATIONS = 1;
    public static final int UPDATE_ALL_TEAMS_CURRENT_LOCATIONS = 2;
    public static final int UPDATE_ALL_LOCATION_BASED_EVENTS = 3;
    private static Context context;
    private int MY_DEFINED_ACCESS_COARSE_LOCATION_CALLBACK_RESULT = 1;
    private int MY_DEFINED_ACCESS_FINE_LOCATION_CALLBACK_RESULT = 2;
    boolean flagCoarseLocation = false;
    boolean flagFineLocation = false;
    private WamsUnitVehicleUnitRelationshipDao vehicleUnitRelationshipDao = new WamsUnitVehicleUnitRelationshipDaoImpl();
    private static WamsUnitVehicleUnitRelationship newVehicleUnitRelationship = null;
    private static CameraPosition cp;
    private static Bundle markersBundle = new Bundle();
    private static Bundle saveStateBundle = new Bundle();
    private boolean createdStateInDestroyView = false;
    private static final String SAVED_BUNDLE_TAG = "IncidentMapFragment_SAVE_STATE";
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.incident_map_fragment, container, false);
        context = rootView.getContext();
        progressBar = rootView.findViewById(R.id.incident_map_progress_bar);
        try {
            FragmentManager fm = getActivity().getSupportFragmentManager();
            if (savedInstanceState == null) {
                mapFragment = SupportMapFragment.newInstance();
                fm.beginTransaction().replace(R.id.incident_map, mapFragment,TAG).commit();
            }
            else {
                mapFragment = (SupportMapFragment) fm
                        .findFragmentByTag(TAG);
            }
            if (savedInstanceState!=null) {
                saveStateBundle = savedInstanceState.getBundle(SAVED_BUNDLE_TAG);
                //restore camera
                cp = saveStateBundle.getParcelable("cp");
                //restore bundle of markers
                markersBundle = saveStateBundle.getParcelable("markersBundle");
                if (cp!=null && markersBundle!=null)
                {
                    reDrawMarkers(markersBundle);
                }
            }
        } catch (Exception exc) {
            Log.e(TAG, exc.getMessage());
            exc.printStackTrace();
        }
        return rootView;
    }
    @Override
    public void onActivityCreated(Bundle bundle) {
        super.onActivityCreated(bundle);
        Log.i(TAG,"onActivityCreated()");
        newVehicleUnitRelationship = vehicleUnitRelationshipDao.getWamsUnitVehicleUnitRelationship(NgfrApp.getInstance().getUniqueDeviceId());
        if (mapFragment!=null) {
            mapFragment.getMapAsync(this);
        }
    }
    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        Log.i(TAG,"onSaveInstanceState()");
        outState.putBundle(SAVED_BUNDLE_TAG, saveState());
        createdStateInDestroyView = false;
        super.onSaveInstanceState(outState);
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        saveStateBundle = saveState();
        createdStateInDestroyView = true;
        cp = null;
        markersBundle = null;
    }
    private Bundle saveState() {
        Bundle state = new Bundle();
        state.putParcelable("cp", cp);
        state.putParcelable("markersBundle", markersBundle);
        return state;
    }
    /*Handler used by outside class such as MqttBroker.
    1) UPDATE_MY_CURRENT_LOCATION. When my location service send a update location(lat,long) call updateMarkersOnMap() which creates a new AsyncTask to update teh display
    2) UPDATE_MY_TEAMS_CURRENT_LOCATIONS. When the MQTT dservice gets new location(lat,long) call updateMarkersOnMap() which creates a new AsyncTask to update teh display
    3) UPDATE_ALL_TEAMS_CURRENT_LOCATIONS, not implemented.
     */
    public static final Handler updateIncidentMap = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            //if the context is null then the MapFragment & GoogleMap objects are NOT instantiated and updating the maps non-existant UI will cause exceptions, NPE, and crashes!
            if (context != null) {
                Location myCurrentLocation = null;
                final int what = msg.what;
                switch (what) {
                    case UPDATE_MY_CURRENT_LOCATION:
                        Log.i(TAG,"UPDATE_MY_CURRENT_LOCATION");
                        myCurrentLocation = (Location) msg.obj;
                        if (map != null) {
                            updateMarkersOnMap(map,markersBundle, myCurrentLocation.getLatitude(),myCurrentLocation.getLongitude(),newVehicleUnitRelationship.getWamsId(), newVehicleUnitRelationship.getVehicleUnitId());
                        }
                        break;
                    case UPDATE_MY_TEAMS_CURRENT_LOCATIONS:
                        Log.i(TAG,"UPDATE_MY_TEAMS_CURRENT_LOCATIONS");
                        if (map != null) {
                            WamsLocationMarker wamsLocationMarker = (WamsLocationMarker) msg.obj;
                            updateMarkersOnMap(map, markersBundle,wamsLocationMarker.getLat(),wamsLocationMarker.getLon(), wamsLocationMarker.getClientId(), wamsLocationMarker.getVehicleId());
                            //mock team
                            mockTeam(map,markersBundle,  wamsLocationMarker.getLat(),wamsLocationMarker.getLon());
                        }
                        break;
                    case UPDATE_ALL_TEAMS_CURRENT_LOCATIONS:
                        break;
                    default:
                        break;
                }
            } //end if context  is NOt null
        } //end handleMessage
    };
    /*I added the @SuppressLint("MissingPermission") because we are handling this in permissionHelper(getActivity()),
    and the IDE is too naive to know*/
    @SuppressLint("MissingPermission")
    @Override
    public void onMapReady(GoogleMap googleMap) {
        Log.i(TAG, "onMapReady()");
        try {
            //remove progress bar
            progressBar.setVisibility(GONE);
            //initially zoom in my location
            map = googleMap;
            if (permissionHelper(getActivity()))
            {
                map.setMyLocationEnabled(true);
                map.getUiSettings().setZoomControlsEnabled(true);
                map.getUiSettings().setCompassEnabled(true);
            }
            if (cp != null) {
                map.moveCamera(CameraUpdateFactory.newCameraPosition(cp));
                cp = null;
            }
            reDrawMarkers(markersBundle);
        }
        catch (NullPointerException exc)
        {
            exc.printStackTrace();
        }
    }
    private static void updateMarkersOnMap(GoogleMap map,Bundle bundle, double lat,double log, String id, String vehicleId) {
        final GoogleMap _map = map;
        final double _lat = lat;
        final double _log = log;
        final String _id = id;
        final String _vehicleId = vehicleId;
        new AsyncTask < Void, Void, WamsLocationMarker > () {
            boolean update = false;
            @Override
            protected WamsLocationMarker doInBackground(Void...voids) {
                Marker marker = null;
                WamsLocationMarker wamsLocationMarker=null;
                try {
                    Log.i(TAG,"async map: "+map);
                    if (_map != null && bundle!=null)
                    {
                        Log.i(TAG,_map.toString());
                        //if the wamsLocationMarker exists,  then UPDATE
                        if (bundle.containsKey(_id)) {
                            Log.i(TAG,"markersBundle.containsKey(_id): "+ bundle.containsKey(_id));
                            Log.i(TAG,"update true");
                            //get from hashmap
                            wamsLocationMarker = (WamsLocationMarker)bundle.get(_id);
                            update = true;
                        } else {
                            //add to map
                            //if the ids are equal then this is YOU
                            wamsLocationMarker = new WamsLocationMarkerFactory().createWamsLocationMarker(_id, _vehicleId, _lat, _log);
                            Log.i(TAG,"WamsLocationMarker");
                            Log.i(TAG,"update false");
                        }
                    } else {
                        Log.e(TAG, " updateMarkersOnMap() map is " + _map);
                    }
                }
                catch (NullPointerException exc)
                {
                    exc.printStackTrace();
                }
                return wamsLocationMarker;
            }
            @Override
            protected void onPostExecute(WamsLocationMarker wamsLocationMarker) {
                super.onPostExecute(wamsLocationMarker);
                try {
                    if (wamsLocationMarker != null) {
                        Log.i(TAG,"onPostExecute() update:"+update+",wamsLocationMarker:"+wamsLocationMarker);
                        if (update) {
                            Log.i(TAG,"onPostExecute() update:"+update);
                            //UPDATE wth new lat & long if the markers coordinates have change, else dont redraw, beacuse the draw causes a refresh affect & its also a waste computationally
                            if (wamsLocationMarker.getMarker().getPosition().latitude != _lat && wamsLocationMarker.getMarker().getPosition().longitude != _log) {
                                LatLng latLng = new LatLng(_lat, _log);
                                //UPDATE THE MARKER POSITION
                                wamsLocationMarker.getMarker().setPosition(latLng);
                            }
                        } else {
                            //ADD A NEW MARKER
                            Marker marker = _map.addMarker(wamsLocationMarker.getMakerOptions());
                            Log.i(TAG,"ASYNC MARKER:"+marker.getId());
                            wamsLocationMarker.setMarker(marker);
                            markersBundle.remove(wamsLocationMarker.getClientId());
                            markersBundle.putParcelable(wamsLocationMarker.getClientId(), wamsLocationMarker);
                        }
                    }
                }
                catch (NullPointerException exc)
                {
                    exc.printStackTrace();
                }
            }
        }.execute();
    }
      public void reDrawMarkers(Bundle bundle) {
    Log.i(TAG,"reDrawMarkers()");
    if (bundle!=null) {
        Set<String> keys = bundle.keySet();
        WamsLocationMarker wamsLocationMarker = null;
        for (String k : keys) {
            Log.i(TAG, "key:" + k);
            wamsLocationMarker = (WamsLocationMarker) bundle.getParcelable(k);
            updateMarkersOnMap(map, bundle, wamsLocationMarker.getLat(), wamsLocationMarker.getLon(), wamsLocationMarker.getClientId(), wamsLocationMarker.getVehicleId());
        }
    }
}
    //Just for test - Im mocking some there points to represent other teams mates on the map, this is just for testing
    private static void mockTeam(GoogleMap map, Bundle bundle, double _lat, double _log) {
        updateMarkersOnMap(map,bundle, _lat+0.001, _log , "mock111111111", newVehicleUnitRelationship.getVehicleUnitId());
        updateMarkersOnMap(map,bundle,_lat, _log+0.001 ,"mock222222222", newVehicleUnitRelationship.getVehicleUnitId());
        updateMarkersOnMap(map,bundle, _lat-0.001, _log,"mock33333333", newVehicleUnitRelationship.getVehicleUnitId());
        updateMarkersOnMap(map,bundle, _lat, _log-0.001,"mock444444444", newVehicleUnitRelationship.getVehicleUnitId());
    }
    //Ask the user if  required & attempt to grant required location services
    private boolean permissionHelper(Activity activity) {
        String permission = Manifest.permission.ACCESS_COARSE_LOCATION;
        int res = getContext().checkCallingPermission(permission);
        //if the required coarse & fine permissions are granted then return true else proceed to get the permissions
        if (res == PackageManager.PERMISSION_GRANTED) {
            Log.i(TAG, "ACCESS_COARSE_LOCATION GRANTED");
            permission = Manifest.permission.ACCESS_FINE_LOCATION;
            res = getContext().checkCallingPermission(permission);
            if (res == PackageManager.PERMISSION_GRANTED) {
                Log.i(TAG, "ACCESS_FINE_LOCATION GRANTED");
                flagFineLocation = true;
            } else {
                Log.i(TAG, "ACCESS_FINE_LOCATION NOT GRANTED");
            }
            flagCoarseLocation = true;
        }
        //prompt user for COARSE location permission. If the user cancel then display toast & navigate back
        if (!flagCoarseLocation) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
                    Manifest.permission.ACCESS_COARSE_LOCATION)) {
                dialogForCoarsePermission();
            } else {
                ActivityCompat.requestPermissions(activity,
                        new String[] {
                                Manifest.permission.ACCESS_COARSE_LOCATION
                        },
                        MY_DEFINED_ACCESS_COARSE_LOCATION_CALLBACK_RESULT);
                flagCoarseLocation = true;
            }
        }
        //prompt user for FINE location permission. If the user cancel then display toast & navigate back
        if (!flagFineLocation) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {
                dialogForFinePermission();
            } else {
                ActivityCompat.requestPermissions(activity,
                        new String[] {
                                Manifest.permission.ACCESS_COARSE_LOCATION
                        },
                        MY_DEFINED_ACCESS_FINE_LOCATION_CALLBACK_RESULT);
                flagFineLocation = true;
            }
        }
        if (!flagCoarseLocation)
        {
            Log.i(TAG, "ACCESS_COARSE_LOCATION NOT GRANTED");
        }
        else
        {
            Log.i(TAG, "ACCESS_COARSE_LOCATION GRANTED");
        }
        if (!flagFineLocation)
        {
            Log.i(TAG, "ACCESS_FINE_LOCATION NOT GRANTED");
        }
        else
        {
            Log.i(TAG, "ACCESS_FINE_LOCATION GRANTED");
        }
        return (flagCoarseLocation && flagFineLocation);
    }
    private void dialogForCoarsePermission() {
        DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which) {
                    case DialogInterface.BUTTON_POSITIVE:
                        //Yes button clicked
                        ActivityCompat.requestPermissions(getActivity(),
                                new String[] {
                                        Manifest.permission.ACCESS_COARSE_LOCATION
                                },
                                MY_DEFINED_ACCESS_COARSE_LOCATION_CALLBACK_RESULT);
                        break;
                    case DialogInterface.BUTTON_NEGATIVE:
                        //No button clicked
                        break;
                }
            }
        };
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage("The map requires coarse location permission.Please it by pressing Yes. ").setPositiveButton("Yes", dialogClickListener)
                .setNegativeButton("No", dialogClickListener).show();
    }
    private void dialogForFinePermission() {
        DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which) {
                    case DialogInterface.BUTTON_POSITIVE:
                        //Yes button clicked
                        ActivityCompat.requestPermissions(getActivity(),
                                new String[] {
                                        Manifest.permission.ACCESS_FINE_LOCATION
                                },
                                MY_DEFINED_ACCESS_FINE_LOCATION_CALLBACK_RESULT);
                        break;
                    case DialogInterface.BUTTON_NEGATIVE:
                        //No button clicked
                        break;
                }
            }
        };
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage("The map ALSO requires fine location permission.Please it by pressing Yes. ").setPositiveButton("Yes", dialogClickListener)
                .setNegativeButton("No", dialogClickListener).show();
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        Log.i(TAG, "onRequestPermissionsResult() request code:" + requestCode); // Log printed
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == MY_DEFINED_ACCESS_COARSE_LOCATION_CALLBACK_RESULT) {
            flagCoarseLocation = true;
            Toast.makeText(context, "Coarse location permission granted.", Toast.LENGTH_SHORT).show();
        }
        if (requestCode == MY_DEFINED_ACCESS_FINE_LOCATION_CALLBACK_RESULT) {
            flagFineLocation = true;
            Toast.makeText(context, "Fine location permission granted.", Toast.LENGTH_SHORT).show();
        }
    }
}
I provided the GUI & corresponding logs for this fragment only.
The 1st time I navigate to the fragment. Everything is ok, and you see the go to my location button & zoom buttons:
Now the issue appears when I navigate to 1st fragment called "Services" or if leave app in the background for a while. I cant see the markers anymore & new location updates coming via the network are added however are NOT being drawn. Map zoom buttons are also missing!!!
08-16 08:06:03.358 1314-1314/com.xyz I/IncidentMapFragment: onSaveInstanceState()
08-16 08:06:03.836 1314-1314/com.xyz I/IncidentMapFragment: reDrawMarkers()
    key:015140000100161
    key:mock33333333
    key:mock444444444
    key:mock111111111
    key:mock222222222
08-16 08:06:03.836 1314-1340/com.xyz I/IncidentMapFragment: async map: com.google.android.gms.maps.GoogleMap@1e72e3b
    com.google.android.gms.maps.GoogleMap@1e72e3b
    markersBundle.containsKey(_id): true
    update true
    async map: com.google.android.gms.maps.GoogleMap@1e72e3b
    com.google.android.gms.maps.GoogleMap@1e72e3b
    markersBundle.containsKey(_id): true
    update true
    async map: com.google.android.gms.maps.GoogleMap@1e72e3b
    com.google.android.gms.maps.GoogleMap@1e72e3b
    markersBundle.containsKey(_id): true
    update true
    async map: com.google.android.gms.maps.GoogleMap@1e72e3b
    com.google.android.gms.maps.GoogleMap@1e72e3b
    markersBundle.containsKey(_id): true
    update true
    async map: com.google.android.gms.maps.GoogleMap@1e72e3b
    com.google.android.gms.maps.GoogleMap@1e72e3b
    markersBundle.containsKey(_id): true
    update true
08-16 08:06:03.837 1314-1314/com.xyz I/IncidentMapFragment: onActivityCreated()
08-16 08:06:03.851 1314-1314/com.xyz I/IncidentMapFragment: onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@19b04df
    onPostExecute() update:true
    onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@47c13e2
    onPostExecute() update:true
    onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@6b22ea9
    onPostExecute() update:true
    onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@e387818
08-16 08:06:03.852 1314-1314/com.xyz I/IncidentMapFragment: onPostExecute() update:true
    onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@dab0d7
    onPostExecute() update:true
    onMapReady()
    ACCESS_COARSE_LOCATION GRANTED
    ACCESS_FINE_LOCATION GRANTED
08-16 08:06:03.853 1314-1314/com.xyz I/IncidentMapFragment: reDrawMarkers()
08-16 08:06:03.854 1314-1314/com.xyz I/IncidentMapFragment: key:015140000100161
    key:mock33333333
    key:mock444444444
    key:mock111111111
    key:mock222222222
08-16 08:06:03.854 1314-1338/com.xyz I/IncidentMapFragment: async map: com.google.android.gms.maps.GoogleMap@b7d1933
    com.google.android.gms.maps.GoogleMap@b7d1933
    markersBundle.containsKey(_id): true
    update true
    async map: com.google.android.gms.maps.GoogleMap@b7d1933
    com.google.android.gms.maps.GoogleMap@b7d1933
    markersBundle.containsKey(_id): true
    update true
    async map: com.google.android.gms.maps.GoogleMap@b7d1933
    com.google.android.gms.maps.GoogleMap@b7d1933
    markersBundle.containsKey(_id): true
    update true
    async map: com.google.android.gms.maps.GoogleMap@b7d1933
    com.google.android.gms.maps.GoogleMap@b7d1933
    markersBundle.containsKey(_id): true
    update true
    async map: com.google.android.gms.maps.GoogleMap@b7d1933
    com.google.android.gms.maps.GoogleMap@b7d1933
    markersBundle.containsKey(_id): true
    update true
08-16 08:06:03.865 1314-1314/com.xyz I/IncidentMapFragment: onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@19b04df
    onPostExecute() update:true
    onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@47c13e2
    onPostExecute() update:true
    onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@6b22ea9
    onPostExecute() update:true
    onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@e387818
    onPostExecute() update:true
    onPostExecute() update:true,wamsLocationMarker:com.xyz.mapping.WamsLocationMarker@dab0d7
    onPostExecute() update:true
See debug window: state is restored but not drawing
 My logs show the markers are being added again with no errors or exceptions, but not being displayed?** Why? And how can i fix this?
My logs show the markers are being added again with no errors or exceptions, but not being displayed?** Why? And how can i fix this?
Thanks


 
     
     
    