48

I am developing an app using a NavigationDrawer i.e. DrawerLayout and navigating to different Fragments. When I call a Map_Fragment_Page the application crashes, but not the first time. For the first time it displays the Map properly but after that when I navigate different fragments and again come to Map_Fragment_Page then it crashes giving an error android.view.InflateException: Binary XML file line #8: Error inflating class fragment

I tried so many different solutions and I also also searched on Google but still not getting the required solution. The problem is not yet fixed.

howtoreach.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</RelativeLayout>

HowToReach.java

    package com.demo.map.howtoreach;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import android.support.v4.app.Fragment;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.demo.map.R;

import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Color;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

public class HowToReach extends Fragment
{
    public static final String TAG = "fragment_5";
    ProgressDialog dialog;

    GoogleMap googleMap;
    Marker marker;

    LocationManager locationManager;
    Location location;
    Criteria criteria;               
    String provider;

    double latitude, longitude;

    public HowToReach(){}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        final View v = inflater.inflate(R.layout.howtoreach, container, false);

        dialog = ProgressDialog.show(getActivity(),"","Loading",true,false);            

        int secondsDelayed = 4;
        new Handler().postDelayed(new Runnable()
                {
                    public void run()
        {               
            dialog.dismiss();
        }
        }, secondsDelayed * 1000);      

        try
        {
            // Loading map                  

            if (googleMap == null)
            {
                googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();

                googleMap.setMyLocationEnabled(true);

                locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);              
                criteria = new Criteria();               
                provider = locationManager.getBestProvider(criteria, true); 
                location = locationManager.getLastKnownLocation(provider);

                latitude = location.getLatitude();
                longitude = location.getLongitude();

                // create marker
                marker = googleMap.addMarker(new MarkerOptions().position(
                            new LatLng(latitude, longitude)).title("You are Here"));                  
                marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                marker.showInfoWindow(); 

                CameraPosition cameraPosition = new CameraPosition.Builder().target(
                        new LatLng(latitude, longitude)).zoom(15).build();

                googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));                         

                Polyline line = googleMap.addPolyline(new PolylineOptions()
                        .add(new LatLng(latitude, longitude), new LatLng(18.520897,73.772396))
                        .width(2).color(Color.RED).geodesic(true));

                marker = googleMap.addMarker(new MarkerOptions().position(
                            new LatLng(18.520897, 73.772396)).title("DSK Ranwara Road"));             
                marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));

                // check if map is created successfully or not
                if (googleMap == null)
                {
                    Toast.makeText(getActivity(),"Sorry! unable to create maps", Toast.LENGTH_SHORT).show();
                }
            }

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return v;

    }
}
Daryl Bennett
  • 462
  • 10
  • 22
Mitesh Shah
  • 1,729
  • 2
  • 19
  • 37
  • On which version are you testing ? –  Jan 04 '14 at 09:11
  • OS version or Map version? – Mitesh Shah Jan 04 '14 at 09:17
  • 2
    4.0.4 IceCream Sandwich. Samsung S DUOS.. I guess its not the problem.. because map is loading first time and when I come back to map page after navigating other fragments then it crashes... – Mitesh Shah Jan 04 '14 at 09:21
  • Have you debugged your code ??? Try to write // Loading map code in onResume method. –  Jan 04 '14 at 09:25
  • Yes.. still not working.. :( – Mitesh Shah Jan 04 '14 at 10:04
  • Actually the thing is you are checking `if(googleMap == null) { //your current code}` you do not specify `if(googleMap != null) {marker = googleMap.addMarker(new MarkerOptions().position( new LatLng(latitude, longitude)).title("You are Here"));}` try to implement like this . –  Jan 04 '14 at 10:13
  • Try to implement like this and tell me if its working. In your case when you go to map, your `googleMap` Object is not null that is why the app is being crashed. I have given some code try to implement that if its working tell me . –  Jan 04 '14 at 10:14
  • @Mitesh what is that you want? You want a map inside a framgent? – Raghunandan Jan 07 '14 at 12:03
  • @Raghunandan:: Yes.. I want Map inside a Fragment.. – Mitesh Shah Jan 07 '14 at 12:07

12 Answers12

64
Yes.. I want Map inside a Fragment.

You should use a MapView

http://developer.android.com/reference/com/google/android/gms/maps/MapView.html

public class HowToReach  extends Fragment {
    MapView mapView;
    GoogleMap map;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment2, container, false);
        // Gets the MapView from the XML layout and creates it

        try {
            MapsInitializer.initialize(getActivity());
        } catch (GooglePlayServicesNotAvailableException e) {
            Log.e("Address Map", "Could not initialize google play", e);
        }

        switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()) )
        {
            case ConnectionResult.SUCCESS:
                Toast.makeText(getActivity(), "SUCCESS", Toast.LENGTH_SHORT).show();
                mapView = (MapView) v.findViewById(R.id.map);
                mapView.onCreate(savedInstanceState);
                // Gets to GoogleMap from the MapView and does initialization stuff
                if(mapView!=null)
                {
                    map = mapView.getMap();
                    map.getUiSettings().setMyLocationButtonEnabled(false);
                    map.setMyLocationEnabled(true);
                    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(43.1, -87.9), 10);
                    map.animateCamera(cameraUpdate);
                }
                break;
            case ConnectionResult.SERVICE_MISSING: 
                Toast.makeText(getActivity(), "SERVICE MISSING", Toast.LENGTH_SHORT).show();
                break;
            case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: 
                Toast.makeText(getActivity(), "UPDATE REQUIRED", Toast.LENGTH_SHORT).show();
                break;
            default: Toast.makeText(getActivity(), GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()), Toast.LENGTH_SHORT).show();
        }




        // Updates the location and zoom of the MapView

        return v;
    }

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

