43

Recently I migrated a project from Eclipse to Android Studio. Everything is setup and working fine except for my one fragment which uses a SupportMapFragment. The below findFragmentById (which worked when building in Eclipse) is now returning null :(

public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    SupportMapFragment m = ((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.safety_map));

snippet of xml...

<FrameLayout 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:orientation="vertical" >

     <fragment
         android:id="@+id/safety_map"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:layout_marginBottom="40dp"
         map:cameraTargetLat="@string/livesafe_latitude"
         map:cameraTargetLng="@string/livesafe_longitude"
         map:uiZoomControls="false"
         class="com.google.android.gms.maps.SupportMapFragment"/>

Here are my dependencies in my build.gradle:

 dependencies {
    //google analytics
    compile 'com.google.apis:google-api-services-analytics:v3-rev103-1.19.0'
    //support library for api 10
    compile 'com.android.support:support-v4:21.0.0'
    //google play services
    compile 'com.google.android.gms:play-services:6.1.11'
    compile project(':facebook')
    compile files('libs/android-support-multidex.jar')
    compile files('libs/aws-android-sdk-1.6.0-debug.jar')
    compile files('libs/FlurryAnalytics_3.3.2.jar')
 }

I haven't changed any code in the xml file or the Fragment class that previously worked in Eclipse.

J_Sizzle
  • 600
  • 1
  • 4
  • 12
  • what is lsActivity? Could you try getActivity() instead? – Y2i Oct 27 '14 at 21:55
  • tried with getActivity() instead but no luck.... lsActivity is just used bc all my activities extends a Common and this is just so I don't have to typecast all over the place. lsActivity = (MyActivity) getActivity(); edited my question to avoid that confusion for others – J_Sizzle Oct 27 '14 at 22:08
  • do this sir, just a callback test.. copy that very code and put it in onresume() of your fragment lifeclycle.. if it does not return null, well, it will be a callback lil problem, if it does happen, call it straight from your oncreatview method and get the id from the inflated layout..directly.. hope it helps you.. – Elltz Oct 27 '14 at 22:17
  • OK moving into onResume() results in null as well. Could you be more specific with "get the id from the inflated layout directly"? – J_Sizzle Oct 27 '14 at 22:31

4 Answers4

175

Judging by the fact that you're overriding Fragment.onActivityCreated(), I take it that your layout containing the map fragment is the layout for your Fragment. In that case, the SupportMapFragment is a child fragment of your hosting Fragment. When you attempt to retrieve it, you're using the Activity FragmentManager. You should instead use your Fragment's FragmentManager:

For example, this:

SupportMapFragment m = ((SupportMapFragment) getActivity()
        .getSupportFragmentManager().findFragmentById(R.id.safety_map));

becomes:

SupportMapFragment m = ((SupportMapFragment) getChildFragmentManager()
        .findFragmentById(R.id.safety_map));
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • Is there really such a difference between _Fragment.getActivity().getSupportFragmentManager()_ and _Fragment.getFragmentManager()_ ? From the documentation it seems they should act the same at first glance. – harism Oct 27 '14 at 23:48
  • 3
    The Activity's fragment manager manages the Activity's direct fragments. Each fragment has its own FragmentManager that manages that fragment's child fragments. So, your Activity contains your map-hosting Fragment in the manager. That map-hosting Fragment contains the SupportMapFragment in *its* manager. – Kevin Coppock Oct 27 '14 at 23:52
  • Shouldn't you call then _Fragment.getChildFragmentManager()_ ? Maybe I'm mistaken though. – harism Oct 27 '14 at 23:58
  • 6
    The confusing thing is, from `FragmentActivity` you need to use `getSupportFragmentManager()`. However, from a `Fragment`, `getFragmentManager()` will call through to `getActivity().getSupportFragmentManager()`. To get the `Fragment`'s manager, you should call `getChildFragmentManager()` from a `Fragment`. – Kevin Coppock Oct 28 '14 at 00:04
  • 1
    Thanks for the comments. We have a winner! I put a breakpoint and tried all three... getFragmentManager(), getActivity().getSupportFragmentManager(), and getChildFragmentManager(). The only one that worked was getChildFragmentManager(). I updated to targetSdkVersion 21 maybe that is why what I had prev no longer works. thx :) – J_Sizzle Oct 28 '14 at 00:12
  • @user1732917 Yes the problem occurs when updating to SDK 21. Just had the same issue. Thanks man! – PaperThick Nov 06 '14 at 12:01
  • 4
    OMG! yes, this happened to me too! you made my day Sir! Sorry Stackoverflow, I know I shouldn't be saying thanks in comment, but this is so important!!! – Prachi Nov 13 '14 at 11:50
  • Wow, thanks. I needed this only when I updated to material design (compileSdkVersion 21 in build.gradle), before that it wasn't needed. – aez Dec 06 '14 at 14:04
  • Its working for me..under Fragment and also I did used ViewPager. – Amitabha Biswas Apr 03 '15 at 11:23
  • 1
    What a brilliant explanation. I wondered why this doesn't work for Fragments but Activity! I too tried with Breakpoints and concluded that **getChildFragmentManager()** is the correct implementation since it addresses the **Support Fragment inside Fragment**. saved my day! – sud007 May 05 '15 at 07:22
  • This is brilliant! Never thought something like this existed! Thanks! – Vikram Gupta Dec 08 '15 at 23:35
  • Worked for me. Thanks – Pavan Pyati Jan 15 '17 at 16:29
  • Perfect solution! – Olkunmustafa Apr 06 '18 at 10:56
  • Or if you're using kotlin, just use `childFragmentManager` instead of `getChildFragmentManager()` – imin Apr 11 '21 at 14:44
18

Yes. It's not work for targetSdkVersion 21, if your Map fragment is inner part of Fragment (due to some issues, that mentioned this and this).

As temporary resolving can advice such trick:

public class MyFragment extends Fragment {

    private SupportMapFragment fragment;
    private GoogleMap map;

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

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        FragmentManager fm = getChildFragmentManager();
        fragment = (SupportMapFragment) fm.findFragmentById(R.id.map_container);
        if (fragment == null) {
            fragment = SupportMapFragment.newInstance();
            fm.beginTransaction().replace(R.id.map_container, fragment).commit();
        }
    }
}
cosic
  • 890
  • 12
  • 20
4

The following code worked for me. I was using Google Map in a Fragment:

 SupportMapFragment m = ((SupportMapFragment) getChildFragmentManager() .findFragmentById(R.id.safety_map));
ishmaelMakitla
  • 3,784
  • 3
  • 26
  • 32
T. pac
  • 51
  • 1
4

All the answers are correct in their respective manner. It may happen that you follow someones's java code which is working for them but not work for you because you had different implementation in your xml code than them.

So let me give you my opinion how I managed to load map in both Activity as well as Fragment

Activity:

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

Java class:

MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map); 

In Fragment:

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

Java class:

 SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
Parsania Hardik
  • 4,593
  • 1
  • 33
  • 33
  • getChildFragmentManager doesn't work with SupportMapFragment. It tells me "can't resolve method". – iBEK Nov 07 '17 at 20:22