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" />
Related
I have a fragment(fragment_search) in which I want add another fragment(map_fragment) programmatically, but I'm running into an issue, where tab_content.onResume() is called BEFORE OnMapReadyCallback.onMapReady().
Here's the code:
fragment_search.xml :
<LinearLayout...>
<FrameLayout
android:id="#+id/search_map_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
some_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<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">
<com.google.android.gms.maps.MapView android:id="#+id/mapview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:enabled="true"
android:apiKey="api key" />
</LinearLayout>
SearchFragment.class (nothing else in this class really):
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search, container, false);
FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
final SomeFragment fragment = new SomeFragment();
OnMapReadyCallback onMapReadyCallback = new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
fragment.setMap(googleMap);
fragmentTransaction.add(R.id.search_map_fragment_container, fragment);
fragmentTransaction.commit();
}
};
fragment.getMapAsync(onMapReadyCallback);
return view;
}
SomeFragment.class :
public class SomeFragment extends SupportMapFragment {
MapView mapView;
GoogleMap map;
private MapView mMapView;
private GoogleMap mGoogleMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.some_layout, container, false);
mMapView = (MapView) v.findViewById(R.id.mapview);
mMapView.onCreate(savedInstanceState);
return v;
}
public void setMap(GoogleMap map){
this.mGoogleMap=map;
}
...}
Stack trace :
java.lang.NullPointerException: Attempt to invoke interface method 'void maps.ei.bz.o()' on a null object reference
at maps.ei.n.b(Unknown Source)
at com.google.android.gms.maps.internal.i$a.onTransact(:com.google.android.gms.alldynamite:115)
at android.os.Binder.transact(Binder.java:387)
at com.google.android.gms.maps.internal.IMapFragmentDelegate$zza$zza.onResume(Unknown Source)
at com.google.android.gms.maps.SupportMapFragment$zza.onResume(Unknown Source)
at com.google.android.gms.dynamic.zza$7.zzb(Unknown Source)
at com.google.android.gms.dynamic.zza.zza(Unknown Source)
at com.google.android.gms.dynamic.zza.onResume(Unknown Source)
at com.google.android.gms.maps.SupportMapFragment.onResume(Unknown Source)
at com.beermeet.ui.search.SearchFragment.onResume(SearchFragment.java:5
7)
I think the SearchFragment.onCreateView is wrong, but i don't know what is the correct way of doing it.
Any hints as to what i'm doing wrong? Thanks!
When you launch SearchFragment, it will apparently call its onResume() method as a part of the fragment lifecycle.
Your logs say there is a NullPointerException in onResume() . You should check for that.
And regarding your question,
fragment.getMapAsync(onMapReadyCallback);
onResume() will be invoked before you get onMapReadyCallback because getMapAsync() is async call and will run in a different thread which will not block UI thread and hence onResume() will get invoked before you get onMapReadyCallback
I having trouble implementing Google Map in Fragment.
This is my the part of my fragment class:
public class FragmentStoreFinderMap extends Fragment implements OnMapReadyCallback {
// Google Map
private GoogleMap googleMap;
private int i;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
googleMap = ((SupportMapFragment)getActivity().getSupportFragmentManager().findFragmentById(
R.id.map)).getMapAsync(this);
I am getting an error in getMapAsync(this). I tells Incompatible type.
it says:
required: com.google.android.gms.map.GoogleMap
found: void
BTW here is my xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
In your XML layout you should do like this
<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">
<com.google.android.gms.maps.MapView
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
inside your fragment implement this
private MapView mapView;
private GoogleMap googleMap;
override onCreateView if there is no onCreateView just like the code below
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.your_layout, container, false);
}
override onViewCreated() inside that
onViewCreated() put this
mapView = (MapView) view.findViewById(R.id.map);
mapView.onCreate(savedInstanceState);
mapView.onResume();
mapView.getMapAsync(this);//when you already implement OnMapReadyCallback in your fragment
when you already implement OnMapReadyCallback in your fragment put this/code like this
#Override
public void onMapReady(GoogleMap map) {
googleMap = map;
}
hope this helps you.
After a few overheats in my head, thanks to this post and https://stackoverflow.com/a/34732804/3925554, I would say that currently there are two ways of adding a MapFragment to your app:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
By this way, you have to use a standard fragment and implement this inside. Actually you are inserting a fragment into another:
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
SupportMapFragment supportMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
supportMapFragment.getMapAsync(this);
}
The other way would be extending the real SupportMapFragment and implement it in this manner without the need of an xml:
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getMapAsync(this);
}
And they work without having to set a layout in onCreateView neither call mapView.onCreate(savedInstanceState); and mapView.onResume(); manually inside onViewCreated(), what is not recommended anyway.
Hope it helps!
SupportMapFragment mMapFragment = SupportMapFragment.newInstance();
FragmentTransaction fragmentTransaction =
getChildFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.flMap, mMapFragment);
fragmentTransaction.commit();
mMapFragment.getMapAsync(this);
Your code is returning this error because getMapAsync() does not return anything. If you look at the documentation for this function:
public void getMapAsync (OnMapReadyCallback callback)
Sets a callback object which will be triggered when the GoogleMap
instance is ready to be used.
Note that:
This method must be called from the main thread. The callback will be
executed in the main thread. In the case where Google Play services is
not installed on the user's device, the callback will not be triggered
until the user installs it. In the rare case where the GoogleMap is
destroyed immediately after creation, the callback is not triggered.
The GoogleMap object provided by the callback is non-null.
OnMapReadyCallback is an interface that needs implemented and passed to through this function. Nothing is currently assigned to your googleMap variable you should instead set its value in this block of code which implements OnMapReadyCallback
#Override
public void onMapReady(GoogleMap googleMap) {
this.googleMap = googleMap;
}
This code should be in your Fragment somewhere. Since your Fragment already implements this interface you do pass it in as this.
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 have an activity that hosts two fragments. One fragment provides some info to the user in various fields. The other fragment should show a Map.
For the fragment hosting the map I need to be able to add custom logic for displaying markers and several other things that I would like to reuse in other places in the app. What is the best way to create a map without defining the fragment in xml like:
<fragment
class="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Thanks,
Nathan
Edit:
I am now using nested fragments, not sure if that is the best way to handle this? My mapfragment is now:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />
</LinearLayout>
and the Fragments code is:
public class ViewCurrentMapFragment extends Fragment implements View.OnClickListener {
public static final String TAG = "MAP_FRAGMENT";
private GoogleMap map;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_view_current_map, container, false);
return rootView;
}
private void getCurrentMarkers() {
// Getting reference to the SupportMapFragment of activity_main.xml
SupportMapFragment smf = ((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map));
map = smf.getMap();
}
#Override
public void onClick(View v) {
}
#Override
public void onResume() {
super.onResume();
getCurrentMarkers();
}
}
The problem I am having now is that smf.getMap() is returning null. Any ideas?
Edit2:
Got it to work by changing:
com.google.android.gms.maps.MapFragment
to
com.google.android.gms.maps.SupportMapFragment
Maybe:
<fragment
class="com.mycompany.MyCustomFragmentExtendingMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
or nest fragments like here: http://code.google.com/p/gmaps-api-issues/issues/detail?id=5064#c1
I get an android.inflate.Exception when inflate this .xml:
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="***"
/>
This class inflate the .xml (fragment_b.xml)
public class BFragment extends Fragment {
private MapView mMapView;
private GoogleMap googleMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflat and return the layout
View v = inflater.inflate(R.layout.fragment_b, container, false);
mMapView = (MapView) v.findViewById(R.id.map);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();//needed to get the map to display immediately
try {
MapsInitializer.initialize(this.getActivity());
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
googleMap = mMapView.getMap();
return v;
}
}
I have try a lot of thing with the .xml without results.
Aren't you mixing map api V1 and map api V2 implementations?
This is map v1:
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="***"
/>
This is how map api V2 would look like:
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
Since in your XML you have created an instance of map_v1, you are not allowed to invoke onCreate() and onResume() - you have to do that for map_v2 though.
Also you should remember that in map_v2 you must call onCreate(), onResume() only when appropriate event happens in your activity/fragment lifecycle... So you must call those only from your activity/fragment onCreate and onResume