fragment2.xml

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

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

</RelativeLayout>

Update:

https://developers.google.com/android/reference/com/google/android/gms/maps/MapView#public-constructors

getMap() is deprecated. Use getMapAsync(OnMapReadyCallback) instead. The callback method provides you with a GoogleMap instance guaranteed to be non-null and ready to be used.

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
10

So if it crashes after opening the fragment second time. All you need is this in OnDestroy

@Override
public void onDestroy() {
    super.onDestroy();
    getFragmentManager().beginTransaction().remove(mapfragmentnamehere).commit();
}

Make what changes you need if you're using support fragment

Xjasz
  • 1,238
  • 1
  • 9
  • 21
  • it gives error on remove method, as it cannot cast to mapfragment. – Trideep Mar 30 '15 at 14:19
  • this solved my problem, thank you Sir! code onDestroy: MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.map); getFragmentManager().beginTransaction().remove(mapFragment).commit(); –  Jul 09 '15 at 13:48
8

My experiences made with fragments added by xml-tag

<fragment>...</fragment>.

Those fragments are normally nested and do not destroy when the parent fragment gets destroyed. Once you try to inflate them again, you get the exception which basically complains of having this fragment already inflated. Therefore I destroy my nested fragments manually once the parent fragment gets destroyed. Simply use the following snipped and adjust it to your needs. This code resides in the parent fragment which has the nested fragment as xml-tag.

@Override
public void onDestroy() {
    super.onDestroy();
    final FragmentManager fragManager = this.getFragmentManager();
    final Fragment fragment = fragManager.findFragmentById(/*id of fragment*/);
    if(fragment!=null){
        fragManager.beginTransaction().remove(fragment).commit();
    }
}

With dynamically created fragments there are no problems at all. Dynamically means: You have no fragment-xml-tag used

Hope this helps! Good programming!

Alessandro Giusa
  • 1,660
  • 15
  • 11
4

I put this in my fragment

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

    getChildFragmentManager().beginTransaction()
            .remove(mMapFragment)
            .commit();
}

It working without replacing to the MapView.

Sergey Nikitin
  • 807
  • 8
  • 23
1

Change this

googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();

to

googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();
Piyush
  • 18,895
  • 5
  • 32
  • 63
  • To do this I need to extends FragmentActivity instead of Fragment. and I can't use FragmentActivity as I am calling this Fragment from previous page. – Mitesh Shah Jan 04 '14 at 09:16
  • @Mitesh what api level do you want your app to work. what is your min sdk in manifest? The activity that hosts the fragment must extend FragmentActivity – Raghunandan Jan 04 '14 at 09:31
  • @Raghunandan didn't get your point. Where it is documented can you post a link. If possible a good tutorial for `Fragment` thanks :-) –  Jan 04 '14 at 09:41
  • @user3110424 if you min sdk is 11you use SupportMapFragment in which case your activity extends FragmentActivity. You can look at the fragment docs and how to use fragment below api level 11 – Raghunandan Jan 04 '14 at 09:43
  • @Raghunandan My minSDKVersion is 14 and My previous class is extends FragmentActivity and from that class I am calling MapFragment.. – Mitesh Shah Jan 04 '14 at 10:03
  • @Mitesh should use `MapFragment`. Activity class should extend Activity – Raghunandan Jan 04 '14 at 10:07
  • @Raghunandan My MapFragmentPage extends Fragment not activity.. If I extend it to Activity.. then how can I call it from MainClass which extends FragmentActivity..?? – Mitesh Shah Jan 04 '14 at 10:12
  • @Mitesh your code is all wrong. Fragment is hosted by a Activity. You can host a MapFragment in Activity. But it looks like you want a map inside a fragment. So in that case you should use a `MapView` – Raghunandan Jan 07 '14 at 11:38
  • @Raghunandan:: I havent shared my FragmentActivity file here.. actually I am calling this MapFragment from Activity.. but error is in this file.. as I checked in LogCat.. – Mitesh Shah Jan 07 '14 at 12:01
  • 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 – Pablo Cegarra Aug 03 '16 at 12:47
