web-dev-qa-db-fra.com

Android - SupportMapFragment avec GoogleMaps API 2.0 donnant IllegalArgumentException

J'essaie d'utiliser la dernière API Map 2.0 fournie pour Android. J'utilise la bibliothèque de support car je veux prendre en charge Android 2.2. Voici mon code:

Classe d'activité principale

public class MainActivity extends FragmentActivity {

    public FragmentManager fManager ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        fManager = getSupportFragmentManager();
        Button showMapButton = (Button) findViewById(R.id.showMapButton);
        showMapButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                loadMapFragment();
            }
        });
    }

    private void loadMapFragment() {
        MapPageFragment plotterFragment = new MapPageFragment();
        FragmentTransaction ft = fManager.beginTransaction();
        ft.replace(R.id.allFragmentsFrameLayout, plotterFragment);
        ft.addToBackStack(null);
        ft.commit();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

fichier de mise en page de l'activité principale

<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <Button
        Android:id="@+id/showMapButton"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:text="Show Map"
        Android:layout_marginLeft="30dp"
        Android:layout_marginRight="30dp"
        Android:layout_marginTop="30dp"
        Android:layout_alignParentTop="true" />


    <FrameLayout
        Android:id="@+id/allFragmentsFrameLayout"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"
        Android:layout_alignParentTop="true">
        <!-- Put fragments dynamically -->
    </FrameLayout>

</RelativeLayout>

Classe de fragment de carte

public class MapPageFragment extends SupportMapFragment {

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

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }
}

Disposition des fragments de carte

<?xml version="1.0" encoding="utf-8"?>
<fragment
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:map="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/map"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    class="com.google.Android.gms.maps.SupportMapFragment"
    map:uiCompass="true"
    map:mapType= "normal"
    map:uiRotateGestures="true"
    map:uiScrollGestures="true"
    map:uiTiltGestures="true"
    map:uiZoomControls="true"
    map:uiZoomGestures="true" />

Fichier manifeste Android

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    package="com.mapfragmentexample"
    Android:versionCode="1"
    Android:versionName="1.0" >

    <uses-sdk
        Android:minSdkVersion="8"
        Android:targetSdkVersion="16" />

    <permission
        Android:name="com.plotter.permission.MAPS_RECEIVE"
        Android:protectionLevel="signature"/>
    <uses-permission Android:name="com.plotter.permission.MAPS_RECEIVE"/>
    <uses-permission Android:name="Android.permission.INTERNET"/>
    <uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission Android:name="com.google.Android.providers.gsf.permission.READ_GSERVICES"/>

    <uses-feature
        Android:glEsVersion="0x00020000"
        Android:required="true"/>

    <application
        Android:allowBackup="true"
        Android:icon="@drawable/ic_launcher"
        Android:label="@string/app_name"
        Android:theme="@style/AppTheme" >
        <activity
            Android:name=".MainActivity"
            Android:label="@string/app_name" >
            <intent-filter>
                <action Android:name="Android.intent.action.MAIN" />
                <category Android:name="Android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            Android:name="com.google.Android.maps.v2.API_KEY"
            Android:value="AIzaSyA5FtIeLQ1gGUihZIZPQVi3Yz_0l4NG9PY"/>
    </application>

</manifest>

Tout fonctionne bien pour la première fois. c'est-à-dire lorsque je clique sur Show Map bouton le fragment de carte est chargé et affiche la carte. Lorsque j'appuie sur le bouton , le fragment de carte est déchargé et je peux voir le Show Map à nouveau.

Je rencontre un problème lorsque j'appuie sur Show Map à nouveau. J'obtiens l'erreur suivante:

FATAL EXCEPTION: main
Android.view.InflateException: Binary XML file line #2: Error inflating class fragment
    at Android.view.LayoutInflater.createViewFromTag(LayoutInflater.Java:699)
    at Android.view.LayoutInflater.inflate(LayoutInflater.Java:468)
    at Android.view.LayoutInflater.inflate(LayoutInflater.Java:397)
    at com.mapfragmentexample.MapPageFragment.onCreateView(MapPageFragment.Java:17)
    at Android.support.v4.app.Fragment.performCreateView(Fragment.Java:1460)
    at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:911)
    at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1088)
    at Android.support.v4.app.BackStackRecord.run(BackStackRecord.Java:682)
    at Android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.Java:1444)
    at Android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.Java:429)
    at Android.os.Handler.handleCallback(Handler.Java:605)
    at Android.os.Handler.dispatchMessage(Handler.Java:92)
    at Android.os.Looper.loop(Looper.Java:137)
    at Android.app.ActivityThread.main(ActivityThread.Java:4503)
    at Java.lang.reflect.Method.invokeNative(Native Method)
    at Java.lang.reflect.Method.invoke(Method.Java:511)
    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:809)
    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:576)
    at dalvik.system.NativeStart.main(Native Method)

Caused by: Java.lang.IllegalArgumentException: Binary XML file line #2: 
       Duplicate id 0x7f040006, tag null, or parent id 0x0 with another fragment 
       for com.google.Android.gms.maps.SupportMapFragment
    at Android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.Java:285)
    at Android.view.LayoutInflater.createViewFromTag(LayoutInflater.Java:671)
    ... 18 more

Je n'arrive pas à me tromper ou à manquer quelque chose.

