package net.osmand.core.samples.android.sample1; import android.Manifest; import android.annotation.SuppressLint; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.PackageManager; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PointF; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.view.View; import android.widget.ImageButton; import android.widget.TextView; import net.osmand.Location; import net.osmand.binary.BinaryMapIndexReader; import net.osmand.core.android.AtlasMapRendererView; import net.osmand.core.jni.AmenitySymbolsProvider.AmenitySymbolsGroup; import net.osmand.core.jni.AreaI; import net.osmand.core.jni.FColorRGB; import net.osmand.core.jni.IBillboardMapSymbol; import net.osmand.core.jni.IMapLayerProvider; import net.osmand.core.jni.IMapRenderer.MapSymbolInformation; import net.osmand.core.jni.IMapStylesCollection; import net.osmand.core.jni.Logger; import net.osmand.core.jni.MapMarker; import net.osmand.core.jni.MapMarker.SymbolsGroup; import net.osmand.core.jni.MapMarkerBuilder; import net.osmand.core.jni.MapMarkersCollection; import net.osmand.core.jni.MapObject; import net.osmand.core.jni.MapObjectsSymbolsProvider; import net.osmand.core.jni.MapObjectsSymbolsProvider.MapObjectSymbolsGroup; import net.osmand.core.jni.MapPresentationEnvironment; import net.osmand.core.jni.MapPrimitivesProvider; import net.osmand.core.jni.MapPrimitiviser; import net.osmand.core.jni.MapRasterLayerProvider_Software; import net.osmand.core.jni.MapStylesCollection; import net.osmand.core.jni.MapSymbolInformationList; import net.osmand.core.jni.MapSymbolsGroup.AdditionalBillboardSymbolInstanceParameters; import net.osmand.core.jni.ObfMapObject; import net.osmand.core.jni.ObfMapObjectsProvider; import net.osmand.core.jni.ObfsCollection; import net.osmand.core.jni.PointI; import net.osmand.core.jni.QIODeviceLogSink; import net.osmand.core.jni.ResolvedMapStyle; import net.osmand.core.jni.SwigUtilities; import net.osmand.core.jni.Utilities; import net.osmand.core.samples.android.sample1.MultiTouchSupport.MultiTouchZoomListener; import net.osmand.core.samples.android.sample1.SampleLocationProvider.SampleCompassListener; import net.osmand.core.samples.android.sample1.SampleLocationProvider.SampleLocationListener; import net.osmand.core.samples.android.sample1.data.PointDescription; import net.osmand.core.samples.android.sample1.mapcontextmenu.MapContextMenu; import net.osmand.core.samples.android.sample1.mapcontextmenu.MenuController; import net.osmand.core.samples.android.sample1.search.QuickSearchDialogFragment; import net.osmand.data.Amenity; import net.osmand.data.LatLon; import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; import net.osmand.osm.PoiCategory; import net.osmand.util.MapUtils; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.List; import static net.osmand.core.samples.android.sample1.SampleApplication.PERMISSION_REQUEST_LOCATION_ON_BUTTON; import static net.osmand.core.samples.android.sample1.SampleApplication.PERMISSION_REQUEST_LOCATION_ON_RESUME; import static net.osmand.core.samples.android.sample1.SampleApplication.PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE; public class MainActivity extends AppCompatActivity implements SampleLocationListener, SampleCompassListener { private static final String TAG = "OsmAndCoreSample"; private float displayDensityFactor; private int referenceTileSize; private int rasterTileSize; private IMapStylesCollection mapStylesCollection; private ResolvedMapStyle mapStyle; private ObfsCollection obfsCollection; private MapPresentationEnvironment mapPresentationEnvironment; private MapPrimitiviser mapPrimitiviser; private ObfMapObjectsProvider obfMapObjectsProvider; private MapPrimitivesProvider mapPrimitivesProvider; private MapObjectsSymbolsProvider mapObjectsSymbolsProvider; private IMapLayerProvider mapLayerProvider0; private QIODeviceLogSink fileLogSink; private AtlasMapRendererView mapView; private TextView textZoom; private ImageButton searchButton; private ImageButton compassButton; private CompassDrawable compassDrawable; private GestureDetector gestureDetector; private PointI target31; private float zoom; private float azimuth = 0; private float elevationAngle; private MultiTouchSupport multiTouchSupport; private MapContextMenu menu; // Context pin marker private MapMarkersCollection contextPinMarkersCollection; private MapMarker contextPinMarker; private static final int MARKER_ID_CONTEXT_PIN = 1; // "My location" marker, "My course" marker and collection private MapMarkersCollection myMarkersCollection; private MapMarker myLocationMarker; private static final int MARKER_ID_MY_LOCATION = 2; // Germany private final static float INIT_LAT = 49.353953f; private final static float INIT_LON = 11.214384f; // Kyiv //private final static float INIT_LAT = 50.450117f; //private final static float INIT_LON = 30.524142f; private final static float INIT_ZOOM = 6.0f; private final static float INIT_AZIMUTH = 0.0f; private final static float INIT_ELEVATION_ANGLE = 90.0f; private final static int MIN_ZOOM_LEVEL = 2; private final static int MAX_ZOOM_LEVEL = 22; private static final String PREF_MAP_CENTER_LAT = "MAP_CENTER_LAT"; private static final String PREF_MAP_CENTER_LON = "MAP_CENTER_LON"; private static final String PREF_MAP_AZIMUTH = "MAP_AZIMUTH"; private static final String PREF_MAP_ZOOM = "MAP_ZOOM"; private static final String PREF_MAP_ELEVATION_ANGLE = "MAP_ELEVATION_ANGLE"; public SampleApplication getMyApplication() { return (SampleApplication) getApplication(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { switch (requestCode) { case PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE: if (!InstallOsmandAppDialog.wasShown()) { checkMapsInstalled(); } getMyApplication().initPoiTypes(); break; case PERMISSION_REQUEST_LOCATION_ON_BUTTON: goToLocation(); case PERMISSION_REQUEST_LOCATION_ON_RESUME: getMyApplication().getLocationProvider().resumeAllUpdates(); break; } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SampleApplication app = getMyApplication(); gestureDetector = new GestureDetector(this, new MapViewOnGestureListener()); multiTouchSupport = new MultiTouchSupport(this, new MapViewMultiTouchZoomListener()); // Inflate views setContentView(R.layout.activity_main); boolean externalStoragePermissionGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; if (!externalStoragePermissionGranted) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE); } // Get map view mapView = (AtlasMapRendererView) findViewById(R.id.mapRendererView); textZoom = (TextView) findViewById(R.id.text_zoom); searchButton = (ImageButton) findViewById(R.id.search_button); searchButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showQuickSearch(ShowQuickSearchMode.NEW_IF_EXPIRED, false); } }); compassButton = (ImageButton) findViewById(R.id.map_compass_button); compassButton.setContentDescription(app.getString("rotate_map_compass_opt")); compassDrawable = new CompassDrawable(app.getIconsCache().getIcon(R.drawable.map_compass)); compassButton.setImageDrawable(compassDrawable); compassButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setAzimuth(0f); } }); ImageButton myLocationButton = (ImageButton) findViewById(R.id.map_my_location_button); myLocationButton.setImageDrawable(app.getIconsCache().getIcon("map_my_location", R.color.color_myloc_distance)); myLocationButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (SampleLocationProvider.isLocationPermissionAvailable(MainActivity.this)) { goToLocation(); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_LOCATION_ON_BUTTON); } } }); findViewById(R.id.map_zoom_in_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setZoom(zoom + 1f); } }); findViewById(R.id.map_zoom_out_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setZoom(zoom - 1f); } }); // Additional log sink fileLogSink = QIODeviceLogSink.createFileLogSink(app.getAbsoluteAppPath() + "/osmandcore.log"); Logger.get().addLogSink(fileLogSink); // Get device display density factor DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); displayDensityFactor = displayMetrics.densityDpi / 160.0f; referenceTileSize = (int) (256 * displayDensityFactor); rasterTileSize = Integer.highestOneBit(referenceTileSize - 1) * 2; Log.i(TAG, "displayDensityFactor = " + displayDensityFactor); Log.i(TAG, "referenceTileSize = " + referenceTileSize); Log.i(TAG, "rasterTileSize = " + rasterTileSize); Log.i(TAG, "Going to resolve default embedded style..."); mapStylesCollection = new MapStylesCollection(); mapStyle = mapStylesCollection.getResolvedStyleByName("default"); if (mapStyle == null) { Log.e(TAG, "Failed to resolve style 'default'"); System.exit(0); } Log.i(TAG, "Going to prepare OBFs collection"); obfsCollection = new ObfsCollection(); Log.i(TAG, "Will load OBFs from " + app.getAbsoluteAppPath()); obfsCollection.addDirectory(app.getAbsoluteAppPath(), false); Log.i(TAG, "Going to prepare all resources for renderer"); mapPresentationEnvironment = new MapPresentationEnvironment( mapStyle, displayDensityFactor, 1.0f, 1.0f, SampleApplication.LANGUAGE); //mapPresentationEnvironment->setSettings(configuration.styleSettings); mapPrimitiviser = new MapPrimitiviser( mapPresentationEnvironment); obfMapObjectsProvider = new ObfMapObjectsProvider( obfsCollection); mapPrimitivesProvider = new MapPrimitivesProvider( obfMapObjectsProvider, mapPrimitiviser, rasterTileSize); mapObjectsSymbolsProvider = new MapObjectsSymbolsProvider( mapPrimitivesProvider, rasterTileSize); mapView.setReferenceTileSizeOnScreenInPixels(referenceTileSize); mapView.addSymbolsProvider(mapObjectsSymbolsProvider); restoreMapState(); mapLayerProvider0 = new MapRasterLayerProvider_Software(mapPrimitivesProvider); mapView.setMapLayerProvider(0, mapLayerProvider0); app.getIconsCache().setDisplayDensityFactor(displayDensityFactor); initMapMarkers(); menu = new MapContextMenu(); menu.setMainActivity(this); if (!InstallOsmandAppDialog.show(getSupportFragmentManager(), this) && externalStoragePermissionGranted) { checkMapsInstalled(); } } private void checkMapsInstalled() { File mapsDir = new File(getMyApplication().getAbsoluteAppPath()); boolean noMapsFound; if (mapsDir.exists()) { File[] maps = mapsDir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { return filename.toLowerCase().endsWith(".obf"); } }); noMapsFound = maps == null || maps.length == 0; } else { noMapsFound = true; } if (noMapsFound) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.install_maps_title); builder.setMessage(R.string.install_maps_desc); builder.setNegativeButton(R.string.shared_string_cancel, null); builder.setPositiveButton(R.string.restart_app, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { SampleUtils.doRestart(MainActivity.this); } }); builder.create().show(); } } public void initMapMarkers() { // Create my location marker Drawable myLocationDrawable = OsmandResources.getDrawable("map_pedestrian_location"); myMarkersCollection = new MapMarkersCollection(); myLocationMarker = new MapMarkerBuilder() .setMarkerId(MARKER_ID_MY_LOCATION) .setIsAccuracyCircleSupported(true) .setAccuracyCircleBaseColor(new FColorRGB(32/255f, 173/255f, 229/255f)) .setBaseOrder(-206000) .setIsHidden(true) //.addOnMapSurfaceIcon(SwigUtilities.getOnSurfaceIconKey(0), SwigUtilities.createSkBitmapARGB888With( // myLocationDrawable.getIntrinsicWidth(), myLocationDrawable.getIntrinsicHeight(), // SampleUtils.getDrawableAsByteArray(myLocationDrawable))) .setPinIcon(SwigUtilities.createSkBitmapARGB888With( myLocationDrawable.getIntrinsicWidth(), myLocationDrawable.getIntrinsicHeight(), SampleUtils.getDrawableAsByteArray(myLocationDrawable))) .buildAndAddToCollection(myMarkersCollection); mapView.addSymbolsProvider(myMarkersCollection); // Create context pin marker Drawable pinDrawable = OsmandResources.getDrawable("map_pin_context_menu"); contextPinMarkersCollection = new MapMarkersCollection(); contextPinMarker = new MapMarkerBuilder() .setMarkerId(MARKER_ID_CONTEXT_PIN) .setIsAccuracyCircleSupported(false) .setBaseOrder(-210000) .setIsHidden(true) .setPinIcon(SwigUtilities.createSkBitmapARGB888With( pinDrawable.getIntrinsicWidth(), pinDrawable.getIntrinsicHeight(), SampleUtils.getDrawableAsByteArray(pinDrawable))) .setPinIconVerticalAlignment(MapMarker.PinIconVerticalAlignment.Top) .setPinIconHorisontalAlignment(MapMarker.PinIconHorisontalAlignment.CenterHorizontal) .buildAndAddToCollection(contextPinMarkersCollection); mapView.addSymbolsProvider(contextPinMarkersCollection); } public void showContextMarker(@NonNull LatLon location) { mapView.suspendSymbolsUpdate(); PointI locationI = Utilities.convertLatLonTo31(new net.osmand.core.jni.LatLon(location.getLatitude(), location.getLongitude())); contextPinMarker.setPosition(locationI); contextPinMarker.setIsHidden(false); mapView.resumeSymbolsUpdate(); } public void hideContextMarker() { mapView.suspendSymbolsUpdate(); contextPinMarker.setIsHidden(true); mapView.resumeSymbolsUpdate(); } public void goToLocation() { if (mapView != null) { SampleLocationProvider locationProvider = getMyApplication().getLocationProvider(); if (locationProvider.getLastKnownLocation() != null) { net.osmand.Location lastKnownLocation = locationProvider.getLastKnownLocation(); int fZoom = zoom < 15 ? 15 : (int)zoom; showOnMap(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude(), fZoom); //todo animation //AnimateDraggingMapThread thread = mapView.getAnimatedDraggingThread(); //thread.startMoving(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude(), fZoom, false); } if (locationProvider.getLastKnownLocation() == null) { getMyApplication().showToastMessage(getMyApplication().getString("unknown_location")); } } } @Override public void updateLocation(Location location) { final SampleApplication app = getMyApplication(); final Location lastKnownLocation = app.getLocationProvider().getLastKnownLocation(); if (lastKnownLocation == null || mapView == null){ app.runInUIThread(new Runnable() { @Override public void run() { if (!myLocationMarker.isHidden()) { mapView.suspendSymbolsUpdate(); myLocationMarker.setIsHidden(true); mapView.resumeSymbolsUpdate(); } } }); return; } final PointI target31 = Utilities.convertLatLonTo31( new net.osmand.core.jni.LatLon(location.getLatitude(), location.getLongitude())); app.runInUIThread(new Runnable() { @Override public void run() { mapView.suspendSymbolsUpdate(); myLocationMarker.setIsHidden(false); myLocationMarker.setPosition(target31); myLocationMarker.setIsAccuracyCircleVisible(true); myLocationMarker.setAccuracyCircleRadius(lastKnownLocation.getAccuracy()); mapView.resumeSymbolsUpdate(); } }); if (menu != null) { menu.updateMyLocation(location); } } @Override public void updateCompassValue(float value) { if (menu != null) { menu.updateCompassValue(value); } } @Override protected void onResume() { super.onResume(); SampleApplication app = getMyApplication(); app.getLocationProvider().checkIfLastKnownLocationIsValid(); app.getLocationProvider().addLocationListener(this); if (SampleLocationProvider.isLocationPermissionAvailable(this)) { app.getLocationProvider().resumeAllUpdates(); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_LOCATION_ON_RESUME); } mapView.handleOnResume(); } @Override protected void onPause() { SampleApplication app = getMyApplication(); app.getLocationProvider().pauseAllUpdates(); app.getLocationProvider().removeLocationListener(this); saveMapState(); mapView.handleOnPause(); super.onPause(); } @Override protected void onDestroy() { mapView.handleOnDestroy(); super.onDestroy(); } public AtlasMapRendererView getMapView() { return mapView; } public void showOnMap(LatLon latLon, int zoom) { if (latLon != null) { showOnMap(latLon.getLatitude(), latLon.getLongitude(), zoom); } } public void showOnMap(double latitude, double longitude, int zoom) { PointI target = Utilities.convertLatLonTo31( new net.osmand.core.jni.LatLon(latitude, longitude)); setTarget(target); setZoom(zoom); } public void refreshMap() { } public MapContextMenu getContextMenu() { return menu; } public boolean showContextMenu(@NonNull LatLon latLon, @Nullable PointDescription pointDescription, @Nullable Object object) { if (menu.getMultiSelectionMenu().isVisible()) { menu.getMultiSelectionMenu().hide(); } if (!getBox().containsLatLon(latLon)) { menu.setMapCenter(latLon); menu.setCenterMarker(true); } menu.show(latLon, pointDescription, object); return true; } private void showContextMenuForSelectedObjects(final LatLon latLon, final List<Object> selectedObjects) { menu.getMultiSelectionMenu().show(latLon, selectedObjects); } private void hideMultiContextMenu() { if (menu.getMultiSelectionMenu().isVisible()) { menu.getMultiSelectionMenu().hide(); } } public RotatedTileBox getBox() { RotatedTileBox.RotatedTileBoxBuilder boxBuilder = new RotatedTileBox.RotatedTileBoxBuilder(); LatLon screenCenter = getScreenCenter(); boxBuilder.setLocation(screenCenter.getLatitude(), screenCenter.getLongitude()); boxBuilder.setPixelDimensions(mapView.getWidth(), mapView.getHeight(), 0.5f, 0.5f); boxBuilder.setZoom((int)getZoom()); boxBuilder.setRotate(mapView.getRotation()); return boxBuilder.build(); } public PointI getScreenCenter31() { PointI point = new PointI(); mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2, mapView.getHeight() / 2), point); return point; } public LatLon getScreenCenter() { PointI point = new PointI(); mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2, mapView.getHeight() / 2), point); net.osmand.core.jni.LatLon jniLatLon = Utilities.convert31ToLatLon(point); return new LatLon(jniLatLon.getLatitude(), jniLatLon.getLongitude()); } public float getZoom() { return zoom; } public void saveMapState() { SharedPreferences prefs = getPreferences(MODE_PRIVATE); Editor edit = prefs.edit(); net.osmand.core.jni.LatLon latLon = Utilities.convert31ToLatLon(target31); edit.putFloat(PREF_MAP_CENTER_LAT, (float) latLon.getLatitude()); edit.putFloat(PREF_MAP_CENTER_LON, (float) latLon.getLongitude()); edit.putFloat(PREF_MAP_AZIMUTH, azimuth); edit.putFloat(PREF_MAP_ZOOM, zoom); edit.putFloat(PREF_MAP_ELEVATION_ANGLE, elevationAngle); edit.commit(); } public void restoreMapState() { SharedPreferences prefs = getPreferences(MODE_PRIVATE); float prefLat = prefs.getFloat(PREF_MAP_CENTER_LAT, INIT_LAT); float prefLon = prefs.getFloat(PREF_MAP_CENTER_LON, INIT_LON); float prefAzimuth = prefs.getFloat(PREF_MAP_AZIMUTH, INIT_AZIMUTH); float prefZoom = prefs.getFloat(PREF_MAP_ZOOM, INIT_ZOOM); float prefElevationAngle = prefs.getFloat(PREF_MAP_ELEVATION_ANGLE, INIT_ELEVATION_ANGLE); setAzimuth(prefAzimuth); setElevationAngle(prefElevationAngle); setTarget(Utilities.convertLatLonTo31(new net.osmand.core.jni.LatLon(prefLat, prefLon))); setZoom(prefZoom); } public boolean setTarget(PointI pointI) { target31 = pointI; return mapView.setTarget(pointI); } @SuppressLint("DefaultLocale") public boolean setZoom(float zoom) { if (zoom < MIN_ZOOM_LEVEL) { zoom = MIN_ZOOM_LEVEL; } else if (zoom > MAX_ZOOM_LEVEL) { zoom = MAX_ZOOM_LEVEL; } this.zoom = zoom; textZoom.setText(String.format("%.0f", zoom)); return mapView.setZoom(zoom); } public void setAzimuth(float angle) { angle = MapUtils.unifyRotationTo360(angle); azimuth = angle; mapView.setAzimuth(angle); if (angle == 0f && compassButton.getVisibility() == View.VISIBLE) { compassButton.setVisibility(View.INVISIBLE); } else if (angle != 0f) { if (compassButton.getVisibility() != View.VISIBLE) { compassButton.setVisibility(View.VISIBLE); } compassButton.invalidate(); } } public void setElevationAngle(float angle) { if (angle < 35f) { angle = 35f; } else if (angle > 90f) { angle = 90f; } this.elevationAngle = angle; mapView.setElevationAngle(angle); } public boolean onTouchEvent(MotionEvent event) { return multiTouchSupport.onTouchEvent(event) || gestureDetector.onTouchEvent(event); } private class MapViewOnGestureListener extends SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { PointI point31 = new PointI(); int[] offset = new int[]{0, 0}; mapView.getLocationInWindow(offset); PointI touchPoint = new PointI((int) e.getX() - offset[0], (int) e.getY() - offset[1]); mapView.getLocationFromScreenPoint(touchPoint, point31); net.osmand.core.jni.LatLon jniLatLon = Utilities.convert31ToLatLon(point31); double lat = jniLatLon.getLatitude(); double lon = jniLatLon.getLongitude(); int delta = 20; AreaI area = new AreaI(new PointI(touchPoint.getX() - delta, touchPoint.getY() - delta), new PointI(touchPoint.getX() + delta, touchPoint.getY() + delta)); List<Object> selectedObjects = new ArrayList<>(); MapSymbolInformationList symbolInfos = mapView.getSymbolsIn(area, false); for (int i = 0; i < symbolInfos.size(); i++) { MapSymbolInformation symbolInfo = symbolInfos.get(i); IBillboardMapSymbol billboardMapSymbol; try { billboardMapSymbol = IBillboardMapSymbol.dynamic_pointer_cast(symbolInfo.getMapSymbol()); } catch (Exception eBillboard) { billboardMapSymbol = null; } if (billboardMapSymbol != null) { lon = Utilities.get31LongitudeX(billboardMapSymbol.getPosition31().getX()); lat = Utilities.get31LatitudeY(billboardMapSymbol.getPosition31().getY()); AdditionalBillboardSymbolInstanceParameters billboardAdditionalParams; try { billboardAdditionalParams = AdditionalBillboardSymbolInstanceParameters.dynamic_pointer_cast(symbolInfo.getInstanceParameters()); } catch (Exception eBillboardParams) { billboardAdditionalParams = null; } if (billboardAdditionalParams != null) { if (billboardAdditionalParams.getOverridesPosition31()) { lon = Utilities.get31LongitudeX(billboardAdditionalParams.getPosition31().getX()); lat = Utilities.get31LatitudeY(billboardAdditionalParams.getPosition31().getY()); } } String name = null; MapMarker mapMarker; try { SymbolsGroup markerSymbolsGroup = SymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()); mapMarker = markerSymbolsGroup.getMapMarker(); } catch (Exception eMapMarker) { mapMarker = null; } if (mapMarker != null) { if (mapMarker.getMarkerId() == MARKER_ID_CONTEXT_PIN) { hideMultiContextMenu(); menu.show(); } else if (mapMarker.getMarkerId() == MARKER_ID_MY_LOCATION) { hideMultiContextMenu(); LatLon latLon = new LatLon(lat, lon); showContextMenu(latLon, new PointDescription( PointDescription.POINT_TYPE_MY_LOCATION, getMyApplication().getString("shared_string_my_location"), ""), latLon); } return true; } else { net.osmand.core.jni.Amenity amenity; try { AmenitySymbolsGroup amenitySymbolGroup = AmenitySymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()); amenity = amenitySymbolGroup.getAmenity(); } catch (Exception eAmenity) { amenity = null; } if (amenity != null) { name = amenity.getNativeName(); net.osmand.core.jni.LatLon aLatLon = Utilities.convert31ToLatLon(amenity.getPosition31()); Amenity osmandAmenity = findAmenity(amenity.getId().getId().longValue() >> 7, aLatLon.getLatitude(), aLatLon.getLongitude(), name); if (osmandAmenity != null) { if (!selectedObjects.contains(osmandAmenity)) { selectedObjects.add(osmandAmenity); } continue; } } else { MapObject mapObject; try { MapObjectSymbolsGroup objSymbolGroup = MapObjectSymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()); mapObject = objSymbolGroup.getMapObject(); } catch (Exception eMapObject) { mapObject = null; } ObfMapObject obfMapObject; if (mapObject != null) { name = mapObject.getCaptionInNativeLanguage(); try { obfMapObject = ObfMapObject.dynamic_pointer_cast(mapObject); } catch (Exception eObfMapObject) { obfMapObject = null; } if (obfMapObject != null) { name = obfMapObject.getCaptionInNativeLanguage(); Amenity osmandAmenity = findAmenity( obfMapObject.getId().getId().longValue() >> 7, lat, lon, name); if (osmandAmenity != null) { if (!selectedObjects.contains(osmandAmenity)) { selectedObjects.add(osmandAmenity); } continue; } } } } if (name != null && name.trim().length() > 0) { selectedObjects.add(new PointDescription("", name)); } else { selectedObjects.add(new PointDescription(lat, lon)); } } } } if (selectedObjects.size() == 1) { Object selectedObj = selectedObjects.get(0); LatLon latLon = new LatLon(lat, lon); //MenuController.getObjectLocation(selectedObj); PointDescription pointDescription = MenuController.getObjectName(selectedObj); //if (latLon == null) { // latLon = new LatLon(lat, lon); //} showContextMenu(latLon, pointDescription, selectedObj); return true; } else if (selectedObjects.size() > 1) { showContextMenuForSelectedObjects(new LatLon(lat, lon), selectedObjects); return true; } hideMultiContextMenu(); hideContextMenu(); return true; } private Amenity findAmenity(long id, double lat, double lon, String name) { QuadRect rect = MapUtils.calculateLatLonBbox(lat, lon, 50); List<Amenity> amenities = getMyApplication().getResourceManager().searchAmenities( new BinaryMapIndexReader.SearchPoiTypeFilter() { @Override public boolean accept(PoiCategory type, String subcategory) { return true; } @Override public boolean isEmpty() { return false; } }, rect.top, rect.left, rect.bottom, rect.right, -1, null); Amenity res = null; for (Amenity amenity : amenities) { Long amenityId = amenity.getId() >> 1; if (amenityId == id) { res = amenity; break; } } if (res == null && name != null && name.length() > 0) { for (Amenity amenity : amenities) { if (name.equals(amenity.getName())) { res = amenity; } if (res != null) { break; } } } return res; } @Override public void onLongPress(MotionEvent e) { if (!multiTouchSupport.isInMultiTouch()) { PointI point31 = new PointI(); int[] offset = new int[]{0, 0}; mapView.getLocationInWindow(offset); mapView.getLocationFromScreenPoint(new PointI((int) e.getX() - offset[0], (int) e.getY() - offset[1]), point31); net.osmand.core.jni.LatLon jniLatLon = Utilities.convert31ToLatLon(point31); showContextMenu(new LatLon(jniLatLon.getLatitude(), jniLatLon.getLongitude()), new PointDescription(jniLatLon.getLatitude(), jniLatLon.getLongitude()), null); } } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { float fromX = e2.getX() + distanceX; float fromY = e2.getY() + distanceY; float toX = e2.getX(); float toY = e2.getY(); float dx = (fromX - toX); float dy = (fromY - toY); PointI newTarget = new PointI(); mapView.getLocationFromScreenPoint(new PointI(mapView.getWidth() / 2 + (int) dx, mapView.getHeight() / 2 + (int) dy), newTarget); setTarget(newTarget); mapView.requestFocus(); hideContextMenu(false); return true; } } private class MapViewMultiTouchZoomListener implements MultiTouchZoomListener { private float initialZoom; private float initialAzimuth; private float initialElevation; private PointF centerPoint; @Override public void onGestureFinished(float scale, float rotation) { } @Override public void onGestureInit(float x1, float y1, float x2, float y2) { } @Override public void onZoomStarted(PointF centerPoint) { initialZoom = zoom; initialAzimuth = azimuth; this.centerPoint = centerPoint; } @Override public void onZoomingOrRotating(float scale, float rotation) { PointI centerLocationBefore = new PointI(); mapView.getLocationFromScreenPoint( new PointI((int) centerPoint.x, (int) centerPoint.y), centerLocationBefore); // Change zoom setZoom(initialZoom + (float) (Math.log(scale) / Math.log(2))); // Adjust current target position to keep touch center the same PointI centerLocationAfter = new PointI(); mapView.getLocationFromScreenPoint( new PointI((int) centerPoint.x, (int) centerPoint.y), centerLocationAfter); PointI centerLocationDelta = new PointI( centerLocationAfter.getX() - centerLocationBefore.getX(), centerLocationAfter.getY() - centerLocationBefore.getY()); setTarget(new PointI(target31.getX() - centerLocationDelta.getX(), target31.getY() - centerLocationDelta.getY())); /* // Convert point from screen to location PointI centerLocation = new PointI(); mapView.getLocationFromScreenPoint( new PointI((int)centerPoint.x, (int)centerPoint.y), centerLocation); // Rotate current target around center location PointI target = new PointI(xI - centerLocation.getX(), yI - centerLocation.getY()); double cosAngle = Math.cos(-Math.toRadians(rotation)); double sinAngle = Math.sin(-Math.toRadians(rotation)); PointI newTarget = new PointI( (int)(target.getX() * cosAngle - target.getY() * sinAngle + centerLocation.getX()), (int)(target.getX() * sinAngle + target.getY() * cosAngle + centerLocation.getY())); setTarget(newTarget); */ // Set rotation setAzimuth(initialAzimuth - rotation); } @Override public void onChangeViewAngleStarted() { initialElevation = elevationAngle; } @Override public void onChangingViewAngle(float angle) { setElevationAngle(initialElevation - angle); } } public void showQuickSearch(double latitude, double longitude) { hideContextMenu(); QuickSearchDialogFragment fragment = getQuickSearchDialogFragment(); if (fragment != null) { fragment.dismiss(); //refreshMap(); } QuickSearchDialogFragment.showInstance(this, "", null, true, new LatLon(latitude, longitude)); } public void showQuickSearch(Object object) { hideContextMenu(); QuickSearchDialogFragment fragment = getQuickSearchDialogFragment(); if (fragment != null) { fragment.dismiss(); //refreshMap(); } QuickSearchDialogFragment.showInstance(this, "", object, true, null); } public void showQuickSearch(ShowQuickSearchMode mode, boolean showCategories) { hideContextMenu(); QuickSearchDialogFragment fragment = getQuickSearchDialogFragment(); if (fragment != null) { if (mode == ShowQuickSearchMode.NEW || (mode == ShowQuickSearchMode.NEW_IF_EXPIRED && fragment.isExpired())) { fragment.dismiss(); QuickSearchDialogFragment.showInstance(this, "", null, showCategories, null); } else { fragment.show(); } refreshMap(); } else { QuickSearchDialogFragment.showInstance(this, "", null, showCategories, null); } } public void closeQuickSearch() { QuickSearchDialogFragment fragment = getQuickSearchDialogFragment(); if (fragment != null) { fragment.closeSearch(); refreshMap(); } } public QuickSearchDialogFragment getQuickSearchDialogFragment() { Fragment fragment = getSupportFragmentManager().findFragmentByTag(QuickSearchDialogFragment.TAG); return fragment != null && !fragment.isDetached() && !fragment.isRemoving() ? (QuickSearchDialogFragment) fragment : null; } private void hideContextMenu() { hideContextMenu(true); } private void hideContextMenu(boolean restorePosition) { if (menu.isVisible()) { if (!restorePosition) { menu.updateMapCenter(null); } menu.hide(); } else if (menu.getMultiSelectionMenu().isVisible()) { menu.getMultiSelectionMenu().hide(); } } public enum ShowQuickSearchMode { NEW, NEW_IF_EXPIRED, CURRENT, } private class CompassDrawable extends Drawable { private Drawable original; public CompassDrawable(Drawable original) { this.original = original; } @Override public void draw(@NonNull Canvas canvas) { canvas.save(); canvas.rotate(azimuth, getIntrinsicWidth() / 2, getIntrinsicHeight() / 2); original.draw(canvas); canvas.restore(); } @Override public int getMinimumHeight() { return original.getMinimumHeight(); } @Override public int getMinimumWidth() { return original.getMinimumWidth(); } @Override public int getIntrinsicHeight() { return original.getIntrinsicHeight(); } @Override public int getIntrinsicWidth() { return original.getIntrinsicWidth(); } @Override public void setChangingConfigurations(int configs) { super.setChangingConfigurations(configs); original.setChangingConfigurations(configs); } @Override public void setBounds(int left, int top, int right, int bottom) { super.setBounds(left, top, right, bottom); original.setBounds(left, top, right, bottom); } @Override public void setAlpha(int alpha) { original.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { original.setColorFilter(cf); } @Override public int getOpacity() { return original.getOpacity(); } } }