Develop Location Based Applications with Huawei Mobile Services — 2

Mustafa Sürücü
Huawei Developers
Published in
5 min readJun 26, 2020

Hi everyone,

In my previous article, we found nearby places to the end user and show them on map according to user selection. If you have not read the first article, you can reach it from the link below.

https://medium.com/huawei-developers/develop-location-based-applications-with-huawei-mobile-services-1-906edb70615

Our next step is to give route information to the users to reach their target points.

Huawei Map Kit provides a Directions API which contains HTTPS-based services. This API returns route data in JSON format and provides route planning capability.

Note: You can examine request and response formats from below link.

We can start by adding new build dependencies to our build.gradle file in the app directory.

dependencies {
implementation 'com.android.volley:volley:1.1.1'
implementation 'com.google.code.gson:gson:2.8.6'
}

Let’s write a method to set URL that will be send a POST request.

public String getUrl (String mode){
String url = "https://mapapi.cloud.huawei.com/mapApi/v1/routeService/" + mode ;
return url;
}

You can arrange your code to set mode of route planning. Direction API supports walking, bicycling and driving routes. We will set it as “driving” for our demo application.

Define Request and Response Class Structure

Before sending our request, we should define our request and response classes in accordance with API document. You can check request classes as sample.

Arrange classes to handle reqeust and response.
public class DirectionRequest {
@SerializedName("origin")
@Expose
private Origin origin;
@SerializedName("destination")
@Expose
private Destination destination;

public Origin getOrigin() {
return origin;
}
public void setOrigin(Origin origin) {
this.origin = origin;
}
public Destination getDestination() {
return destination;
}
public void setDestination(Destination destination) {
this.destination = destination;
}
}
public class Origin {

@SerializedName("lng")
@Expose
private Double lng;
@SerializedName("lat")
@Expose
private Double lat;

public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
}
public class Destination {

@SerializedName("lng")
@Expose
private Double lng;
@SerializedName("lat")
@Expose
private Double lat;

public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
}

Now, we will define and instantiate our request objects that will be used.

//Define as global variable
DirectionRequest dirRequest;
Origin ori;
Destination dest;
//Instantiate in onCreate() method
dirRequest = new DirectionRequest();
ori = new Origin();
dest = new Destination();

After we specify our origin and destination points, we can send a request. I would like to set “origin” as users’ current location and “destination” as the first item of the target array list that we created before for nearby places.

//Set origin as current location inside of setLocation() methodfor (Location location : locations) {
Coordinate myLocation = new Coordinate(locationResult.getLastLocation().getLatitude(), locationResult.getLastLocation().getLongitude());
request.setLocation(myLocation);
//update camera to your current location
LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(currentLatLng, 15F);
hMap.moveCamera(update);
ori.setLat(location.getLatitude());
ori.setLng(location.getLongitude());

}

Setting destination coordinates as first place of Array list in addMarker() method.

for (int k = 0; k < targetlat.size(); k++) {
options.position(new LatLng(targetlat.get(k), targetlon.get(k)));
options.title(targetName.get(k));
if(type == LocationType.RESTAURANT) {
hMap.addMarker(options).setIcon(BitmapDescriptorFactory.fromResource(R.mipmap.restaurant_45));
} else if (type == LocationType.ATM){
hMap.addMarker(options).setIcon(BitmapDescriptorFactory.fromResource(R.mipmap.atm_45));
} else if (type == LocationType.SUPERMARKET) {
hMap.addMarker(options).setIcon(BitmapDescriptorFactory.fromResource(R.mipmap.shop_45));
} else if (type == LocationType.PHARMACY) {
hMap.addMarker(options).setIcon(BitmapDescriptorFactory.fromResource(R.mipmap.pill_45));
}
dest.setLat(targetlat.get(0));
dest.setLng(targetlon.get(0));

}

When user clicks on any button, getNearby() method will be called first. Since we fetch destination coordinates in addMarker() method, we will set directionRequest object and call apiRequest() method right after addMarker() method is called.

public void getNearby(){
request.setPoiType(type);
resultListener = new SearchResultListener<NearbySearchResponse>() {
@Override
public void onSearchResult(NearbySearchResponse results) {
targetlat.clear();
targetlon.clear();
targetName.clear();
List<Site> sites = results.getSites();
if (results == null || results.getTotalCount() <= 0 || sites == null || sites.size() <= 0) {
return;
}
for (Site site : sites) {
Log.i("nearbyme", String.format("siteId: '%s', name: %s\r\n", site.getSiteId(), site.getName()));
targetlat.add(site.getLocation().getLat());
targetlon.add(site.getLocation().getLng());
targetName.add(site.getName());
}
addMarker();
//Setting Request Object
dirRequest.setDestination(dest);
dirRequest.setOrigin(ori);

try {
apiRequest();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onSearchError(SearchStatus status) {
Log.i("TAG", "Error : " + status.getErrorCode() + " " + status.getErrorMessage());
}
};
searchService.nearbySearch(request,resultListener);
}

Generate API Request

Let’s write an apiRequest() method. We will use Volley library to send request and get related response.

Note: “API Key” is mandatory for Directions API. You can find it in agconnect-services.json file.

public void apiRequest() throws JSONException {
RequestQueue requestQueue = Volley.newRequestQueue(this);
Gson gson = new Gson();
String dirReq = gson.toJson(dirRequest);
Response.ErrorListener err = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d("ERROR", "onErrorResponse: " + error.getMessage());

}
};
Response.Listener res = new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {

Gson gson = new Gson();
DirectionResponse directionResponse = new DirectionResponse();
directionResponse = gson.fromJson(response.toString(), DirectionResponse.class);
drawPolyline(directionResponse);
Log.d("mapres", "onResponse: " + response.toString());
}
};
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, getUrl("driving"), new JSONObject(dirReq), res , err )
{ //this is the part, that adds API Key to the request
@Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<String, String>();
params.put("Authorization", "Bearer " + "API Key");
return params;
}
};

requestQueue.add(jsonObjectRequest);
}

Our response gave us directions to reach destination point. First direction has been fetched and the lines will be drawn has been specified for each step inside drawPolyline() method.

public void drawPolyline(DirectionResponse directionResponse){
PolylineOptions options = new PolylineOptions();
if (directionResponse.getRoutes() != null){
Route r = directionResponse.getRoutes().get(0);
if (r.getPaths() != null){
Path p = r.getPaths().get(0);
if (p.getSteps() != null) {
for (Step s : p.getSteps()) {
options.add(new LatLng(s.getStartLocation().getLat(), s.getStartLocation().getLng()));
options.add(new LatLng(s.getEndLocation().getLat(), s.getEndLocation().getLng()));
for (Polyline polyline : s.getPolyline()) {
options.add(new LatLng(polyline.getLat(), polyline.getLng()));
}
}
}
}
}
options.color(Color.BLUE);
options.width(6f);
hMap.addPolyline(options);
}
Route for ATM

Now, we can check the route on our map, that’s it !

Thank you for reading my article, I hope it was useful for you.

--

--