Android - android.view.InflateException: двоичная строка XML файла # 8: ошибка раздувания фрагмента класса

Я разрабатываю приложение, используя NavigationDrawer i.e. DrawerLayout и переходя к различным Fragments. Когда я вызываю Map_Fragment_Page, приложение падает, но не в первый раз. В первый раз он правильно отображает Map, но после этого, когда я перемещаюсь по разным фрагментам и снова перехожу к Map_Fragment_Page, он выдает сообщение об ошибке android.view.InflateException: Binary XML file line #8: Error inflating class fragment

Я пробовал так много разных решений, и я также искал на Google, но все еще не получал требуемого решения. Проблема еще не установлена.

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;

    }
}

Ответ 1

Yes.. I want Map inside a Fragment.

Вы должны использовать 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() устарел. Вместо этого используйте getMapAsync(OnMapReadyCallback). Метод обратного вызова предоставляет экземпляр GoogleMap, который должен быть не нулем и готов к использованию.

Ответ 2

Итак, если он сработает после открытия фрагмента второй раз. Все, что вам нужно, это в OnDestroy

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

Сделайте необходимые изменения, если вы используете фрагмент поддержки

Ответ 3

Мой опыт, сделанный с фрагментами, добавленными xml-тегом

<fragment>...</fragment>.

Эти фрагменты обычно вложены и не уничтожаются при уничтожении родительского фрагмента. Как только вы попытаетесь раздуть их снова, вы получите исключение, которое в основном жалуется на то, что этот фрагмент уже завышен. Поэтому я уничтожаю свои вложенные фрагменты вручную после уничтожения родительского фрагмента. Просто используйте следующий отрезанный и отрегулируйте его к вашим потребностям. Этот код находится в родительском фрагменте, который имеет вложенный фрагмент в виде xml-тега.

@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();
    }
}

С динамически создаваемыми фрагментами проблем вообще нет. Динамически означает: у вас нет используемого фрагмента-xml-тега

Надеюсь, это поможет! Хорошее программирование!

Ответ 4

Я помещаю это в свой фрагмент

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

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

Работает без замены MapView.

Ответ 5

Измените это

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

к

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

Ответ 6

В вашем классе


    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>

Ответ 7

Как вы говорите в первый раз, когда ваш код работает, поэтому я думаю, что когда вы снова назовете свою карту, ваш объект googlemap не будет null, и вы не обработали его правильно, попробуйте реализовать как это в вашем коде

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"));
}

Ответ 8

Проверьте, есть ли у вас точное разрешение манифеста. Я не включил нижеприведенное разрешение в манифест, и он дал эту ошибку.

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

Пожалуйста, включите в файл манифеста некоторые из следующих разрешений                  

<!-- - 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"/>

Ответ 9

Я помещаю это в свой фрагмент, когда у меня есть 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();
}

Ответ 10

Чтобы Google API v2 работал (я также использую SupportMapFragment), вы должны включить эти разрешения

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

Надеюсь, это поможет вам, ребята.

P.S Я использовал эти разрешения для добавления простой карты в свое приложение. Существуют и другие разрешения, которые указывает на эту ссылку.

Ответ 11

Я получил такое же сообщение об ошибке:

Причиной для меня было просто: воссоздать представление

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 может вызываться более одного раза.

Когда это произойдет, приведенный выше код создает новое представление для фрагмента, а старый - еще.

Ошибка появляется с некоторым адаптером и не с другим; в моем случае FragmentStatePagerAdapter был счастлив, и FragmentPagerAdapter был убийственным, потому что прежний уничтожил его фрагменты, а последний использовал их повторно.

Ответ 12

Как я исправил свою проблему после многого поиска, Поместите эти строки внутри фрагмента в метод Pause.

@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;
    }
}

Обязательно null googlemap. Нет необходимости использовать MapView, вы можете сделать это, не используя MapView