From 76d87db4a3dcf6c33a8072fda932fd3d3ab7aef3 Mon Sep 17 00:00:00 2001 From: crimean Date: Thu, 30 Aug 2018 17:20:00 +0300 Subject: [PATCH] Added search and navigate api feature. Fixes. --- .../net/osmand/aidl/IOsmAndAidlInterface.aidl | 2 + OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java | 443 ++++++++++-------- .../net/osmand/aidl/OsmandAidlService.java | 94 +--- .../aidl/navigation/NavigateSearchParams.aidl | 3 + .../aidl/navigation/NavigateSearchParams.java | 88 ++++ .../net/osmand/aidl/search/SearchParams.java | 14 +- .../plus/helpers/ExternalApiHelper.java | 224 ++++++++- 7 files changed, 569 insertions(+), 299 deletions(-) create mode 100644 OsmAnd/src/net/osmand/aidl/navigation/NavigateSearchParams.aidl create mode 100644 OsmAnd/src/net/osmand/aidl/navigation/NavigateSearchParams.java diff --git a/OsmAnd/src/net/osmand/aidl/IOsmAndAidlInterface.aidl b/OsmAnd/src/net/osmand/aidl/IOsmAndAidlInterface.aidl index 22efaa72dd..b4b8a5bd28 100644 --- a/OsmAnd/src/net/osmand/aidl/IOsmAndAidlInterface.aidl +++ b/OsmAnd/src/net/osmand/aidl/IOsmAndAidlInterface.aidl @@ -65,6 +65,7 @@ import net.osmand.aidl.IOsmAndAidlCallback; import net.osmand.aidl.search.SearchResult; import net.osmand.aidl.search.SearchParams; +import net.osmand.aidl.navigation.NavigateSearchParams; // NOTE: Add new methods at the end of file!!! @@ -128,4 +129,5 @@ interface IOsmAndAidlInterface { boolean unmuteNavigation(in UnmuteNavigationParams params); boolean search(in SearchParams params, IOsmAndAidlCallback callback); + boolean navigateSearch(in NavigateSearchParams params); } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java index db2cb7e6cf..0e83de41d9 100644 --- a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java +++ b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java @@ -19,6 +19,7 @@ import android.view.View; import android.widget.ArrayAdapter; import net.osmand.IndexConstants; +import net.osmand.Location; import net.osmand.PlatformUtil; import net.osmand.aidl.favorite.AFavorite; import net.osmand.aidl.favorite.group.AFavoriteGroup; @@ -48,14 +49,14 @@ import net.osmand.plus.MapMarkersHelper; import net.osmand.plus.MapMarkersHelper.MapMarker; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.TargetPointsHelper; +import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.audionotes.AudioVideoNotesPlugin; import net.osmand.plus.dialogs.ConfigureMapMenu; import net.osmand.plus.helpers.ColorDialogs; +import net.osmand.plus.helpers.ExternalApiHelper; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.search.listitems.QuickSearchListItem; import net.osmand.plus.views.AidlMapLayer; import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.OsmandMapLayer; @@ -63,10 +64,6 @@ import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo; import net.osmand.plus.views.mapwidgets.TextInfoWidget; -import net.osmand.search.SearchUICore; -import net.osmand.search.SearchUICore.SearchResultCollection; -import net.osmand.search.core.ObjectType; -import net.osmand.search.core.SearchSettings; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -82,6 +79,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; @@ -90,15 +88,6 @@ import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; -import static net.osmand.search.core.ObjectType.CITY; -import static net.osmand.search.core.ObjectType.HOUSE; -import static net.osmand.search.core.ObjectType.POI; -import static net.osmand.search.core.ObjectType.POSTCODE; -import static net.osmand.search.core.ObjectType.STREET; -import static net.osmand.search.core.ObjectType.STREET_INTERSECTION; -import static net.osmand.search.core.ObjectType.VILLAGE; -import static net.osmand.search.core.SearchCoreFactory.MAX_DEFAULT_SEARCH_RADIUS; - public class OsmandAidlApi { private static final Log LOG = PlatformUtil.getLog(OsmandAidlApi.class); @@ -119,6 +108,7 @@ public class OsmandAidlApi { private static final String AIDL_DATA = "aidl_data"; private static final String AIDL_URI = "aidl_uri"; private static final String AIDL_FORCE = "aidl_force"; + private static final String AIDL_SEARCH_QUERY = "aidl_search_query"; private static final String AIDL_OBJECT_ID = "aidl_object_id"; @@ -135,6 +125,7 @@ public class OsmandAidlApi { private static final String AIDL_NAVIGATE = "aidl_navigate"; private static final String AIDL_NAVIGATE_GPX = "aidl_navigate_gpx"; + private static final String AIDL_NAVIGATE_SEARCH = "aidl_navigate_search"; private static final String AIDL_PAUSE_NAVIGATION = "pause_navigation"; private static final String AIDL_RESUME_NAVIGATION = "resume_navigation"; private static final String AIDL_STOP_NAVIGATION = "stop_navigation"; @@ -165,7 +156,7 @@ public class OsmandAidlApi { this.app = app; } - public void onCreateMapActivity(final MapActivity mapActivity) { + public void onCreateMapActivity(MapActivity mapActivity) { registerRefreshMapReceiver(mapActivity); registerSetMapLocationReceiver(mapActivity); registerAddMapWidgetReceiver(mapActivity); @@ -178,6 +169,7 @@ public class OsmandAidlApi { registerStopRecordingReceiver(mapActivity); registerNavigateReceiver(mapActivity); registerNavigateGpxReceiver(mapActivity); + registerNavigateSearchReceiver(mapActivity); registerPauseNavigationReceiver(mapActivity); registerResumeNavigationReceiver(mapActivity); registerStopNavigationReceiver(mapActivity); @@ -185,7 +177,7 @@ public class OsmandAidlApi { registerUnmuteNavigationReceiver(mapActivity); } - public void onDestroyMapActivity(final MapActivity mapActivity) { + public void onDestroyMapActivity(MapActivity mapActivity) { for (BroadcastReceiver b : receivers.values()) { if(b == null) { continue; @@ -199,40 +191,48 @@ public class OsmandAidlApi { receivers = new TreeMap<>(); } - private void registerRefreshMapReceiver(final MapActivity mapActivity) { + private void registerRefreshMapReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver refreshMapReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - mapActivity.refreshMap(); + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + mapActivity.refreshMap(); + } } }; registerReceiver(refreshMapReceiver, mapActivity, AIDL_REFRESH_MAP); } - private void registerSetMapLocationReceiver(final MapActivity mapActivity) { + private void registerSetMapLocationReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver setMapLocationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - double lat = intent.getDoubleExtra(AIDL_LATITUDE, Double.NaN); - double lon = intent.getDoubleExtra(AIDL_LONGITUDE, Double.NaN); - int zoom = intent.getIntExtra(AIDL_ZOOM, 0); - boolean animated = intent.getBooleanExtra(AIDL_ANIMATED, false); - if (!Double.isNaN(lat) && !Double.isNaN(lon)) { - OsmandMapTileView mapView = mapActivity.getMapView(); - if (zoom == 0) { - zoom = mapView.getZoom(); - } else { - zoom = zoom > mapView.getMaxZoom() ? mapView.getMaxZoom() : zoom; - zoom = zoom < mapView.getMinZoom() ? mapView.getMinZoom() : zoom; - } - if (animated) { - mapView.getAnimatedDraggingThread().startMoving(lat, lon, zoom, true); - } else { - mapView.setLatLon(lat, lon); - mapView.setIntZoom(zoom); + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + double lat = intent.getDoubleExtra(AIDL_LATITUDE, Double.NaN); + double lon = intent.getDoubleExtra(AIDL_LONGITUDE, Double.NaN); + int zoom = intent.getIntExtra(AIDL_ZOOM, 0); + boolean animated = intent.getBooleanExtra(AIDL_ANIMATED, false); + if (!Double.isNaN(lat) && !Double.isNaN(lon)) { + OsmandMapTileView mapView = mapActivity.getMapView(); + if (zoom == 0) { + zoom = mapView.getZoom(); + } else { + zoom = zoom > mapView.getMaxZoom() ? mapView.getMaxZoom() : zoom; + zoom = zoom < mapView.getMinZoom() ? mapView.getMinZoom() : zoom; + } + if (animated) { + mapView.getAnimatedDraggingThread().startMoving(lat, lon, zoom, true); + } else { + mapView.setLatLon(lat, lon); + mapView.setIntZoom(zoom); + } } + mapActivity.refreshMap(); } - mapActivity.refreshMap(); } }; registerReceiver(setMapLocationReceiver, mapActivity, AIDL_SET_MAP_LOCATION); @@ -246,12 +246,14 @@ public class OsmandAidlApi { } } - private void registerAddMapWidgetReceiver(final MapActivity mapActivity) { + private void registerAddMapWidgetReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver addMapWidgetReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); String widgetId = intent.getStringExtra(AIDL_OBJECT_ID); - if (widgetId != null) { + if (mapActivity != null && widgetId != null) { AMapWidget widget = widgets.get(widgetId); if (widget != null) { MapInfoLayer layer = mapActivity.getMapLayers().getMapInfoLayer(); @@ -280,12 +282,14 @@ public class OsmandAidlApi { ma.registerReceiver(rec, new IntentFilter(filter)); } - private void registerRemoveMapWidgetReceiver(final MapActivity mapActivity) { + private void registerRemoveMapWidgetReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver removeMapWidgetReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); String widgetId = intent.getStringExtra(AIDL_OBJECT_ID); - if (widgetId != null) { + if (mapActivity != null && widgetId != null) { MapInfoLayer layer = mapActivity.getMapLayers().getMapInfoLayer(); TextInfoWidget widgetControl = widgetControls.get(widgetId); if (layer != null && widgetControl != null) { @@ -316,12 +320,14 @@ public class OsmandAidlApi { } } - private void registerAddMapLayerReceiver(final MapActivity mapActivity) { + private void registerAddMapLayerReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver addMapLayerReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); String layerId = intent.getStringExtra(AIDL_OBJECT_ID); - if (layerId != null) { + if (mapActivity != null && layerId != null) { AMapLayer layer = layers.get(layerId); if (layer != null) { OsmandMapLayer mapLayer = mapLayers.get(layerId); @@ -338,12 +344,14 @@ public class OsmandAidlApi { registerReceiver(addMapLayerReceiver, mapActivity, AIDL_ADD_MAP_LAYER); } - private void registerRemoveMapLayerReceiver(final MapActivity mapActivity) { + private void registerRemoveMapLayerReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver removeMapLayerReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); String layerId = intent.getStringExtra(AIDL_OBJECT_ID); - if (layerId != null) { + if (mapActivity != null && layerId != null) { OsmandMapLayer mapLayer = mapLayers.remove(layerId); if (mapLayer != null) { mapActivity.getMapView().removeLayer(mapLayer); @@ -355,12 +363,14 @@ public class OsmandAidlApi { registerReceiver(removeMapLayerReceiver, mapActivity, AIDL_REMOVE_MAP_LAYER); } - private void registerTakePhotoNoteReceiver(final MapActivity mapActivity) { + private void registerTakePhotoNoteReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver takePhotoNoteReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); final AudioVideoNotesPlugin plugin = OsmandPlugin.getEnabledPlugin(AudioVideoNotesPlugin.class); - if (plugin != null) { + if (mapActivity != null && plugin != null) { double lat = intent.getDoubleExtra(AIDL_LATITUDE, Double.NaN); double lon = intent.getDoubleExtra(AIDL_LONGITUDE, Double.NaN); plugin.takePhoto(lat, lon, mapActivity, false, true); @@ -370,12 +380,14 @@ public class OsmandAidlApi { registerReceiver(takePhotoNoteReceiver, mapActivity, AIDL_TAKE_PHOTO_NOTE); } - private void registerStartVideoRecordingReceiver(final MapActivity mapActivity) { + private void registerStartVideoRecordingReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver startVideoRecordingReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); final AudioVideoNotesPlugin plugin = OsmandPlugin.getEnabledPlugin(AudioVideoNotesPlugin.class); - if (plugin != null) { + if (mapActivity != null && plugin != null) { double lat = intent.getDoubleExtra(AIDL_LATITUDE, Double.NaN); double lon = intent.getDoubleExtra(AIDL_LONGITUDE, Double.NaN); plugin.recordVideo(lat, lon, mapActivity, true); @@ -385,12 +397,14 @@ public class OsmandAidlApi { registerReceiver(startVideoRecordingReceiver, mapActivity, AIDL_START_VIDEO_RECORDING); } - private void registerStartAudioRecordingReceiver(final MapActivity mapActivity) { + private void registerStartAudioRecordingReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver startAudioRecordingReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); final AudioVideoNotesPlugin plugin = OsmandPlugin.getEnabledPlugin(AudioVideoNotesPlugin.class); - if (plugin != null) { + if (mapActivity != null && plugin != null) { double lat = intent.getDoubleExtra(AIDL_LATITUDE, Double.NaN); double lon = intent.getDoubleExtra(AIDL_LONGITUDE, Double.NaN); plugin.recordAudio(lat, lon, mapActivity); @@ -400,12 +414,14 @@ public class OsmandAidlApi { registerReceiver(startAudioRecordingReceiver, mapActivity, AIDL_START_AUDIO_RECORDING); } - private void registerStopRecordingReceiver(final MapActivity mapActivity) { + private void registerStopRecordingReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver stopRecordingReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); final AudioVideoNotesPlugin plugin = OsmandPlugin.getEnabledPlugin(AudioVideoNotesPlugin.class); - if (plugin != null) { + if (mapActivity != null && plugin != null) { plugin.stopRecording(mapActivity, false); } } @@ -413,7 +429,8 @@ public class OsmandAidlApi { registerReceiver(stopRecordingReceiver, mapActivity, AIDL_STOP_RECORDING); } - private void registerNavigateReceiver(final MapActivity mapActivity) { + private void registerNavigateReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver navigateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -426,7 +443,8 @@ public class OsmandAidlApi { break; } } - if (validProfile) { + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null && validProfile) { String startName = intent.getStringExtra(AIDL_START_NAME); if (Algorithms.isEmpty(startName)) { startName = ""; @@ -461,13 +479,14 @@ public class OsmandAidlApi { @Override public void onDismiss(DialogInterface dialog) { - if (!routingHelper.isFollowingMode()) { - startNavigation(mapActivity, null, start, startDesc, dest, destDesc, profile); + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null && !routingHelper.isFollowingMode()) { + ExternalApiHelper.startNavigation(mapActivity, start, startDesc, dest, destDesc, profile); } } }); } else { - startNavigation(mapActivity, null, start, startDesc, dest, destDesc, profile); + ExternalApiHelper.startNavigation(mapActivity, start, startDesc, dest, destDesc, profile); } } } @@ -475,51 +494,120 @@ public class OsmandAidlApi { registerReceiver(navigateReceiver, mapActivity, AIDL_NAVIGATE); } - private void registerNavigateGpxReceiver(final MapActivity mapActivity) { - BroadcastReceiver navigateGpxReceiver = new BroadcastReceiver() { + private void registerNavigateSearchReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); + BroadcastReceiver navigateSearchReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - boolean force = intent.getBooleanExtra(AIDL_FORCE, false); - - GPXFile gpx = null; - if (intent.getStringExtra(AIDL_DATA) != null) { - String gpxStr = intent.getStringExtra(AIDL_DATA); - if (!Algorithms.isEmpty(gpxStr)) { - gpx = GPXUtilities.loadGPXFile(mapActivity, new ByteArrayInputStream(gpxStr.getBytes())); + String profileStr = intent.getStringExtra(AIDL_PROFILE); + final ApplicationMode profile = ApplicationMode.valueOfStringKey(profileStr, DEFAULT_PROFILE); + boolean validProfile = false; + for (ApplicationMode mode : VALID_PROFILES) { + if (mode == profile) { + validProfile = true; + break; + } + } + MapActivity mapActivity = mapActivityRef.get(); + final String searchQuery = intent.getStringExtra(AIDL_SEARCH_QUERY); + if (mapActivity != null && validProfile && !Algorithms.isEmpty(searchQuery)) { + String startName = intent.getStringExtra(AIDL_START_NAME); + if (Algorithms.isEmpty(startName)) { + startName = ""; } - } else if (intent.getParcelableExtra(AIDL_URI) != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - Uri gpxUri = intent.getParcelableExtra(AIDL_URI); - ParcelFileDescriptor gpxParcelDescriptor = null; - try { - gpxParcelDescriptor = mapActivity.getContentResolver().openFileDescriptor(gpxUri, "r"); - } catch (FileNotFoundException e) { - e.printStackTrace(); + final LatLon start; + final PointDescription startDesc; + double startLat = intent.getDoubleExtra(AIDL_START_LAT, 0); + double startLon = intent.getDoubleExtra(AIDL_START_LON, 0); + if (startLat != 0 && startLon != 0) { + start = new LatLon(startLat, startLon); + startDesc = new PointDescription(PointDescription.POINT_TYPE_LOCATION, startName); + } else { + Location location = app.getLocationProvider().getLastKnownLocation(); + if (location != null) { + start = new LatLon(location.getLatitude(), location.getLongitude()); + startDesc = new PointDescription(PointDescription.POINT_TYPE_MY_LOCATION, mapActivity.getString(R.string.shared_string_my_location)); + } else { + start = null; + startDesc = null; } - if (gpxParcelDescriptor != null) { - FileDescriptor fileDescriptor = gpxParcelDescriptor.getFileDescriptor(); - gpx = GPXUtilities.loadGPXFile(mapActivity, new FileInputStream(fileDescriptor)); + } + + if (start != null) { + final RoutingHelper routingHelper = app.getRoutingHelper(); + boolean force = intent.getBooleanExtra(AIDL_FORCE, true); + if (routingHelper.isFollowingMode() && !force) { + AlertDialog dlg = mapActivity.getMapActions().stopNavigationActionConfirm(); + dlg.setOnDismissListener(new DialogInterface.OnDismissListener() { + + @Override + public void onDismiss(DialogInterface dialog) { + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null && !routingHelper.isFollowingMode()) { + ExternalApiHelper.searchAndNavigate(mapActivity, start, startDesc, profile, searchQuery); + } + } + }); + } else { + ExternalApiHelper.searchAndNavigate(mapActivity, start, startDesc, profile, searchQuery); } } } + } + }; + registerReceiver(navigateSearchReceiver, mapActivity, AIDL_NAVIGATE_SEARCH); + } - if (gpx != null) { - final RoutingHelper routingHelper = app.getRoutingHelper(); - if (routingHelper.isFollowingMode() && !force) { - final GPXFile gpxFile = gpx; - AlertDialog dlg = mapActivity.getMapActions().stopNavigationActionConfirm(); - dlg.setOnDismissListener(new DialogInterface.OnDismissListener() { + private void registerNavigateGpxReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); + BroadcastReceiver navigateGpxReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + boolean force = intent.getBooleanExtra(AIDL_FORCE, false); + GPXFile gpx = null; + if (intent.getStringExtra(AIDL_DATA) != null) { + String gpxStr = intent.getStringExtra(AIDL_DATA); + if (!Algorithms.isEmpty(gpxStr)) { + gpx = GPXUtilities.loadGPXFile(mapActivity, new ByteArrayInputStream(gpxStr.getBytes())); + } + } else if (intent.getParcelableExtra(AIDL_URI) != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + Uri gpxUri = intent.getParcelableExtra(AIDL_URI); - @Override - public void onDismiss(DialogInterface dialog) { - if (!routingHelper.isFollowingMode()) { - startNavigation(mapActivity, gpxFile, null, null, null, null, null); - } + ParcelFileDescriptor gpxParcelDescriptor = null; + try { + gpxParcelDescriptor = mapActivity.getContentResolver().openFileDescriptor(gpxUri, "r"); + } catch (FileNotFoundException e) { + e.printStackTrace(); } - }); - } else { - startNavigation(mapActivity, gpx, null, null, null, null, null); + if (gpxParcelDescriptor != null) { + FileDescriptor fileDescriptor = gpxParcelDescriptor.getFileDescriptor(); + gpx = GPXUtilities.loadGPXFile(mapActivity, new FileInputStream(fileDescriptor)); + } + } + } + + if (gpx != null) { + final RoutingHelper routingHelper = app.getRoutingHelper(); + if (routingHelper.isFollowingMode() && !force) { + final GPXFile gpxFile = gpx; + AlertDialog dlg = mapActivity.getMapActions().stopNavigationActionConfirm(); + dlg.setOnDismissListener(new DialogInterface.OnDismissListener() { + + @Override + public void onDismiss(DialogInterface dialog) { + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null && !routingHelper.isFollowingMode()) { + ExternalApiHelper.startNavigation(mapActivity, gpxFile); + } + } + }); + } else { + ExternalApiHelper.startNavigation(mapActivity, gpx); + } } } } @@ -527,95 +615,85 @@ public class OsmandAidlApi { registerReceiver(navigateGpxReceiver, mapActivity, AIDL_NAVIGATE_GPX); } - private void startNavigation(MapActivity mapActivity, - GPXFile gpx, - LatLon from, PointDescription fromDesc, - LatLon to, PointDescription toDesc, - ApplicationMode mode) { - OsmandApplication app = mapActivity.getMyApplication(); - RoutingHelper routingHelper = app.getRoutingHelper(); - if (gpx == null) { - app.getSettings().APPLICATION_MODE.set(mode); - final TargetPointsHelper targets = mapActivity.getMyApplication().getTargetPointsHelper(); - targets.removeAllWayPoints(false, true); - targets.navigateToPoint(to, true, -1, toDesc); - } - mapActivity.getMapActions().enterRoutePlanningModeGivenGpx(gpx, from, fromDesc, true, false); - if (!app.getTargetPointsHelper().checkPointToNavigateShort()) { - mapActivity.getMapLayers().getMapControlsLayer().getMapRouteInfoMenu().show(); - } else { - if (app.getSettings().APPLICATION_MODE.get() != routingHelper.getAppMode()) { - app.getSettings().APPLICATION_MODE.set(routingHelper.getAppMode()); - } - mapActivity.getMapViewTrackingUtilities().backToLocationImpl(); - app.getSettings().FOLLOW_THE_ROUTE.set(true); - routingHelper.setFollowingMode(true); - routingHelper.setRoutePlanningMode(false); - mapActivity.getMapViewTrackingUtilities().switchToRoutePlanningMode(); - app.getRoutingHelper().notifyIfRouteIsCalculated(); - routingHelper.setCurrentLocation(app.getLocationProvider().getLastKnownLocation(), false); - } - } - - private void registerPauseNavigationReceiver(final MapActivity mapActivity) { + private void registerPauseNavigationReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver pauseNavigationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - RoutingHelper routingHelper = mapActivity.getRoutingHelper(); - if (routingHelper.isRouteCalculated() && !routingHelper.isRoutePlanningMode()) { - routingHelper.setRoutePlanningMode(true); - routingHelper.setFollowingMode(false); - routingHelper.setPauseNavigation(true); + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + RoutingHelper routingHelper = mapActivity.getRoutingHelper(); + if (routingHelper.isRouteCalculated() && !routingHelper.isRoutePlanningMode()) { + routingHelper.setRoutePlanningMode(true); + routingHelper.setFollowingMode(false); + routingHelper.setPauseNavigation(true); + } } } }; registerReceiver(pauseNavigationReceiver, mapActivity, AIDL_PAUSE_NAVIGATION); } - private void registerResumeNavigationReceiver(final MapActivity mapActivity) { + private void registerResumeNavigationReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver resumeNavigationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - RoutingHelper routingHelper = mapActivity.getRoutingHelper(); - if (routingHelper.isRouteCalculated() && routingHelper.isRoutePlanningMode()) { - routingHelper.setRoutePlanningMode(false); - routingHelper.setFollowingMode(true); + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + RoutingHelper routingHelper = mapActivity.getRoutingHelper(); + if (routingHelper.isRouteCalculated() && routingHelper.isRoutePlanningMode()) { + routingHelper.setRoutePlanningMode(false); + routingHelper.setFollowingMode(true); + } } } }; registerReceiver(resumeNavigationReceiver, mapActivity, AIDL_RESUME_NAVIGATION); } - private void registerStopNavigationReceiver(final MapActivity mapActivity) { + private void registerStopNavigationReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver stopNavigationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - RoutingHelper routingHelper = mapActivity.getRoutingHelper(); - if (routingHelper.isPauseNavigation() || routingHelper.isFollowingMode()) { - mapActivity.getMapLayers().getMapControlsLayer().stopNavigationWithoutConfirm(); + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + RoutingHelper routingHelper = mapActivity.getRoutingHelper(); + if (routingHelper.isPauseNavigation() || routingHelper.isFollowingMode()) { + mapActivity.getMapLayers().getMapControlsLayer().stopNavigationWithoutConfirm(); + } } } }; registerReceiver(stopNavigationReceiver, mapActivity, AIDL_STOP_NAVIGATION); } - private void registerMuteNavigationReceiver(final MapActivity mapActivity) { + private void registerMuteNavigationReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver muteNavigationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - mapActivity.getMyApplication().getSettings().VOICE_MUTE.set(true); - mapActivity.getRoutingHelper().getVoiceRouter().setMute(true); + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + mapActivity.getMyApplication().getSettings().VOICE_MUTE.set(true); + mapActivity.getRoutingHelper().getVoiceRouter().setMute(true); + } } }; registerReceiver(muteNavigationReceiver, mapActivity, AIDL_MUTE_NAVIGATION); } - private void registerUnmuteNavigationReceiver(final MapActivity mapActivity) { + private void registerUnmuteNavigationReceiver(MapActivity mapActivity) { + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); BroadcastReceiver unmuteNavigationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - mapActivity.getMyApplication().getSettings().VOICE_MUTE.set(false); - mapActivity.getRoutingHelper().getVoiceRouter().setMute(false); + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + mapActivity.getMyApplication().getSettings().VOICE_MUTE.set(false); + mapActivity.getRoutingHelper().getVoiceRouter().setMute(false); + } } }; registerReceiver(unmuteNavigationReceiver, mapActivity, AIDL_UNMUTE_NAVIGATION); @@ -639,7 +717,7 @@ public class OsmandAidlApi { app.sendBroadcast(intent); } - private TextInfoWidget createWidgetControl(final MapActivity mapActivity, final String widgetId) { + private TextInfoWidget createWidgetControl(MapActivity mapActivity, final String widgetId) { final TextInfoWidget control = new TextInfoWidget(mapActivity) { @Override @@ -1285,6 +1363,19 @@ public class OsmandAidlApi { return true; } + boolean navigateSearch(String startName, double startLat, double startLon, String searchQuery, String profile, boolean force) { + Intent intent = new Intent(); + intent.setAction(AIDL_NAVIGATE_SEARCH); + intent.putExtra(AIDL_START_NAME, startName); + intent.putExtra(AIDL_START_LAT, startLat); + intent.putExtra(AIDL_START_LON, startLon); + intent.putExtra(AIDL_SEARCH_QUERY, searchQuery); + intent.putExtra(AIDL_PROFILE, profile); + intent.putExtra(AIDL_FORCE, force); + app.sendBroadcast(intent); + return true; + } + boolean pauseNavigation() { Intent intent = new Intent(); intent.setAction(AIDL_PAUSE_NAVIGATION); @@ -1343,73 +1434,15 @@ public class OsmandAidlApi { @Override public void onFinish(AppInitializer init) { - runSearch(searchQuery, searchType, latitude, longitude, radiusLevel, totalLimit, callback); + ExternalApiHelper.runSearch(app, searchQuery, searchType, latitude, longitude, radiusLevel, totalLimit, callback); } }); } else { - runSearch(searchQuery, searchType, latitude, longitude, radiusLevel, totalLimit, callback); + ExternalApiHelper.runSearch(app, searchQuery, searchType, latitude, longitude, radiusLevel, totalLimit, callback); } return true; } - private void runSearch(String searchQuery, int searchType, double latitude, double longitude, int radiusLevel, - int totalLimit, final SearchCompleteCallback callback) { - if (radiusLevel < 1) { - radiusLevel = 1; - } else if (radiusLevel > MAX_DEFAULT_SEARCH_RADIUS) { - radiusLevel = MAX_DEFAULT_SEARCH_RADIUS; - } - if (totalLimit <= 0) { - totalLimit = -1; - } - final int limit = totalLimit; - - final SearchUICore core = app.getSearchUICore().getCore(); - core.setOnResultsComplete(new Runnable() { - @Override - public void run() { - List resultSet = new ArrayList<>(); - SearchResultCollection resultCollection = core.getCurrentSearchResult(); - int count = 0; - for (net.osmand.search.core.SearchResult r : resultCollection.getCurrentSearchResults()) { - String name = QuickSearchListItem.getName(app, r); - String typeName = QuickSearchListItem.getTypeName(app, r); - SearchResult result = new SearchResult(r.location.getLatitude(), r.location.getLongitude(), - name, typeName, r.alternateName, new ArrayList<>(r.otherNames)); - resultSet.add(result); - count++; - if (limit != -1 && count >= limit) { - break; - } - } - callback.onSearchComplete(resultSet); - } - }); - - SearchSettings searchSettings = new SearchSettings(core.getSearchSettings()) - .setRadiusLevel(radiusLevel) - .setEmptyQueryAllowed(false) - .setSortByName(false) - .setOriginalLocation(new LatLon(latitude, longitude)) - .setTotalLimit(totalLimit); - - List searchTypes = new ArrayList<>(); - if ((searchType & SearchParams.SEARCH_TYPE_POI) != 0) { - searchTypes.add(POI); - } - if ((searchType & SearchParams.SEARCH_TYPE_ADDRESS) != 0) { - searchTypes.add(CITY); - searchTypes.add(VILLAGE); - searchTypes.add(POSTCODE); - searchTypes.add(STREET); - searchTypes.add(HOUSE); - searchTypes.add(STREET_INTERSECTION); - } - searchSettings = searchSettings.setSearchTypes(searchTypes.toArray(new ObjectType[searchTypes.size()])); - - core.search(searchQuery, false, null, searchSettings); - } - boolean setNavDrawerItems(String appPackage, List items) { if (!TextUtils.isEmpty(appPackage) && items != null) { if (items.isEmpty()) { diff --git a/OsmAnd/src/net/osmand/aidl/OsmandAidlService.java b/OsmAnd/src/net/osmand/aidl/OsmandAidlService.java index bd68ae9ceb..1bb2c804f0 100644 --- a/OsmAnd/src/net/osmand/aidl/OsmandAidlService.java +++ b/OsmAnd/src/net/osmand/aidl/OsmandAidlService.java @@ -3,12 +3,7 @@ package net.osmand.aidl; import android.app.Service; import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Parcelable; import android.os.RemoteException; import net.osmand.PlatformUtil; @@ -45,6 +40,7 @@ import net.osmand.aidl.navdrawer.SetNavDrawerItemsParams; import net.osmand.aidl.navigation.MuteNavigationParams; import net.osmand.aidl.navigation.NavigateGpxParams; import net.osmand.aidl.navigation.NavigateParams; +import net.osmand.aidl.navigation.NavigateSearchParams; import net.osmand.aidl.navigation.PauseNavigationParams; import net.osmand.aidl.navigation.ResumeNavigationParams; import net.osmand.aidl.navigation.StopNavigationParams; @@ -61,20 +57,14 @@ import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; import java.util.ArrayList; -import java.util.Collections; import java.util.List; public class OsmandAidlService extends Service { private static final Log LOG = PlatformUtil.getLog(OsmandAidlService.class); - private static final int MSG_RUN_SEARCH = 53; private static final String DATA_KEY_RESULT_SET = "resultSet"; - private ArrayList mRemoteCallbacks; - private ServiceHandler mHandler = null; - HandlerThread mHandlerThread = new HandlerThread("OsmAndAidlServiceThread"); - OsmandApplication getApp() { return (OsmandApplication) getApplication(); } @@ -86,21 +76,10 @@ public class OsmandAidlService extends Service { @Override public IBinder onBind(Intent intent) { - // Handler Thread handling all call back methods - mHandlerThread.start(); - mHandler = new ServiceHandler(mHandlerThread.getLooper()); - // Return the interface return mBinder; } - @Override - public void onCreate() { - super.onCreate(); - - mRemoteCallbacks = new ArrayList<>(); - } - private final IOsmAndAidlInterface.Stub mBinder = new IOsmAndAidlInterface.Stub() { private void handleException(Exception e) { @@ -475,7 +454,10 @@ public class OsmandAidlService extends Service { @Override public boolean navigate(NavigateParams params) throws RemoteException { try { - return params != null && getApi("navigate").navigate(params.getStartName(), params.getStartLat(), params.getStartLon(), params.getDestName(), params.getDestLat(), params.getDestLon(), params.getProfile(), params.isForce()); + return params != null && getApi("navigate").navigate( + params.getStartName(), params.getStartLat(), params.getStartLon(), + params.getDestName(), params.getDestLat(), params.getDestLon(), + params.getProfile(), params.isForce()); } catch (Exception e) { handleException(e); return false; @@ -556,14 +538,18 @@ public class OsmandAidlService extends Service { public boolean search(SearchParams params, final IOsmAndAidlCallback callback) throws RemoteException { try { return params != null && getApi("search").search(params.getSearchQuery(), params.getSearchType(), - params.getLatutude(), params.getLongitude(), params.getRadiusLevel(), params.getTotalLimit(), new SearchCompleteCallback() { + params.getLatitude(), params.getLongitude(), params.getRadiusLevel(), params.getTotalLimit(), new SearchCompleteCallback() { @Override public void onSearchComplete(List resultSet) { Bundle data = new Bundle(); if (resultSet.size() > 0) { data.putParcelableArrayList(DATA_KEY_RESULT_SET, new ArrayList<>(resultSet)); } - sendMsgToHandler(callback, MSG_RUN_SEARCH, data); + try { + callback.onSearchComplete(resultSet); + } catch (RemoteException e) { + handleException(e); + } } }); } catch (Exception e) { @@ -571,57 +557,17 @@ public class OsmandAidlService extends Service { return false; } } - }; - - /** - * Create handler message to be sent - */ - void sendMsgToHandler(IOsmAndAidlCallback callback, int flag, Bundle data) { - - mRemoteCallbacks.add(callback); - - Message message = mHandler.obtainMessage(); - message.arg1 = mRemoteCallbacks.size() - 1; - message.setData(data); - - message.what = flag; - mHandler.sendMessage(message); - } - - /** - * Handler class sending result in callback to respective - * application - */ - private class ServiceHandler extends Handler { - int callbackIndex = 0; - - ServiceHandler(Looper looper) { - super(looper); - } @Override - public void handleMessage(Message msg) { - callbackIndex = msg.arg1; - - switch (msg.what) { - - case MSG_RUN_SEARCH: - - Bundle data = msg.getData(); - List resultSet; - if (data.containsKey(DATA_KEY_RESULT_SET)) { - resultSet = data.getParcelableArrayList(DATA_KEY_RESULT_SET); - } else { - resultSet = Collections.emptyList(); - } - - try { - mRemoteCallbacks.get(callbackIndex).onSearchComplete(resultSet); - } catch (RemoteException e) { - LOG.error("AIDL e.getMessage()", e); - } - break; + public boolean navigateSearch(NavigateSearchParams params) throws RemoteException { + try { + return params != null && getApi("navigateSearch").navigateSearch( + params.getStartName(), params.getStartLat(), params.getStartLon(), + params.getSearchQuery(), params.getProfile(), params.isForce()); + } catch (Exception e) { + handleException(e); + return false; } } - } + }; } diff --git a/OsmAnd/src/net/osmand/aidl/navigation/NavigateSearchParams.aidl b/OsmAnd/src/net/osmand/aidl/navigation/NavigateSearchParams.aidl new file mode 100644 index 0000000000..57433b8fde --- /dev/null +++ b/OsmAnd/src/net/osmand/aidl/navigation/NavigateSearchParams.aidl @@ -0,0 +1,3 @@ +package net.osmand.aidl.navigation; + +parcelable NavigateSearchParams; \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/aidl/navigation/NavigateSearchParams.java b/OsmAnd/src/net/osmand/aidl/navigation/NavigateSearchParams.java new file mode 100644 index 0000000000..1c539d08cc --- /dev/null +++ b/OsmAnd/src/net/osmand/aidl/navigation/NavigateSearchParams.java @@ -0,0 +1,88 @@ +package net.osmand.aidl.navigation; + +import android.os.Parcel; +import android.os.Parcelable; + +public class NavigateSearchParams implements Parcelable { + + private String startName; + private double startLat; + private double startLon; + private String searchQuery; + private String profile; + private boolean force; + + public NavigateSearchParams(String startName, double startLat, double startLon, String searchQuery, String profile, boolean force) { + this.startName = startName; + this.startLat = startLat; + this.startLon = startLon; + this.searchQuery = searchQuery; + this.profile = profile; + this.force = force; + } + + public NavigateSearchParams(Parcel in) { + readFromParcel(in); + } + + public static final Creator CREATOR = new Creator() { + @Override + public NavigateSearchParams createFromParcel(Parcel in) { + return new NavigateSearchParams(in); + } + + @Override + public NavigateSearchParams[] newArray(int size) { + return new NavigateSearchParams[size]; + } + }; + + public String getStartName() { + return startName; + } + + public double getStartLat() { + return startLat; + } + + public double getStartLon() { + return startLon; + } + + public String getSearchQuery() { + return searchQuery; + } + + public String getProfile() { + return profile; + } + + public boolean isForce() { + return force; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeString(startName); + out.writeDouble(startLat); + out.writeDouble(startLon); + out.writeString(searchQuery); + out.writeString(profile); + out.writeByte((byte) (force ? 1 : 0)); + } + + private void readFromParcel(Parcel in) { + startName = in.readString(); + startLat = in.readDouble(); + startLon = in.readDouble(); + searchQuery = in.readString(); + profile = in.readString(); + force = in.readByte() != 0; + } + + @Override + public int describeContents() { + return 0; + } + +} diff --git a/OsmAnd/src/net/osmand/aidl/search/SearchParams.java b/OsmAnd/src/net/osmand/aidl/search/SearchParams.java index 32447f4b45..303cecb25c 100644 --- a/OsmAnd/src/net/osmand/aidl/search/SearchParams.java +++ b/OsmAnd/src/net/osmand/aidl/search/SearchParams.java @@ -11,15 +11,15 @@ public class SearchParams implements Parcelable { private String searchQuery; private int searchType; - private double latutude; + private double latitude; private double longitude; private int radiusLevel = 1; private int totalLimit = -1; - public SearchParams(String searchQuery, int searchType, double latutude, double longitude, int radiusLevel, int totalLimit) { + public SearchParams(String searchQuery, int searchType, double latitude, double longitude, int radiusLevel, int totalLimit) { this.searchQuery = searchQuery; this.searchType = searchType; - this.latutude = latutude; + this.latitude = latitude; this.longitude = longitude; this.radiusLevel = radiusLevel; this.totalLimit = totalLimit; @@ -49,8 +49,8 @@ public class SearchParams implements Parcelable { return searchType; } - public double getLatutude() { - return latutude; + public double getLatitude() { + return latitude; } public double getLongitude() { @@ -69,7 +69,7 @@ public class SearchParams implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(searchQuery); out.writeInt(searchType); - out.writeDouble(latutude); + out.writeDouble(latitude); out.writeDouble(longitude); out.writeInt(radiusLevel); out.writeInt(totalLimit); @@ -78,7 +78,7 @@ public class SearchParams implements Parcelable { private void readFromParcel(Parcel in) { searchQuery = in.readString(); searchType = in.readInt(); - latutude = in.readDouble(); + latitude = in.readDouble(); longitude = in.readDouble(); radiusLevel = in.readInt(); totalLimit = in.readInt(); diff --git a/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java index 2468520da4..730335463d 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java @@ -1,17 +1,24 @@ package net.osmand.plus.helpers; import android.app.Activity; +import android.app.Dialog; +import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.ParcelFileDescriptor; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import net.osmand.AndroidUtils; import net.osmand.IndexConstants; import net.osmand.Location; import net.osmand.PlatformUtil; +import net.osmand.aidl.OsmandAidlApi; +import net.osmand.aidl.search.SearchParams; +import net.osmand.aidl.search.SearchResult; import net.osmand.data.FavouritePoint; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; @@ -23,6 +30,7 @@ import net.osmand.plus.MapMarkersHelper; import net.osmand.plus.MapMarkersHelper.MapMarker; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; +import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.audionotes.AudioVideoNotesPlugin; @@ -31,14 +39,30 @@ import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.search.listitems.QuickSearchListItem; import net.osmand.router.TurnType; +import net.osmand.search.SearchUICore; +import net.osmand.search.core.ObjectType; +import net.osmand.search.core.SearchSettings; import net.osmand.util.Algorithms; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; +import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; + +import static net.osmand.search.core.ObjectType.CITY; +import static net.osmand.search.core.ObjectType.HOUSE; +import static net.osmand.search.core.ObjectType.POI; +import static net.osmand.search.core.ObjectType.POSTCODE; +import static net.osmand.search.core.ObjectType.STREET; +import static net.osmand.search.core.ObjectType.STREET_INTERSECTION; +import static net.osmand.search.core.ObjectType.VILLAGE; +import static net.osmand.search.core.SearchCoreFactory.MAX_DEFAULT_SEARCH_RADIUS; public class ExternalApiHelper { private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(ExternalApiHelper.class); @@ -47,6 +71,8 @@ public class ExternalApiHelper { public static final String API_CMD_NAVIGATE_GPX = "navigate_gpx"; public static final String API_CMD_NAVIGATE = "navigate"; + public static final String API_CMD_NAVIGATE_SEARCH = "navigate_search"; + public static final String API_CMD_PAUSE_NAVIGATION = "pause_navigation"; public static final String API_CMD_RESUME_NAVIGATION = "resume_navigation"; public static final String API_CMD_STOP_NAVIGATION = "stop_navigation"; @@ -124,6 +150,8 @@ public class ExternalApiHelper { public static final int RESULT_CODE_ERROR_PLUGIN_INACTIVE = 1003; public static final int RESULT_CODE_ERROR_GPX_NOT_FOUND = 1004; public static final int RESULT_CODE_ERROR_INVALID_PROFILE = 1005; + public static final int RESULT_CODE_ERROR_EMPTY_SEARCH_QUERY = 1006; + public static final int RESULT_CODE_ERROR_START_LOCATION_UNDEFINED = 1007; private MapActivity mapActivity; private int resultCode; @@ -199,12 +227,12 @@ public class ExternalApiHelper { @Override public void onDismiss(DialogInterface dialog) { if (!routingHelper.isFollowingMode()) { - startNavigation(gpxFile, null, null, null, null, null); + startNavigation(mapActivity, gpxFile); } } }); } else { - startNavigation(gpx, null, null, null, null, null); + startNavigation(mapActivity, gpx); } } else { app.getSelectedGpxHelper().setGpxFileToDisplay(gpx); @@ -237,7 +265,6 @@ public class ExternalApiHelper { destName = ""; } - final LatLon start; final PointDescription startDesc; String startLatStr = uri.getQueryParameter(PARAM_START_LAT); @@ -252,7 +279,6 @@ public class ExternalApiHelper { startDesc = null; } - String destSearchQuery = uri.getQueryParameter(PARAM_DEST_SEARCH_QUERY); String destLatStr = uri.getQueryParameter(PARAM_DEST_LAT); String destLonStr = uri.getQueryParameter(PARAM_DEST_LON); final LatLon dest; @@ -262,9 +288,6 @@ public class ExternalApiHelper { dest = new LatLon(destLat, destLon); } else { dest = null; - } - if (!Algorithms.isEmpty(destSearchQuery)) { - } final PointDescription destDesc = new PointDescription(PointDescription.POINT_TYPE_LOCATION, destName); @@ -278,12 +301,76 @@ public class ExternalApiHelper { @Override public void onDismiss(DialogInterface dialog) { if (!routingHelper.isFollowingMode()) { - startNavigation(null, start, startDesc, dest, destDesc, profile); + startNavigation(mapActivity, start, startDesc, dest, destDesc, profile); } } }); } else { - startNavigation(null, start, startDesc, dest, destDesc, profile); + startNavigation(mapActivity, start, startDesc, dest, destDesc, profile); + } + } + + } else if (API_CMD_NAVIGATE_SEARCH.equals(cmd)) { + String profileStr = uri.getQueryParameter(PARAM_PROFILE); + final ApplicationMode profile = ApplicationMode.valueOfStringKey(profileStr, DEFAULT_PROFILE); + boolean validProfile = false; + for (ApplicationMode mode : VALID_PROFILES) { + if (mode == profile) { + validProfile = true; + break; + } + } + final String searchQuery = uri.getQueryParameter(PARAM_DEST_SEARCH_QUERY); + if (Algorithms.isEmpty(searchQuery)) { + resultCode = RESULT_CODE_ERROR_EMPTY_SEARCH_QUERY; + } else if (!validProfile) { + resultCode = RESULT_CODE_ERROR_INVALID_PROFILE; + } else { + String startName = uri.getQueryParameter(PARAM_START_NAME); + if (Algorithms.isEmpty(startName)) { + startName = ""; + } + final LatLon start; + final PointDescription startDesc; + String startLatStr = uri.getQueryParameter(PARAM_START_LAT); + String startLonStr = uri.getQueryParameter(PARAM_START_LON); + if (!Algorithms.isEmpty(startLatStr) && !Algorithms.isEmpty(startLonStr)) { + double lat = Double.parseDouble(uri.getQueryParameter(PARAM_START_LAT)); + double lon = Double.parseDouble(uri.getQueryParameter(PARAM_START_LON)); + start = new LatLon(lat, lon); + startDesc = new PointDescription(PointDescription.POINT_TYPE_LOCATION, startName); + } else { + Location location = app.getLocationProvider().getLastKnownLocation(); + if (location != null) { + start = new LatLon(location.getLatitude(), location.getLongitude()); + startDesc = new PointDescription(PointDescription.POINT_TYPE_MY_LOCATION, mapActivity.getString(R.string.shared_string_my_location)); + } else { + start = null; + startDesc = null; + } + } + + if (start == null) { + resultCode = RESULT_CODE_ERROR_START_LOCATION_UNDEFINED; + } else { + boolean force = uri.getBooleanQueryParameter(PARAM_FORCE, false); + + final RoutingHelper routingHelper = app.getRoutingHelper(); + if (routingHelper.isFollowingMode() && !force) { + AlertDialog dlg = mapActivity.getMapActions().stopNavigationActionConfirm(); + dlg.setOnDismissListener(new DialogInterface.OnDismissListener() { + + @Override + public void onDismiss(DialogInterface dialog) { + if (!routingHelper.isFollowingMode()) { + searchAndNavigate(mapActivity, start, startDesc, profile, searchQuery); + } + } + }); + } else { + searchAndNavigate(mapActivity, start, startDesc, profile, searchQuery); + } + resultCode = Activity.RESULT_OK; } } @@ -498,10 +585,23 @@ public class ExternalApiHelper { mapContextMenu.show(new LatLon(lat, lon), pointDescription, object); } - private void startNavigation(GPXFile gpx, - LatLon from, PointDescription fromDesc, - LatLon to, PointDescription toDesc, - ApplicationMode mode) { + static public void startNavigation(MapActivity mapActivity, + @NonNull GPXFile gpx) { + startNavigation(mapActivity, gpx, null, null, null, null, null); + } + + static public void startNavigation(MapActivity mapActivity, + @Nullable LatLon from, @Nullable PointDescription fromDesc, + @Nullable LatLon to, @Nullable PointDescription toDesc, + @NonNull ApplicationMode mode) { + startNavigation(mapActivity, null, from, fromDesc, to, toDesc, mode); + } + + static private void startNavigation(MapActivity mapActivity, + GPXFile gpx, + LatLon from, PointDescription fromDesc, + LatLon to, PointDescription toDesc, + ApplicationMode mode) { OsmandApplication app = mapActivity.getMyApplication(); RoutingHelper routingHelper = app.getRoutingHelper(); if (gpx == null) { @@ -527,6 +627,104 @@ public class ExternalApiHelper { } } + static public void searchAndNavigate(@NonNull MapActivity mapActivity, + @NonNull final LatLon from, @Nullable final PointDescription fromDesc, + @NonNull final ApplicationMode mode, @NonNull final String searchQuery) { + + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); + OsmandApplication app = mapActivity.getMyApplication(); + ProgressDialog dlg = new ProgressDialog(mapActivity); + dlg.setTitle(""); + dlg.setMessage(mapActivity.getString(R.string.searching_address)); + dlg.show(); + final WeakReference dlgRef = new WeakReference<>(dlg); + runSearch(app, searchQuery, SearchParams.SEARCH_TYPE_ALL, + from.getLatitude(), from.getLongitude(), 1, 1, new OsmandAidlApi.SearchCompleteCallback() { + @Override + public void onSearchComplete(final List resultSet) { + final MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + mapActivity.getMyApplication().runInUIThread(new Runnable() { + @Override + public void run() { + ProgressDialog dlg = dlgRef.get(); + if (dlg != null) { + dlg.dismiss(); + } + if (resultSet.size() > 0) { + final SearchResult res = resultSet.get(0); + LatLon to = new LatLon(res.getLatitude(), res.getLongitude()); + PointDescription toDesc = new PointDescription(PointDescription.POINT_TYPE_TARGET, res.getLocalName() + ", " + res.getLocalTypeName()); + startNavigation(mapActivity, from, fromDesc, to, toDesc, mode); + } else { + mapActivity.getMyApplication().showToastMessage(mapActivity.getString(R.string.search_nothing_found)); + } + } + }); + } + } + }); + } + + static public void runSearch(final OsmandApplication app, String searchQuery, int searchType, + double latitude, double longitude, int radiusLevel, + int totalLimit, final OsmandAidlApi.SearchCompleteCallback callback) { + if (radiusLevel < 1) { + radiusLevel = 1; + } else if (radiusLevel > MAX_DEFAULT_SEARCH_RADIUS) { + radiusLevel = MAX_DEFAULT_SEARCH_RADIUS; + } + if (totalLimit <= 0) { + totalLimit = -1; + } + final int limit = totalLimit; + + final SearchUICore core = app.getSearchUICore().getCore(); + core.setOnResultsComplete(new Runnable() { + @Override + public void run() { + List resultSet = new ArrayList<>(); + SearchUICore.SearchResultCollection resultCollection = core.getCurrentSearchResult(); + int count = 0; + for (net.osmand.search.core.SearchResult r : resultCollection.getCurrentSearchResults()) { + String name = QuickSearchListItem.getName(app, r); + String typeName = QuickSearchListItem.getTypeName(app, r); + SearchResult result = new SearchResult(r.location.getLatitude(), r.location.getLongitude(), + name, typeName, r.alternateName, new ArrayList<>(r.otherNames)); + resultSet.add(result); + count++; + if (limit != -1 && count >= limit) { + break; + } + } + callback.onSearchComplete(resultSet); + } + }); + + SearchSettings searchSettings = new SearchSettings(core.getSearchSettings()) + .setRadiusLevel(radiusLevel) + .setEmptyQueryAllowed(false) + .setSortByName(false) + .setOriginalLocation(new LatLon(latitude, longitude)) + .setTotalLimit(totalLimit); + + List searchTypes = new ArrayList<>(); + if ((searchType & SearchParams.SEARCH_TYPE_POI) != 0) { + searchTypes.add(POI); + } + if ((searchType & SearchParams.SEARCH_TYPE_ADDRESS) != 0) { + searchTypes.add(CITY); + searchTypes.add(VILLAGE); + searchTypes.add(POSTCODE); + searchTypes.add(STREET); + searchTypes.add(HOUSE); + searchTypes.add(STREET_INTERSECTION); + } + searchSettings = searchSettings.setSearchTypes(searchTypes.toArray(new ObjectType[searchTypes.size()])); + + core.search(searchQuery, false, null, searchSettings); + } + public void testApi(OsmandApplication app, String command) { Uri uri = null; Intent intent = null;