I am trying to get a Google Map inside of a Fragment, but I'm getting a NullPointerException. I have read other answers for similar questions but they haven't helped me.
HomeFragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
SupportMapFragment mapFragment = (SupportMapFragment) getFragmentManager()
.findFragmentById(R.id.ftMap);
mapFragment.getMapAsync(this);
return view;
}
fragment_home.xml:
<fragment
android:id="#+id/ftMap"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_centerInParent="true"
android:layout_margin="8dp" />
Since you are using a SupportMapFragment nested inside of an outer Fragment, you need to use getChildFragmentManager() instead of getFragmentManager():
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager()
.findFragmentById(R.id.ftMap);
Related
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.
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));
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();
}
}
}
The following code worked for me. I was using Google Map in a Fragment:
SupportMapFragment m = ((SupportMapFragment) getChildFragmentManager() .findFragmentById(R.id.safety_map));
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);
I have a problem with Google Maps, i.e. getSupportFragmentManager().findFragmentById returns always null. Do you have an idea how to solve this?
Here is the code:
fragment_map.xml:
<FrameLayout 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="com.myapp.something.MapFragment">
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
</FrameLayout>
MapsFragment.java:
public class MapFragment extends Fragment implements OnMapReadyCallback, android.location.LocationListener
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
SupportMapFragment mapFragment = (SupportMapFragment) this.getActivity().getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
...
I have Google Maps in Activity and it works with code:
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
I am trying to reuse this in fragment, becouse I need maps in fragment, not in activity, but it doesn't work.
I tried:
calling this code in "onCreateView" function
SupportMapFragment mapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.map);
GoogleMap mGoogleMap = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMap(); is deprecated, and application crashes
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
and similar variations, but in all cases I get null for mapFragment.
Do you know how could I solve this problem?
The problem is that you're trying to use the Activity's FragmentManager, and you should be using the Fragment's child FragmentManager.
Remove the onCreate() override in the Fragment, and add an onCreateView() Override where you inflate the layout and call getMapAsync():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_map, container, false);
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
return rootView;
}
I am developing an app that use fragments. One of my fragments i want to use google map but i am getting errors.
public class Map extends Fragment {
public Map() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
GoogleMap map = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
//Error:(38, 84) error: inconvertible types
//required: SupportMapFragment
//found: Fragment
return inflater.inflate(R.layout.fragment_map, container, false);
}
}
When i trying to cast map fragment i am getting the error in comment. What should i do to solve this? Thanks for everyone.
Edit: the layout ;
<fragment
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment" />
You can go through this approach.This is my Fragment class which has MapView
public class DashBoardFragment extends Fragment{
//-------------- class variables
private MapView mMapView;
private GoogleMap mGoogleMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.fragment_dash_board, container, false);
mMapView = (MapView) view.findViewById(R.id.map_dashBoard);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
mGoogleMap = mMapView.getMap();
}
}
Below is my xml for the fragment
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.dev.abc">
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map_dashBoard"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
Manifest should have the following along with permissions
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="your api key" />
You are casting to a mapFragment AFTER the return statement. Since the program believes the method is complete at that point it never reaches it. Try this:
Inflater v = inflater.inflate(R.layout.fragment_map, container, false);
GoogleMap map = ((SupportMapFragment)v.getFragmentManager().findFragmentById(R.id.map)).getMap();
return v;
Also I don't see you using an intent to start the google map activity.
Latest update of Google for Maps, only MapView is supported for fragments.
<com.google.android.gms.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I`m developing an application that uses an activity with navigation drawer. I have two fragments in the drawer one of which is a google map.
In the map fragment class I want to initialize the GoogleMap object to do some things to the map, but in the onCreateView after I initialize the view through inflater, my app doesn't find the id in R class to initialize the google map.
I call the fragment from the activity through:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.mainContent, map, Map.class.getSimpleName());
fragmentTransaction.addToBackStack(Map.class.getSimpleName());
fragmentTransaction.commit();
the container xml:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/mainContent"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<ListView
android:id="#+id/drawerList"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/background_color" >
</ListView>
</android.support.v4.widget.DrawerLayout>
layout_fragment_map.xml:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
The Map fragment class:
public class Map extends Fragment {
private View view;
private MapFragment mapFragment;
private GoogleMap googleMap;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null)
parent.removeView(view);
}
try {
view = inflater.inflate(R.layout.layout_fragment_map, container, false);
} catch (InflateException e) {
/* map is already there, just return view as it is */
}
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
googleMap = mapFragment.getMap();
return view;
}
In the line:
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
the R.id.map is undefined Eclipse gives "could not resolve type".
Something is missing or my whole concept is faulty?
Thank you and happy coding!
I resolved the issue by modifying the line:
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.googleMap);
with
mapFragment = (MapFragment) getChildFragmentManager().findFragmentById(R.id.googleMap);
It is strange because the R.id.googleMap is still undefined but the object gets created correctly.
I'm trying to load a map with com.google.android.gms.maps.SupportMapFragment, but I get null in findFragmentById.
My xml fragment file:
<fragment
android:id="#+id/map"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
class="com.google.android.gms.maps.SupportMapFragment" />
MainActivity.java:
public class MainActivity extends ActionBarActivity{
private void selectItem(int position){
//some code
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, new MyMapFragment).commit();
}
}
MapFragment:
MyMapFragment extends android.support.v4.app.Fragment{
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
SupportMapFragment smf = (SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map);
//here smf is null
}
}
This is the answer:
Note: You cannot inflate a layout into a fragment when that layout includes a fragment. Nested fragments are only supported when added to a fragment dynamically.
And furthermore when playing with nested fragments, use getChildFragmentManager().