Integrating HERE On-Street Parking API via HERE SDK
Introduction
In an era where seamless navigation and real-time data are reshaping user expectations, integrating advanced location services into your applications is no longer optional—it's a necessity. HERE Technologies, a leader in mapping and geospatial services, empowers developers with cutting-edge tools to build smarter, location-aware apps.
One such innovation is the integration of HERE On-Street Parking API visualization via the HERE SDK. With the increasing demand for real-time parking information and user-friendly map interfaces, this guide demonstrates how to leverage HERE SDK's powerful features to bring intuitive parking solutions to your applications.
This knowledge base article walks you through the process of fetching and visualizing on-street parking data, dynamically drawing parking segments on the map, and enabling user interaction with highlighted polylines for an engaging experience. Whether you’re in sales, professional services, or development, this guide equips you with the insights and tools to harness the full potential of HERE SDK's capabilities, delivering a transformative edge to your app’s navigation and mapping functionalities.
Embark on this journey to create highly interactive, feature-rich applications that redefine how users interact with location data—because innovation starts with the right tools and a clear roadmap.
Overview
The solution involves:
- Using HERE SDK's Search API to reverse-geocode a location and fetch nearby places.
- Calling the On-Street Parking API to retrieve parking segment data for a bounding box around a selected location.
- Visualizing the parking segments as polylines on the HERE map.
Steps for Integration
1. Setting Up the HERE SDK
Ensure the HERE SDK is initialized in your app. Refer to HERE SDK documentation for initialization steps.
2. Making the On-Street Parking API Request
Search Integration
Use the HERE SDK Search API to get a place or location details for reverse-geocoding.
private final SearchCallback addressSearchCallback = new SearchCallback() {
@Override
public void onSearchCompleted(@Nullable SearchError searchError, @Nullable List<Place> list) {
if (searchError != null) {
showDialog("Reverse Geocoding", "Error: " + searchError.toString());
return;
}
// If error is null, the list is guaranteed to be non-empty.
Place place = list.get(0);
addPoiMapMarker(place.getGeoCoordinates(), null); // Add a marker for the place.
getOnStreetParkingData(mapView, place); // Fetch parking data.
}
};
On-Street Parking API Call
Once a place is identified, its bounding box is used to fetch parking segments via the On-Street Parking API.
private void getOnStreetParkingData(MapView mapView, Place placeData) {
SDKNativeEngine sdkNativeEngine = SDKNativeEngine.getSharedInstance();
Authentication.authenticate(sdkNativeEngine, (authenticationError, authenticationData) -> {
if (authenticationError != null) {
Log.e("Authentication", "Failed: " + authenticationError.toString());
return;
}
// Use the bounding box to fetch parking data
if (placeData.getBoundingBox() != null) {
String bbox = placeData.getBoundingBox().northEastCorner.latitude + "," +
placeData.getBoundingBox().northEastCorner.longitude + "," +
placeData.getBoundingBox().southWestCorner.latitude + "," +
placeData.getBoundingBox().southWestCorner.longitude;
String geometryType = "segmentAnchor";
// Retrofit call to fetch parking data
Call<ParkingResponse> call = RetrofitClient.getInstance().getMyApi().getOnStreetParking(
bbox, geometryType, "Bearer " + authenticationData.token);
call.enqueue(new Callback<ParkingResponse>() {
@Override
public void onResponse(Call<ParkingResponse> call, Response<ParkingResponse> response) {
if (response.isSuccessful() && response.body() != null) {
List<ParkingSegmentsItem> segments = response.body().getParkingSegments();
drawSegmentsOnMap(mapView, segments); // Visualize parking data on the map.
} else {
Log.e("API Response", "Empty or Error Response");
}
}
@Override
public void onFailure(Call<ParkingResponse> call, Throwable t) {
Log.e("API Error", t.getMessage());
}
});
}
});
}
3. Visualizing Parking Segments
The parking segments are drawn as polylines on the map using HERE SDK's MapPolyline class.
private void drawSegmentsOnMap(MapView mapView, List<ParkingSegmentsItem> segmentsItems) {
List<MapPolyline> mapPolylines = new ArrayList<>();
for (ParkingSegmentsItem segment : segmentsItems) {
List<OrientedSegmentRefItem> orientedSegmentRefs = segment.getSegmentAnchor().getOrientedSegmentRef();
for (OrientedSegmentRefItem ref : orientedSegmentRefs) {
GeoPolyline geoPolyline = getSegmentGeometry(ref); // Retrieve the segment geometry.
if (geoPolyline != null) {
MapPolyline polyline = createPolyline(geoPolyline);
if (polyline != null) {
mapPolylines.add(polyline);
}
}
}
}
mapView.getMapScene().addMapPolylines(mapPolylines); // Add all polylines to the map.
}
Getting Segment Geometry
The segment geometry is retrieved using HERE's SegmentReferenceConverter and SegmentDataLoader.
public GeoPolyline getSegmentGeometry(OrientedSegmentRefItem orientedSegmentRefBean) {
try {
SegmentReference segmentReference = SegmentReference.fromString(orientedSegmentRefBean.getSegmentRef().getIdentifier());
segmentReference.tilePartitionId = Integer.parseInt(orientedSegmentRefBean.getSegmentRef().getPartitionName());
segmentReference.travelDirection = orientedSegmentRefBean.isInverted() ? TravelDirection.NEGATIVE : TravelDirection.POSITIVE;
SegmentReferenceConverter converter = new SegmentReferenceConverter(SDKNativeEngine.getSharedInstance());
DirectedOCMSegmentId ocmSegmentId = converter.getOCMSegmentId(segmentReference);
SegmentDataLoader segmentDataLoader = new SegmentDataLoader(SDKNativeEngine.getSharedInstance());
SegmentData segmentData = segmentDataLoader.loadData(ocmSegmentId.id, new SegmentDataLoaderOptions());
return segmentData != null ? segmentData.getPolyline() : null;
} catch (Exception e) {
Log.e("Segment Geometry Error", e.getMessage());
return null;
}
}
Creating Polylines
Polylines are styled and added to the map.
private MapPolyline createPolyline(GeoPolyline geoPolyline) {
try {
float widthInPixels = 20;
com.here.sdk.core.Color lineColor = com.here.sdk.core.Color.valueOf(ContextCompat.getColor(context, R.color.design_default_color_secondary_variant));
return new MapPolyline(geoPolyline, new MapPolyline.SolidRepresentation(
new MapMeasureDependentRenderSize(RenderSize.Unit.PIXELS, widthInPixels), lineColor, LineCap.ROUND));
} catch (Exception e) {
Log.e("Polyline Error", e.getMessage());
return null;
}
}
4. Highlighting Polylines
To achieve this functionality, we dynamically adjust the width and color of the selected polyline and revert any previously selected polylines to their original appearance.
Define State for Selected Polylines
Use a List<MapPolyline> to keep track of the currently selected polyline(s).
private List<MapPolyline> selectedParkingPolylines = new ArrayList<>();
Handle Click Events
The onClickPolyline() method processes the user's interaction. It adjusts the visual properties of both the previously selected and newly selected polylines.
@Override
public void onClickPolyLine(List<MapPolyline> place) {
int selectedWidthInPixels = 30; // Width for the selected polyline
int unSelectedWidthInPixels = 20; // Width for the unselected polyline
// Colors for unselected and selected states
com.here.sdk.core.Color lineColor = com.here.sdk.core.Color.valueOf(ContextCompat.getColor(this, R.color.design_default_color_secondary_variant));
com.here.sdk.core.Color selectedLineColor = com.here.sdk.core.Color.valueOf(ContextCompat.getColor(this, R.color.selectedRouteColor));
// Reset previously selected polylines
if (!selectedParkingPolylines.isEmpty()) {
mapView.getMapScene().removeMapPolylines(selectedParkingPolylines); // Remove current polylines
try {
MapPolyline.Representation representation = new MapPolyline.SolidRepresentation(
new MapMeasureDependentRenderSize(RenderSize.Unit.PIXELS, unSelectedWidthInPixels),
lineColor, LineCap.ROUND);
selectedParkingPolylines.forEach(mapPolyline -> mapPolyline.setRepresentation(representation)); // Revert appearance
} catch (Exception e) {
Log.e(TAG, "onClickPolyLine: " + e.getLocalizedMessage());
}
mapView.getMapScene().addMapPolylines(selectedParkingPolylines); // Re-add with default style
}
// Highlight the newly selected polyline(s)
mapView.getMapScene().removeMapPolylines(place);
try {
MapPolyline.Representation representation = new MapPolyline.SolidRepresentation(
new MapMeasureDependentRenderSize(RenderSize.Unit.PIXELS, selectedWidthInPixels),
selectedLineColor, LineCap.ROUND);
place.forEach(mapPolyline -> mapPolyline.setRepresentation(representation)); // Apply selected style
} catch (Exception e) {
Log.e(TAG, "onClickPolyLine: " + e.getLocalizedMessage());
}
mapView.getMapScene().addMapPolylines(place); // Add the selected polyline(s) to the map
// Update the selected state
selectedParkingPolylines = place;
}
5. API Definition
Retrofit Interface
Defines the endpoint for fetching on-street parking data.
public interface Api {
String ON_STREET_PARKING_BASE_URL = "https://osp.cc.api.here.com/";
@GET("parking/segments")
Call<ParkingResponse> getOnStreetParking(@Query("bbox") String bbox, @Query("geometryType") String geometryType, @Header("Authorization") String token);
}
Retrofit Client
Singleton pattern for Retrofit client initialization.
public class RetrofitClient {
private static RetrofitClient instance = null;
private Api myApi;
private RetrofitClient() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Api.ON_STREET_PARKING_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
myApi = retrofit.create(Api.class);
}
public static synchronized RetrofitClient getInstance() {
if (instance == null) {
instance = new RetrofitClient();
}
return instance;
}
public Api getMyApi() {
return myApi;
}
}
6. Dependencies
Add the following dependencies to build.gradle(:app):
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-gson:2.7.2'
Please download the full sample integration from this link.
Please note: Kindly get in touch with your Account Executive(AE) or HERE sales representative to get your whitelisted credentials in order to access HERE On-Street Parking API with HERE SDK's.
Conclusion
Integrating HERE On-Street Parking API visualization with HERE SDK's is a powerful demonstration of how advanced geospatial technology can transform user experiences. By implementing features such as real-time parking data retrieval, dynamic map drawing, and interactive polyline highlighting, developers can create applications that meet the modern demands for intuitive navigation and contextual insights.
This blog serves as a practical framework for integrating HERE SDK into your applications, enabling teams across development, sales, and professional services to deliver innovative, user-centric solutions. From efficient API usage to visually engaging map interactions, this integration enhances the value your app provides to users by solving real-world challenges in parking and navigation.
As technology continues to shape user expectations, embracing tools like HERE SDK allows organizations to stay ahead of the curve. Whether you're building for Android, iOS, or other platforms, this integration not only enriches your app's functionality but also underscores the potential of geospatial intelligence in delivering seamless and efficient user experiences.
Unlock the future of location services with HERE SDK and empower your applications with the tools to lead in the rapidly evolving digital landscape. Together, let’s redefine what’s possible in mapping and navigation.
Have your say
Sign up for our newsletter
Why sign up:
- Latest offers and discounts
- Tailored content delivered weekly
- Exclusive events
- One click to unsubscribe