Java tutorial
/* * Copyright (C) 2011-2014 Paul Watts (paulcwatts@gmail.com), * University of South Florida (sjbarbeau@gmail.com), and individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onebusaway.android.map.googlemapsv2; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.LocationSource; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.UiSettings; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; import com.google.android.gms.maps.model.VisibleRegion; import org.onebusaway.android.R; import org.onebusaway.android.app.Application; import org.onebusaway.android.io.elements.ObaReferences; import org.onebusaway.android.io.elements.ObaRegion; import org.onebusaway.android.io.elements.ObaRoute; import org.onebusaway.android.io.elements.ObaShape; import org.onebusaway.android.io.elements.ObaStop; import org.onebusaway.android.io.request.ObaResponse; import org.onebusaway.android.io.request.ObaTripsForRouteResponse; import org.onebusaway.android.map.MapModeController; import org.onebusaway.android.map.MapParams; import org.onebusaway.android.map.RouteMapController; import org.onebusaway.android.map.StopMapController; import org.onebusaway.android.region.ObaRegionsTask; import org.onebusaway.android.util.LocationHelper; import org.onebusaway.android.util.LocationUtils; import org.onebusaway.android.util.UIUtils; import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.graphics.drawable.Drawable; import android.location.Location; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.concurrent.TimeUnit; /** * The MapFragment class is split into two basic modes: * stop mode and route mode. It needs to be able to switch * between the two. * <p/> * So this class handles the common functionality between * the two modes: zooming, the options menu, * saving/restoring state, and other minor bookkeeping * (the stop user map). * <p/> * Everything else is handed off to a specific * MapFragmentController instance. * * @author paulw, barbeau */ public class BaseMapFragment extends SupportMapFragment implements MapModeController.Callback, ObaRegionsTask.Callback, MapModeController.ObaMapView, LocationSource, LocationHelper.Listener, com.google.android.gms.maps.GoogleMap.OnCameraChangeListener, StopOverlay.OnFocusChangedListener, OnMapReadyCallback { public static final String TAG = "BaseMapFragment"; private static final int REQUEST_NO_LOCATION = 41; // // Location Services and Maps API v2 constants // private static final int CAMERA_MOVE_NOTIFY_THRESHOLD_MS = 500; public static final float CAMERA_DEFAULT_ZOOM = 16.0f; public static final float DEFAULT_MAP_PADDING_DP = 20.0f; // Keep track of current map padding private int mMapPaddingLeft = 0; private int mMapPaddingTop = 0; private int mMapPaddingRight = 0; private int mMapPaddingBottom = 0; // Use fully-qualified class name to avoid import statement, because it interferes with scripted // copying of Maps API v2 classes between Google/Amazon build flavors (see #254) private com.google.android.gms.maps.GoogleMap mMap; private UIUtils.StopUserInfoMap mStopUserMap; private String mFocusStopId; private ObaStop mFocusStop; private HashMap<String, ObaRoute> mFocusStopRoutes; // The Fragment controls the stop overlay, since that // is used by both modes. private StopOverlay mStopOverlay; private VehicleOverlay mVehicleOverlay; // We only display the out of range dialog once private boolean mWarnOutOfRange = true; private boolean mRunning = false; private MapModeController mController; private ArrayList<Polyline> mLineOverlay = new ArrayList<Polyline>(); // Markers that are added to the map by classes external to this map package private SimpleMarkerOverlay mSimpleMarkerOverlay; // We have to convert from LatLng to Location, so hold references to both private LatLng mCenter; private Location mCenterLocation; private OnLocationChangedListener mListener; // Listen to map tap events OnFocusChangedListener mOnFocusChangedListener; LocationHelper mLocationHelper; Bundle mLastSavedInstanceState; public interface OnFocusChangedListener { /** * Called when a stop on the map is clicked (i.e., tapped), which sets focus to a stop, * or when the user taps on an area away from the map for the first time after a stop * is already selected, which removes focus * * @param stop the ObaStop that obtained focus, or null if no stop is in focus * @param routes a HashMap of all route display names that serve this stop - key is * routeId * @param location the user touch location on the map */ void onFocusChanged(ObaStop stop, HashMap<String, ObaRoute> routes, Location location); } public static BaseMapFragment newInstance() { return new BaseMapFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = super.onCreateView(inflater, container, savedInstanceState); mMap = getMap(); if (MapHelpV2.isMapsInstalled(getActivity())) { if (mMap != null) { initMap(savedInstanceState); } else { // Save the savedInstanceState mLastSavedInstanceState = savedInstanceState; // Register for an async callback when the map is ready getMapAsync(this); } } else { MapHelpV2.promptUserInstallMaps(getActivity()); } mLocationHelper = new LocationHelper(getActivity()); mLocationHelper.registerListener(this); // If we have a recent location, show this while we're waiting on the LocationHelper Location l = Application.getLastKnownLocation(getActivity(), mLocationHelper.getGoogleApiClient()); if (l != null) { final long TIME_THRESHOLD = TimeUnit.MINUTES.toMillis(5); if (System.currentTimeMillis() - l.getTime() < TIME_THRESHOLD) { onLocationChanged(l); } } return v; } @Override public void onMapReady(com.google.android.gms.maps.GoogleMap map) { initMap(mLastSavedInstanceState); } private void initMap(Bundle savedInstanceState) { UiSettings uiSettings = mMap.getUiSettings(); // Show the location on the map mMap.setMyLocationEnabled(true); // Set location source mMap.setLocationSource(this); // Listener for camera changes mMap.setOnCameraChangeListener(this); // Hide MyLocation button on map, since we have our own button uiSettings.setMyLocationButtonEnabled(false); // Hide Zoom controls uiSettings.setZoomControlsEnabled(false); // Hide Toolbar uiSettings.setMapToolbarEnabled(false); // Instantiate class that holds generic markers to be added by outside classes mSimpleMarkerOverlay = new SimpleMarkerOverlay(mMap); if (savedInstanceState != null) { initMapState(savedInstanceState); } else { Bundle args = getActivity().getIntent().getExtras(); // The rest of this code assumes a bundle exists, // even if it's empty if (args == null) { args = new Bundle(); } initMapState(args); } } private void initMapState(Bundle args) { mFocusStopId = args.getString(MapParams.STOP_ID); mMapPaddingLeft = args.getInt(MapParams.MAP_PADDING_LEFT, MapParams.DEFAULT_MAP_PADDING); mMapPaddingTop = args.getInt(MapParams.MAP_PADDING_TOP, MapParams.DEFAULT_MAP_PADDING); mMapPaddingRight = args.getInt(MapParams.MAP_PADDING_RIGHT, MapParams.DEFAULT_MAP_PADDING); mMapPaddingBottom = args.getInt(MapParams.MAP_PADDING_BOTTOM, MapParams.DEFAULT_MAP_PADDING); setPadding(mMapPaddingLeft, mMapPaddingTop, mMapPaddingRight, mMapPaddingBottom); String mode = args.getString(MapParams.MODE); if (mode == null) { mode = MapParams.MODE_STOP; } setMapMode(mode, args); } @Override public void onDestroy() { if (mController != null) { mController.destroy(); } super.onDestroy(); } @Override public void onPause() { mLocationHelper.onPause(); if (mController != null) { mController.onPause(); } mRunning = false; super.onPause(); } /** * This is called when fm.beginTransaction().hide() or fm.beginTransaction().show() is called * * @param hidden True if the fragment is now hidden, false if it is not visible. */ @Override public void onHiddenChanged(boolean hidden) { if (mController != null) { mController.onHidden(hidden); } super.onHiddenChanged(hidden); } @Override public void onResume() { mLocationHelper.onResume(); mRunning = true; if (mController != null) { mController.onResume(); } super.onResume(); } @Override public void onSaveInstanceState(Bundle outState) { if (mController != null) { mController.onSaveInstanceState(outState); } outState.putString(MapParams.MODE, getMapMode()); outState.putString(MapParams.STOP_ID, mFocusStopId); Location center = getMapCenterAsLocation(); if (mMap != null) { outState.putDouble(MapParams.CENTER_LAT, center.getLatitude()); outState.putDouble(MapParams.CENTER_LON, center.getLongitude()); outState.putFloat(MapParams.ZOOM, getZoomLevelAsFloat()); } outState.putInt(MapParams.MAP_PADDING_LEFT, mMapPaddingLeft); outState.putInt(MapParams.MAP_PADDING_TOP, mMapPaddingTop); outState.putInt(MapParams.MAP_PADDING_RIGHT, mMapPaddingRight); outState.putInt(MapParams.MAP_PADDING_BOTTOM, mMapPaddingBottom); } public boolean isRouteDisplayed() { return (mController != null) && MapParams.MODE_ROUTE.equals(mController.getMode()); } public void setupStopOverlay() { if (mStopOverlay == null) { mStopOverlay = new StopOverlay(getActivity(), mMap); mStopOverlay.setOnFocusChangeListener(this); } } public void setupVehicleOverlay() { Activity a = getActivity(); if (mVehicleOverlay == null && a != null) { mVehicleOverlay = new VehicleOverlay(a, mMap); } } protected void showDialog(int id) { MapDialogFragment.newInstance(id, this).show(getFragmentManager(), MapDialogFragment.TAG); } // @Override // public void onActivityResult(int requestCode, int resultCode, Intent data) { // super.onActivityResult(requestCode, resultCode, data); // switch (requestCode) { // case REQUEST_NO_LOCATION: // // Clear the map center so we can get the user's location again // setMyLocation(); // break; // } // } // // Fragment Controller // @Override public String getMapMode() { if (mController != null) { return mController.getMode(); } return null; } @Override public void setMapMode(String mode, Bundle args) { String oldMode = getMapMode(); if (oldMode != null && oldMode.equals(mode)) { mController.setState(args); return; } if (mController != null) { mController.destroy(); } if (mStopOverlay != null) { mStopOverlay.clear(false); } if (MapParams.MODE_ROUTE.equals(mode)) { mController = new RouteMapController(this); } else if (MapParams.MODE_STOP.equals(mode)) { mController = new StopMapController(this); } mController.setState(args); mController.onResume(); } @Override public MapModeController.ObaMapView getMapView() { // We implement the ObaMapView interface too (since we're using MapFragment) return this; } /** * Adds a generic marker to the map and returns the ID associated with that marker, which can * be used to remove the marker via removeMarker() * * @param location Location at which the marker should be added * @return the ID associated with the marker that was just added */ @Override public int addMarker(Location location) { return mSimpleMarkerOverlay.addMarker(location); } /** * Removes the marker from the map that has the given ID, which was previously generated by * addMarker() in this class * * @param markerId the ID for the marker that should be removed from the map */ @Override public void removeMarker(int markerId) { mSimpleMarkerOverlay.removeMarker(markerId); } /** * Define a visible region on the map, to signal to the map that portions of the map around * the edges may be obscured, by setting padding on each of the four edges of the map. * * @param left the number of pixels of padding to be added on the left of the map, or null * if the existing padding should be used * @param top the number of pixels of padding to be added on the top of the map, or null * if the existing padding should be used * @param right the number of pixels of padding to be added on the right of the map, or null * if the existing padding should be used * @param bottom the number of pixels of padding to be added on the bottom of the map, or null * if the existing padding should be used */ @Override public void setPadding(Integer left, Integer top, Integer right, Integer bottom) { if (left != null) { mMapPaddingLeft = left; } if (top != null) { mMapPaddingTop = top; } if (right != null) { mMapPaddingRight = right; } if (bottom != null) { mMapPaddingBottom = bottom; } if (mMap != null) { mMap.setPadding(mMapPaddingLeft, mMapPaddingTop, mMapPaddingRight, mMapPaddingBottom); } } @Override public void showProgress(boolean show) { // setSupportProgressBarIndeterminateVisibility(show); } @Override public void showStops(List<ObaStop> stops, ObaReferences refs) { // Make sure that the stop overlay has been initialized setupStopOverlay(); if (stops != null) { mStopOverlay.populateStops(stops, refs); } } @Override public void notifyOutOfRange() { //Before we trigger the out of range warning, make sure we have region info //or have a API URL that was custom set by the user in via Preferences //Otherwise, its premature since we don't know the device's relationship to //available OBA regions or the manually set API region String serverName = Application.get().getCustomApiUrl(); if (mWarnOutOfRange && (Application.get().getCurrentRegion() != null || !TextUtils.isEmpty(serverName))) { if (mRunning && UIUtils.canManageDialog(getActivity())) { showDialog(MapDialogFragment.OUTOFRANGE_DIALOG); } } } // // Region Task Callback // @Override public void onRegionTaskFinished(boolean currentRegionChanged) { if (currentRegionChanged && Application.getLastKnownLocation(this.getActivity(), mLocationHelper.getGoogleApiClient()) == null) { // Move map view after a new region has been selected, if we don't have user location zoomToRegion(); } // If region changed and was auto-selected, show user what region we're using if (currentRegionChanged && Application.getPrefs().getBoolean(getString(R.string.preference_key_auto_select_region), true) && Application.get().getCurrentRegion() != null && mRunning && UIUtils.canManageDialog(getActivity())) { Toast.makeText(getActivity(), getString(R.string.region_region_found, Application.get().getCurrentRegion().getName()), Toast.LENGTH_LONG).show(); } } public void setOnFocusChangeListener(OnFocusChangedListener onFocusChangedListener) { mOnFocusChangedListener = onFocusChangedListener; } // // Stop changed handler // final Handler mStopChangedHandler = new Handler(); public void onFocusChanged(final ObaStop stop, final HashMap<String, ObaRoute> routes, final Location location) { // Run in a separate thread, to avoid blocking UI for long running events mStopChangedHandler.post(new Runnable() { public void run() { if (stop != null) { mFocusStop = stop; mFocusStopId = stop.getId(); mFocusStopRoutes = routes; //Log.d(TAG, "Focused changed to " + stop.getName()); } else { //Log.d(TAG, "Removed focus"); } // Pass overlay focus event up to listeners for this fragment mOnFocusChangedListener.onFocusChanged(stop, routes, location); } }); } @Override @SuppressWarnings("deprecation") public void setMyLocation(boolean useDefaultZoom, boolean animateToLocation) { if (!LocationUtils.isLocationEnabled(getActivity()) && mRunning && UIUtils.canManageDialog(getActivity())) { showDialog(MapDialogFragment.NOLOCATION_DIALOG); return; } Location lastLocation = Application.getLastKnownLocation(this.getActivity(), null); if (lastLocation == null) { Toast.makeText(getActivity(), getResources().getString(R.string.main_waiting_for_location), Toast.LENGTH_SHORT).show(); return; } setMyLocation(lastLocation, useDefaultZoom, animateToLocation); } private void setMyLocation(Location l, boolean useDefaultZoom, boolean animateToLocation) { if (mMap != null) { // Move camera to current location CameraPosition.Builder cameraPosition = new CameraPosition.Builder().target(MapHelpV2.makeLatLng(l)); if (useDefaultZoom) { // Use default zoom level cameraPosition.zoom(CAMERA_DEFAULT_ZOOM); } else { // Use current zoom level cameraPosition.zoom(mMap.getCameraPosition().zoom); } if (animateToLocation) { // Smooth animation to position mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition.build())); } else { // Abrupt change to position mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition.build())); } } if (mController != null) { mController.onLocation(); } } void zoomToRegion() { // If we have a region, then zoom to it. ObaRegion region = Application.get().getCurrentRegion(); if (region != null && mMap != null) { LatLngBounds b = MapHelpV2.getRegionBounds(region); int padding = 0; mMap.animateCamera((CameraUpdateFactory.newLatLngBounds(b, padding))); } } // // Error handlers // public static void showMapError(Context context, ObaResponse response) { Toast.makeText(context, context.getString(UIUtils.getMapErrorString(context, response.getCode())), Toast.LENGTH_LONG).show(); } // // MapView interactions // @Override public void setZoom(float zoomLevel) { if (mMap != null) { mMap.moveCamera(CameraUpdateFactory.zoomTo(zoomLevel)); } } @Override public Location getMapCenterAsLocation() { // If the center is the same as the last call to this method, pass back the same Location // object if (mMap != null) { LatLng center = mMap.getCameraPosition().target; if (mCenter == null || mCenter != center) { mCenter = center; mCenterLocation = MapHelpV2.makeLocation(mCenter); } } return mCenterLocation; } /** * Sets the map center to the given parameter * * @param location location to center on * @param animateToLocation true if the map should animate to the location, false if it should * snap to it * @param overlayExpanded true if the sliding panel is expanded, false if it is not */ @Override public void setMapCenter(Location location, boolean animateToLocation, boolean overlayExpanded) { if (mMap != null) { CameraPosition cp = mMap.getCameraPosition(); LatLng target = MapHelpV2.makeLatLng(location); LatLng offsetTarget; if (isRouteDisplayed() && overlayExpanded) { // Adjust camera target if the route header is currently displayed - map padding // doesn't get this quite right, as the header is slid up some and full padding doesn't apply double percentageOffset = 0.2; double bias = (getLongitudeSpanInDecDegrees() * percentageOffset) / 2; offsetTarget = new LatLng(target.latitude - bias, target.longitude); target = offsetTarget; } if (animateToLocation) { mMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().target(target) .zoom(cp.zoom).bearing(cp.bearing).tilt(cp.tilt).build())); } else { mMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().target(target) .zoom(cp.zoom).bearing(cp.bearing).tilt(cp.tilt).build())); } } } @Override public double getLatitudeSpanInDecDegrees() { VisibleRegion vr = mMap.getProjection().getVisibleRegion(); return Math.abs(vr.latLngBounds.northeast.latitude - vr.latLngBounds.southwest.latitude); } @Override public double getLongitudeSpanInDecDegrees() { VisibleRegion vr = mMap.getProjection().getVisibleRegion(); return Math.abs(vr.latLngBounds.northeast.longitude - vr.latLngBounds.southwest.longitude); } @Override public float getZoomLevelAsFloat() { return mMap.getCameraPosition().zoom; } @Override public void setRouteOverlay(int lineOverlayColor, ObaShape[] shapes) { if (mMap != null) { mLineOverlay.clear(); PolylineOptions lineOptions; for (ObaShape s : shapes) { lineOptions = new PolylineOptions(); lineOptions.color(lineOverlayColor); for (Location l : s.getPoints()) { lineOptions.add(MapHelpV2.makeLatLng(l)); } // Add the line to the map, and keep a reference in the ArrayList mLineOverlay.add(mMap.addPolyline(lineOptions)); } } } /** * Updates markers for the provided routeIds from the status info from the given * ObaTripsForRouteResponse * * @param routeIds markers representing real-time positions for the provided routeIds will be * added to the map * @param response response that contains the real-time status info */ @Override public void updateVehicles(HashSet<String> routeIds, ObaTripsForRouteResponse response) { setupVehicleOverlay(); if (mVehicleOverlay != null) { mVehicleOverlay.updateVehicles(routeIds, response); } } @Override public void removeVehicleOverlay() { if (mVehicleOverlay != null) { mVehicleOverlay.clear(); } } @Override public void zoomToRoute() { if (mMap != null) { if (!mLineOverlay.isEmpty()) { LatLngBounds.Builder builder = new LatLngBounds.Builder(); for (Polyline p : mLineOverlay) { for (LatLng l : p.getPoints()) { builder.include(l); } } Activity a = getActivity(); if (a != null) { int padding = UIUtils.dpToPixels(a, DEFAULT_MAP_PADDING_DP); mMap.moveCamera((CameraUpdateFactory.newLatLngBounds(builder.build(), padding))); } } else { Toast.makeText(getActivity(), getString(R.string.route_info_no_shape_data), Toast.LENGTH_SHORT) .show(); } } } /** * Zoom to include the current map bounds plus the location of the nearest vehicle * * @param routeIds markers representing real-time positions for the provided routeIds will be * checked for proximity to the location (all other routes are ignored) * @param response trips-for-route API response, which includes real-time vehicle locations in * status */ @Override public void zoomIncludeClosestVehicle(HashSet<String> routeIds, ObaTripsForRouteResponse response) { if (mMap == null) { return; } LatLng closestVehicleLocation = MapHelpV2.getClosestVehicle(response, routeIds, getMapCenterAsLocation()); LatLngBounds visibleBounds = mMap.getProjection().getVisibleRegion().latLngBounds; if (closestVehicleLocation == null || visibleBounds.contains(closestVehicleLocation)) { // Closest vehicle is already in view or is null - don't change camera return; } // Zoom to include current map bounds and closest vehicle location LatLngBounds.Builder builder = new LatLngBounds.Builder(); builder.include(visibleBounds.northeast); builder.include(visibleBounds.southwest); builder.include(closestVehicleLocation); Activity a = getActivity(); if (a != null) { int padding = UIUtils.dpToPixels(a, DEFAULT_MAP_PADDING_DP); mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), padding)); } } @Override public void removeRouteOverlay() { for (Polyline p : mLineOverlay) { p.remove(); } mLineOverlay.clear(); } /** * Clears any stop markers from the map * @param clearFocusedStop true to clear the currently focused stop, false to leave it on map */ @Override public void removeStopOverlay(boolean clearFocusedStop) { if (mStopOverlay != null) { mStopOverlay.clear(clearFocusedStop); } } @Override public boolean canWatchMapChanges() { // Android Map API v2 has an OnCameraChangeListener return true; } /** * Sets focus to a particular stop, or pass in null for the stop to clear the focus * * @param stop ObaStop to focus on, or null to clear the focus * @param routes a list of all route display names that serve this stop, or null to clear the * focus */ @Override public void setFocusStop(ObaStop stop, List<ObaRoute> routes) { // Make sure that the stop overlay has been initialized setupStopOverlay(); mStopOverlay.setFocus(stop, routes); } @Override public void onCameraChange(CameraPosition cameraPosition) { Log.d(TAG, "onCameraChange"); if (mController != null) { mController.notifyMapChanged(); } } // Maps V2 Location updates @Override public void activate(OnLocationChangedListener listener) { mListener = listener; } @Override public void deactivate() { mListener = null; } public void onLocationChanged(Location l) { if (mListener != null) { // Show real-time location on map mListener.onLocationChanged(l); } } @Override public void postInvalidate() { // Do nothing - calling `this.postInvalidate()` causes a StackOverflowError } // // Dialogs // public static class MapDialogFragment extends android.support.v4.app.DialogFragment { private static final String TAG = "MapDialogFragment"; int mDialogType; private static BaseMapFragment mMapFragment; private final static String DIALOG_TYPE_KEY = "dialog_type"; private static final int NOLOCATION_DIALOG = 103; private static final int OUTOFRANGE_DIALOG = 104; /** * Creates a new dialog of type NOLOCATION_DIALOG or OUTOFRANGE_DIALOG * * @param dialogType NOLOCATION_DIALOG to create a no location dialog, or OUTOFRANGE_DIALOG * to create an out of range dialog * @return a fragment to show the dialog */ static MapDialogFragment newInstance(int dialogType, BaseMapFragment fragment) { mMapFragment = fragment; MapDialogFragment f = new MapDialogFragment(); // Provide dialog type as an argument. Bundle args = new Bundle(); args.putInt(DIALOG_TYPE_KEY, dialogType); f.setArguments(args); f.setCancelable(false); return f; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { mDialogType = getArguments().getInt(DIALOG_TYPE_KEY); switch (mDialogType) { case NOLOCATION_DIALOG: return createNoLocationDialog(); case OUTOFRANGE_DIALOG: return createOutOfRangeDialog(); default: throw new IllegalArgumentException("Invalid map dialog type - " + DIALOG_TYPE_KEY); } } private Dialog createOutOfRangeDialog() { Drawable icon = getResources().getDrawable(android.R.drawable.ic_dialog_map); DrawableCompat.setTint(icon, getResources().getColor(R.color.theme_primary)); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) .setTitle(R.string.main_outofrange_title).setIcon(icon).setCancelable(false) .setMessage(getString(R.string.main_outofrange, Application.get().getCurrentRegion() != null ? Application.get().getCurrentRegion().getName() : "")) .setPositiveButton(R.string.main_outofrange_yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mMapFragment.zoomToRegion(); } }).setNegativeButton(R.string.main_outofrange_no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mMapFragment.mWarnOutOfRange = false; } }); return builder.create(); } @SuppressWarnings("deprecation") private Dialog createNoLocationDialog() { Drawable icon = getResources().getDrawable(android.R.drawable.ic_dialog_map); DrawableCompat.setTint(icon, getResources().getColor(R.color.theme_primary)); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) .setTitle(R.string.main_nolocation_title).setIcon(icon).setCancelable(false) .setMessage(R.string.main_nolocation) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), REQUEST_NO_LOCATION); } }).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // Ok, I suppose we can just try looking from where we // are. mMapFragment.mController.onLocation(); } }); return builder.create(); } } }