I\'m trying to show the map from the Google Maps API V2 in fragment. I tried with the SupportMapFragment, but I can\'t get the expected output. Also I\'m a beginner on this
Here is my code.
Create project in google map concole and generate api key.
and then add dependency to build.gradle(app level).
compile 'com.google.android.gms:play-services-maps:10.2.1'
compile 'com.google.android.gms:play-services-location:10.2.1'
compile 'com.google.android.gms:play-services-places:10.2.1'
remember to add permissions in Android.manifest
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-feature android:name="android.hardware.location.gps" android:required="true"/>
create activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MergeRootFrame">
<fragment
class="com.googlelocationmapdemo.FragmentLocation"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
nothing to call from MainActivity.class
Create fragment_location.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearMap"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
class="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Create FragmentLocation.class
public class FragmentLocation extends Fragment implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
public static final String TAG = FragmentLocation.class.getSimpleName();
public static final int REQUEST_CODE_FOR_PERMISSIONS = 1;
GoogleApiClient mGoogleApiClient;
LatLng mLatLng;
GoogleMap mGoogleMap;
Marker mCurrLocationMarker;
private LinearLayout linearMap;
Location mLastLocation;
LocationManager locationManager;
boolean statusOfGPS;
private Dialog mDialogGPS;
View view;
LocationRequest mLocationRequest;
SupportMapFragment mFragment;
FragmentManager fragmentManager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view=inflater.inflate(R.layout.fragment_location,container,false);
fragmentManager=getChildFragmentManager();
mFragment = (SupportMapFragment)fragmentManager.findFragmentById(R.id.map);
mFragment.getMapAsync(this);
if (!isGooglePlayServicesAvailable()) {
Toast.makeText(getActivity(), "play services not available", Toast.LENGTH_SHORT).show();
}
locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
statusOfGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
return view;
}
@Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000); //5 seconds
mLocationRequest.setFastestInterval(2000); //3 seconds
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
mLatLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(mLatLng);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(mLatLng));
// Zoom in the Google Map
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(15));
}
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (getActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED &&
getActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mGoogleMap.setMyLocationEnabled(true);
} else {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION
, Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_FOR_PERMISSIONS);
}
} else {
buildGoogleApiClient();
mGoogleMap.setMyLocationEnabled(true);
}
//show dialog when click on location top-right side located on map.
mGoogleMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
@Override
public boolean onMyLocationButtonClick() {
statusOfGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!statusOfGPS) {
turnOnGps();
} else {
getCurrentLocation(mLastLocation);
}
return false;
}
});
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity());
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, getActivity(), 0).show();
return false;
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE_FOR_PERMISSIONS:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (getActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED &&
getActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mGoogleMap.setMyLocationEnabled(true);
}
} else {
if (!(shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_COARSE_LOCATION)) && (!(shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)))) {
Snackbar snackbar = Snackbar.make(linearMap, "Never asked"
, Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("Allow", new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
});
snackbar.show();
}
}
break;
}
}
private void getCurrentLocation(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
if (locationManager != null) {
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLastLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);//getting last location
}
if (mLastLocation != null) {
if (mGoogleMap != null) {
Log.d("activity", "LOC by Network");
mLatLng = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(mLatLng);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(mLatLng));
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(15));
}
}
}
}
private void turnOnGps() {
if (mGoogleMap != null) {
mGoogleMap.clear();
}
statusOfGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);//getting status of gps whether gps is on or off.
mDialogGPS = new Dialog(getActivity(), R.style.MyDialogTheme);
mDialogGPS.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialogGPS.setContentView(R.layout.dialog_turnongps);
TextView txtCancel = (TextView) mDialogGPS.findViewById(R.id.txtCancel);
TextView txtOK = (TextView) mDialogGPS.findViewById(R.id.txtSetting);
ImageView imgLocation = (ImageView) mDialogGPS.findViewById(R.id.imgLocation);
imgLocation.setImageResource(R.drawable.ic_location_my);
txtCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mDialogGPS.dismiss();
//finish();
if (!statusOfGPS) {
getCurrentLocationByDefault();
} else {
getCurrentLocation(mLastLocation);
}
}
});
txtOK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//It is use to redirect to setting->location to turn on gps when press ok.
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
mDialogGPS.dismiss();
if (!statusOfGPS) {
getCurrentLocationByDefault();
} else {
getCurrentLocation(mLastLocation);
}
}
});
mDialogGPS.show();
}
private void getCurrentLocationByDefault() {
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
if (mGoogleMap != null) {
LatLng xFrom1 = new LatLng(0.0, 0.0);
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(xFrom1, (float) 0.0));
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(xFrom1);
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_taxi));
mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);
} else {
Log.i("MainActivity", "getCurrentLocationByDefault else");
}
}
@Override
public void onResume() {
super.onResume();
statusOfGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (mDialogGPS != null) {
if (mDialogGPS.isShowing()) {
mDialogGPS.dismiss();
}
}
if (!statusOfGPS) {
turnOnGps();
} else {
getCurrentLocation(mLastLocation);
}
}
protected synchronized void buildGoogleApiClient() {
if (mGoogleApiClient != null) {
mGoogleApiClient = null;
}
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
}
create dailog_gps.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/txtPhoneNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Use Location?"
android:textColor="@android:color/black"
android:textSize="16sp"
/>
</LinearLayout>
<LinearLayout
android:layout_marginTop="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="This app wants to change your \ndevice settings:"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:layout_marginTop="10dp"
android:weightSum="2"
android:gravity="center"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imgLocation"
android:layout_weight="1"
android:layout_gravity="top"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Use GPS, Wi-Fi and mobile \nnetwork for location"
android:layout_marginLeft="20dp"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:orientation="horizontal"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/txtCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NO"
android:layout_marginRight="30dp"
android:textSize="16sp" />
<TextView
android:id="@+id/txtSetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="YES"
android:layout_marginRight="30dp"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
Hope this will help you :-)
SupportMapFragment
instead of MapFragment
and use getActivity()
This is a basic example using SupportMapFragment:
public class MainActivity extends ActionBarActivity implements OnMapReadyCallback{
private SupportMapFragment map;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
map = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
map.getMapAsync(this);//remember getMap() is deprecated!
}
@Override
public void onMapReady(GoogleMap map) {
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(47.17, 27.5699), 16));
map.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher))
.anchor(0.0f, 1.0f) // Anchors the marker on the bottom left
.position(new LatLng(47.17, 27.5699))); //Iasi, Romania
map.setMyLocationEnabled(true);
}
}
and change the reference in your layout:
<fragment
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
For all those friends who are facing the problem:-
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.GoogleMap com.google.android.gms.maps.SupportMapFragment.getMap()
Please try integrate GoogleMap using code
FragmentManager fm = getChildFragmentManager();
googleMap = ((SupportMapFragment)fm.findFragmentById(R.id.googleMap)).getMap();
Using MapView within Fragment under Google Maps Android API v2.0
public class MapFragment extends Fragment {
MapView m;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflat and return the layout
View v = inflater.inflate(R.layout.map_fragment, container, false);
m = (MapView) v.findViewById(R.id.mapView);
m.onCreate(savedInstanceState);
return v;
}
@Override
public void onResume() {
super.onResume();
m.onResume();
}
@Override
public void onPause() {
super.onPause();
m.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
m.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
m.onLowMemory();
}
}
http://ucla.jamesyxu.com/?p=287
This example was build from the auto generated code from android studio, you dont need to change nothing in maps activity, only the context in the layout file to match your maps Activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1">
<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="300dp"
tools:context="com.gearwell.app.gpsmaps02.Gpsenmapa"
/>
<LinearLayout
android:id="@+id/layButtonH"
android:layout_height="150dp"
android:layout_marginTop="50dp"
android:layout_width="fill_parent"
android:gravity="center"
android:layout_weight="0.15">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Obtener Ubicacion"
android:id="@+id/btnLocation"
android:onClick="onClick"/>
</LinearLayout>
</LinearLayout>
Update 10/24/2014 This is all wrong. You shouldn't have a fragment in a fragment. Rather you should extend the SupportMapFragment. See this stackoverflow post for some details: https://stackoverflow.com/a/19815266/568197
here is my onDestroyView()
public void onDestroyView() {
super.onDestroyView();
if (mMap != null) {
getFragmentManager()
.beginTransaction()
.remove(getFragmentManager().findFragmentById(R.id.map))
.commit();
}
}