I am trying to do a tab layout same in Play Store. I got to display the tab layout using a fragments and viewpager from androidhive. However, I can't implement google maps v2 on it. I searched the internet for hours already, but I can't find a tutorial on how to do it. Can some one please show me how?
By using this code we can setup MapView anywhere, inside any ViewPager or Fragment or Activity.
In the latest update of Google for Maps, only MapView is supported for fragments. MapFragment & SupportMapFragment didn't work for me.
Setting up the layout for showing the map in the file location_fragment.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:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Now, we setup the Java class for showing the map in the file MapViewFragment.java
:
public class MapViewFragment extends Fragment {
MapView mMapView;
private GoogleMap googleMap;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.location_fragment, container, false);
mMapView = (MapView) rootView.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.onResume(); // needed to get the map to display immediately
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap mMap) {
googleMap = mMap;
// For showing a move to my location button
googleMap.setMyLocationEnabled(true);
// For dropping a marker at a point on the Map
LatLng sydney = new LatLng(-34, 151);
googleMap.addMarker(new MarkerOptions().position(sydney).title("Marker Title").snippet("Marker Description"));
// For zooming automatically to the location of the marker
CameraPosition cameraPosition = new CameraPosition.Builder().target(sydney).zoom(12).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
});
return rootView;
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
}
Finally you need to get the API Key for your app by registering your app at Google Cloud Console. Register your app as Native Android App.
<uses-library android:name="com.google.android.maps" android:required="true" />
is for Maps V1, not Maps V2. There will be devices in the future that do not have the com.google.android.maps
firmware library but are perfectly capable of showing Maps V2 maps. Having this line in your manifest will prevent you from running on such devices, and this line is not required for Maps V2 use. For example, the 17 projects at github.com/commonsguy/cw-omnibus/tree/master/MapsV2 do not have this <uses-library>
element and work fine. –
Septi "com.google.android.maps"
now the Maps library is in the Google Play Services –
Kamchatka googleMap.setMyLocationEnabled(true);
it's showing me a red line and when i hover over it , it says some permission checks
, as a newbie i don't know what to do? –
Shaquitashara java.lang.NullPointerException: Attempt to invoke interface method 'void com.google.maps.api.android.lib6.impl.bo.o()' on a null object reference
–
Bolick The following approach works for me.
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
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.MarkerOptions;
/**
* A fragment that launches other parts of the demo application.
*/
public class MapFragment extends Fragment {
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_location_info, container,
false);
mMapView = (MapView) v.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();// needed to get the map to display immediately
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
googleMap = mMapView.getMap();
// latitude and longitude
double latitude = 17.385044;
double longitude = 78.486671;
// create marker
MarkerOptions marker = new MarkerOptions().position(
new LatLng(latitude, longitude)).title("Hello Maps");
// Changing marker icon
marker.icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
// adding marker
googleMap.addMarker(marker);
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(new LatLng(17.385044, 78.486671)).zoom(12).build();
googleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
// Perform any camera updates here
return v;
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
}
fragment_location_info.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
java.lang.NullPointerException: IBitmapDescriptorFactory is not initialized
. I thought that the try catch would take care of this. Can someone help me out? –
Uteutensil mMapView
? –
Hardden getMap()
is deprecated. Use getMapAsync and onMapReadyCallback instead: https://mcmap.net/q/161110/-replace-getmap-with-getmapasync –
Wildman googleMap.setMyLocationEnabled(true);
it's showing me a red line and when i hover over it , it says some permission checks
, as a newbie i don't know what to do? –
Shaquitashara You can use this line if you want to use GoogleMap
in a fragment:
<fragment
android:id="@+id/map"
android:layout_width="wrap_content"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
GoogleMap mGoogleMap = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMap();
Latest stuff with getMapAsync
instead of the deprecated one.
1. check manifest for
<meta-data android:name="com.google.android.geo.API_KEY" android:value="xxxxxxxxxxxxxxxxxxxxxxxxx"/>
You can get the API Key for your app by registering your app at Google Cloud Console
. Register your app as Native Android App
2. in your fragment layout .xml add FrameLayout(not fragment):
<FrameLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_weight="2"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="@+id/mapwhere" />
or whatever height you want
3. In onCreateView in your fragment
private SupportMapFragment mSupportMapFragment;
mSupportMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.mapwhere);
if (mSupportMapFragment == null) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
mSupportMapFragment = SupportMapFragment.newInstance();
fragmentTransaction.replace(R.id.mapwhere, mSupportMapFragment).commit();
}
if (mSupportMapFragment != null)
{
mSupportMapFragment.getMapAsync(new OnMapReadyCallback() {
@Override public void onMapReady(GoogleMap googleMap) {
if (googleMap != null) {
googleMap.getUiSettings().setAllGesturesEnabled(true);
-> marker_latlng // MAKE THIS WHATEVER YOU WANT
CameraPosition cameraPosition = new CameraPosition.Builder().target(marker_latlng).zoom(15.0f).build();
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition);
googleMap.moveCamera(cameraUpdate);
}
}
});
<fragment
instead of FrameLayout
–
Jenniejennifer SupportMapFragment
into MapFragment
in the activity, changed the FrameLayout
into fragment
in the layout file and and changed the com.google.android.gms.maps.SupportMapFragment
into com.google.android.gms.maps.MapFragment
it works fine for me. Before these changes it didn't work. Maybe this helps others.... –
Roscoeroscommon here what i did in detail:
From here you can get google map api key
alternative and simple way
first log in to your google account and visit google libraries and select Google Maps Android API
dependency found in android studio default map activity :
compile 'com.google.android.gms:play-services:10.0.1'
put your key into android mainifest file under application like below
in AndroidMainifest.xml make these changes:
// required permission
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
// google map api key put under/inside <application></application>
// android:value="YOUR API KEY"
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzasdfasdf645asd4f847sad5f45asdf7845" />
Fragment code :
public class MainBranchFragment extends Fragment implements OnMapReadyCallback{
private GoogleMap mMap;
public MainBranchFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_main_branch, container, false);
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.main_branch_map);
mapFragment.getMapAsync(this);
return view;
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
LatLng UCA = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(UCA).title("YOUR TITLE")).showInfoWindow();
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(UCA,17));
}
}
in you fragment xml :
<fragment
android:id="@+id/main_branch_map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.googlemap.googlemap.MapsActivity" />
For the issue of getting a NullPointerException
when we change the Tabs in a FragmentTabHost
you just need to add this code to your class which has the TabHost
. I mean the class where you initialize the tabs. This is the code :
/**** Fix for error : Activity has been destroyed, when using Nested tabs
* We are actually detaching this tab fragment from the `ChildFragmentManager`
* so that when this inner tab is viewed back then the fragment is attached again****/
import java.lang.reflect.Field;
@Override
public void onDetach() {
super.onDetach();
try {
Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
childFragmentManager.setAccessible(true);
childFragmentManager.set(this, null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public class DemoFragment extends Fragment {
MapView mapView;
GoogleMap map;
LatLng CENTER = null;
public LocationManager locationManager;
double longitudeDouble;
double latitudeDouble;
String snippet;
String title;
Location location;
String myAddress;
String LocationId;
String CityName;
String imageURL;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater
.inflate(R.layout.fragment_layout, container, false);
mapView = (MapView) view.findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
setMapView();
}
private void setMapView() {
try {
MapsInitializer.initialize(getActivity());
switch (GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getActivity())) {
case ConnectionResult.SUCCESS:
// Toast.makeText(getActivity(), "SUCCESS", Toast.LENGTH_SHORT)
// .show();
// Gets to GoogleMap from the MapView and does initialization
// stuff
if (mapView != null) {
locationManager = ((LocationManager) getActivity()
.getSystemService(Context.LOCATION_SERVICE));
Boolean localBoolean = Boolean.valueOf(locationManager
.isProviderEnabled("network"));
if (localBoolean.booleanValue()) {
CENTER = new LatLng(latitude, longitude);
} else {
}
map = mapView.getMap();
if (map == null) {
Log.d("", "Map Fragment Not Found or no Map in it!!");
}
map.clear();
try {
map.addMarker(new MarkerOptions().position(CENTER)
.title(CityName).snippet(""));
} catch (Exception e) {
e.printStackTrace();
}
map.setIndoorEnabled(true);
map.setMyLocationEnabled(true);
map.moveCamera(CameraUpdateFactory.zoomTo(5));
if (CENTER != null) {
map.animateCamera(
CameraUpdateFactory.newLatLng(CENTER), 1750,
null);
}
// add circle
CircleOptions circle = new CircleOptions();
circle.center(CENTER).fillColor(Color.BLUE).radius(10);
map.addCircle(circle);
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
break;
case ConnectionResult.SERVICE_MISSING:
break;
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
break;
default:
}
} catch (Exception e) {
}
}
in fragment_layout
<com.google.android.gms.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_marginRight="10dp" />
When you add yor map use:
getChildFragmentManager().beginTransaction()
.replace(R.id.menu_map_container, mapFragment, "f" + shabbatIndex).commit();
instead of .add
and instead of getFragmentManager
.
This is the Kotlin way:
In fragment_map.xml
you should have:
<?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.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
In your MapFragment.kt
you should have:
private fun setupMap() {
(childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?)!!.getMapAsync(this)
}
Call setupMap()
in onCreateView
.
According to https://developer.android.com/about/versions/android-4.2.html#NestedFragments, you can use nested fragments to achieve this by calling getChildFragmentManager() if you still want to use the Google Maps fragment instead of the view inside your own fragment:
SupportMapFragment mapFragment = new SupportMapFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.content, mapFragment).commit();
where "content" is the root layout in your fragment (preferably a FrameLayout). The advantage of using a map fragment is that then the map lifecycle is managed automatically by the system.
Although the documentation says "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. ", I have somehow successfully done this and it worked fine. Here is my code:
In the fragment's onCreateView() method:
View view = inflater.inflate(R.layout.layout_maps, container, false);
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(...);
In the layout:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Hope it helps!
i just create MapActivity and inflate it to fragment . MapActivity.java:
package com.example.ahmedsamra.mansouratourguideapp;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_categories);//layout for container
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new MapFragment())
.commit();
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng mansoura = new LatLng(31.037933, 31.381523);
mMap.addMarker(new MarkerOptions().position(mansoura).title("Marker in mansoura"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(mansoura));
}
}
activity_map.xml:
<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:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.ahmedsamra.mansouratourguideapp.MapsActivity" />
MapFragment.java:-
package com.example.ahmedsamra.mansouratourguideapp;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* A simple {@link Fragment} subclass.
*/
public class MapFragment extends Fragment {
public MapFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_maps,container,false);
return rootView;
}
}
I've a workaround for NullPointerException
when remove fragment in on DestoryView
, Just put your code in onStop()
not onDestoryView
. It works fine!
@Override
public void onStop() {
super.onStop();
if (mMap != null) {
MainActivity.fragmentManager.beginTransaction()
.remove(MainActivity.fragmentManager.findFragmentById(R.id.location_map)).commit();
mMap = null;
}
}
Dynamically adding map fragment to view Pager:
If you are targeting an application earlier than API level 12 make an instance of SupportedMapFragment and add it to your view page adapter.
SupportMapFragment supportMapFragment=SupportMapFragment.newInstance();
supportMapFragment.getMapAsync(this);
API level 12 or higher support MapFragment objects
MapFragment mMapFragment=MapFragment.newInstance();
mMapFragment.getMapAsync(this);
© 2022 - 2024 — McMap. All rights reserved.
Activity
andFragment
oncegetChildFragmentManager()
was used. – Jeffersonjeffery