package net.osmand.plus.activities;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.osmand.Algoritms;
import net.osmand.FavouritePoint;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFileResult;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.LogUtil;
import net.osmand.OsmAndFormatter;
import net.osmand.Version;
import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.data.preparation.MapTileDownloader;
import net.osmand.data.preparation.MapTileDownloader.DownloadRequest;
import net.osmand.data.preparation.MapTileDownloader.IMapDownloaderCallback;
import net.osmand.map.IMapLocationListener;
import net.osmand.map.ITileSource;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.plus.AmenityIndexRepository;
import net.osmand.plus.AmenityIndexRepositoryOdb;
import net.osmand.plus.BusyIndicator;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.ApplicationMode;
import net.osmand.plus.PoiFilter;
import net.osmand.plus.PoiFiltersHelper;
import net.osmand.plus.R;
import net.osmand.plus.ResourceManager;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.activities.search.SearchActivity;
import net.osmand.plus.activities.search.SearchPoiFilterActivity;
import net.osmand.plus.activities.search.SearchTransportActivity;
import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.render.RendererLayer;
import net.osmand.plus.views.AGHTrafficLayer;
import net.osmand.plus.views.AnimateDraggingMapThread;
import net.osmand.plus.views.ContextMenuLayer;
import net.osmand.plus.views.FavoritesLayer;
import net.osmand.plus.views.GPXLayer;
import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmBugsLayer;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.POIMapLayer;
import net.osmand.plus.views.PointLocationLayer;
import net.osmand.plus.views.PointNavigationLayer;
import net.osmand.plus.views.RouteInfoLayer;
import net.osmand.plus.views.RouteLayer;
import net.osmand.plus.views.TransportInfoLayer;
import net.osmand.plus.views.TransportStopsLayer;
import net.osmand.plus.views.YandexTrafficLayer;
import pl.edu.agh.logic.LocationBuffer;
import pl.edu.agh.model.LocationInfo;
import pl.edu.agh.service.LocationLogger;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.text.ClipboardManager;
import android.text.Html;
import android.util.FloatMath;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.widget.ZoomControls;
public class MapActivity extends Activity implements IMapLocationListener, SensorEventListener {
private static final String GPS_STATUS_ACTIVITY = "com.eclipsim.gpsstatus2.GPSStatus"; //$NON-NLS-1$
private static final String GPS_STATUS_COMPONENT = "com.eclipsim.gpsstatus2"; //$NON-NLS-1$
// stupid error but anyway hero 2.1 : always lost gps signal (temporarily unavailable) for timeout = 2000
private static final int GPS_TIMEOUT_REQUEST = 1000;
private static final int GPS_DIST_REQUEST = 5;
// use only gps (not network) for 12 seconds
private static final int USE_ONLY_GPS_INTERVAL = 12000;
private boolean providerSupportsBearing = false;
@SuppressWarnings("unused")
private boolean providerSupportsSpeed = false;
private String currentLocationProvider = null;
private long lastTimeAutoZooming = 0;
private long lastTimeGPXLocationFixed = 0;
/** Called when the activity is first created. */
private OsmandMapTileView mapView;
private ImageButton backToLocation;
private ImageButton backToMenu;
// the order of layer should be preserved ! when you are inserting new layer
private RendererLayer rendererLayer;
private GPXLayer gpxLayer;
private RouteLayer routeLayer;
private YandexTrafficLayer trafficLayer;
private OsmBugsLayer osmBugsLayer;
private POIMapLayer poiMapLayer;
private FavoritesLayer favoritesLayer;
private TransportStopsLayer transportStopsLayer;
private TransportInfoLayer transportInfoLayer;
private PointLocationLayer locationLayer;
private PointNavigationLayer navigationLayer;
private MapInfoLayer mapInfoLayer;
private ContextMenuLayer contextMenuLayer;
private RouteInfoLayer routeInfoLayer;
private AGHTrafficLayer aghTrafficLayer;
private SavingTrackHelper savingTrackHelper;
private RoutingHelper routingHelper;
private WakeLock wakeLock;
private boolean sensorRegistered = false;
private NotificationManager mNotificationManager;
private Handler mapPositionHandler = null;
private int APP_NOTIFICATION_ID;
private int currentScreenOrientation;
private int currentMapRotation;
private boolean currentShowingAngle;
private OsmandApplication application;
private Dialog progressDlg = null;
private SharedPreferences settings;
/* private boolean boundToLoggingService = false;
private LocationLogger locationLogger;
private ServiceConnection locationLoggerConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
boundToLoggingService = true;
locationLogger = ((ServiceAccess)service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
boundToLoggingService = false;
}
};
*/
private boolean isMapLinkedToLocation(){
return OsmandSettings.isMapSyncToGpsLocation(settings);
}
private Notification getNotification(){
Intent notificationIndent = new Intent(this, MapActivity.class);
notificationIndent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
Notification notification = new Notification(R.drawable.icon, "", //$NON-NLS-1$
System.currentTimeMillis());
notification.setLatestEventInfo(this, Version.APP_NAME,
getString(R.string.go_back_to_osmand), PendingIntent.getActivity(
this, 0, notificationIndent,
PendingIntent.FLAG_UPDATE_CURRENT));
return notification;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.application = (OsmandApplication)this.getApplication();
settings = OsmandSettings.getPrefs(this);
// for voice navigation
setVolumeControlStream(AudioManager.STREAM_MUSIC);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Full screen is not used here
// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
ProgressDialog dlg = ((OsmandApplication)getApplication()).checkApplicationIsBeingInitialized(this);
if(dlg != null){
// Do some action on close
dlg.setOnDismissListener(new DialogInterface.OnDismissListener(){
@Override
public void onDismiss(DialogInterface dialog) {
OsmandApplication app = ((OsmandApplication)getApplication());
if(OsmandSettings.isUsingMapVectorData(settings) && app.getResourceManager().getRenderer().isEmpty()){
Toast.makeText(MapActivity.this, getString(R.string.no_vector_map_loaded), Toast.LENGTH_LONG).show();
}
}
});
}
parseLaunchIntentLocation();
mapView = (OsmandMapTileView) findViewById(R.id.MapView);
mapView.setTrackBallDelegate(new OsmandMapTileView.OnTrackBallListener(){
@Override
public boolean onTrackBallEvent(MotionEvent e) {
showAndHideMapPosition();
return MapActivity.this.onTrackballEvent(e);
}
});
MapTileDownloader.getInstance().addDownloaderCallback(new IMapDownloaderCallback(){
@Override
public void tileDownloaded(DownloadRequest request) {
if(request != null && !request.error && request.fileToSave != null){
ResourceManager mgr = ((OsmandApplication)getApplication()).getResourceManager();
mgr.tileDownloaded(request);
}
mapView.tileDownloaded(request);
}
});
mapView.setMapLocationListener(this);
routingHelper = ((OsmandApplication) getApplication()).getRoutingHelper();
// 0.5 layer
rendererLayer = new RendererLayer();
mapView.addLayer(rendererLayer, 0.5f);
// 0.6 gpx layer
gpxLayer = new GPXLayer();
mapView.addLayer(gpxLayer, 0.6f);
//0.8 agh traffic layer
aghTrafficLayer = new AGHTrafficLayer();
// 1. route layer
routeLayer = new RouteLayer(routingHelper);
mapView.addLayer(routeLayer, 1);
// 1.5. traffic layer
trafficLayer = new YandexTrafficLayer();
mapView.addLayer(trafficLayer, 1.5f);
// 2. osm bugs layer
osmBugsLayer = new OsmBugsLayer(this);
// 3. poi layer
poiMapLayer = new POIMapLayer();
// 4. favorites layer
favoritesLayer = new FavoritesLayer();
// 5. transport layer
transportStopsLayer = new TransportStopsLayer();
// 5.5 transport info layer
transportInfoLayer = new TransportInfoLayer(TransportRouteHelper.getInstance());
mapView.addLayer(transportInfoLayer, 5.5f);
// 6. point navigation layer
navigationLayer = new PointNavigationLayer();
mapView.addLayer(navigationLayer, 6);
// 7. point location layer
locationLayer = new PointLocationLayer();
mapView.addLayer(locationLayer, 7);
// 8. map info layer
mapInfoLayer = new MapInfoLayer(this, routeLayer);
mapView.addLayer(mapInfoLayer, 8);
// 9. context menu layer
contextMenuLayer = new ContextMenuLayer(this);
mapView.addLayer(contextMenuLayer, 9);
// 10. route info layer
routeInfoLayer = new RouteInfoLayer(routingHelper, (LinearLayout) findViewById(R.id.RouteLayout));
mapView.addLayer(routeInfoLayer, 10);
savingTrackHelper = new SavingTrackHelper(this);
LatLon pointToNavigate = OsmandSettings.getPointToNavigate(settings);
// This situtation could be when navigation suddenly crashed and after restarting
// it tries to continue the last route
if(!Algoritms.objectEquals(routingHelper.getFinalLocation(), pointToNavigate)){
routingHelper.setFollowingMode(false);
OsmandSettings.setFollowingByRoute(this, false);
stopLogger();
routingHelper.setFinalAndCurrentLocation(pointToNavigate, null);
}
if(OsmandSettings.isFollowingByRoute(settings)){
if(pointToNavigate == null){
OsmandSettings.setFollowingByRoute(this, false);
} else if(!routingHelper.isRouteCalculated()){
Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.continue_follow_previous_route);
builder.setPositiveButton(R.string.default_buttons_yes, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
routingHelper.setFollowingMode(true);
OsmandSettings.setFollowingByRoute(MapActivity.this, true);
startLogger();
((OsmandApplication)getApplication()).showDialogInitializingCommandPlayer(MapActivity.this);
}
});
builder.setNegativeButton(R.string.default_buttons_no, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
routingHelper.setFollowingMode(false);
OsmandSettings.setFollowingByRoute(MapActivity.this, false);
routingHelper.setFinalLocation(null);
mapView.refreshMap();
}
});
builder.show();
}
}
navigationLayer.setPointToNavigate(pointToNavigate);
SharedPreferences prefs = getSharedPreferences(OsmandSettings.SHARED_PREFERENCES_NAME, MODE_WORLD_READABLE);
if(prefs == null || !prefs.contains(OsmandSettings.LAST_KNOWN_MAP_LAT)){
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
Location location = null;
try {
location = service.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
catch(IllegalArgumentException e) {
Log.d(LogUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
}
if(location == null){
try {
location = service.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
} catch(IllegalArgumentException e) {
Log.d(LogUtil.TAG, "Network location provider not available"); //$NON-NLS-1$
}
}
if(location != null){
mapView.setLatLon(location.getLatitude(), location.getLongitude());
mapView.setZoom(14);
}
}
final ZoomControls zoomControls = (ZoomControls) findViewById(R.id.ZoomControls);
zoomControls.setOnZoomInClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
zoomControls.setIsZoomInEnabled(mapView.getZoom() + 1 < mapView.getMaximumShownMapZoom());
zoomControls.setIsZoomOutEnabled(mapView.getZoom() + 1 > mapView.getMinimumShownMapZoom());
mapView.getAnimatedDraggingThread().stopAnimatingSync();
mapView.getAnimatedDraggingThread().startZooming(mapView.getZoom(), mapView.getZoom() + 1);
showAndHideMapPosition();
// user can preview map manually switch off auto zoom while user don't press back to location
if(OsmandSettings.isAutoZoomEnabled(settings)){
locationChanged(mapView.getLatitude(), mapView.getLongitude(), null);
}
}
});
zoomControls.setOnZoomOutClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
zoomControls.setIsZoomInEnabled(mapView.getZoom() - 1 < mapView.getMaximumShownMapZoom());
zoomControls.setIsZoomOutEnabled(mapView.getZoom() - 1 > mapView.getMinimumShownMapZoom());
mapView.getAnimatedDraggingThread().stopAnimatingSync();
mapView.getAnimatedDraggingThread().startZooming(mapView.getZoom(), mapView.getZoom() - 1);
showAndHideMapPosition();
// user can preview map manually switch off auto zoom while user don't press back to location
if(OsmandSettings.isAutoZoomEnabled(settings)){
locationChanged(mapView.getLatitude(), mapView.getLongitude(), null);
}
}
});
backToLocation = (ImageButton)findViewById(R.id.BackToLocation);
backToLocation.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
backToLocationImpl();
}
});
backToMenu = (ImageButton)findViewById(R.id.BackToMenu);
backToMenu.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent newIntent = new Intent(MapActivity.this, MainMenuActivity.class);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);
}
});
// Possibly use that method instead of
/*mapView.setOnLongClickListener(new OsmandMapTileView.OnLongClickListener(){
@Override
public boolean onLongPressEvent(PointF point) {
LatLon l = mapView.getLatLonFromScreenPoint(point.x, point.y);
return true;
}
});*/
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() == 0) {
Intent newIntent = new Intent(MapActivity.this, SearchActivity.class);
startActivity(newIntent);
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onTrackballEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_MOVE && OsmandSettings.isUsingTrackBall(settings)){
float x = event.getX();
float y = event.getY();
LatLon l = mapView.getLatLonFromScreenPoint(mapView.getCenterPointX() + x * 15, mapView.getCenterPointY() + y * 15);
setMapLocation(l.getLatitude(), l.getLongitude());
return true;
}
return super.onTrackballEvent(event);
}
@Override
protected void onStart() {
super.onStart();
/*if (!boundToLoggingService) {
this.bindService(new Intent(this, LocationLogger.class), locationLoggerConnection, Context.BIND_AUTO_CREATE);
}*/
}
@Override
protected void onStop() {
// TODO keep this check?
if(routingHelper.isFollowingMode()){
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.notify(APP_NOTIFICATION_ID, getNotification());
}
if(progressDlg != null){
progressDlg.dismiss();
progressDlg = null;
}
/*if(boundToLoggingService) {
this.unbindService(locationLoggerConnection);
}*/
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
savingTrackHelper.close();
if(mNotificationManager != null){
mNotificationManager.cancel(APP_NOTIFICATION_ID);
}
MapTileDownloader.getInstance().removeDownloaderCallback(mapView);
if(mapView.getLayers().contains(aghTrafficLayer)) {
mapView.removeLayer(aghTrafficLayer);
}
}
private void registerUnregisterSensor(Location location){
boolean show = (currentShowingAngle && location != null) || currentMapRotation == OsmandSettings.ROTATE_MAP_COMPASS;
// show point view only if gps enabled
if (sensorRegistered && !show) {
Log.d(LogUtil.TAG, "Disable sensor"); //$NON-NLS-1$
((SensorManager) getSystemService(SENSOR_SERVICE)).unregisterListener(this);
sensorRegistered = false;
locationLayer.setHeading(null);
} else if (!sensorRegistered && show) {
Log.d(LogUtil.TAG, "Enable sensor"); //$NON-NLS-1$
SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor s = sensorMgr.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (s != null) {
sensorMgr.registerListener(this, s, SensorManager.SENSOR_DELAY_UI);
}
sensorRegistered = true;
}
}
private void updateSpeedBearing(Location location) {
// For network/gps it's bad way (not accurate). It's widely used for testing purposes
// possibly keep using only for emulator case
// if (!providerSupportsSpeed
if (isRunningOnEmulator()
&& locationLayer.getLastKnownLocation() != null && location != null) {
if (locationLayer.getLastKnownLocation().distanceTo(location) > 3) {
float d = location.distanceTo(locationLayer.getLastKnownLocation());
long time = location.getTime() - locationLayer.getLastKnownLocation().getTime();
float speed;
if (time == 0) {
speed = 0;
} else {
speed = ((float) d * 1000) / time ;
}
// incorrect in case of airplane
if (speed > 100) {
speed = 100;
}
location.setSpeed(speed);
}
}
if(!providerSupportsBearing && locationLayer.getLastKnownLocation() != null && location != null){
if(locationLayer.getLastKnownLocation().distanceTo(location) > 10){
location.setBearing(locationLayer.getLastKnownLocation().bearingTo(location));
}
}
}
public void setLocation(Location location){
if(Log.isLoggable(LogUtil.TAG, Log.DEBUG)){
Log.d(LogUtil.TAG, "Location changed " + location.getProvider()); //$NON-NLS-1$
}
if(location != null && OsmandSettings.isSavingTrackToGpx(this)){
savingTrackHelper.insertData(location.getLatitude(), location.getLongitude(),
location.getAltitude(), location.getSpeed(), location.getTime(), settings);
}
registerUnregisterSensor(location);
updateSpeedBearing(location);
locationLayer.setLastKnownLocation(location);
if(routingHelper.isFollowingMode()){
routingHelper.setCurrentLocation(location);
}
if (location != null) {
if (isMapLinkedToLocation()) {
if(OsmandSettings.isAutoZoomEnabled(settings) && location.hasSpeed()){
int z = defineZoomFromSpeed(location.getSpeed(), mapView.getZoom());
if(mapView.getZoom() != z && !mapView.mapIsAnimating()){
long now = System.currentTimeMillis();
// prevent ui hysterisis (check time interval for autozoom)
if(Math.abs(mapView.getZoom() - z) > 1 || (lastTimeAutoZooming - now) > 6500){
lastTimeAutoZooming = now;
mapView.setZoom(z);
}
}
}
if (location.hasBearing() && currentMapRotation == OsmandSettings.ROTATE_MAP_BEARING) {
mapView.setRotate(-location.getBearing());
}
mapView.setLatLon(location.getLatitude(), location.getLongitude());
} else {
if(backToLocation.getVisibility() != View.VISIBLE){
backToLocation.setVisibility(View.VISIBLE);
}
}
} else {
if(backToLocation.getVisibility() != View.INVISIBLE){
backToLocation.setVisibility(View.INVISIBLE);
}
}
}
public int defineZoomFromSpeed(float speed, int currentZoom){
speed *= 3.6;
if(speed < 4){
return currentZoom;
} else if(speed < 33){
// less than 33 - show 17
return 17;
} else if(speed < 53){
return 16;
} else if(speed < 83){
return 15;
}
// more than 80 - show 14 (it is slow)
return 14;
}
public void navigateToPoint(LatLon point){
if(point != null){
OsmandSettings.setPointToNavigate(this, point.getLatitude(), point.getLongitude());
} else {
OsmandSettings.clearPointToNavigate(settings);
}
routingHelper.setFinalAndCurrentLocation(point, null, routingHelper.getCurrentGPXRoute());
if(point == null){
routingHelper.setFollowingMode(false);
stopLogger();
OsmandSettings.setFollowingByRoute(MapActivity.this, false);
}
navigationLayer.setPointToNavigate(point);
}
public Location getLastKnownLocation(){
return locationLayer.getLastKnownLocation();
}
public LatLon getMapLocation(){
return new LatLon(mapView.getLatitude(), mapView.getLongitude());
}
public LatLon getPointToNavigate(){
return navigationLayer.getPointToNavigate();
}
public RoutingHelper getRoutingHelper() {
return routingHelper;
}
private boolean isRunningOnEmulator(){
if (Build.DEVICE.equals("generic")) { //$NON-NLS-1$
return true;
}
return false;
}
private boolean useOnlyGPS() {
return (routingHelper != null && routingHelper.isFollowingMode())
|| (System.currentTimeMillis() - lastTimeGPXLocationFixed) < USE_ONLY_GPS_INTERVAL || isRunningOnEmulator();
}
// Working with location listeners
private LocationListener networkListener = new LocationListener(){
@Override
public void onLocationChanged(Location location) {
// double check about use only gps
// that strange situation but it could happen?
if(!Algoritms.objectEquals(currentLocationProvider, LocationManager.GPS_PROVIDER) &&
!useOnlyGPS()){
setLocation(location);
}
}
@Override
public void onProviderDisabled(String provider) {
if(!useOnlyGPS()){
setLocation(null);
}
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
if(LocationProvider.OUT_OF_SERVICE == status && !useOnlyGPS()){
setLocation(null);
}
}
};
private LocationListener gpsListener = new LocationListener(){
@Override
public void onLocationChanged(Location location) {
if (location != null) {
lastTimeGPXLocationFixed = location.getTime();
}
setLocation(location);
}
@Override
public void onProviderDisabled(String provider) {
setLocation(null);
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
LocationProvider prov = service.getProvider(LocationManager.NETWORK_PROVIDER);
// do not change provider for temporarily unavailable (possible bug for htc hero 2.1 ?)
if (LocationProvider.OUT_OF_SERVICE == status /*|| LocationProvider.TEMPORARILY_UNAVAILABLE == status*/) {
if(LocationProvider.OUT_OF_SERVICE == status){
setLocation(null);
}
// do not use it in routing
if (!useOnlyGPS() &&
service.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
if (!Algoritms.objectEquals(currentLocationProvider, LocationManager.NETWORK_PROVIDER)) {
currentLocationProvider = LocationManager.NETWORK_PROVIDER;
service.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, this);
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
}
}
} else if (LocationProvider.AVAILABLE == status) {
if (!Algoritms.objectEquals(currentLocationProvider, LocationManager.GPS_PROVIDER)) {
currentLocationProvider = LocationManager.GPS_PROVIDER;
service.removeUpdates(networkListener);
prov = service.getProvider(LocationManager.GPS_PROVIDER);
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
}
}
}
};
@Override
protected void onPause() {
super.onPause();
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
service.removeUpdates(gpsListener);
service.removeUpdates(networkListener);
SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorMgr.unregisterListener(this);
sensorRegistered = false;
currentLocationProvider = null;
routingHelper.setUiActivity(null);
((OsmandApplication)getApplication()).getDaynightHelper().onMapPause();
OsmandSettings.setLastKnownMapLocation(this, (float) mapView.getLatitude(), (float) mapView.getLongitude());
AnimateDraggingMapThread animatedThread = mapView.getAnimatedDraggingThread();
if(animatedThread.isAnimating() && animatedThread.getTargetZoom() != 0){
OsmandSettings.setMapLocationToShow(this, animatedThread.getTargetLatitude(), animatedThread.getTargetLongitude(),
animatedThread.getTargetZoom());
}
OsmandSettings.setLastKnownMapZoom(this, mapView.getZoom());
if (wakeLock != null) {
wakeLock.release();
wakeLock = null;
}
OsmandSettings.setMapActivityEnabled(this, false);
((OsmandApplication)getApplication()).getResourceManager().interruptRendering();
((OsmandApplication)getApplication()).getResourceManager().setBusyIndicator(null);
}
private void updateApplicationModeSettings(){
currentMapRotation = OsmandSettings.getRotateMap(settings);
currentShowingAngle = OsmandSettings.isShowingViewAngle(settings);
if(currentMapRotation == OsmandSettings.ROTATE_MAP_NONE){
mapView.setRotate(0);
}
if(!currentShowingAngle){
locationLayer.setHeading(null);
}
locationLayer.setAppMode(OsmandSettings.getApplicationMode(settings));
routingHelper.setAppMode(OsmandSettings.getApplicationMode(settings));
mapView.setMapPosition(OsmandSettings.getPositionOnMap(settings));
registerUnregisterSensor(getLastKnownLocation());
updateLayers();
}
private void updateLayers(){
if(mapView.getLayers().contains(transportStopsLayer) != OsmandSettings.isShowingTransportOverMap(settings)){
if(OsmandSettings.isShowingTransportOverMap(settings)){
mapView.addLayer(transportStopsLayer, 5);
} else {
mapView.removeLayer(transportStopsLayer);
}
}
if(mapView.getLayers().contains(osmBugsLayer) != OsmandSettings.isShowingOsmBugs(settings)){
if(OsmandSettings.isShowingOsmBugs(settings)){
mapView.addLayer(osmBugsLayer, 2);
} else {
mapView.removeLayer(osmBugsLayer);
}
}
if(mapView.getLayers().contains(poiMapLayer) != OsmandSettings.isShowingPoiOverMap(settings)){
if(OsmandSettings.isShowingPoiOverMap(settings)){
mapView.addLayer(poiMapLayer, 3);
} else {
mapView.removeLayer(poiMapLayer);
}
}
if(mapView.getLayers().contains(favoritesLayer) != OsmandSettings.isShowingFavorites(settings)){
if(OsmandSettings.isShowingFavorites(settings)){
mapView.addLayer(favoritesLayer, 4);
} else {
mapView.removeLayer(favoritesLayer);
}
}
if(mapView.getLayers().contains(aghTrafficLayer) != OsmandSettings.isShowingAghTraffic(settings)){
if(OsmandSettings.isShowingAghTraffic(settings)){
mapView.addLayer(aghTrafficLayer, 0.8f);
} else {
mapView.removeLayer(aghTrafficLayer);
}
}
trafficLayer.setVisible(OsmandSettings.isShowingYandexTraffic(settings));
}
private void updateMapSource(){
boolean vectorData = OsmandSettings.isUsingMapVectorData(settings);
OsmandApplication app = ((OsmandApplication)getApplication());
ResourceManager rm = app.getResourceManager();
if(vectorData && !app.isApplicationInitializing()){
if(rm.getRenderer().isEmpty()){
Toast.makeText(MapActivity.this, getString(R.string.no_vector_map_loaded), Toast.LENGTH_LONG).show();
vectorData = false;
}
}
ITileSource newSource = OsmandSettings.getMapTileSource(settings);
if(mapView.getMap() instanceof SQLiteTileSource){
((SQLiteTileSource)mapView.getMap()).closeDB();
}
rm.updateMapSource(vectorData, newSource);
mapView.setMap(vectorData ? null : newSource);
ZoomControls zoomControls = (ZoomControls) findViewById(R.id.ZoomControls);
zoomControls.setIsZoomInEnabled(mapView.getZoom() + 1 < mapView.getMaximumShownMapZoom());
zoomControls.setIsZoomOutEnabled(mapView.getZoom() + 1 > mapView.getMinimumShownMapZoom());
rendererLayer.setVisible(vectorData);
}
@Override
protected void onResume() {
super.onResume();
if(OsmandSettings.getMapOrientation(settings) != getRequestedOrientation()){
setRequestedOrientation(OsmandSettings.getMapOrientation(settings));
// can't return from this method we are not sure if activity will be recreated or not
}
currentScreenOrientation = getWindow().getWindowManager().getDefaultDisplay().getOrientation();
boolean showTiles = !OsmandSettings.isUsingMapVectorData(settings);
ITileSource source = showTiles ? OsmandSettings.getMapTileSource(settings) : null;
if (showTiles != !rendererLayer.isVisible() || !Algoritms.objectEquals(mapView.getMap(), source)) {
updateMapSource();
}
updateApplicationModeSettings();
poiMapLayer.setFilter(OsmandSettings.getPoiFilterForMap(this, (OsmandApplication) getApplication()));
backToLocation.setVisibility(View.INVISIBLE);
routingHelper.setUiActivity(this);
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, gpsListener);
currentLocationProvider = LocationManager.GPS_PROVIDER;
} catch (IllegalArgumentException e) {
Log.d(LogUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
}
if(!useOnlyGPS()){
// try to always ask for network provide : it is faster way to find location
try {
service.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, networkListener);
currentLocationProvider = LocationManager.NETWORK_PROVIDER;
} catch(IllegalArgumentException e) {
Log.d(LogUtil.TAG, "Network location provider not available"); //$NON-NLS-1$
}
}
LocationProvider prov = service.getProvider(currentLocationProvider);
providerSupportsBearing = prov == null ? false : prov.supportsBearing() && !isRunningOnEmulator();
providerSupportsSpeed = prov == null ? false : prov.supportsSpeed() && !isRunningOnEmulator();
if(settings != null && settings.contains(OsmandSettings.LAST_KNOWN_MAP_LAT)){
LatLon l = OsmandSettings.getLastKnownMapLocation(settings);
mapView.setLatLon(l.getLatitude(), l.getLongitude());
mapView.setZoom(OsmandSettings.getLastKnownMapZoom(settings));
}
if (wakeLock == null) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "net.osmand.map"); //$NON-NLS-1$
wakeLock.acquire();
}
OsmandSettings.setMapActivityEnabled(this, true);
checkExternalStorage();
showAndHideMapPosition();
LatLon latLon = OsmandSettings.getAndClearMapLocationToShow(settings);
LatLon cur = new LatLon(mapView.getLatitude(), mapView.getLongitude());
if (latLon != null && !latLon.equals(cur)) {
mapView.getAnimatedDraggingThread().startMoving(cur.getLatitude(), cur.getLongitude(), latLon.getLatitude(),
latLon.getLongitude(), mapView.getZoom(), OsmandSettings.getMapZoomToShow(settings), mapView.getSourceTileSize(),
mapView.getRotate(), true);
}
View progress = findViewById(R.id.ProgressBar);
if(progress != null){
((OsmandApplication) getApplication()).getResourceManager().setBusyIndicator(new BusyIndicator(this, progress));
}
((OsmandApplication)getApplication()).getDaynightHelper().onMapResume();
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
contextMenuPoint(mapView.getLatitude(), mapView.getLongitude());
return true;
}
return false;
}
public void checkExternalStorage(){
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
// ok
} else if(Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){
Toast.makeText(this, R.string.sd_mounted_ro, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, R.string.sd_unmounted, Toast.LENGTH_LONG).show();
}
}
public void showAndHideMapPosition(){
mapView.setShowMapPosition(true);
if(mapPositionHandler == null){
mapPositionHandler = new Handler();
}
Message msg = Message.obtain(mapPositionHandler, new Runnable(){
@Override
public void run() {
if(mapView.isShowMapPosition()){
mapView.setShowMapPosition(false);
mapView.refreshMap();
}
}
});
msg.what = 7;
mapPositionHandler.removeMessages(7);
mapPositionHandler.sendMessageDelayed(msg, 2500);
}
@Override
public void locationChanged(double newLatitude, double newLongitude, Object source) {
// when user start dragging
if(locationLayer.getLastKnownLocation() != null){
if(isMapLinkedToLocation()){
OsmandSettings.setSyncMapToGpsLocation(MapActivity.this, false);
}
if (backToLocation.getVisibility() != View.VISIBLE) {
runOnUiThread(new Runnable() {
@Override
public void run() {
backToLocation.setVisibility(View.VISIBLE);
}
});
}
}
}
public void setMapLocation(double lat, double lon){
mapView.setLatLon(lat, lon);
locationChanged(lat, lon, this);
}
public OsmandMapTileView getMapView() {
return mapView;
}
@Override
public void onSensorChanged(SensorEvent event) {
// Attention : sensor produces a lot of events & can hang the system
float val = event.values[0];
if(currentScreenOrientation == 1){
val += 90;
}
if (currentMapRotation == OsmandSettings.ROTATE_MAP_COMPASS) {
mapView.setRotate(-val);
}
if(currentShowingAngle){
if(locationLayer.getHeading() == null || Math.abs(locationLayer.getHeading() - val) > 10){
locationLayer.setHeading(val);
}
}
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.map_menu, menu);
MenuItem item = menu.findItem(R.id.map_enable_ad_hoc);
if(application.adHocModule.isProcessRunning()) {
item.setChecked(true);
} else {
item.setChecked(false);
}
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean val = super.onPrepareOptionsMenu(menu);
MenuItem navigateToPointMenu = menu.findItem(R.id.map_navigate_to_point);
if (navigateToPointMenu != null) {
navigateToPointMenu.setTitle(routingHelper.isRouteCalculated() ? R.string.stop_routing : R.string.stop_navigation);
if (OsmandSettings.getPointToNavigate(settings) != null) {
navigateToPointMenu.setVisible(true);
} else {
navigateToPointMenu.setVisible(false);
}
}
MenuItem muteMenu = menu.findItem(R.id.map_mute);
if(muteMenu != null){
muteMenu.setTitle(routingHelper.getVoiceRouter().isMute() ? R.string.menu_mute_on : R.string.menu_mute_off);
if (routingHelper.getFinalLocation() != null && routingHelper.isFollowingMode()) {
muteMenu.setVisible(true);
} else {
muteMenu.setVisible(false);
}
}
return val;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.map_show_settings) {
final Intent settings = new Intent(MapActivity.this, SettingsActivity.class);
startActivity(settings);
return true;
} else if (item.getItemId() == R.id.map_menu_send_points) {
// for test only
LocationBuffer.INSTANCE.sendLocations();
return true;
} else if (item.getItemId() == R.id.map_menu_clear_points) {
// for test only
LocationBuffer.INSTANCE.getAndClearLocations();
return true;
} else if (item.getItemId() == R.id.map_where_am_i) {
backToLocationImpl();
return true;
} else if (item.getItemId() == R.id.map_show_gps_status) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(GPS_STATUS_COMPONENT, GPS_STATUS_ACTIVITY));
ResolveInfo resolved = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
if(resolved != null){
startActivity(intent);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.gps_status_app_not_found));
builder.setPositiveButton(getString(R.string.default_buttons_yes),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:" + GPS_STATUS_COMPONENT));
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
}
}
});
builder.setNegativeButton(getString(R.string.default_buttons_no), null);
builder.show();
}
return true;
// } else if (item.getItemId() == R.id.map_mark_point) {
// contextMenuPoint(mapView.getLatitude(), mapView.getLongitude());
// return true;
} else if (item.getItemId() == R.id.map_get_directions) {
getDirections(mapView.getLatitude(), mapView.getLongitude(), true);
return true;
} else if (item.getItemId() == R.id.map_layers) {
openLayerSelectionDialog();
return true;
} else if (item.getItemId() == R.id.map_specify_point) {
openChangeLocationDialog();
return true;
} else if (item.getItemId() == R.id.map_mute) {
routingHelper.getVoiceRouter().setMute(!routingHelper.getVoiceRouter().isMute());
return true;
} else if (item.getItemId() == R.id.map_navigate_to_point) {
if(navigationLayer.getPointToNavigate() != null){
if(routingHelper.isRouteCalculated()){
routingHelper.setFinalAndCurrentLocation(null, null);
OsmandSettings.setFollowingByRoute(MapActivity.this, false);
routingHelper.setFollowingMode(false);
stopLogger();
} else {
navigateToPoint(null);
}
} else {
navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude()));
}
mapView.refreshMap();
} else if (item.getItemId() == R.id.map_gpx_routing) {
useGPXFileLayer(true, navigationLayer.getPointToNavigate());
return true;
} else if (item.getItemId() == R.id.map_show_point_options) {
contextMenuPoint(mapView.getLatitude(), mapView.getLongitude());
return true;
} else if (item.getItemId() == R.id.map_enable_ad_hoc) {
if(item.isChecked()) {
stopAdHoc();
item.setChecked(false);
} else {
startAdHoc();
item.setChecked(true);
}
}
return super.onOptionsItemSelected(item);
}
private ApplicationMode getAppMode(ToggleButton[] buttons){
for(int i=0; i<buttons.length; i++){
if(buttons[i] != null && buttons[i].isChecked() && i < ApplicationMode.values().length){
return ApplicationMode.values()[i];
}
}
return OsmandSettings.getApplicationMode(settings);
}
protected void getDirections(final double lat, final double lon, boolean followEnabled){
if(navigationLayer.getPointToNavigate() == null){
Toast.makeText(this, R.string.mark_final_location_first, Toast.LENGTH_LONG).show();
return;
}
Builder builder = new AlertDialog.Builder(this);
View view = getLayoutInflater().inflate(R.layout.calculate_route, null);
final ToggleButton[] buttons = new ToggleButton[ApplicationMode.values().length];
buttons[ApplicationMode.CAR.ordinal()] = (ToggleButton) view.findViewById(R.id.CarButton);
buttons[ApplicationMode.BICYCLE.ordinal()] = (ToggleButton) view.findViewById(R.id.BicycleButton);
buttons[ApplicationMode.PEDESTRIAN.ordinal()] = (ToggleButton) view.findViewById(R.id.PedestrianButton);
ApplicationMode appMode = OsmandSettings.getApplicationMode(settings);
for(int i=0; i< buttons.length; i++){
if(buttons[i] != null){
final int ind = i;
ToggleButton b = buttons[i];
b.setChecked(appMode == ApplicationMode.values()[i]);
b.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
for (int j = 0; j < buttons.length; j++) {
if (buttons[j] != null) {
if(buttons[j].isChecked() != (ind == j)){
buttons[j].setChecked(ind == j);
}
}
}
} else {
// revert state
boolean revert = true;
for (int j = 0; j < buttons.length; j++) {
if (buttons[j] != null) {
if(buttons[j].isChecked()){
revert = false;
break;
}
}
}
if (revert){
buttons[ind].setChecked(true);
}
}
}
});
}
}
DialogInterface.OnClickListener onlyShowCall = new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
ApplicationMode mode = getAppMode(buttons);
Location map = new Location("map"); //$NON-NLS-1$
map.setLatitude(lat);
map.setLongitude(lon);
routingHelper.setAppMode(mode);
OsmandSettings.setFollowingByRoute(MapActivity.this, false);
routingHelper.setFollowingMode(false);
stopLogger();
routingHelper.setFinalAndCurrentLocation(navigationLayer.getPointToNavigate(), map);
}
};
DialogInterface.OnClickListener followCall = new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
ApplicationMode mode = getAppMode(buttons);
// change global settings
ApplicationMode old = OsmandSettings.getApplicationMode(settings);
if (old != mode) {
Editor edit = getSharedPreferences(OsmandSettings.SHARED_PREFERENCES_NAME, MODE_WORLD_WRITEABLE).edit();
edit.putString(OsmandSettings.APPLICATION_MODE, mode.name());
SettingsActivity.setAppMode(mode, edit, (OsmandApplication) getApplication(), old);
edit.commit();
updateApplicationModeSettings();
mapView.refreshMap();
}
Location location = locationLayer.getLastKnownLocation();
if(location == null){
location = new Location("map"); //$NON-NLS-1$
location.setLatitude(lat);
location.setLongitude(lon);
}
routingHelper.setAppMode(mode);
OsmandSettings.setFollowingByRoute(MapActivity.this, true);
routingHelper.setFollowingMode(true);
startLogger();
routingHelper.setFinalAndCurrentLocation(navigationLayer.getPointToNavigate(), location);
((OsmandApplication) getApplication()).showDialogInitializingCommandPlayer(MapActivity.this);
}
};
DialogInterface.OnClickListener showRoute = new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(MapActivity.this, ShowRouteInfoActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
};
builder.setView(view);
if (followEnabled) {
builder.setTitle(R.string.follow_route);
builder.setPositiveButton(R.string.follow, followCall);
if (routingHelper.isRouterEnabled() && routingHelper.isRouteCalculated()) {
builder.setNeutralButton(R.string.route_about, showRoute);
}
builder.setNegativeButton(R.string.only_show, onlyShowCall);
} else {
builder.setTitle(R.string.show_route);
view.findViewById(R.id.TextView).setVisibility(View.GONE);
builder.setPositiveButton(R.string.show_route, onlyShowCall);
builder.setNegativeButton(R.string.default_buttons_cancel, null);
}
builder.show();
}
protected void reloadTile(final int zoom, final double latitude, final double longitude){
Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.context_menu_item_update_map_confirm);
builder.setNegativeButton(R.string.default_buttons_cancel, null);
builder.setPositiveButton(R.string.context_menu_item_update_map, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
Rect pixRect = new Rect(0, 0, mapView.getWidth(), mapView.getHeight());
RectF tilesRect = new RectF();
mapView.calculateTileRectangle(pixRect, mapView.getCenterPointX(), mapView.getCenterPointY(),
mapView.getXTile(), mapView.getYTile(), tilesRect);
int left = (int) FloatMath.floor(tilesRect.left);
int top = (int) FloatMath.floor(tilesRect.top);
int width = (int) (FloatMath.ceil(tilesRect.right) - left);
int height = (int) (FloatMath.ceil(tilesRect.bottom) - top);
for (int i = 0; i <width; i++) {
for (int j = 0; j< height; j++) {
((OsmandApplication)getApplication()).getResourceManager().
clearTileImageForMap(null, mapView.getMap(), i + left, j + top, zoom);
}
}
mapView.refreshMap();
}
});
builder.setNeutralButton(R.string.context_menu_item_update_poi, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
updatePoiDb(zoom, latitude, longitude);
}
});
builder.create().show();
}
protected void parseLaunchIntentLocation(){
Intent intent = getIntent();
if(intent != null && intent.getData() != null){
Uri data = intent.getData();
if("http".equalsIgnoreCase(data.getScheme()) && "download.osmand.net".equals(data.getHost()) &&
"/go".equals( data.getPath())) {
String lat = data.getQueryParameter("lat");
String lon = data.getQueryParameter("lon");
if (lat != null && lon != null) {
try {
double lt = Double.parseDouble(lat);
double ln = Double.parseDouble(lon);
SharedPreferences prefs = OsmandSettings.getSharedPreferences(this);
Editor edit = prefs.edit();
edit.putFloat(OsmandSettings.LAST_KNOWN_MAP_LAT, (float) lt);
edit.putFloat(OsmandSettings.LAST_KNOWN_MAP_LON, (float) ln);
String zoom = data.getQueryParameter("z");
if(zoom != null){
edit.putInt(OsmandSettings.LAST_KNOWN_MAP_ZOOM, Integer.parseInt(zoom));
}
edit.commit();
} catch (NumberFormatException e) {
}
}
}
}
}
protected void showToast(final String msg){
runOnUiThread(new Runnable(){
@Override
public void run() {
Toast.makeText(MapActivity.this, msg, Toast.LENGTH_LONG).show();
}
});
}
protected void updatePoiDb(int zoom, double latitude, double longitude){
if(zoom < 15){
Toast.makeText(this, getString(R.string.update_poi_is_not_available_for_zoom), Toast.LENGTH_SHORT).show();
return;
}
final List<AmenityIndexRepository> repos = ((OsmandApplication) getApplication()).
getResourceManager().searchAmenityRepositories(latitude, longitude);
if(repos.isEmpty()){
Toast.makeText(this, getString(R.string.update_poi_no_offline_poi_index), Toast.LENGTH_SHORT).show();
return;
}
Rect pixRect = new Rect(-mapView.getWidth()/2, -mapView.getHeight()/2, 3*mapView.getWidth()/2, 3*mapView.getHeight()/2);
RectF tileRect = new RectF();
mapView.calculateTileRectangle(pixRect, mapView.getCenterPointX(), mapView.getCenterPointY(),
mapView.getXTile(), mapView.getYTile(), tileRect);
final double leftLon = MapUtils.getLongitudeFromTile(zoom, tileRect.left);
final double topLat = MapUtils.getLatitudeFromTile(zoom, tileRect.top);
final double rightLon = MapUtils.getLongitudeFromTile(zoom, tileRect.right);
final double bottomLat = MapUtils.getLatitudeFromTile(zoom, tileRect.bottom);
progressDlg = ProgressDialog.show(this, getString(R.string.loading), getString(R.string.loading_data));
new Thread(new Runnable(){
@Override
public void run() {
try {
List<Amenity> amenities = new ArrayList<Amenity>();
boolean loadingPOIs = AmenityIndexRepositoryOdb.loadingPOIs(amenities, leftLon, topLat, rightLon, bottomLat);
if(!loadingPOIs){
showToast(getString(R.string.update_poi_error_loading));
} else {
for(AmenityIndexRepository r : repos){
if(r instanceof AmenityIndexRepositoryOdb){
((AmenityIndexRepositoryOdb) r).updateAmenities(amenities, leftLon, topLat, rightLon, bottomLat);
}
}
showToast(MessageFormat.format(getString(R.string.update_poi_success), amenities.size()));
mapView.refreshMap();
}
} catch(Exception e) {
Log.e(LogUtil.TAG, "Error updating local data", e); //$NON-NLS-1$
showToast(getString(R.string.update_poi_error_local));
} finally {
if(progressDlg !=null){
progressDlg.dismiss();
progressDlg = null;
}
}
}
}, "LoadingPOI").start(); //$NON-NLS-1$
}
private void openLayerSelectionDialog(){
List<String> layersList = new ArrayList<String>();
layersList.add(getString(R.string.layer_map));
layersList.add(getString(R.string.layer_poi));
layersList.add(getString(R.string.layer_transport));
layersList.add(getString(R.string.layer_osm_bugs));
layersList.add(getString(R.string.layer_favorites));
layersList.add(getString(R.string.layer_gpx_layer));
layersList.add(getString(R.string.layer_agh_traffic));
final int routeInfoInd = routeInfoLayer.couldBeVisible() ? layersList.size() : -1;
if(routeInfoLayer.couldBeVisible()){
layersList.add(getString(R.string.layer_route));
}
final int transportRouteInfoInd = !TransportRouteHelper.getInstance().routeIsCalculated() ? - 1 : layersList.size();
if(transportRouteInfoInd > -1){
layersList.add(getString(R.string.layer_transport_route));
}
final boolean[] selected = new boolean[layersList.size()];
Arrays.fill(selected, true);
selected[1] = OsmandSettings.isShowingPoiOverMap(settings);
selected[2] = OsmandSettings.isShowingTransportOverMap(settings);
selected[3] = OsmandSettings.isShowingOsmBugs(settings);
selected[4] = OsmandSettings.isShowingFavorites(settings);
selected[5] = gpxLayer.isVisible();
selected[6] = OsmandSettings.isShowingAghTraffic(settings);
if(routeInfoInd != -1){
selected[routeInfoInd] = routeInfoLayer.isUserDefinedVisible();
}
if(transportRouteInfoInd != -1){
selected[transportRouteInfoInd] = transportInfoLayer.isVisible();
}
Builder builder = new AlertDialog.Builder(this);
builder.setMultiChoiceItems(layersList.toArray(new String[layersList.size()]), selected, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int item, boolean isChecked) {
if (item == 0) {
dialog.dismiss();
selectMapLayer();
} else if(item == 1){
if(isChecked){
selectPOIFilterLayer();
}
OsmandSettings.setShowPoiOverMap(MapActivity.this, isChecked);
} else if(item == 2){
OsmandSettings.setShowTransortOverMap(MapActivity.this, isChecked);
} else if(item == 3){
OsmandSettings.setShowingOsmBugs(MapActivity.this, isChecked);
} else if(item == 4){
OsmandSettings.setShowingFavorites(MapActivity.this, isChecked);
} else if(item == 5){
if(gpxLayer.isVisible()){
gpxLayer.clearCurrentGPX();
getFavoritesHelper().setFavoritePointsFromGPXFile(null);
} else {
dialog.dismiss();
useGPXFileLayer(false, null);
}
} else if (item == 6) {
OsmandSettings.setShowingAghTraffic(MapActivity.this, isChecked);
} else if(item == routeInfoInd){
routeInfoLayer.setVisible(isChecked);
} else if(item == transportRouteInfoInd){
transportInfoLayer.setVisible(isChecked);
}
updateLayers();
mapView.refreshMap();
}
});
builder.show();
}
private void useGPXFileLayer(final boolean useRouting, final LatLon endForRouting) {
final List<String> list = new ArrayList<String>();
final File dir = OsmandSettings.extendOsmandPath(getApplicationContext(), ResourceManager.APP_DIR + SavingTrackHelper.TRACKS_PATH);
if (dir != null && dir.canRead()) {
File[] files = dir.listFiles();
if (files != null) {
Arrays.sort(files, new Comparator<File>() {
@Override
public int compare(File object1, File object2) {
if (object1.lastModified() > object2.lastModified()) {
return -1;
} else if (object1.lastModified() == object2.lastModified()) {
return 0;
}
return 1;
}
});
for (File f : files) {
if (f.getName().endsWith(".gpx")) { //$NON-NLS-1$
list.add(f.getName());
}
}
}
}
if(list.isEmpty()){
Toast.makeText(this, R.string.gpx_files_not_found, Toast.LENGTH_LONG).show();
} else {
Builder builder = new AlertDialog.Builder(this);
builder.setItems(list.toArray(new String[list.size()]), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
final ProgressDialog dlg = ProgressDialog.show(MapActivity.this, getString(R.string.loading),
getString(R.string.loading_data));
final File f = new File(dir, list.get(which));
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
final GPXFileResult res = GPXUtilities.loadGPXFile(MapActivity.this, f);
if (res.error != null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MapActivity.this, res.error, Toast.LENGTH_LONG).show();
}
});
}
dlg.dismiss();
if(useRouting){
runOnUiThread(new Runnable() {
@Override
public void run() {
useGPXRouting(endForRouting, res);
}
});
} else {
OsmandSettings.setShowingFavorites(MapActivity.this, true);
List<FavouritePoint> pts = new ArrayList<FavouritePoint>();
for(WptPt p : res.wayPoints){
FavouritePoint pt = new FavouritePoint();
pt.setLatitude(p.lat);
pt.setLongitude(p.lon);
pt.setName(p.name);
pts.add(pt);
}
getFavoritesHelper().setFavoritePointsFromGPXFile(pts);
gpxLayer.setTracks(res.locations);
}
mapView.refreshMap();
}
}, "Loading gpx").start(); //$NON-NLS-1$
}
});
builder.show();
}
}
public FavouritesDbHelper getFavoritesHelper() {
return ((OsmandApplication)getApplication()).getFavorites();
}
private void useGPXRouting(final LatLon endForRouting, final GPXFileResult res) {
Builder builder = new AlertDialog.Builder(this);
builder.setItems(new String[]{getString(R.string.gpx_direct_route), getString(R.string.gpx_reverse_route)},
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
boolean reverse = which == 1;
ArrayList<List<Location>> locations = res.locations;
List<Location> l = new ArrayList<Location>();
for(List<Location> s : locations){
l.addAll(s);
}
if(reverse){
Collections.reverse(l);
}
Location startForRouting = locationLayer.getLastKnownLocation();
if(startForRouting == null && !l.isEmpty()){
startForRouting = l.get(0);
}
LatLon endPoint = endForRouting;
if(/*endForRouting == null && */!l.isEmpty()){
LatLon point = new LatLon(l.get(l.size() - 1).getLatitude(), l.get(l.size() - 1).getLongitude());
OsmandSettings.setPointToNavigate(MapActivity.this, point.getLatitude(), point.getLongitude());
endPoint = point;
navigationLayer.setPointToNavigate(point);
}
if(endForRouting != null){
OsmandSettings.setFollowingByRoute(MapActivity.this, true);
routingHelper.setFollowingMode(true);
startLogger();
routingHelper.setFinalAndCurrentLocation(endPoint, startForRouting, l);
((OsmandApplication)getApplication()).showDialogInitializingCommandPlayer(MapActivity.this);
}
}
});
builder.show();
}
private void selectPOIFilterLayer(){
final List<PoiFilter> userDefined = new ArrayList<PoiFilter>();
List<String> list = new ArrayList<String>();
list.add(getString(R.string.any_poi));
final PoiFiltersHelper poiFilters = ((OsmandApplication)getApplication()).getPoiFilters();
for (PoiFilter f : poiFilters.getUserDefinedPoiFilters()) {
userDefined.add(f);
list.add(f.getName());
}
for(AmenityType t : AmenityType.values()){
list.add(OsmAndFormatter.toPublicString(t, this));
}
Builder builder = new AlertDialog.Builder(this);
builder.setItems(list.toArray(new String[list.size()]), new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
String filterId;
if (which == 0) {
filterId = PoiFiltersHelper.getOsmDefinedFilterId(null);
} else if (which <= userDefined.size()) {
filterId = userDefined.get(which - 1).getFilterId();
} else {
filterId = PoiFiltersHelper.getOsmDefinedFilterId(AmenityType.values()[which - userDefined.size() - 1]);
}
if(filterId.equals(PoiFilter.CUSTOM_FILTER_ID)){
Intent newIntent = new Intent(MapActivity.this, EditPOIFilterActivity.class);
newIntent.putExtra(EditPOIFilterActivity.AMENITY_FILTER, filterId);
newIntent.putExtra(EditPOIFilterActivity.SEARCH_LAT, mapView.getLatitude());
newIntent.putExtra(EditPOIFilterActivity.SEARCH_LON, mapView.getLongitude());
startActivity(newIntent);
} else {
OsmandSettings.setPoiFilterForMap(MapActivity.this, filterId);
poiMapLayer.setFilter(poiFilters.getFilterById(filterId));
mapView.refreshMap();
}
}
});
builder.show();
}
private void selectMapLayer(){
Map<String, String> entriesMap = SettingsActivity.getTileSourceEntries(this);
Builder builder = new AlertDialog.Builder(this);
final ArrayList<String> keys = new ArrayList<String>(entriesMap.keySet());
String[] items = new String[entriesMap.size() + 1];
items[0] = getString(R.string.vector_data);
int i = 1;
for(String it : entriesMap.values()){
items[i++] = it;
}
builder.setItems(items, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
Editor edit = OsmandSettings.getWriteableEditor(MapActivity.this);
if(which == 0){
MapRenderRepositories r = ((OsmandApplication)getApplication()).getResourceManager().getRenderer();
if(r.isEmpty()){
Toast.makeText(MapActivity.this, getString(R.string.no_vector_map_loaded), Toast.LENGTH_LONG).show();
return;
} else {
edit.putBoolean(OsmandSettings.MAP_VECTOR_DATA, true);
}
} else {
edit.putBoolean(OsmandSettings.MAP_VECTOR_DATA, false);
edit.putString(OsmandSettings.MAP_TILE_SOURCES, keys.get(which - 1));
}
edit.commit();
updateMapSource();
}
});
builder.show();
}
public void contextMenuPoint(final double latitude, final double longitude){
contextMenuPoint(latitude, longitude, null, null);
}
public void contextMenuPoint(final double latitude, final double longitude, List<String> additionalItems,
final DialogInterface.OnClickListener additionalActions){
Builder builder = new AlertDialog.Builder(this);
final int sizeAdditional = additionalActions == null || additionalItems == null ? 0 : additionalItems.size();
List<String> actions = new ArrayList<String>();
if(sizeAdditional > 0){
actions.addAll(additionalItems);
}
final int[] contextMenuStandardActions = new int[]{
R.string.context_menu_item_navigate_point,
R.string.context_menu_item_select_for_agh,
R.string.context_menu_item_search_poi,
R.string.context_menu_item_show_route,
R.string.context_menu_item_search_transport,
R.string.context_menu_item_add_favorite,
R.string.context_menu_item_share_location,
R.string.context_menu_item_create_poi,
R.string.context_menu_item_add_waypoint,
R.string.context_menu_item_open_bug,
R.string.context_menu_item_update_map,
R.string.context_menu_item_download_map
};
for(int j = 0; j<contextMenuStandardActions.length; j++){
actions.add(getResources().getString(contextMenuStandardActions[j]));
}
builder.setItems(actions.toArray(new String[actions.size()]), new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(which < sizeAdditional){
additionalActions.onClick(dialog, which);
return;
}
int standardId = contextMenuStandardActions[which - sizeAdditional];
if(standardId == R.string.context_menu_item_navigate_point){
navigateToPoint(new LatLon(latitude, longitude));
} else if (standardId == R.string.context_menu_item_select_for_agh) {
// for test only
LocationInfo loc = new LocationInfo();
loc.setLatitude(latitude);
loc.setLongitude(longitude);
loc.setTime(new Date());
LocationBuffer.INSTANCE.addLocation(loc);
} else if(standardId == R.string.context_menu_item_search_poi){
Intent intent = new Intent(MapActivity.this, SearchPoiFilterActivity.class);
intent.putExtra(SearchPoiFilterActivity.SEARCH_LAT, latitude);
intent.putExtra(SearchPoiFilterActivity.SEARCH_LON, longitude);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
} else if(standardId == R.string.context_menu_item_show_route){
getDirections(latitude, longitude, false);
} else if(standardId == R.string.context_menu_item_search_transport){
Intent intent = new Intent(MapActivity.this, SearchTransportActivity.class);
intent.putExtra(SearchTransportActivity.LAT_KEY, latitude);
intent.putExtra(SearchTransportActivity.LON_KEY, longitude);
startActivity(intent);
} else if(standardId == R.string.context_menu_item_add_favorite){
addFavouritePoint(latitude, longitude);
} else if(standardId == R.string.context_menu_item_share_location){
shareLocation(latitude, longitude, mapView.getZoom());
} else if(standardId == R.string.context_menu_item_search_poi){
EditingPOIActivity activity = new EditingPOIActivity(MapActivity.this, (OsmandApplication) getApplication(), mapView);
activity.showCreateDialog(latitude, longitude);
} else if(standardId == R.string.context_menu_item_add_waypoint){
addWaypoint(latitude, longitude);
} else if(standardId == R.string.context_menu_item_open_bug){
osmBugsLayer.openBug(MapActivity.this, getLayoutInflater(), mapView, latitude, longitude);
} else if(standardId == R.string.context_menu_item_update_map){
reloadTile(mapView.getZoom(), latitude, longitude);
} else if(standardId == R.string.context_menu_item_download_map){
DownloadTilesDialog dlg = new DownloadTilesDialog(MapActivity.this,
(OsmandApplication) getApplication(), mapView);
dlg.openDialog();
}
}
});
builder.create().show();
}
protected void addFavouritePoint(final double latitude, final double longitude){
final Resources resources = this.getResources();
final FavouritePoint p = new FavouritePoint(latitude, longitude, resources.getString(R.string.add_favorite_dialog_default_favourite_name));
Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.add_favorite_dialog_top_text);
final EditText editText = new EditText(this);
builder.setView(editText);
builder.setNegativeButton(R.string.default_buttons_cancel, null);
builder.setNeutralButton(R.string.update_existing, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
Builder b = new AlertDialog.Builder(MapActivity.this);
final FavouritesDbHelper helper = ((OsmandApplication)getApplication()).getFavorites();
final Collection<FavouritePoint> points = helper.getFavouritePoints();
final String[] ar = new String[points.size()];
Iterator<FavouritePoint> it = points.iterator();
int i=0;
while(it.hasNext()){
ar[i++] = it.next().getName();
}
b.setItems(ar, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
FavouritePoint fv = helper.getFavoritePointByName(ar[which]);
if(helper.editFavourite(fv, latitude, longitude)){
Toast.makeText(MapActivity.this, getString(R.string.fav_points_edited), Toast.LENGTH_SHORT).show();
}
mapView.refreshMap();
}
});
if(ar.length == 0){
Toast.makeText(MapActivity.this, getString(R.string.fav_points_not_exist), Toast.LENGTH_SHORT).show();
helper.close();
} else {
b.show();
}
}
});
builder.setPositiveButton(R.string.default_buttons_add, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final FavouritesDbHelper helper = ((OsmandApplication)getApplication()).getFavorites();
p.setName(editText.getText().toString());
boolean added = helper.addFavourite(p);
if (added) {
Toast.makeText(MapActivity.this, MessageFormat.format(getString(R.string.add_favorite_dialog_favourite_added_template), p.getName()), Toast.LENGTH_SHORT)
.show();
}
mapView.refreshMap();
}
});
builder.create().show();
}
protected void addWaypoint(final double latitude, final double longitude){
Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.add_waypoint_dialog_title);
final EditText editText = new EditText(this);
builder.setView(editText);
builder.setNegativeButton(R.string.default_buttons_cancel, null);
builder.setPositiveButton(R.string.default_buttons_add, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String name = editText.getText().toString();
savingTrackHelper.insertPointData(latitude, longitude, System.currentTimeMillis(), name);
Toast.makeText(MapActivity.this, MessageFormat.format(getString(R.string.add_waypoint_dialog_added), name), Toast.LENGTH_SHORT)
.show();
}
});
builder.create().show();
}
protected void shareLocation(final double latitude, final double longitude, int zoom){
final String shortOsmUrl = MapUtils.buildShortOsmUrl(latitude, longitude, zoom);
// final String simpleGeo = "geo:"+((float) latitude)+","+((float)longitude) +"?z="+zoom;
final String appLink = "http://download.osmand.net/go?lat="+((float) latitude)+"&lon="+((float)longitude) +"&z="+zoom;
AlertDialog.Builder builder = new Builder(this);
builder.setTitle(R.string.send_location_way_choose_title);
builder.setItems(new String[]{
"Email", "SMS", "Clipboard"
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String sms = MessageFormat.format(getString(R.string.send_location_sms_pattern), shortOsmUrl, appLink);
String email = MessageFormat.format(getString(R.string.send_location_email_pattern), shortOsmUrl, appLink );
if(which == 0){
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("vnd.android.cursor.dir/email"); //$NON-NLS-1$
intent.putExtra(Intent.EXTRA_SUBJECT, "Mine location"); //$NON-NLS-1$
intent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(email));
intent.setType("text/html");
startActivity(Intent.createChooser(intent, getString(R.string.send_location)));
} else if(which == 1){
Intent sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.putExtra("sms_body", sms);
sendIntent.setType("vnd.android-dir/mms-sms");
startActivity(sendIntent);
} else if (which == 2){
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(sms);
}
}
});
builder.show();
}
private void openChangeLocationDialog() {
NavigatePointActivity dlg = new NavigatePointActivity(this);
dlg.showDialog();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
protected void backToLocationImpl() {
backToLocation.setVisibility(View.INVISIBLE);
if(!isMapLinkedToLocation()){
OsmandSettings.setSyncMapToGpsLocation(MapActivity.this, true);
if(locationLayer.getLastKnownLocation() != null){
Location lastKnownLocation = locationLayer.getLastKnownLocation();
AnimateDraggingMapThread thread = mapView.getAnimatedDraggingThread();
int fZoom = mapView.getZoom() < 15 ? 15 : mapView.getZoom();
thread.startMoving(mapView.getLatitude(), mapView.getLongitude(),
lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude(), mapView.getZoom(), fZoom,
mapView.getSourceTileSize(), mapView.getRotate(), false);
}
}
if(locationLayer.getLastKnownLocation() == null){
Toast.makeText(this, R.string.unknown_location, Toast.LENGTH_LONG).show();
}
}
public void startLogger() {
startService(new Intent(MapActivity.this, LocationLogger.class));
}
public void stopLogger() {
stopService(new Intent(MapActivity.this, LocationLogger.class));
}
public void startAdHoc() {
new Thread(new Runnable(){
public void run(){
if (application.adHocModule.startupCheckPerformed == false) {
application.adHocModule.startupCheckPerformed = true;
// Check root-permission, files
if (!application.adHocModule.coretask.hasRootPermission())
Toast.makeText(MapActivity.this, "No root permission. Ad-hoc disabled!", Toast.LENGTH_SHORT).show();
// Check if binaries need to be updated
if (application.adHocModule.binariesExists() == false) {
if (application.adHocModule.coretask.hasRootPermission()) {
application.adHocModule.installFiles();
}
}
// Check if native-library needs to be moved
application.adHocModule.renewLibrary();
}
if(!application.adHocModule.isProcessRunning()) {
application.adHocModule.startAdHoc();
application.adHocModule.showStartNotification();
}
}
}).start();
}
public void stopAdHoc() {
new Thread(new Runnable() {
public void run() {
if(application.adHocModule.isProcessRunning()) {
application.adHocModule.stopAdHoc();
application.adHocModule.notificationManager.cancelAll();
}
}
}).start();
}
}