Skip to main content

Integrating HERE On-Street Parking API via HERE SDK

HERE SDK w On Street Parking

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.

dem_Sach

Overview

The solution involves:

  1. Using HERE SDK's Search API to reverse-geocode a location and fetch nearby places.
  2. Calling the On-Street Parking API to retrieve parking segment data for a bounding box around a selected location.
  3. 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.

Copied
        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.

Copied
        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.

Copied
        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.

Copied
        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.

Copied
        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.

Copied
        @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.

Copied
        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):

Copied
        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.

Sachin Jonda

Sachin Jonda

Lead Onboarding Engineer

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