Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android map v2 error on second inflating

I'm trying to use new android maps in my app.

I've got a FragmentActivity which layout contains (among other things):

<LinearLayout a:id="@+id/fragment_container"
    a:layout_width="fill_parent"
    a:layout_height="100dp"
    a:layout_weight="1"/>

It also has a button which changes this fragment using (mostly copied from sample project):

if (condition) {
    fragment = new Fragment1();
} else {
    fragment = new LocationFragment();
}
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();

and LocationFragment is:

public class LocationFragment extends SupportMapFragment{
private GoogleMap mMap;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    view = inflater.inflate(R.layout.map_fragment, container, false);
    setUpMapIfNeeded();
    return view;
}

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

private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the map.
    if (mMap == null) {
        // Try to obtain the map from the SupportMapFragment.
        mMap = ((SupportMapFragment)  getActivity().getSupportFragmentManager().findFragmentById(R.id.map))
                .getMap();
        // Check if we were successful in obtaining the map.
        if (mMap != null) {
            setUpMap();
        }
    }
}

private void setUpMap() {
    mMap.addMarker(new MarkerOptions().position(new LatLng(60.02532, 30.370552)).title(getString(R.string.map_current_location)));
}
}

xml layout is:

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

The problem is that when we replacing fragment with LocationFragment for the second time android is unable to inflate from xml. It crashes on line:

view = inflater.inflate(R.layout.map_fragment, container, false);

with exception:

12-17 01:47:31.209: ERROR/AndroidRuntime(4679): FATAL EXCEPTION: main
    android.view.InflateException: Binary XML file line #4: Error inflating class fragment
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:587)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:386)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
    at my.package.LocationFragment.onCreateView(LocationFragment.java:29)
    ...

And I have no Idea how to solve it. I think that it could be connected with an old issue that you cannot use more than one map view (found questions on android map v1). But in case of v2 and fragments support it must be the way to replace fragment container with map fragment, am I right?

like image 911
leshka Avatar asked Dec 16 '12 22:12

leshka


3 Answers

Remove your mapview fragment into onDestroyView method.

Fragment fragment = (getFragmentManager().findFragmentById(R.id.mapview));
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();
like image 107
iAndroid Avatar answered Oct 20 '22 07:10

iAndroid


You are extending SupportMapFragment. That is perfectly fine, though I am uncertain how common that pattern will be (this is all a bit too new).

However, SupportMapFragment is a fragment and knows how to display a map. You should not be overriding onCreateView() in most cases, and you certainly should not be overriding onCreateView() and trying to inflate a layout file that contains a <fragment> element pointing back to SupportMapFragment.

Here is a sample app that uses SupportMapFragment from the Maps V2 library. The activity loads a layout that has SupportMapFragment:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  class="com.google.android.gms.maps.SupportMapFragment"/>
like image 25
CommonsWare Avatar answered Oct 20 '22 06:10

CommonsWare


I'm not extending SupportMapFragment but rather just including it inside a (regular) fragment using XML as in the above answer but I GOT THE SAME RESULT... android.view.InflateException: Binary XML file line #4: Error inflating class when I tried to inflate the containing fragment for the second time since launch.

I solved this issue by not inflating the MapFragment from XML but rather leaving a placeholder using a FragmentLayout in the containing fragment XML and then adding this MapFragment programmatically at runtime. Works perfectly.

The containing fragment XML looks something like this:

<?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" >

    <!-- This is commented out because it crashed on second inflate.
    <fragment
        android:id="@+id/mapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginBottom="60dp"
        class="com.google.android.gms.maps.SupportMapFragment" />
    -->

    <FrameLayout
            android:id="@+id/mapFragmentHole"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_marginBottom="60dp"
            android:layout_gravity="center_vertical|center_horizontal" /> 
    .
    .
    .

Then in my containing fragment java code I do the following. This also shows how to configure the MapFragment prior to it's appearance using GoogleMapOptions.

_view = inflater.inflate(R.layout.fragment_map, container, false);

GoogleMapOptions gmo = (new GoogleMapOptions()).zoomControlsEnabled(false).rotateGesturesEnabled(false);
mapFragment = SupportMapFragment.newInstance(gmo);
FragmentTransaction fragmentTransaction = getFragmentManager()
        .beginTransaction();
fragmentTransaction.add(R.id.mapFragmentHole, mapFragment);
fragmentTransaction.commit();

In the above code mapFragment is a member variable so I can access it later to fetch the GoogleMap object later like so...

GoogleMap map = mapFragment.getMap();

However, if you inflate and do the MapFragment switcheroo in your onCreateView you won't be able to get a valid GoogleMap object inside the same method, so you'll have to wait until later to fill the map with data. In my code I launch a background thread to load data from my onCreateView method. Once the data is loaded it calls a method back on the UiThread to fill the map with artifacts.

Hope this helps. Good luck!

-M.

like image 3
Matt Galloway Avatar answered Oct 20 '22 07:10

Matt Galloway