/** ** Copyright (c) 2010 Ushahidi Inc ** All rights reserved ** Contact: team@ushahidi.com ** Website: http://www.ushahidi.com ** ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: http://www.gnu.org/licenses/lgpl.html. ** ** ** If you have questions regarding the use of this file, please contact ** Ushahidi developers at team@ushahidi.com. ** **/ package com.ushahidi.android.app; import java.io.IOException; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.location.Address; import android.location.Geocoder; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.location.LocationProvider; import android.os.Bundle; import android.os.Handler; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.Toast; import com.google.android.maps.GeoPoint; import com.google.android.maps.ItemizedOverlay; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import com.google.android.maps.OverlayItem; import com.google.android.maps.Projection; import com.ushahidi.android.app.data.Database; import com.ushahidi.android.app.data.IncidentsData; import com.ushahidi.android.app.util.Util; public class MapLocation extends MapActivity { private MapView mapView = null; private MapController mapController; private static Geocoder gc; private GeoPoint defaultLocation; private double latitude; private double longitude; private List<IncidentsData> mNewIncidents; private List<IncidentsData> mOldIncidents; private Button btnReset; private Button btnSave; private Button btnFind; private Bundle bundle = new Bundle(); private List<Address> foundAddresses; private String locationName; private String title; private String date; private String description; private String location; private String categories; private String thumbnail; // Need handler for callbacks to the UI thread final Handler mHandler = new Handler(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.view_map); mapView = (MapView)findViewById(R.id.location_map); locationName = ""; foundAddresses = new ArrayList<Address>(); gc = new Geocoder(this); btnSave = (Button)findViewById(R.id.btn_save); btnSave.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { bundle.putDouble("latitude", latitude); bundle.putDouble("longitude", longitude); bundle.putString("location", locationName); // Pass the data to the calling activity Intent intent = new Intent(); intent.putExtra("locations", bundle); setResult(RESULT_OK, intent); finish(); } }); btnFind = (Button)findViewById(R.id.btn_find); btnFind.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Util.showToast(MapLocation.this, R.string.find_location); updateLocation(); } }); mapController = mapView.getController(); mOldIncidents = new ArrayList<IncidentsData>(); mNewIncidents = showIncidents("All"); if (mNewIncidents.size() > 0) { latitude = Double.parseDouble(mNewIncidents.get(0).getIncidentLocLatitude()); longitude = Double.parseDouble(mNewIncidents.get(0).getIncidentLocLongitude()); } defaultLocation = getPoint(latitude, longitude); centerLocation(defaultLocation); btnReset = (Button)findViewById(R.id.btn_reset); btnReset.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { centerLocation(defaultLocation); } }); } // Create runnable for posting final Runnable mUpdateResults = new Runnable() { public void run() { updateResultsInUi(); } }; protected void startLongRunningOperation() { // Fire off a thread to do some work that we shouldn't do directly in // the UI thread Thread t = new Thread() { @Override public void run() { updateLocation(); mHandler.post(mUpdateResults); } }; t.start(); } private void updateResultsInUi() { Toast.makeText(MapLocation.this, "Found you at " + locationName, Toast.LENGTH_SHORT).show(); } @Override protected boolean isRouteDisplayed() { return false; } private void placeMarker(int markerLatitude, int markerLongitude) { Drawable marker = getResources().getDrawable(R.drawable.map_marker_red); marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight()); mapView.getController().setZoom(14); mapView.setBuiltInZoomControls(true); mapView.getOverlays().add(new MapMarker(marker, markerLatitude, markerLongitude)); } public GeoPoint getPoint(double lat, double lon) { return (new GeoPoint((int)(lat * 1000000.0), (int)(lon * 1000000.0))); } private void centerLocation(GeoPoint centerGeoPoint) { mapController.animateTo(centerGeoPoint); // initilaize latitude and longitude for them to be passed to the // AddIncident Activity. this.latitude = centerGeoPoint.getLatitudeE6() / 1.0E6; this.longitude = centerGeoPoint.getLongitudeE6() / 1.0E6; mapView.getOverlays().clear(); placeMarker(centerGeoPoint.getLatitudeE6(), centerGeoPoint.getLongitudeE6()); } /** * get the real location name from the latitude and longitude. */ private String getLocationFromLatLon(double lat, double lon) { try { Address address; foundAddresses = gc.getFromLocation(lat, lon, 5); if (foundAddresses.size() > 0) { address = foundAddresses.get(0); return address.getFeatureName(); } else { return ""; } } catch (IOException e) { e.printStackTrace(); } return ""; } // get incidents from the db public List<IncidentsData> showIncidents(String by) { Cursor cursor; if (by.equals("All")) cursor = MainApplication.mDb.fetchAllIncidents(); else cursor = MainApplication.mDb.fetchIncidentsByCategories(by); if (cursor.moveToFirst()) { int idIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_ID); int titleIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_TITLE); int dateIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_DATE); int verifiedIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_VERIFIED); int locationIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_LOC_NAME); int descIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_DESC); int categoryIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_CATEGORIES); int mediaIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_MEDIA); int latitudeIndex = cursor .getColumnIndexOrThrow(Database.INCIDENT_LOC_LATITUDE); int longitudeIndex = cursor .getColumnIndexOrThrow(Database.INCIDENT_LOC_LONGITUDE); do { IncidentsData incidentData = new IncidentsData(); mOldIncidents.add(incidentData); int id = Util.toInt(cursor.getString(idIndex)); incidentData.setIncidentId(id); title = Util.capitalizeString(cursor.getString(titleIndex)); incidentData.setIncidentTitle(title); description = cursor.getString(descIndex); incidentData.setIncidentDesc(description); categories = cursor.getString(categoryIndex); incidentData.setIncidentCategories(categories); location = cursor.getString(locationIndex); incidentData.setIncidentLocLongitude(location); date = Util.joinString("Date: ", Util.formatDate("yyyy-MM-dd hh:mm:ss", cursor.getString(dateIndex), "MMMM dd, yyyy 'at' hh:mm:ss aaa")); incidentData.setIncidentDate(date); thumbnail = cursor.getString(mediaIndex); incidentData.setIncidentThumbnail(thumbnail); incidentData.setIncidentVerified(Util.toInt(cursor.getString(verifiedIndex))); incidentData.setIncidentLocLatitude(cursor.getString(latitudeIndex)); incidentData.setIncidentLocLongitude(cursor.getString(longitudeIndex)); } while (cursor.moveToNext()); } cursor.close(); return mOldIncidents; } // update the device current location private void updateLocation() { MyLocationListener listener = new MyLocationListener(); LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); long updateTimeMsec = 1000L; LocationProvider low = locationManager.getProvider(locationManager.getBestProvider( Util.createCoarseCriteria(), true)); // get high accuracy provider LocationProvider high = locationManager.getProvider(locationManager.getBestProvider( Util.createFineCriteria(), true)); // Register for GPS location if enabled or if neither is enabled locationManager.requestLocationUpdates(low.getName(), updateTimeMsec, 500.0f, listener); locationManager.requestLocationUpdates(high.getName(), updateTimeMsec, 500.0f, listener); } // get the current location of the user public class MyLocationListener implements LocationListener { public void onLocationChanged(Location location) { double latitude = 0; double longitude = 0; String locName = ""; if (location != null) { // Dipo Fix // Stop asking for updates when location has been retrieved latitude = location.getLatitude(); longitude = location.getLongitude(); locName = getLocationFromLatLon(latitude, longitude); centerLocation(getPoint(latitude, longitude)); ((LocationManager)getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this); if (locName == null) { Util.showToast(MapLocation.this, R.string.location_not_found); } else { locationName = locName; Toast.makeText(MapLocation.this, "Found you at " + locationName, Toast.LENGTH_SHORT).show(); } } } public void onProviderDisabled(String provider) { Util.showToast(MapLocation.this, R.string.location_not_found); } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } } private class MapMarker extends ItemizedOverlay<OverlayItem> { private List<OverlayItem> locations = new ArrayList<OverlayItem>(); private Drawable marker; private OverlayItem myOverlayItem; private boolean MoveMap = false; private long timer; public MapMarker(Drawable defaultMarker, int LatitudeE6, int LongitudeE6) { super(defaultMarker); this.timer = 0; this.marker = defaultMarker; // create locations of interest GeoPoint myPlace = new GeoPoint(LatitudeE6, LongitudeE6); myOverlayItem = new OverlayItem(myPlace, " ", " "); locations.add(myOverlayItem); populate(); } @Override protected OverlayItem createItem(int i) { return locations.get(i); } @Override public int size() { return locations.size(); } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { super.draw(canvas, mapView, shadow); boundCenterBottom(marker); } /** * Fixed by Joey at http://goo.gl/UUiN */ @Override public boolean onTouchEvent(MotionEvent motionEvent, MapView mapview) { int Action = motionEvent.getAction(); String foundLoc = ""; if (Action == MotionEvent.ACTION_UP) { if (!MoveMap && (System.currentTimeMillis() - timer <= 1000)) { Projection proj = mapView.getProjection(); GeoPoint loc = proj .fromPixels((int)motionEvent.getX(), (int)motionEvent.getY()); foundLoc = getLocationFromLatLon(loc.getLatitudeE6() / 1.0E6, loc.getLatitudeE6() / 1.0E6); if (foundLoc == "") { locationName = ""; Util.showToast(MapLocation.this, R.string.loc_not_found); } else { locationName = foundLoc; Toast.makeText(MapLocation.this, locationName, Toast.LENGTH_SHORT).show(); } // remove the last marker centerLocation(loc); } } else if (Action == MotionEvent.ACTION_DOWN) { timer = System.currentTimeMillis(); MoveMap = false; } else if (Action == MotionEvent.ACTION_MOVE) { float difX = 0.0f; float difY = 0.0f; if (motionEvent.getHistorySize() >= 2) { difX = motionEvent.getHistoricalX(0) - motionEvent.getHistoricalX(motionEvent.getHistorySize() - 1); difY = motionEvent.getHistoricalY(0) - motionEvent.getHistoricalY(motionEvent.getHistorySize() - 1); } if (difX >= 5 || difX <= -5 || difY >= 5 || difY <= -5) { MoveMap = true; } } return super.onTouchEvent(motionEvent, mapview); } } }