title: Google Maps Fragment replacing current fragment
body: <p><strong>Background:</strong><br>
  Create an app that will center on the user's location and allow for them to text their location to contacts.  To do this, we need a simple credential check and server address to test on in the preferences. </p>
  
  <p><strong>Issue:</strong><br>
  Whenever the user navigates from the original map fragment that shows their location with a marker, the proper map type (hybrid), etc. to another fragment and then wants to return to the map fragment, it defaults to LatLng 0,0 and a generic map (no indication of user location for example).  </p>
  
  <p>My initial thought was to try and save the state of the map fragment upon switching to another fragment and reload that when popping the other fragment from the stack.  However I then thought it might be simpler to just replace the current fragment in the MainActivity whenever I need to switch.  So on opening the app, MainActivity creates a new MapFragment then replaces it with a Preferences Fragment and when 'saving' creates a new MapFragment to replace the current fragment with.  Thought this might fix my problem as on initial load the map functions like I want.  </p>
  
  <p>The code for MFragment that contains the Map Fragment:</p>
  
  <pre><code>public class MFragment extends Fragment implements android.location.LocationListener,
                      GooglePlayServicesClient.ConnectionCallbacks, 
                      GooglePlayServicesClient.OnConnectionFailedListener{
  
  private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
  private static GoogleMap map;
  private static LocationClient lClient;
  private final static String TAG = "MFragment";
  private String provider;
  private Location loc;
  private LocationManager lManager;
  private LatLng currentLatLng;
  private final long MIN_TIME = 1000;
  private final float MIN_DIST = 10;
  private Update updateMarkers = new Update();
  private View view;
  private MapFragment mFrag;
  
  public void onCreate(Bundle savedInstanceState){
      super.onCreate(savedInstanceState);
      mFrag = MapFragment.newInstance();
  }
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState)  {
      super.onCreateView(inflater, container, savedInstanceState);
      //sets the layout for this fragment
      view = inflater.inflate(R.layout.fragment_map, container, false);
      //insert MapFragment into this Fragment 
      getActivity().getFragmentManager().beginTransaction()
              .replace(R.id.mapview, mFrag)
              .commit();
      //get a handle on the map from the MapFragment
  //      map = mFrag.getMap();
      //instantiates the location manager
      lManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
      //instantiate the location client
      lClient = new LocationClient(getActivity(), this, this);
      lClient.connect();
      //run through initialization of all objects 
      setUpMapIfNeeded();
      Log.d(TAG, "Successfully created MFragment");
      return view;
  }
  
  /**
   * instantiates map from the MapFragment if map is null.  
   */
  private void setUpMapIfNeeded() {
      if (getActivity() != null &amp;&amp; getActivity().getFragmentManager() != null &amp;&amp;
              map == null)    {
          map = mFrag.getMap();
          Log.d(TAG, "Map generated.");
          setUpMap();
      }   else if (lClient.isConnected()) {
          updateMap();
      }   else    {
          setUpMap();
      }
  }
  
  /**
   * sets up the location data for the map.  conditional clause so that the GPS doesn't crash
   * if the app can't get a location straight away.
   */
  private void setUpMap() {
      if (map != null) {
          map.setMyLocationEnabled(true);
          map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
          Criteria crit = new Criteria();
          provider = lManager.getBestProvider(crit, false);
          if (lManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
              loc = lManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
          }   else {
              loc = lManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
          }
          lManager.requestLocationUpdates(provider, MIN_TIME, MIN_DIST, this);
  
      }
  }
  
  
  protected void updateMap()  {
      if (servicesConnected())    {
          map.clear();
          currentLatLng = new LatLng(this.loc.getLatitude(), this.loc.getLongitude());
          map.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 14));
          map.addMarker(new MarkerOptions()
                      .position(currentLatLng)
                      .title("You"));
          map.setOnMarkerClickListener(new OnMarkerClickListener() {
  
              @Override
              public boolean onMarkerClick(Marker m) {
                  SMSFragment sFrag = new SMSFragment();
                  sFrag.setMarker(m);
                  getActivity().getFragmentManager().beginTransaction()
                      .replace(android.R.id.content, sFrag)
                      .commit();
                  return false;
              }
          });
  
      }
  }
  
  /**
   * checks for connection to google play services
   * @return
   */
  private boolean servicesConnected() {
      int resultCode = GooglePlayServicesUtil
              .isGooglePlayServicesAvailable(getActivity().getApplicationContext());
      if (ConnectionResult.SUCCESS == resultCode) {
          Log.d(TAG, getString(R.string.play_available));
          return true;
      } else {
          if (GooglePlayServicesUtil.isUserRecoverableError(resultCode))  {
              GooglePlayServicesUtil
                  .getErrorDialog(resultCode, getActivity(), 
                      CONNECTION_FAILURE_RESOLUTION_REQUEST).show();
          }   else    {
              Log.i(TAG, "This device is not supported");
          }
          return false;
      }
  }
  
  @Override
  public void onConnectionFailed(ConnectionResult connectionResult) {
      if (connectionResult.hasResolution())   {
          try {
              connectionResult
                  .startResolutionForResult(getActivity(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
          }   catch (IntentSender.SendIntentException e)  {
              e.printStackTrace();
          }
      }   else    {
          Toast.makeText(getActivity(), R.string.connect_failed, Toast.LENGTH_SHORT).show();
      }
  }
  
  /**
   * Called after location client connects
   */
  @Override
  public void onConnected(Bundle arg0) {
      updateMap();
  }
  
  /**
   * simple display message after disconnecting.
   */
  @Override
  public void onDisconnected() {
      Toast.makeText(getActivity(), R.string.disconnected, Toast.LENGTH_SHORT).show();
  }
  
  
  public void onStart()   {
      super.onStart();
      lClient.connect();
      setUpMapIfNeeded();
  }
  
  public void onResume()  {
      super.onResume();
      lClient.connect();
      setUpMapIfNeeded();
  }
  
  public void onPause()   {
      lClient.disconnect();
      super.onPause();
  }
  
  public void onStop()    {
      lClient.disconnect();
      super.onStop();
  }
  
  public void onDestroy() {
      lClient.disconnect();
      super.onDestroy();
  }
  
  @Override
  public void onLocationChanged(Location location) {
      this.loc = location;
      updateMap();
  }
  
  @Override
  public void onProviderDisabled(String provider) {
      // TODO Auto-generated method stub
  
  }
  
  @Override
  public void onProviderEnabled(String provider) {
      // TODO Auto-generated method stub
  
  }
  
  @Override
  public void onStatusChanged(String provider, int status, Bundle extras) {
      // TODO Auto-generated method stub
  
  }
  
  
  public void updateMarkers(List&lt;Record&gt; records){
      //update map with markers corresponding to each latitude, longitude passed back from records
      for (Record r : records){
          map.addMarker( new MarkerOptions()
                  .position(new LatLng(r.getValueOfLatitude(), r.getValueOfLongitude())));
      }
  }
  
  private class Update extends AsyncTask&lt;Void, Void, Boolean&gt; {
  
      private List&lt;Record&gt; records;
  
      protected Update()  {
          super();
          records = new ArrayList&lt;Record&gt;();
      }
  
      @Override
      protected Boolean doInBackground(Void... params) {
          Connect conn = new Connect(getActivity());
          try {
              records = conn.getAll();
              return true;
          } catch (IOException e) {
              e.printStackTrace();
          }
          return false;
      }
  
      protected void onPostExecute(Boolean result)    {
          if (result) {
              updateMarkers(records);
          }   else    {
              Toast.makeText(getActivity(), R.string.rec_fail, Toast.LENGTH_SHORT).show();
          }
      }
  }
  }
  </code></pre>
  
  <p>And an example of replacing the Fragment from another Fragment (From PrefsFragment to MFragment):</p>
  
  <pre><code>    register = (Button) v.findViewById(R.id.register);
  
      save.setOnClickListener(new View.OnClickListener() {
  
          @Override
          public void onClick(View v) {
              saveToPreferences(v);
              ((MainActivity)getActivity()).replaceFragment();
          }
      });
  
      register.setOnClickListener(new View.OnClickListener() {
  
          @Override
          public void onClick(View v) {
              getActivity().getFragmentManager().beginTransaction()
                  .replace(android.R.id.content, new RegFragment())
                  .commit();
          }
      });
  
      return v;
  }
  </code></pre>
  
  <p>the save button calls a method in MainActivity to replace the current fragment with a MapFragment as an attempted work-around but doesn't function like I was hoping and using the similar method for the register button using FragmentManager doesn't fix the Map issue either.</p>
  
  <p>Any help is appreciated.</p>