1

In Your Class


    View mTrackView = inflater.inflate(R.layout.mylayout, container, false);
    SupportMapFragment mSupportMapFragment = SupportMapFragment.newInstance();
    FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
    fragmentTransaction.add(R.id.mapwhere, mSupportMapFragment);
    fragmentTransaction.commit();

    if(mSupportMapFragment!=null){

        googleMap = mSupportMapFragment.getMap();
        if(googleMap!=null){
        googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        googleMap.getUiSettings().setMyLocationButtonEnabled(false);
        googleMap.setMyLocationEnabled(false);
        if (mgpr_tracker.canGetLocation())
            CURREN_POSITION = new LatLng(mgpr_tracker.getLatitude(),
                    mgpr_tracker.getLongitude());

        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(
                CURREN_POSITION, ZOOM_LEVEL);
        googleMap.animateCamera(cameraUpdate);
          }
        }

mylayout.xml


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >
 <FrameLayout
   android:layout_width="match_parent"
   android:layout_height="0dp"
   android:layout_weight="1.03"

   android:id="@+id/mapwhere" />


  <TextView
   android:layout_width="match_parent"
   android:layout_height="wrap_content"/>

</LinearLayout>
PinkTurtle
  • 6,942
  • 3
  • 25
  • 44
Ravv
  • 482
  • 4
  • 7
0

As you are telling first time your code is working so i think when you again call your map your googlemap object is not null and you have not handled it properly try to Implement like this in your code

if (googleMap == null) {
// Your code 
} else if(googleMap != null) {
     marker = googleMap.addMarker(new MarkerOptions().position(new LatLng(18.520897, 73.772396)).title("DSK Ranwara Road"));
}
  • nope.... same error.. at Line no 52 in java file.. i.e. `final View v = inflater.inflate(R.layout.howtoreach, container, false);` – Mitesh Shah Jan 04 '14 at 10:28
  • http://stackoverflow.com/questions/14825331/binary-xml-file-line-8-error-inflating-class-fragment-google-maps refer this please.... –  Jan 04 '14 at 10:42
  • Sorry buddy... no solution.. Map is loading first time and after that it is getting crashed.. the solution your are giving is "When the map is getting crahsed for the first time." – Mitesh Shah Jan 04 '14 at 11:02
  • Is there any use of constructor in your Fragment ???? Please closely follow the link i have provided. –  Jan 04 '14 at 11:11
0

Check out that whether you have the exact manifest permission. I had not included the below permission in manifest, and it were giving this error.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Please include some of the following permission in your manifest file

<!-- - THIS IS THE USER PERMISSION FOR GETTING LATITUDE AND LONGTITUDE FROM INTERNET -->      
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> 
 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 <uses-permission android:name="android.permission.GET_ACCOUNTS" /> 
 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
 <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS"/>
 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
Pir Fahim Shah
  • 10,505
  • 1
  • 82
  • 81
0

I put this in my fragment when I have a viewpager:

@Override
public void onPause() {
    Fragment fragment = (getChildFragmentManager().findFragmentById(R.id.fragment_map_map));
    FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
    ft.remove(fragment);
    ft.commit();
    super.onPause();
}
Cabezas
  • 9,329
  • 7
  • 67
  • 69
0

For Google API v2 to work (I am also using SupportMapFragment), you must include these permissions

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:glEsVersion="0x00020000" android:required="true"/>

I hope this will help you guys.

P.S I used these permissions for adding a simple map in my app. There are certain other permissions which this link suggests as well.

Junaid
  • 3,477
  • 1
  • 24
  • 24
0

I got the same error message:

The cause for me was simple: re-creating a view

public View onCreateView(
        LayoutInflater inflater,
        ViewGroup container,
        Bundle savedInstanceState){
    super.onCreateView(inflater,container,savedInstanceState);
    self_view=inflater.inflate(R.layout.fragment_player,container,false);
    return self_view;
    }

onCreateView may be called more than once.

When that happens, the above code creates a new view for the fragment while the old one is still around.

The error pops up with some adapter and does not with another; in my case FragmentStatePagerAdapter was happy and FragmentPagerAdapter was murderous because the former destroyed its fragments and the latter reused them.

TastyCatFood
  • 1,632
  • 1
  • 15
  • 27
0

How i fixed my issue after searching alot, Put these lines inside fragment onPause Method.

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

    final FragmentManager fragManager = this.getChildFragmentManager();
    final Fragment fragment = fragManager.findFragmentById(R.id.map);
    if(fragment!=null){
        fragManager.beginTransaction().remove(fragment).commit();
        googleMap=null;
    }
}

It is compulsory to null googlemap. There is no need to use MapView, you can do it without using MapView

Naeem Ibrahim
  • 3,375
  • 1
  • 21
  • 21