14
Nik

Vous pouvez résoudre ce problème si vous supprimez tous les fragments imbriqués dans onDestroyView(). Je ne sais pas si c'est une bonne solution.

public void onDestroyView() {
   super.onDestroyView(); 
   Fragment fragment = (getFragmentManager().findFragmentById(R.id.map));   
   FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
   ft.remove(fragment);
   ft.commit();
}

Et les gonfler comme d'habitude dans onCreateView()

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.map, container, false);
}
49
Natalia

Vous devez utiliser getChildFragmentManager () pour ajouter SupportMapFragment non pas via xml.

Pour "pourquoi", consultez la documentation officielle: http://developer.Android.com/about/versions/Android-4.2.html#NestedFragments

Jetez un œil à ma réponse ici: https://stackoverflow.com/a/15512285/2183804

9
MaciejGórski

Vous ne pouvez pas gonfler une disposition dans un fragment lorsque cette disposition comprend un fragment . Les fragments imbriqués ne sont pris en charge que lorsqu'ils sont ajoutés à un fragment de manière dynamique. Plus de détails ici !

2
ToolFan

Utilisé cette solution (similaire aux autres):

public void onDestroyView() {

    FragmentManager fm = getActivity().getSupportFragmentManager();
    Fragment fragment = (fm.findFragmentById(R.id.map));

    if (fragment.isResumed()) {
        FragmentTransaction ft = fm.beginTransaction();
        ft.remove(fragment);
        ft.commit();
    }
    super.onDestroyView();
}

J'ai eu des problèmes avant d'utiliser l'if (fragment.isResumed).

2
sourcerebels

J'ai utilisé la réponse de Natalia mais j'ai parfois interrompu l'application. Utilisez celui-ci et cela a fonctionné parfaitement sans se casser.

@Override
public void onDestroyView() {

  try{
    FragmentTransaction transaction = getSupportFragmentManager()
            .beginTransaction();

    transaction.remove(nestedFragment);

    transaction.commit();
  }catch(Exception e){
  }

    super.onDestroyView();
}

https://stackoverflow.com/a/7953801/3364157

0
Emmanuel Guther
Fragment fragment = (getChildFragmentManager().findFragmentById(R.id.mapview));
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.remove(fragment);
ft.commit();

Utilisez-le pour sauver la journée.

0
Praseed M

Utilisez des indicateurs d'intention:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

lors de l'appel de l'activité principale.

0
Praseed M

J'étais confronté au même problème dans JakeWhartonViewPagerIndicatore avec SherlockFragments. Voici un exemple de TestFragment avec un problème résolu, merci à Natalia pour avoir fourni la solution ci-dessus. Votre fragment peut être un peu différent du mien.

Référence: Faire en sorte que ActionBarSherlock et ViewPagerIndicator jouent Nice

Bonne chance .. !!

package com.example.vpiabstest;

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentTransaction;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.TextView;

import com.actionbarsherlock.app.SherlockFragment;

public class TestFragment extends SherlockFragment {
    private String mContent = "???";
    private String text;
    private static final String KEY_TAB_NUM = "key.tab.num";

    public static TestFragment newInstance(String text) {
        TestFragment fragment = new TestFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putString(KEY_TAB_NUM, text);
        fragment.setArguments(args);


        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        text = getString(R.string.tab_page_num) + mContent;

        View view = null;

        if(text.contains("2")) {
            view = inflater.inflate(R.layout.pinpoints_list, null);
        } else if(text.contains("1")) {
            view = inflater.inflate(R.layout.main_fragment_activity, null);
        } else {
            view = inflater.inflate(R.layout.activity_main, null);
            ((TextView)view.findViewById(R.id.text)).setText(text);
        }


        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContent =  getArguments() != null ? getArguments().getString(KEY_TAB_NUM) : "???";
    }

    public void onDestroyView() {
        super.onDestroyView();

        // Your Programing skills goes here

        if(text == null || !text.contains("1")) {
            return;
        }

        // Do Not Miss this
        try {
            Fragment fragment = (getFragmentManager().findFragmentById(R.id.map_fragment));  
            FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
            ft.remove(fragment);
            ft.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
0
Rizwan Sohaib

Essaye ça

Disposition des fragments de cartes

<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:map="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools"
Android:id="@+id/map"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
map:uiCompass="true"
map:mapType= "normal"
map:uiRotateGestures="true"
map:uiScrollGestures="true"
map:uiTiltGestures="true"
map:uiZoomControls="true"
map:uiZoomGestures="true" 
tools:context="the.package.name.of.mappagefragment.MapPageFragment" />

Classe de fragment de carte

public class MapPageFragment extends SupportMapFragment 
{

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{
    View rootView = super.onCreateView(inflater, container, savedInstanceState);
    if (rootView == null)
    {
        rootView = inflater.inflate(R.layout.map_fragment_layout, container, false);
    }
    return rootView;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) 
{
    super.onViewCreated(view, savedInstanceState);
}
}
0
user4568328

Utilisez la méthode dialog.SetContentView() dans la cause onCreate() de votre activité lorsque nous essayons de charger.

Dialogue à nouveau, il charge uniquement la boîte de dialogue et non le cycle de vie complet de l'activité et le conduit à l'exception de l'ID en double.

Essayez-le.

0
suraj bokankar