Java tutorial
/* * Copyright (C) 2016 GeoODK * * 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.odk.collect.android.activities; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.graphics.Paint; import android.location.LocationManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.support.v4.content.ContextCompat; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.ImageButton; import org.odk.collect.android.R; import org.odk.collect.android.spatial.MapHelper; import org.odk.collect.android.widgets.GeoShapeWidget; import org.osmdroid.events.MapEventsReceiver; import org.osmdroid.events.MapListener; import org.osmdroid.events.ScrollEvent; import org.osmdroid.events.ZoomEvent; import org.osmdroid.tileprovider.IRegisterReceiver; import org.osmdroid.util.BoundingBox; import org.osmdroid.util.GeoPoint; import org.osmdroid.views.MapView; import org.osmdroid.views.overlay.MapEventsOverlay; import org.osmdroid.views.overlay.Marker; import org.osmdroid.views.overlay.Polyline; import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider; import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay; import java.util.ArrayList; import java.util.List; /** * Version of the GeoPointMapActivity that uses the new Maps v2 API and Fragments to enable * specifying a location via placing a tracker on a map. * * @author jonnordling@gmail.com */ public class GeoShapeOsmMapActivity extends Activity implements IRegisterReceiver { private MapView map; private ArrayList<Marker> mapMarkers = new ArrayList<Marker>(); private Polyline polyline; public int zoomLevel = 3; public static final int stroke_width = 5; public String finalReturnString; private MapEventsOverlay overlayEvents; private boolean clearButtonTest = false; private ImageButton clearButton; public Boolean gpsStatus = true; private ImageButton locationButton; public MyLocationNewOverlay myLocationOverlay; public Boolean dataLoaded = false; private MapHelper helper; private AlertDialog zoomDialog; private View zoomDialogView; private Button zoomPointButton; private Button zoomLocationButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.geoshape_osm_layout); setTitle(getString(R.string.geoshape_title)); // Setting title of the action ImageButton saveButton = (ImageButton) findViewById(R.id.save); clearButton = (ImageButton) findViewById(R.id.clear); map = (MapView) findViewById(R.id.geoshape_mapview); helper = new MapHelper(this, map, GeoShapeOsmMapActivity.this); map.setMultiTouchControls(true); map.setBuiltInZoomControls(true); map.setMapListener(mapViewListener); overlayPointPathListener(); saveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { returnLocation(); } }); clearButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mapMarkers.size() != 0) { showClearDialog(); } } }); ImageButton layersButton = (ImageButton) findViewById(R.id.layers); layersButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { helper.showLayersDialog(GeoShapeOsmMapActivity.this); } }); locationButton = (ImageButton) findViewById(R.id.gps); locationButton.setEnabled(false); locationButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { showZoomDialog(); } }); GpsMyLocationProvider imlp = new GpsMyLocationProvider(this.getBaseContext()); imlp.setLocationUpdateMinDistance(1000); imlp.setLocationUpdateMinTime(60000); myLocationOverlay = new MyLocationNewOverlay(map); Intent intent = getIntent(); if (intent != null && intent.getExtras() != null) { if (intent.hasExtra(GeoShapeWidget.SHAPE_LOCATION)) { clearButton.setEnabled(true); dataLoaded = true; String s = intent.getStringExtra(GeoShapeWidget.SHAPE_LOCATION); overlayIntentPolygon(s); //zoomToCentroid(); locationButton.setEnabled(true); zoomToBounds(); } } else { myLocationOverlay.runOnFirstFix(centerAroundFix); clearButton.setEnabled(false); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { public void run() { GeoPoint point = new GeoPoint(34.08145, -39.85007); map.getController().setZoom(3); map.getController().setCenter(point); } }, 100); } map.invalidate(); zoomDialogView = getLayoutInflater().inflate(R.layout.geoshape_zoom_dialog, null); zoomLocationButton = (Button) zoomDialogView.findViewById(R.id.zoom_location); zoomLocationButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { zoomToMyLocation(); map.invalidate(); zoomDialog.dismiss(); } }); zoomPointButton = (Button) zoomDialogView.findViewById(R.id.zoom_shape); zoomPointButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //zoomToCentroid(); zoomToBounds(); map.invalidate(); zoomDialog.dismiss(); } }); } @Override protected void onResume() { super.onResume(); if (map != null) { helper.setBasemap(); } upMyLocationOverlayLayers(); } @Override public void onBackPressed() { if (mapMarkers != null && mapMarkers.size() > 0) { showBackDialog(); } else { finish(); } } @Override protected void onPause() { super.onPause(); disableMyLocation(); } @Override protected void onStop() { super.onStop(); disableMyLocation(); } private void overlayIntentPolygon(String str) { clearButton.setEnabled(true); clearButtonTest = true; String s = str.replace("; ", ";"); String[] sa = s.split(";"); for (int i = 0; i < (sa.length - 1); i++) { String[] sp = sa[i].split(" "); double[] gp = new double[4]; String lat = sp[0].replace(" ", ""); String lng = sp[1].replace(" ", ""); gp[0] = Double.parseDouble(lat); gp[1] = Double.parseDouble(lng); Marker marker = new Marker(map); marker.setPosition(new GeoPoint(gp[0], gp[1])); marker.setDraggable(true); marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place_black_36dp)); marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM); marker.setOnMarkerClickListener(nullMarkerListener); mapMarkers.add(marker); // pathOverlay.addPoint(marker.getPosition()); marker.setDraggable(true); marker.setOnMarkerDragListener(dragListener); map.getOverlays().add(marker); } update_polygon(); map.getOverlays().remove(overlayEvents); } private Handler handler = new Handler(Looper.getMainLooper()); private Runnable centerAroundFix = new Runnable() { public void run() { handler.post(new Runnable() { public void run() { locationButton.setEnabled(true); showZoomDialog(); } }); } }; private void showGPSDisabledAlertToUser() { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); alertDialogBuilder.setMessage(getString(R.string.gps_enable_message)).setCancelable(false) .setPositiveButton(getString(R.string.enable_gps), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), 0); } }); alertDialogBuilder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = alertDialogBuilder.create(); alert.show(); } private void upMyLocationOverlayLayers() { LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { overlayMyLocationLayers(); } else { showGPSDisabledAlertToUser(); } } private void overlayMyLocationLayers() { map.getOverlays().add(myLocationOverlay); myLocationOverlay.setEnabled(true); myLocationOverlay.enableMyLocation(); } private void zoomToMyLocation() { if (myLocationOverlay.getMyLocation() != null) { map.getController().setZoom(15); map.getController().setCenter(myLocationOverlay.getMyLocation()); } } private void disableMyLocation() { LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { myLocationOverlay.setEnabled(false); myLocationOverlay.disableFollowLocation(); myLocationOverlay.disableMyLocation(); gpsStatus = false; } } private void overlayPointPathListener() { overlayEvents = new MapEventsOverlay(receive); polyline = new Polyline(); polyline.setColor(Color.RED); Paint paint = polyline.getPaint(); paint.setStrokeWidth(stroke_width); map.getOverlays().add(polyline); map.getOverlays().add(overlayEvents); map.invalidate(); } private void clearFeatures() { clearButtonTest = false; mapMarkers.clear(); polyline.setPoints(new ArrayList<GeoPoint>()); map.getOverlays().clear(); clearButton.setEnabled(false); //saveButton.setEnabled(false); overlayPointPathListener(); overlayMyLocationLayers(); map.invalidate(); } private void showClearDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(getString(R.string.geo_clear_warning)) .setPositiveButton(getString(R.string.clear), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { clearFeatures(); } }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }).show(); } private void showBackDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(getString(R.string.geo_exit_warning)) .setPositiveButton(getString(R.string.discard), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { finish(); } }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }).show(); } private String generateReturnString() { String tempString = ""; if (mapMarkers.size() > 1) { mapMarkers.add(mapMarkers.get(0)); for (int i = 0; i < mapMarkers.size(); i++) { String lat = Double.toString(mapMarkers.get(i).getPosition().getLatitude()); String lng = Double.toString(mapMarkers.get(i).getPosition().getLongitude()); String alt = "0.0"; String acu = "0.0"; tempString = tempString + lat + " " + lng + " " + alt + " " + acu + ";"; } } return tempString; } private void returnLocation() { finalReturnString = generateReturnString(); Intent i = new Intent(); i.putExtra(FormEntryActivity.GEOSHAPE_RESULTS, finalReturnString); setResult(RESULT_OK, i); finish(); } private void update_polygon() { List<GeoPoint> points = new ArrayList<>(); for (int i = 0; i < mapMarkers.size(); i++) { points.add(mapMarkers.get(i).getPosition()); } points.add(mapMarkers.get(0).getPosition()); polyline.setPoints(points); map.invalidate(); } private MapEventsReceiver receive = new MapEventsReceiver() { @Override public boolean longPressHelper(GeoPoint point) { if (!clearButtonTest) { clearButton.setEnabled(true); clearButtonTest = true; } Marker marker = new Marker(map); marker.setPosition(point); marker.setDraggable(true); marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place_black_36dp)); marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM); marker.setOnMarkerClickListener(nullMarkerListener); mapMarkers.add(marker); marker.setDraggable(true); marker.setOnMarkerDragListener(dragListener); map.getOverlays().add(marker); List<GeoPoint> points = polyline.getPoints(); points.add(marker.getPosition()); polyline.setPoints(points); update_polygon(); map.invalidate(); return false; } @Override public boolean singleTapConfirmedHelper(GeoPoint arg0) { return false; } }; private MapListener mapViewListener = new MapListener() { @Override public boolean onZoom(ZoomEvent zoomLev) { zoomLevel = zoomLev.getZoomLevel(); return false; } @Override public boolean onScroll(ScrollEvent arg0) { return false; } }; private Marker.OnMarkerDragListener dragListener = new Marker.OnMarkerDragListener() { @Override public void onMarkerDragStart(Marker marker) { } @Override public void onMarkerDragEnd(Marker marker) { update_polygon(); } @Override public void onMarkerDrag(Marker marker) { update_polygon(); } }; private Marker.OnMarkerClickListener nullMarkerListener = new Marker.OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker arg0, MapView arg1) { return false; } }; /* This functions should be added to the mapHelper Class */ private void zoomToBounds() { map.getController().setZoom(4); map.invalidate(); Handler handler = new Handler(); handler.postDelayed(new Runnable() { public void run() { double minLat = Double.MAX_VALUE; double maxLat = Double.MIN_VALUE; double minLong = Double.MAX_VALUE; double maxLong = Double.MIN_VALUE; Integer size = mapMarkers.size(); for (int i = 0; i < size; i++) { GeoPoint tempMarker = mapMarkers.get(i).getPosition(); if (tempMarker.getLatitude() < minLat) { minLat = tempMarker.getLatitude(); } if (tempMarker.getLatitude() > maxLat) { maxLat = tempMarker.getLatitude(); } if (tempMarker.getLongitude() < minLong) { minLong = tempMarker.getLongitude(); } if (tempMarker.getLongitude() > maxLong) { maxLong = tempMarker.getLongitude(); } } BoundingBox boundingBox = new BoundingBox(maxLat, maxLong, minLat, minLong); map.zoomToBoundingBox(boundingBox, false); map.invalidate(); } }, 100); map.invalidate(); } public void showZoomDialog() { if (zoomDialog == null) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.zoom_to_where)); builder.setView(zoomDialogView) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }).setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { dialog.cancel(); zoomDialog.dismiss(); } }); zoomDialog = builder.create(); } //If feature enable zoom to button else disable if (myLocationOverlay.getMyLocation() != null) { zoomLocationButton.setEnabled(true); zoomLocationButton.setBackgroundColor(Color.parseColor("#50cccccc")); zoomLocationButton.setTextColor(Color.parseColor("#ff333333")); } else { zoomLocationButton.setEnabled(false); zoomLocationButton.setBackgroundColor(Color.parseColor("#50e2e2e2")); zoomLocationButton.setTextColor(Color.parseColor("#FF979797")); } if (mapMarkers.size() != 0) { zoomPointButton.setEnabled(true); zoomPointButton.setBackgroundColor(Color.parseColor("#50cccccc")); zoomPointButton.setTextColor(Color.parseColor("#ff333333")); } else { zoomPointButton.setEnabled(false); zoomPointButton.setBackgroundColor(Color.parseColor("#50e2e2e2")); zoomPointButton.setTextColor(Color.parseColor("#FF979797")); } zoomDialog.show(); } @Override public void destroy() { } }