package mil.nga.dice.map; //import android.app.Fragment; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.PackageManager; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentActivity; import android.support.v4.content.ContextCompat; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.CancelableCallback; import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener; import com.google.android.gms.maps.GoogleMap.OnMapClickListener; import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener; import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener; import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import mil.nga.dice.DICEConstants; import mil.nga.dice.R; import mil.nga.dice.ReportCollectionActivity; import mil.nga.dice.map.geopackage.GeoPackageMapOverlays; import mil.nga.dice.report.Report; import mil.nga.dice.report.ReportDetailActivity; import mil.nga.dice.report.ReportManager; public class ReportMapFragment extends android.support.v4.app.Fragment implements OnMapReadyCallback, OnMapClickListener, OnMarkerClickListener, OnMapLongClickListener, OnInfoWindowClickListener { private static final String TAG = "ReportMap"; private List<Report> reports; private List<Marker> reportMarkers; private MapView mapView; private GoogleMap map; private OfflineMap offlineMap; private GeoPackageMapOverlays geoPackageMapOverlays; private View mapOverlaysView; private SharedPreferences settings; public ReportMapFragment() {} @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); reports = ReportManager.getInstance().getReports(); LocalBroadcastManager bm = LocalBroadcastManager.getInstance(getActivity().getApplicationContext()); bm.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { refreshMapMarkers(); } }, new IntentFilter(ReportManager.INTENT_UPDATE_REPORT_LIST)); settings = PreferenceManager .getDefaultSharedPreferences(getActivity()); Editor editor = settings.edit(); editor.putBoolean(DICEConstants.DICE_ZOOM_TO_REPORTS, true); editor.commit(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.fragment_report_map, container, false); mapView = (MapView) view.findViewById(R.id.map); mapView.onCreate(savedInstanceState); mapView.getMapAsync(this); mapOverlaysView = view.findViewById(R.id.mapOverlays); ImageButton mapOverlaysButton = (ImageButton) mapOverlaysView .findViewById(R.id.mapOverlaysButton); mapOverlaysButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Intent intent = new Intent(getActivity(), OverlaysActivity.class); getActivity().startActivityForResult(intent, ReportCollectionActivity.OVERLAYS_ACTIVITY); } }); return view; } private void refreshMapMarkers () { if (map == null) { return; } if (reportMarkers != null) { Iterator<Marker> markers = this.reportMarkers.iterator(); while (markers.hasNext()) { Marker marker = markers.next(); markers.remove(); marker.remove(); } } boolean zoom = settings.getBoolean(DICEConstants.DICE_ZOOM_TO_REPORTS, true); if(zoom){ Editor editor = settings.edit(); editor.putBoolean(DICEConstants.DICE_ZOOM_TO_REPORTS, false); editor.commit(); } reportMarkers = new ArrayList<>(reports.size()); LatLngBounds.Builder zoomBounds = null; for (Report report : reports) { if (report.getLat() != null && report.getLon() != null) { MarkerOptions marker = new MarkerOptions() .position(new LatLng(report.getLat(), report.getLon())) .title(report.getTitle()) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)); reportMarkers.add(map.addMarker(marker)); if(zoom){ if(zoomBounds == null){ zoomBounds = new LatLngBounds.Builder(); } zoomBounds.include(marker.getPosition()); } } } // Zoom to the reports if(zoomBounds != null){ View view = getView(); if(view != null) { int minViewLength = Math.min(view.getWidth(), view.getHeight()); final int padding = (int) Math.floor(minViewLength * 0.1); try { map.animateCamera(CameraUpdateFactory.newLatLngBounds( zoomBounds.build(), padding)); } catch (Exception e) { Log.w(ReportMapFragment.class.getSimpleName(), "Unable to move camera", e); } } } // Check for permission final FragmentActivity activity = getActivity(); if(activity != null) { if (ContextCompat.checkSelfPermission(activity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { // Only show the overlay button if there are GeoPackages if (geoPackageMapOverlays.hasGeoPackages()) { mapOverlaysView.setVisibility(View.VISIBLE); } else { mapOverlaysView.setVisibility(View.INVISIBLE); } geoPackageMapOverlays.updateMap(); } else { mapOverlaysView.setVisibility(View.INVISIBLE); if (ActivityCompat.shouldShowRequestPermissionRationale(activity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) { new AlertDialog.Builder(activity, R.style.AppCompatAlertDialogStyle) .setTitle(R.string.storage_access_rational_title) .setMessage(R.string.storage_access_rational_message) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(activity, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, ReportCollectionActivity.PERMISSIONS_REQUEST_OVERLAYS); } }) .create() .show(); } else { ActivityCompat.requestPermissions(activity, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, ReportCollectionActivity.PERMISSIONS_REQUEST_OVERLAYS); } } } } @Override public void onResume() { super.onResume(); mapView.onResume(); } @Override public void onPause () { geoPackageMapOverlays.deselectedReport(); super.onPause(); mapView.onPause(); } @Override public void onLowMemory() { super.onLowMemory(); mapView.onLowMemory(); // TODO: clear the offline map and add logic to restore it later } @Override public void onDestroy() { super.onDestroy(); mapView.onDestroy(); offlineMap.clear(); } @Override public void onInfoWindowClick(Marker marker) { Report report = getReport(marker); if(report != null) { geoPackageMapOverlays.deselectedReport(); Intent detailIntent = new Intent(getActivity(), ReportDetailActivity.class); detailIntent.putExtra("report", report); startActivity(detailIntent); } } /** * Get the Report from the marker * @param marker * @return report */ private Report getReport(Marker marker) { String title = marker.getTitle(); Report report = null; Iterator<Report> cursor = reports.iterator(); Report currentReport = null; while (cursor.hasNext()) { currentReport = cursor.next(); if (currentReport.getTitle().equalsIgnoreCase(title)) { report = currentReport; break; } } return report; } @Override public void onMapLongClick(LatLng latLng) { } @Override public boolean onMarkerClick(Marker marker) { boolean consumed = false; String message = geoPackageMapOverlays.mapClickMessage(marker); if(message != null && !message.isEmpty()) { consumed = true; geoPackageMapOverlays.deselectedReport(); displayMessage(message); }else{ Report report = getReport(marker); if(report != null) { geoPackageMapOverlays.selectedReport(report); }else{ geoPackageMapOverlays.deselectedReport(); } } return consumed; } @Override public void onMapClick(LatLng latLng) { geoPackageMapOverlays.deselectedReport(); String message = geoPackageMapOverlays.mapClickMessage(latLng); displayMessage(message); } /** * Display a message * @param message message string */ private void displayMessage(String message){ if(message != null && !message.isEmpty()){ new AlertDialog.Builder(getActivity()) .setMessage(message) .setPositiveButton(android.R.string.yes, null) .show(); } } @Override public void onMapReady(GoogleMap googleMap) { map = googleMap; map.setMapType(GoogleMap.MAP_TYPE_NONE); map.setOnInfoWindowClickListener(this); map.setOnMapClickListener(this); map.setOnMarkerClickListener(this); map.setOnMapLongClickListener(this); LatLng latLng = new LatLng(0.0, 0.0); float zoom = map.getCameraPosition().zoom < 1 ? 1 : map.getCameraPosition().zoom; map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom), new CancelableCallback() { @Override public void onCancel() { // TODO } @Override public void onFinish() { // TODO } }); offlineMap = new OfflineMap(map); offlineMap.setVisible(true); geoPackageMapOverlays = new GeoPackageMapOverlays(getActivity(), mapView, map); refreshMapMarkers(); } }