[android] #5869 - visible feature querying
This commit is contained in:
@@ -27,6 +27,11 @@ dependencies {
|
||||
compile "com.android.support:design:${supportLibVersion}"
|
||||
compile 'com.squareup.okhttp3:okhttp:3.3.0'
|
||||
compile 'com.mapzen.android:lost:1.1.0'
|
||||
|
||||
// Mapbox Android Services
|
||||
compile('com.mapbox.mapboxsdk:mapbox-android-services:2.0.0-SNAPSHOT@aar') {
|
||||
transitive = true
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.mapbox.mapboxsdk.maps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.location.Location;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.FloatRange;
|
||||
@@ -42,6 +44,7 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
|
||||
import com.mapbox.mapboxsdk.style.layers.Layer;
|
||||
import com.mapbox.mapboxsdk.style.layers.NoSuchLayerException;
|
||||
import com.mapbox.mapboxsdk.style.sources.Source;
|
||||
import com.mapbox.services.commons.geojson.Feature;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.ArrayList;
|
||||
@@ -1722,6 +1725,33 @@ public class MapboxMap {
|
||||
mMapView.snapshot(callback, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the map for rendered features
|
||||
*
|
||||
* @param coordinates the point to query
|
||||
* @param layerIds optionally - only query these layers
|
||||
* @return the list of feature
|
||||
*/
|
||||
@UiThread
|
||||
@NonNull
|
||||
public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullable String... layerIds) {
|
||||
return mMapView.getNativeMapView().queryRenderedFeatures(coordinates, layerIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the map for rendered features
|
||||
*
|
||||
* @param coordinates the box to query
|
||||
* @param layerIds optionally - only query these layers
|
||||
* @return the list of feature
|
||||
*/
|
||||
@UiThread
|
||||
@NonNull
|
||||
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, @Nullable String... layerIds) {
|
||||
return mMapView.getNativeMapView().queryRenderedFeatures(coordinates, layerIds);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Interfaces
|
||||
//
|
||||
|
||||
@@ -20,7 +20,10 @@ import com.mapbox.mapboxsdk.offline.OfflineManager;
|
||||
import com.mapbox.mapboxsdk.style.layers.Layer;
|
||||
import com.mapbox.mapboxsdk.style.layers.NoSuchLayerException;
|
||||
import com.mapbox.mapboxsdk.style.sources.Source;
|
||||
import com.mapbox.services.commons.geojson.Feature;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
// Class that wraps the native methods for convenience
|
||||
@@ -42,6 +45,8 @@ final class NativeMapView {
|
||||
// Used for callbacks
|
||||
private MapView mMapView;
|
||||
|
||||
private final float pixelRatio;
|
||||
|
||||
//
|
||||
// Static methods
|
||||
//
|
||||
@@ -63,7 +68,7 @@ final class NativeMapView {
|
||||
// the system
|
||||
String cachePath = dataPath;
|
||||
|
||||
float pixelRatio = context.getResources().getDisplayMetrics().density;
|
||||
pixelRatio = context.getResources().getDisplayMetrics().density;
|
||||
String apkPath = context.getPackageCodePath();
|
||||
int availableProcessors = Runtime.getRuntime().availableProcessors();
|
||||
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
|
||||
@@ -501,6 +506,26 @@ final class NativeMapView {
|
||||
nativeRemoveSource(mNativeMapViewPtr, sourceId);
|
||||
}
|
||||
|
||||
// Feature querying
|
||||
|
||||
@NonNull
|
||||
public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) {
|
||||
Feature[] features = nativeQueryRenderedFeaturesForPoint(mNativeMapViewPtr, coordinates.x / pixelRatio, coordinates.y / pixelRatio, layerIds);
|
||||
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) {
|
||||
Feature[] features = nativeQueryRenderedFeaturesForBox(
|
||||
mNativeMapViewPtr,
|
||||
coordinates.left / pixelRatio,
|
||||
coordinates.top / pixelRatio,
|
||||
coordinates.right / pixelRatio,
|
||||
coordinates.bottom / pixelRatio,
|
||||
layerIds);
|
||||
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
|
||||
}
|
||||
|
||||
public void scheduleTakeSnapshot() {
|
||||
nativeScheduleTakeSnapshot(mNativeMapViewPtr);
|
||||
}
|
||||
@@ -696,4 +721,8 @@ final class NativeMapView {
|
||||
private native long nativeUpdatePolyline(long nativeMapviewPtr, long polylineId, Polyline polyline);
|
||||
|
||||
private native void nativeScheduleTakeSnapshot(long nativeMapViewPtr);
|
||||
|
||||
private native Feature[] nativeQueryRenderedFeaturesForPoint(long nativeMapViewPtr, float x, float y, String[] layerIds);
|
||||
|
||||
private native Feature[] nativeQueryRenderedFeaturesForBox(long mNativeMapViewPtr, float left, float top, float right, float bottom, String[] layerIds);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mapbox.mapboxsdk.testapp">
|
||||
<manifest package="com.mapbox.mapboxsdk.testapp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<application
|
||||
android:name=".MapboxApplication"
|
||||
@@ -20,8 +20,8 @@
|
||||
android:name=".activity.FeatureOverviewActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
@@ -30,7 +30,7 @@
|
||||
android:label="@string/activity_info_window">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_infowindow" />
|
||||
android:value="@string/category_infowindow"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.infowindow.InfoWindowAdapterActivity"
|
||||
@@ -38,7 +38,7 @@
|
||||
android:label="@string/activity_infowindow_adapter">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_infowindow" />
|
||||
android:value="@string/category_infowindow"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.infowindow.DynamicInfoWindowAdapterActivity"
|
||||
@@ -46,7 +46,7 @@
|
||||
android:label="@string/activity_dynamic_infowindow_adapter">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_infowindow" />
|
||||
android:value="@string/category_infowindow"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.annotation.BulkMarkerActivity"
|
||||
@@ -55,7 +55,7 @@
|
||||
android:label="@string/activity_add_bulk_markers">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_annotation" />
|
||||
android:value="@string/category_annotation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.annotation.AnimatedMarkerActivity"
|
||||
@@ -63,7 +63,7 @@
|
||||
android:label="@string/activity_animated_marker">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_annotation" />
|
||||
android:value="@string/category_annotation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.annotation.DynamicMarkerChangeActivity"
|
||||
@@ -71,7 +71,7 @@
|
||||
android:label="@string/activity_dynamic_marker">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_annotation" />
|
||||
android:value="@string/category_annotation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.annotation.PressForMarkerActivity"
|
||||
@@ -79,7 +79,7 @@
|
||||
android:label="@string/activity_press_for_marker">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_annotation" />
|
||||
android:value="@string/category_annotation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.camera.CameraAnimationTypeActivity"
|
||||
@@ -87,7 +87,7 @@
|
||||
android:label="@string/activity_camera_animation_types">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_camera" />
|
||||
android:value="@string/category_camera"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.camera.CameraPositionActivity"
|
||||
@@ -95,7 +95,7 @@
|
||||
android:label="@string/activity_camera_position">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_camera" />
|
||||
android:value="@string/category_camera"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.camera.LatLngBoundsActivity"
|
||||
@@ -104,7 +104,7 @@
|
||||
android:screenOrientation="portrait">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_camera" />
|
||||
android:value="@string/category_camera"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.fragment.MapFragmentActivity"
|
||||
@@ -112,7 +112,7 @@
|
||||
android:label="@string/activity_map_fragment">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_fragment" />
|
||||
android:value="@string/category_fragment"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.fragment.SupportMapFragmentActivity"
|
||||
@@ -120,7 +120,7 @@
|
||||
android:label="@string/activity_map_fragment_suport">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_fragment" />
|
||||
android:value="@string/category_fragment"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.camera.ManualZoomActivity"
|
||||
@@ -128,7 +128,7 @@
|
||||
android:label="@string/activity_camera_zoom">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_camera" />
|
||||
android:value="@string/category_camera"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.camera.MaxMinZoomActivity"
|
||||
@@ -136,7 +136,7 @@
|
||||
android:label="@string/activity_minmax_zoom">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_camera" />
|
||||
android:value="@string/category_camera"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.customlayer.CustomLayerActivity"
|
||||
@@ -144,7 +144,7 @@
|
||||
android:label="@string/activity_custom_layer">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_custom_layer" />
|
||||
android:value="@string/category_custom_layer"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.userlocation.MyLocationTrackingModeActivity"
|
||||
@@ -152,7 +152,7 @@
|
||||
android:label="@string/activity_user_tracking_mode">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_userlocation" />
|
||||
android:value="@string/category_userlocation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.userlocation.MyLocationDrawableActivity"
|
||||
@@ -160,7 +160,7 @@
|
||||
android:label="@string/activity_user_tracking_customization">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_userlocation" />
|
||||
android:value="@string/category_userlocation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.userlocation.MyLocationTintActivity"
|
||||
@@ -168,7 +168,7 @@
|
||||
android:label="@string/activity_user_dot_color">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_userlocation" />
|
||||
android:value="@string/category_userlocation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.userlocation.MyLocationToggleActivity"
|
||||
@@ -176,7 +176,7 @@
|
||||
android:label="@string/activity_user_location_toggle">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_userlocation" />
|
||||
android:value="@string/category_userlocation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.annotation.PolygonActivity"
|
||||
@@ -184,7 +184,7 @@
|
||||
android:label="@string/activity_polygon">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_annotation" />
|
||||
android:value="@string/category_annotation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.annotation.PolylineActivity"
|
||||
@@ -192,7 +192,7 @@
|
||||
android:label="@string/activity_polyline">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_annotation" />
|
||||
android:value="@string/category_annotation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.directions.DirectionsActivity"
|
||||
@@ -200,7 +200,7 @@
|
||||
android:label="@string/activity_directions">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_directions" />
|
||||
android:value="@string/category_directions"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.geocoding.GeocoderActivity"
|
||||
@@ -208,7 +208,7 @@
|
||||
android:label="@string/activity_geocoder">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_geocoding" />
|
||||
android:value="@string/category_geocoding"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.camera.ScrollByActivity"
|
||||
@@ -216,7 +216,7 @@
|
||||
android:label="@string/activity_scroll_by">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_camera" />
|
||||
android:value="@string/category_camera"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.maplayout.MapPaddingActivity"
|
||||
@@ -225,7 +225,7 @@
|
||||
android:screenOrientation="portrait">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_maplayout" />
|
||||
android:value="@string/category_maplayout"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.maplayout.DebugModeActivity"
|
||||
@@ -233,7 +233,7 @@
|
||||
android:label="@string/activity_debug_mode">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_maplayout" />
|
||||
android:value="@string/category_maplayout"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.offline.OfflineActivity"
|
||||
@@ -241,7 +241,7 @@
|
||||
android:label="@string/activity_offline">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_offline" />
|
||||
android:value="@string/category_offline"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.imagegenerator.SnapshotActivity"
|
||||
@@ -249,7 +249,7 @@
|
||||
android:label="@string/activity_snapshot">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_imagegenerator" />
|
||||
android:value="@string/category_imagegenerator"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.maplayout.DoubleMapActivity"
|
||||
@@ -257,7 +257,7 @@
|
||||
android:label="@string/activity_double_map">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_maplayout" />
|
||||
android:value="@string/category_maplayout"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.annotation.MarkerViewActivity"
|
||||
@@ -265,7 +265,7 @@
|
||||
android:label="@string/activity_view_marker">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_annotation" />
|
||||
android:value="@string/category_annotation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.annotation.MarkerViewScaleActivity"
|
||||
@@ -273,7 +273,7 @@
|
||||
android:label="@string/activity_view_marker_scale">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_annotation" />
|
||||
android:value="@string/category_annotation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.navigation.LocationPickerActivity"
|
||||
@@ -281,7 +281,7 @@
|
||||
android:label="@string/activity_location_picker">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_navigation" />
|
||||
android:value="@string/category_navigation"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.fragment.ViewPagerActivity"
|
||||
@@ -289,7 +289,7 @@
|
||||
android:label="@string/activity_viewpager">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_fragment" />
|
||||
android:value="@string/category_fragment"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.maplayout.NavigationDrawerActivity"
|
||||
@@ -298,7 +298,7 @@
|
||||
android:theme="@style/AppTheme.ActionBar.Transparent">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_fragment" />
|
||||
android:value="@string/category_fragment"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.style.RuntimeStyleActivity"
|
||||
@@ -306,7 +306,7 @@
|
||||
android:label="@string/activity_runtime_style">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_style" />
|
||||
android:value="@string/category_style"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.style.GeoJsonClusteringActivity"
|
||||
@@ -323,7 +323,7 @@
|
||||
android:label="@string/activity_print">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_imagegenerator" />
|
||||
android:value="@string/category_imagegenerator"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.maplayout.SurfaceViewMediaControlActivity"
|
||||
@@ -331,27 +331,53 @@
|
||||
android:label="@string/activity_surfaceview_overlay">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_maplayout" />
|
||||
android:value="@string/category_maplayout"/>
|
||||
</activity>
|
||||
|
||||
<!-- Features -->
|
||||
<activity
|
||||
android:name=".activity.feature.QueryRenderedFeaturesPropertiesActivity"
|
||||
android:description="@string/description_query_rendered_feature_properties_point"
|
||||
android:label="@string/activity_query_rendered_feature_properties">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_features" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.feature.QueryRenderedFeaturesBoxCountActivity"
|
||||
android:description="@string/description_query_rendered_features_box_count"
|
||||
android:label="@string/activity_query_rendered_features_box_count">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_features" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.feature.QueryRenderedFeaturesBoxHighlightActivity"
|
||||
android:description="@string/description_query_rendered_features_box_highlight"
|
||||
android:label="@string/activity_query_rendered_features_box_highlight">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_features" />
|
||||
</activity>
|
||||
|
||||
<!-- For Unit tests -->
|
||||
<activity android:name=".activity.style.RuntimeStyleTestActivity" />
|
||||
<activity android:name=".activity.style.RuntimeStyleTimingTestActivity" />
|
||||
<activity android:name=".activity.style.RuntimeStyleTestActivity"/>
|
||||
<activity android:name=".activity.style.RuntimeStyleTimingTestActivity"/>
|
||||
|
||||
<!-- Configuration Settings -->
|
||||
<meta-data
|
||||
android:name="com.mapbox.TestEventsServer"
|
||||
android:value="https://cloudfront-staging.tilestream.net" />
|
||||
android:value="https://cloudfront-staging.tilestream.net"/>
|
||||
<meta-data
|
||||
android:name="com.mapbox.TestEventsAccessToken"
|
||||
android:value="sk.eyJ1IjoiYmxlZWdlIiwiYSI6InNpcml1c2x5In0.KyT-boMyC_xZYTYojTc8zg" />
|
||||
android:value="sk.eyJ1IjoiYmxlZWdlIiwiYSI6InNpcml1c2x5In0.KyT-boMyC_xZYTYojTc8zg"/>
|
||||
|
||||
<!-- Comment out this setting to switch to external storage (and disable internal) in your app -->
|
||||
<!-- <meta-data -->
|
||||
<!-- android:name="com.mapbox.SetStorageExternal" -->
|
||||
<!-- android:value="true" /> -->
|
||||
|
||||
<service android:name="com.mapbox.mapboxsdk.telemetry.TelemetryService" />
|
||||
<service android:name="com.mapbox.mapboxsdk.telemetry.TelemetryService"/>
|
||||
|
||||
</application>
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.feature;
|
||||
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.services.commons.geojson.Feature;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Demo's query rendered features
|
||||
*/
|
||||
public class QueryRenderedFeaturesBoxCountActivity extends AppCompatActivity {
|
||||
private static final String TAG = QueryRenderedFeaturesBoxCountActivity.class.getSimpleName();
|
||||
|
||||
public MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private Marker marker;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_query_features_box);
|
||||
setupActionBar();
|
||||
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
|
||||
final View selectionBox = findViewById(R.id.selection_box);
|
||||
|
||||
//Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(new OnMapReadyCallback() {
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public void onMapReady(final MapboxMap mapboxMap) {
|
||||
QueryRenderedFeaturesBoxCountActivity.this.mapboxMap = mapboxMap;
|
||||
|
||||
|
||||
selectionBox.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
//Query
|
||||
int top = selectionBox.getTop() - mapView.getTop();
|
||||
int left = selectionBox.getLeft() - mapView.getLeft();
|
||||
RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
|
||||
Log.i(TAG, String.format("Querying box %s", box));
|
||||
List<Feature> features = mapboxMap.queryRenderedFeatures(box);
|
||||
|
||||
//Show count
|
||||
Toast.makeText(QueryRenderedFeaturesBoxCountActivity.this, String.format("%s features in box", features.size()), Toast.LENGTH_SHORT).show();
|
||||
|
||||
//Debug output
|
||||
debugOutput(features);
|
||||
}
|
||||
});
|
||||
|
||||
//Little taste of home
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.0907, 5.1214), 16));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void debugOutput(List<Feature> features) {
|
||||
Log.i(TAG, String.format("Got %s features", features.size()));
|
||||
for (Feature feature : features) {
|
||||
if (feature != null) {
|
||||
Log.i(TAG, String.format("Got feature %s with %s properties and Geometry %s",
|
||||
feature.getId(),
|
||||
feature.getProperties() != null ? feature.getProperties().entrySet().size() : "<null>",
|
||||
feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>")
|
||||
);
|
||||
if (feature.getProperties() != null) {
|
||||
for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) {
|
||||
Log.i(TAG, String.format("Prop %s - %s", entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "Got NULL feature %s");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MapboxMap getMapboxMap() {
|
||||
return mapboxMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupActionBar() {
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.feature;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.services.commons.geojson.Feature;
|
||||
import com.mapbox.services.commons.geojson.Polygon;
|
||||
import com.mapbox.services.commons.models.Position;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Demo's query rendered features
|
||||
*/
|
||||
public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity {
|
||||
private static final String TAG = QueryRenderedFeaturesBoxHighlightActivity.class.getSimpleName();
|
||||
|
||||
public MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private Marker marker;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_query_features_box);
|
||||
setupActionBar();
|
||||
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
|
||||
final View selectionBox = findViewById(R.id.selection_box);
|
||||
|
||||
//Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(new OnMapReadyCallback() {
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public void onMapReady(final MapboxMap mapboxMap) {
|
||||
QueryRenderedFeaturesBoxHighlightActivity.this.mapboxMap = mapboxMap;
|
||||
|
||||
|
||||
selectionBox.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
//Query
|
||||
int top = selectionBox.getTop() - mapView.getTop();
|
||||
int left = selectionBox.getLeft() - mapView.getLeft();
|
||||
RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
|
||||
Log.i(TAG, String.format("Querying box %s for buildings", box));
|
||||
List<Feature> features = mapboxMap.queryRenderedFeatures(box, "building");
|
||||
|
||||
//Show count
|
||||
Toast.makeText(QueryRenderedFeaturesBoxHighlightActivity.this, String.format("%s features in box", features.size()), Toast.LENGTH_SHORT).show();
|
||||
|
||||
for (Feature feature : features) {
|
||||
if (feature.getGeometry() instanceof Polygon) {
|
||||
Polygon building = (Polygon) feature.getGeometry();
|
||||
|
||||
//Convert outer ring
|
||||
List<List<Position>> coordinates = building.getCoordinates();
|
||||
List<Position> outerRing = coordinates.get(0);
|
||||
List<LatLng> points = new ArrayList<LatLng>();
|
||||
for (Position position : outerRing) {
|
||||
points.add(new LatLng(position.getLatitude(), position.getLongitude()));
|
||||
}
|
||||
|
||||
mapboxMap.addPolygon(new PolygonOptions().addAll(points).fillColor(Color.RED));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Little taste of home
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.0907, 5.1214), 16));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public MapboxMap getMapboxMap() {
|
||||
return mapboxMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupActionBar() {
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
package com.mapbox.mapboxsdk.testapp.activity.feature;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
|
||||
import com.mapbox.mapboxsdk.testapp.R;
|
||||
import com.mapbox.services.commons.geojson.Feature;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Demo's query rendered features
|
||||
*/
|
||||
public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity {
|
||||
private static final String TAG = QueryRenderedFeaturesPropertiesActivity.class.getSimpleName();
|
||||
|
||||
public MapView mapView;
|
||||
private MapboxMap mapboxMap;
|
||||
private Marker marker;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_query_features_point);
|
||||
setupActionBar();
|
||||
|
||||
final float density = getResources().getDisplayMetrics().density;
|
||||
|
||||
//Initialize map as normal
|
||||
mapView = (MapView) findViewById(R.id.mapView);
|
||||
mapView.onCreate(savedInstanceState);
|
||||
mapView.getMapAsync(new OnMapReadyCallback() {
|
||||
@Override
|
||||
public void onMapReady(final MapboxMap mapboxMap) {
|
||||
QueryRenderedFeaturesPropertiesActivity.this.mapboxMap = mapboxMap;
|
||||
|
||||
//Add custom window adapter
|
||||
addCustomInfoWindowAdapter(mapboxMap);
|
||||
|
||||
//Add a click listener
|
||||
mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
|
||||
@Override
|
||||
public void onMapClick(@NonNull LatLng point) {
|
||||
//Query
|
||||
final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
|
||||
Log.i(TAG, String.format("Requesting features for %sx%s (%sx%s adjusted for density)", pixel.x, pixel.y, pixel.x / density, pixel.y / density));
|
||||
List<Feature> features = mapboxMap.queryRenderedFeatures(pixel);
|
||||
|
||||
//Debug output
|
||||
debugOutput(features);
|
||||
|
||||
//Remove any previous markers
|
||||
if (marker != null) {
|
||||
mapboxMap.removeMarker(marker);
|
||||
}
|
||||
|
||||
//Add a marker on the clicked point
|
||||
marker = mapboxMap.addMarker(new CustomMarkerOptions().position(point).features(features));
|
||||
mapboxMap.selectMarker(marker);
|
||||
}
|
||||
});
|
||||
|
||||
//Little taste of home
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.0907, 5.1214), 16));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void debugOutput(List<Feature> features) {
|
||||
Log.i(TAG, String.format("Got %s features", features.size()));
|
||||
for (Feature feature : features) {
|
||||
if (feature != null) {
|
||||
Log.i(TAG, String.format("Got feature %s with %s properties and Geometry %s",
|
||||
feature.getId(),
|
||||
feature.getProperties() != null ? feature.getProperties().entrySet().size() : "<null>",
|
||||
feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>")
|
||||
);
|
||||
if (feature.getProperties() != null) {
|
||||
for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) {
|
||||
Log.i(TAG, String.format("Prop %s - %s", entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "Got NULL feature %s");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addCustomInfoWindowAdapter(MapboxMap mapboxMap) {
|
||||
mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
|
||||
|
||||
private TextView row(String text) {
|
||||
TextView view = new TextView(QueryRenderedFeaturesPropertiesActivity.this);
|
||||
view.setText(text);
|
||||
return view;
|
||||
}
|
||||
|
||||
private int tenDp = (int) getResources().getDimension(R.dimen.attr_margin);
|
||||
|
||||
@Override
|
||||
public View getInfoWindow(@NonNull Marker marker) {
|
||||
CustomMarker customMarker = (CustomMarker) marker;
|
||||
LinearLayout view = new LinearLayout(QueryRenderedFeaturesPropertiesActivity.this);
|
||||
view.setOrientation(LinearLayout.VERTICAL);
|
||||
view.setBackgroundColor(Color.WHITE);
|
||||
|
||||
if (customMarker.features.size() > 0) {
|
||||
view.addView(row(String.format("Found %s features", customMarker.features.size())));
|
||||
Feature feature = customMarker.features.get(0);
|
||||
for (Map.Entry<String, JsonElement> prop : feature.getProperties().entrySet()) {
|
||||
view.addView(row(String.format("%s: %s", prop.getKey(), prop.getValue())));
|
||||
}
|
||||
} else {
|
||||
view.addView(row("No features here"));
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public MapboxMap getMapboxMap() {
|
||||
return mapboxMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mapView.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupActionBar() {
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CustomMarker extends Marker {
|
||||
|
||||
private final List<Feature> features;
|
||||
|
||||
public CustomMarker(BaseMarkerOptions baseMarkerOptions, List<Feature> features) {
|
||||
super(baseMarkerOptions);
|
||||
this.features = features;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CustomMarkerOptions extends BaseMarkerOptions<CustomMarker, CustomMarkerOptions> {
|
||||
|
||||
|
||||
private List<Feature> features;
|
||||
|
||||
public CustomMarkerOptions features(List<Feature> features) {
|
||||
this.features = features;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CustomMarkerOptions() {
|
||||
}
|
||||
|
||||
private CustomMarkerOptions(Parcel in) {
|
||||
//Should implement this
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomMarkerOptions getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomMarker getMarker() {
|
||||
return new CustomMarker(this, features);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<CustomMarkerOptions> CREATOR
|
||||
= new Parcelable.Creator<CustomMarkerOptions>() {
|
||||
public CustomMarkerOptions createFromParcel(Parcel in) {
|
||||
return new CustomMarkerOptions(in);
|
||||
}
|
||||
|
||||
public CustomMarkerOptions[] newArray(int size) {
|
||||
return new CustomMarkerOptions[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
//Should implement this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@color/primary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<com.mapbox.mapboxsdk.maps.MapView
|
||||
android:id="@+id/mapView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/toolbar" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/selection_box"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="150dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:alpha="0.3"
|
||||
android:background="#1d72da" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@color/primary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
||||
|
||||
<com.mapbox.mapboxsdk.maps.MapView
|
||||
android:id="@+id/mapView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/toolbar"/>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -57,6 +57,9 @@
|
||||
<string name="activity_geojson_clustering">GeoJson Clustering</string>
|
||||
<string name="activity_print">Print a map</string>
|
||||
<string name="activity_surfaceview_overlay">SurfaceView MediaOverlay</string>
|
||||
<string name="activity_query_rendered_feature_properties">Query feature properties</string>
|
||||
<string name="activity_query_rendered_features_box_count">Count features in box</string>
|
||||
<string name="activity_query_rendered_features_box_highlight">Highlight features in box</string>
|
||||
<string name="title_activity_navigation_drawer">Android SDK View integration</string>
|
||||
|
||||
<!-- Description -->
|
||||
@@ -100,6 +103,9 @@
|
||||
<string name="description_print">Shows how to print a map</string>
|
||||
<string name="description_navigation_drawer">Test animation of Android SDK View components</string>
|
||||
<string name="description_surfaceview_mediacontrols">Test overlaying SurfaceView</string>
|
||||
<string name="description_query_rendered_feature_properties_point">Query rendered feature properties on click</string>
|
||||
<string name="description_query_rendered_features_box_count">Count all rendered features in box</string>
|
||||
<string name="description_query_rendered_features_box_highlight">Hightligh buildings in box</string>
|
||||
|
||||
<string name="menuitem_title_concurrent_infowindow">Concurrent Open InfoWindows</string>
|
||||
<string name="menuitem_title_deselect_markers_on_tap">Deselect Markers On Tap</string>
|
||||
@@ -121,6 +127,7 @@
|
||||
<string name="category_userlocation">User Location</string>
|
||||
<string name="category_navigation">Navigation</string>
|
||||
<string name="category_style">Styling</string>
|
||||
<string name="category_features">Features</string>
|
||||
|
||||
<string name="action_visible_bounds_explanation">Center map around 2 markers</string>
|
||||
<string name="action_remove_polylines">Remove polylines</string>
|
||||
|
||||
42
platform/android/src/conversion/collection.hpp
Normal file
42
platform/android/src/conversion/collection.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "conversion.hpp"
|
||||
#include "constant.hpp"
|
||||
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
/**
|
||||
* Convert jarray -> ArrayList
|
||||
*/
|
||||
template <class T>
|
||||
inline jni::jobject* toArrayList(JNIEnv& env, jni::jarray<T>& array) {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Arrays")).release();
|
||||
static jni::jmethodID* asList = &jni::GetStaticMethodID(env, *javaClass, "asList", "([Ljava/lang/Object;)Ljava/util/List;");
|
||||
return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *asList, array));
|
||||
}
|
||||
|
||||
// Java -> C++
|
||||
|
||||
|
||||
inline std::vector<std::string> toVector(JNIEnv& env, jni::jarray<jni::jobject>& array) {
|
||||
std::vector<std::string> vector;
|
||||
std::size_t len = jni::GetArrayLength(env, array);
|
||||
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
jni::jstring* jstr = reinterpret_cast<jni::jstring*>(jni::GetObjectArrayElement(env, array, i));
|
||||
vector.push_back(*convert<std::string, jni::String>(env, jni::String(jstr)));
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,13 @@ struct Converter<jni::jobject*, bool> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jboolean, bool> {
|
||||
Result<jni::jboolean> operator()(jni::JNIEnv&, const bool& value) const {
|
||||
return {(jni::jboolean) value};
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jobject*, float> {
|
||||
Result<jni::jobject*> operator()(jni::JNIEnv& env, const float& value) const {
|
||||
@@ -32,6 +39,45 @@ struct Converter<jni::jobject*, float> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jfloat, float> {
|
||||
Result<jni::jfloat> operator()(jni::JNIEnv&, const float& value) const {
|
||||
return {(jni::jfloat) value};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jobject*, double> {
|
||||
Result<jni::jobject*> operator()(jni::JNIEnv& env, const double& value) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Double")).release();
|
||||
static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(D)V");
|
||||
return {&jni::NewObject(env, *javaClass, *constructor, (jfloat) value)};
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jdouble, float> {
|
||||
Result<jni::jdouble> operator()(jni::JNIEnv&, const double& value) const {
|
||||
return {(jni::jdouble) value};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* All integrals. java is limited to 64 bit signed, so...
|
||||
* TODO: use BigDecimal for > 64 / unsigned?
|
||||
*/
|
||||
template<typename T>
|
||||
struct Converter<jni::jobject*, T, typename std::enable_if<std::is_integral<T>::value>::type> {
|
||||
Result<jni::jobject*> operator()(jni::JNIEnv& env, const T& value) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Long")).release();
|
||||
static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(J)V");
|
||||
return {&jni::NewObject(env, *javaClass, *constructor, (jlong) value)};
|
||||
}
|
||||
};
|
||||
|
||||
//TODO: convert integral types to primitive jni types
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jobject*, std::string> {
|
||||
Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::string& value) const {
|
||||
@@ -39,6 +85,13 @@ struct Converter<jni::jobject*, std::string> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jstring*, std::string> {
|
||||
Result<jni::jstring*> operator()(jni::JNIEnv& env, const std::string& value) const {
|
||||
return {jni::Make<jni::String>(env, value).Get()};
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jobject*, Color> {
|
||||
Result<jni::jobject*> operator()(jni::JNIEnv& env, const Color& value) const {
|
||||
@@ -90,6 +143,15 @@ struct Converter<jni::jobject*, std::vector<float>> {
|
||||
}
|
||||
};
|
||||
|
||||
// Java -> C++
|
||||
|
||||
template <>
|
||||
struct Converter<std::string, jni::String> {
|
||||
Result<std::string> operator()(jni::JNIEnv& env, const jni::String& value) const {
|
||||
return { jni::Make<std::string>(env, value) };
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class V>
|
||||
template <class T, class V, class Enable = void>
|
||||
struct Converter;
|
||||
|
||||
template <class T, typename V, class...Args>
|
||||
|
||||
209
platform/android/src/geometry/conversion/feature.hpp
Normal file
209
platform/android/src/geometry/conversion/feature.hpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../conversion/constant.hpp"
|
||||
#include "../../conversion/conversion.hpp"
|
||||
#include "geometry.hpp"
|
||||
|
||||
#include <mbgl/util/feature.hpp>
|
||||
#include <mapbox/variant.hpp>
|
||||
#include <mapbox/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
#include "../../jni/local_object.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
/**
|
||||
* Turn feature identifier into std::string
|
||||
*/
|
||||
class FeatureIdVisitor {
|
||||
public:
|
||||
|
||||
template<class T>
|
||||
std::string operator()(const T& i) const {
|
||||
return std::to_string(i);
|
||||
}
|
||||
|
||||
std::string operator()(const std::string& i) const {
|
||||
return i;
|
||||
}
|
||||
|
||||
std::string operator()(const std::nullptr_t&) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn properties into Java GSON JsonObject's
|
||||
*/
|
||||
class PropertyValueEvaluator {
|
||||
public:
|
||||
jni::JNIEnv& env;
|
||||
|
||||
/**
|
||||
* null
|
||||
*/
|
||||
jni::jobject* operator()(const mapbox::geometry::null_value_t &) const {
|
||||
return (jni::jobject*) nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean primitive
|
||||
*/
|
||||
jni::jobject* operator()(const bool& value) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
|
||||
static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Z)V");
|
||||
|
||||
//Create JsonPrimitive
|
||||
jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, bool>(env, value));
|
||||
jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, *converted);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* String primitive
|
||||
*/
|
||||
jni::jobject* operator()(const std::string& value) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
|
||||
static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/String;)V");
|
||||
|
||||
//Create JsonPrimitive
|
||||
jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, value));
|
||||
jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number primitives
|
||||
*/
|
||||
template <class Number>
|
||||
jni::jobject* operator()(const Number& value) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonPrimitive")).release();
|
||||
static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Number;)V");
|
||||
|
||||
//Create JsonPrimitive
|
||||
jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, Number>(env, value));
|
||||
jni::jobject* object = &jni::NewObject(env, *javaClass, *constructor, converted.get());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Json Array
|
||||
*/
|
||||
jni::jobject* operator()(const std::vector<mbgl::Value> &values) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonArray")).release();
|
||||
static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
|
||||
static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Lcom/google/gson/JsonElement;)V");
|
||||
|
||||
//Create json array
|
||||
jni::jobject* jarray = &jni::NewObject(env, *javaClass, *constructor);
|
||||
|
||||
//Add values
|
||||
for (const auto &v : values) {
|
||||
jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(v, *this));
|
||||
jni::CallMethod<void>(env, jarray, *add, converted.get());
|
||||
}
|
||||
|
||||
return jarray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Json Object
|
||||
*/
|
||||
jni::jobject* operator()(const std::unordered_map<std::string, mbgl::Value> &value) const {
|
||||
//TODO: clean up duplication here
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release();
|
||||
static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
|
||||
static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V");
|
||||
|
||||
//Create json object
|
||||
jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor);
|
||||
|
||||
//Add items
|
||||
for (auto &item : value) {
|
||||
jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, *this));
|
||||
jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first));
|
||||
jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get());
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jobject*, std::unordered_map<std::string, mbgl::Value>> {
|
||||
Result<jni::jobject*> operator()(jni::JNIEnv& env, const std::unordered_map<std::string, mbgl::Value>& value) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/google/gson/JsonObject")).release();
|
||||
static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "()V");;
|
||||
static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(Ljava/lang/String;Lcom/google/gson/JsonElement;)V");
|
||||
|
||||
//Create json object
|
||||
jni::jobject* jsonObject = &jni::NewObject(env, *javaClass, *constructor);
|
||||
|
||||
//Add items
|
||||
PropertyValueEvaluator evaluator {env};
|
||||
for (auto &item : value) {
|
||||
jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mbgl::Value::visit(item.second, evaluator));
|
||||
jni::LocalObject<jni::jobject> key = jni::NewLocalObject(env, *convert<jni::jobject*, std::string>(env, item.first));
|
||||
jni::CallMethod<void>(env, jsonObject, *add, key.get(), converted.get());
|
||||
}
|
||||
|
||||
return {jsonObject};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jobject*, mbgl::Feature> {
|
||||
Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::Feature& value) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Feature")).release();
|
||||
static jni::jmethodID* fromGeometry = &jni::GetStaticMethodID(env, *javaClass, "fromGeometry", "(Lcom/mapbox/services/commons/geojson/Geometry;Lcom/google/gson/JsonObject;Ljava/lang/String;)Lcom/mapbox/services/commons/geojson/Feature;");
|
||||
|
||||
//Convert Id
|
||||
FeatureIdVisitor idEvaluator;
|
||||
std::string id = (value.id) ? mapbox::geometry::identifier::visit(value.id.value(), idEvaluator) : "";
|
||||
jni::LocalObject<jni::jobject> jid = jni::NewLocalObject(env, *convert<jni::jobject*>(env, id));
|
||||
|
||||
//Convert properties
|
||||
jni::LocalObject<jni::jobject> properties = jni::NewLocalObject(env, *convert<jni::jobject*>(env, value.properties));
|
||||
|
||||
//Convert geometry
|
||||
jni::LocalObject<jni::jobject> geometry = jni::NewLocalObject(env, *convert<jni::jobject*>(env, value.geometry));
|
||||
|
||||
//Create feature
|
||||
return {reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometry, geometry.get(), properties.get(), jid.get()))};
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>> {
|
||||
Result<jni::jarray<jni::jobject>*> operator()(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) const {
|
||||
static jni::jclass* featureClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Feature")).release();
|
||||
jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *featureClass);
|
||||
|
||||
for(size_t i = 0; i < value.size(); i = i + 1) {
|
||||
jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, *convert<jni::jobject*, mbgl::Feature>(env, value.at(i)));
|
||||
jni::SetObjectArrayElement(env, jarray, i, converted.get());
|
||||
}
|
||||
|
||||
return {&jarray};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
184
platform/android/src/geometry/conversion/geometry.hpp
Normal file
184
platform/android/src/geometry/conversion/geometry.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../conversion/constant.hpp"
|
||||
#include "../../conversion/collection.hpp"
|
||||
|
||||
#include <mapbox/geometry.hpp>
|
||||
#include <jni/jni.hpp>
|
||||
#include "../../jni/local_object.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
namespace conversion {
|
||||
|
||||
/**
|
||||
* Turn mapbox::geometry type into Java GeoJson Geometries
|
||||
*/
|
||||
template <typename T>
|
||||
class GeometryEvaluator {
|
||||
public:
|
||||
|
||||
jni::JNIEnv& env;
|
||||
|
||||
/**
|
||||
* Point (double[])
|
||||
*/
|
||||
jni::jobject* operator()(const mapbox::geometry::point<T> &geometry) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Point")).release();
|
||||
static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([D)Lcom/mapbox/services/commons/geojson/Point;");
|
||||
|
||||
//Create Point
|
||||
jni::LocalObject<jni::jarray<jni::jdouble>> position = jni::NewLocalObject(env, toGeoJsonPosition(env, geometry.x, geometry.y));
|
||||
return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, position.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* LineString (double[][])
|
||||
*/
|
||||
jni::jobject* operator()(const mapbox::geometry::line_string<T> &geometry) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/LineString")).release();
|
||||
static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[D)Lcom/mapbox/services/commons/geojson/LineString;");
|
||||
|
||||
//Create
|
||||
jni::LocalObject<jni::jarray<jni::jobject>> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, geometry));
|
||||
return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, coordinates.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* MultiPoint (double[][])
|
||||
*/
|
||||
jni::jobject* operator()(const mapbox::geometry::multi_point<T> &geometry) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiPoint")).release();
|
||||
static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[D)Lcom/mapbox/services/commons/geojson/MultiPoint;");
|
||||
|
||||
//Create
|
||||
jni::LocalObject<jni::jarray<jni::jobject>> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, geometry));
|
||||
return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, coordinates.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Polygon (double[][][])
|
||||
*/
|
||||
jni::jobject* operator()(const mapbox::geometry::polygon<T> &geometry) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Polygon")).release();
|
||||
static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[D)Lcom/mapbox/services/commons/geojson/Polygon;");
|
||||
|
||||
//Create
|
||||
jni::LocalObject<jni::jarray<jni::jobject>> shape = jni::NewLocalObject(env, toShape<>(env, geometry));
|
||||
return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, shape.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* MultiLineString (double[][][])
|
||||
*/
|
||||
jni::jobject* operator()(const mapbox::geometry::multi_line_string<T> &geometry) const {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiLineString")).release();
|
||||
static jni::jmethodID* fromCoordinates = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[D)Lcom/mapbox/services/commons/geojson/MultiLineString;");
|
||||
|
||||
//Create
|
||||
jni::LocalObject<jni::jarray<jni::jobject>> shape = jni::NewLocalObject(env, toShape<>(env, geometry));
|
||||
return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromCoordinates, shape.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* MultiPolygon (double[][][][]) -> [[[D + Object array == [[[[D
|
||||
*/
|
||||
jni::jobject* operator()(const mapbox::geometry::multi_polygon<T> &geometry) const {
|
||||
static jni::jclass* listClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[[D")).release();
|
||||
jni::LocalObject<jni::jarray<jni::jobject>> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, geometry.size(), *listClass));
|
||||
|
||||
for(size_t i = 0; i < geometry.size(); i = i + 1) {
|
||||
jni::LocalObject<jni::jarray<jni::jobject>> shape = jni::NewLocalObject(env, toShape<>(env, geometry.at(i)));
|
||||
jni::SetObjectArrayElement(env, *jarray, i, shape.get());
|
||||
}
|
||||
|
||||
//Create the MultiPolygon
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/MultiPolygon")).release();
|
||||
static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromCoordinates", "([[[[D)Lcom/mapbox/services/commons/geojson/MultiPolygon;");
|
||||
return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometries, jarray.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* GeometryCollection
|
||||
*/
|
||||
jni::jobject* operator()(const mapbox::geometry::geometry_collection<T> &collection) const {
|
||||
static jni::jclass* geometryClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/Geometry")).release();
|
||||
jni::LocalObject<jni::jarray<jni::jobject>> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, collection.size(), *geometryClass));
|
||||
|
||||
for(size_t i = 0; i < collection.size(); i = i + 1) {
|
||||
auto& geometry = collection.at(i);
|
||||
jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mapbox::geometry::geometry<T>::visit(geometry, *this));
|
||||
jni::SetObjectArrayElement(env, *jarray, i, converted.get());
|
||||
}
|
||||
|
||||
//Turn into array list and create the GeometryCollection
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/services/commons/geojson/GeometryCollection")).release();
|
||||
static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromGeometries", "(Ljava/util/List;)Lcom/mapbox/services/commons/geojson/GeometryCollection;");
|
||||
|
||||
jni::LocalObject<jni::jobject> list = jni::NewLocalObject(env, toArrayList<>(env, *jarray));
|
||||
return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometries, list.get()));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* x, y -> jarray<jdouble> ([x,y])
|
||||
*/
|
||||
static jni::jarray<jni::jdouble>* toGeoJsonPosition(JNIEnv& env, double x, double y) {
|
||||
jni::jarray<jni::jdouble>& jarray = jni::NewArray<jni::jdouble>(env, 2);
|
||||
jni::jdouble array[] = {x, y};
|
||||
jni::SetArrayRegion(env, jarray, 0, 2, array);
|
||||
return &jarray;
|
||||
}
|
||||
|
||||
/**
|
||||
* vector<point<T>> -> jarray<jobject> (double[][]) -> [D + Object array == [[D
|
||||
*/
|
||||
static jni::jarray<jni::jobject>* toGeoJsonCoordinates(JNIEnv& env, std::vector<mapbox::geometry::point<T>> points) {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[D")).release();
|
||||
jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, points.size(), *javaClass);
|
||||
|
||||
for(size_t i = 0; i < points.size(); i = i + 1) {
|
||||
mapbox::geometry::point<T> point = points.at(i);
|
||||
jni::LocalObject<jni::jarray<jni::jdouble>> position = jni::NewLocalObject(env, toGeoJsonPosition(env, point.x, point.y));
|
||||
jni::SetObjectArrayElement(env, jarray, i, position.get());
|
||||
}
|
||||
|
||||
return &jarray;
|
||||
}
|
||||
|
||||
/**
|
||||
* polygon<T>
|
||||
* multi_line_string<T>
|
||||
* -> jarray<jobject> (double[][][]) -> [[D + Object array == [[[D
|
||||
*/
|
||||
template <class SHAPE>
|
||||
static jni::jarray<jni::jobject>* toShape(JNIEnv& env, SHAPE value) {
|
||||
static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "[[D")).release();
|
||||
jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *javaClass);
|
||||
|
||||
for(size_t i = 0; i < value.size(); i = i + 1) {
|
||||
jni::LocalObject<jni::jarray<jni::jobject>> coordinates = jni::NewLocalObject(env, toGeoJsonCoordinates(env, value.at(i)));
|
||||
jni::SetObjectArrayElement(env, jarray, i, coordinates.get());
|
||||
}
|
||||
|
||||
return &jarray;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* mapbox::geometry::geometry<T> -> Java GeoJson Geometry<>
|
||||
*/
|
||||
template <class T>
|
||||
struct Converter<jni::jobject*, mapbox::geometry::geometry<T>> {
|
||||
Result<jni::jobject*> operator()(jni::JNIEnv& env, const mapbox::geometry::geometry<T>& value) const {
|
||||
GeometryEvaluator<double> evaluator { env } ;
|
||||
jni::jobject* converted = mapbox::geometry::geometry<double>::visit(value, evaluator);
|
||||
return {converted};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,10 @@
|
||||
#include "style/layers/layers.hpp"
|
||||
#include "style/sources/sources.hpp"
|
||||
|
||||
#include "conversion/conversion.hpp"
|
||||
#include "conversion/collection.hpp"
|
||||
#include "geometry/conversion/feature.hpp"
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
@@ -23,9 +27,12 @@
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/exception.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <mapbox/geometry.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
@@ -929,6 +936,40 @@ void nativeSetVisibleCoordinateBounds(JNIEnv *env, jni::jobject* obj, jlong nati
|
||||
nativeMapView->getMap().easeTo(cameraOptions, animationOptions);
|
||||
}
|
||||
|
||||
jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForPoint(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jfloat x, jni::jfloat y, jni::jarray<jni::jobject>* layerIds) {
|
||||
using namespace mbgl::android::conversion;
|
||||
using namespace mapbox::geometry;
|
||||
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeQueryRenderedFeatures for Point");
|
||||
assert(nativeMapViewPtr != 0);
|
||||
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
||||
|
||||
mbgl::optional<std::vector<std::string>> layers;
|
||||
if (layerIds != nullptr && jni::GetArrayLength(*env, *layerIds) > 0) {
|
||||
layers = toVector(*env, *layerIds);
|
||||
}
|
||||
point<double> point = {x, y};
|
||||
|
||||
return *convert<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>>(*env, nativeMapView->getMap().queryRenderedFeatures(point, layers));
|
||||
}
|
||||
|
||||
jni::jarray<jni::jobject>* nativeQueryRenderedFeaturesForBox(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jfloat left, jni::jfloat top, jni::jfloat right, jni::jfloat bottom, jni::jarray<jni::jobject>* layerIds) {
|
||||
using namespace mbgl::android::conversion;
|
||||
using namespace mapbox::geometry;
|
||||
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeQueryRenderedFeatures for Box %.2f %.2f %.2f %.2f", left, top, right, bottom);
|
||||
assert(nativeMapViewPtr != 0);
|
||||
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
||||
|
||||
mbgl::optional<std::vector<std::string>> layers;
|
||||
if (layerIds != nullptr && jni::GetArrayLength(*env, *layerIds) > 0) {
|
||||
layers = toVector(*env, *layerIds);
|
||||
}
|
||||
box<double> box = { point<double>{ left, top}, point<double>{ right, bottom } };
|
||||
|
||||
return *convert<jni::jarray<jni::jobject>*, std::vector<mbgl::Feature>>(*env, nativeMapView->getMap().queryRenderedFeatures(box, layers));
|
||||
}
|
||||
|
||||
void nativeOnLowMemory(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeOnLowMemory");
|
||||
assert(nativeMapViewPtr != 0);
|
||||
@@ -1800,7 +1841,9 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
MAKE_NATIVE_METHOD(nativeAddSource, "(JLjava/lang/String;Lcom/mapbox/mapboxsdk/style/sources/Source;)V"),
|
||||
MAKE_NATIVE_METHOD(nativeRemoveSource, "(JLjava/lang/String;)V"),
|
||||
MAKE_NATIVE_METHOD(nativeSetContentPadding, "(JDDDD)V"),
|
||||
MAKE_NATIVE_METHOD(nativeScheduleTakeSnapshot, "(J)V")
|
||||
MAKE_NATIVE_METHOD(nativeScheduleTakeSnapshot, "(J)V"),
|
||||
MAKE_NATIVE_METHOD(nativeQueryRenderedFeaturesForPoint, "(JFF[Ljava/lang/String;)[Lcom/mapbox/services/commons/geojson/Feature;"),
|
||||
MAKE_NATIVE_METHOD(nativeQueryRenderedFeaturesForBox, "(JFFFF[Ljava/lang/String;)[Lcom/mapbox/services/commons/geojson/Feature;")
|
||||
);
|
||||
|
||||
// Offline begin
|
||||
|
||||
33
platform/android/src/jni/local_object.hpp
Normal file
33
platform/android/src/jni/local_object.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace jni {
|
||||
|
||||
class LocalRefDeleter {
|
||||
private:
|
||||
JNIEnv* env = nullptr;
|
||||
|
||||
public:
|
||||
LocalRefDeleter() = default;
|
||||
LocalRefDeleter(JNIEnv& e) : env(&e) {}
|
||||
|
||||
void operator()(jobject* object) const {
|
||||
if (object) {
|
||||
assert(env);
|
||||
DeleteLocalRef(*env, object);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template < class T >
|
||||
using LocalObject = std::unique_ptr< T, LocalRefDeleter >;
|
||||
|
||||
/**
|
||||
* Use a LocalObject to discard of local references as soon as possible
|
||||
*/
|
||||
template < class T >
|
||||
LocalObject<T> NewLocalObject(JNIEnv& env, T* t) {
|
||||
return LocalObject<T>(t, LocalRefDeleter(env));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user