Map Kit is the most common service in lifestyle apps. In this application, a map kit was used to track taxis and routes. The user location can be displayed on the map, the desired destination can be selected on the map, icons can be added to the desired location (nearby taxis are shown.), the route and the movement on the route can be displayed on the map. These features were included in the application.
The destination and starting point of the route can be determined with the site kit. This process was achieved by using the place search feature of the Site Kit in the application. Site Kit allows your app to provide users convenient yet secure access to diverse location-based services. Also, the user location can be provided with the Location Kit to set as the route start point. Location Kit allows you to provide flexible location-based services for global users. The user's movement on the route can be tracked with the location kit and its progress can be displayed on the map. In this application, we made the progress on the route as an animation to be an example for visuality.
To use those kits, you will need to:
In this codelab, you will learn how to:
Create an app in AppGallery Connect and obtain the project configuration file agconnect-services.json. The procedure is as follows:
For details, please refer to Preparations for Integrating HUAWEI HMS Core
You can download the sample code for HiTaxi at GitHub.
Note: You need to register as a developer to complete the operations above.
For Android Studio, Huawei provides the HMS Core SDK that can be integrated by using the Maven repository. Before developing your app, you will need to integrate the HMS Core SDK into your Android Studio project.


allprojects {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
}
buildscript {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
}
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:4.1.2'
classpath 'com.huawei.agconnect:agcp:1.4.2.300'
}
}

dependencies {
implementation 'com.huawei.hms:site:{version}'
implementation 'com.huawei.hms:maps:{version}'
implementation 'com.huawei.hms:location:{version}'
implementation 'com.huawei.agconnect:agconnect-core:{version}'
}

In this codelab, we will create a Splash Page to check if location services are enabled by phone. We will create a page for requesting permission to use location services in the app. Also, we will create a page with a map to display the map, locations, routes, and nearby taxis. This page will be the application's main page. We will add a search bar for Site Kit and we will add a bottom sheet dialog to choosing taxi types, displaying ETA, estimated charge, and driver's information.







Kotlin:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initSearchIntent()
}
private fun initSearchIntent() {
searchIntent = SearchIntent()
searchIntent.setApiKey(URLEncoder.encode(BuildConfig.API_KEY, "UTF-8"))
}
Java:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initSearchIntent();
}
private void initSearchIntent() {
searchIntent = SearchIntent();
searchIntent.setApiKey(URLEncoder.encode(BuildConfig.API_KEY, "UTF-8"));
}

Kotlin:
fragmentViewBinding.searchLayout.setOnClickListener {
showSiteSearchFragment()
}
Java:
fragmentViewBinding.searchLayout.setOnClickListener(view -> {
showSiteSearchFragment();
});
Kotlin:
private fun showSiteSearchFragment() {
val intent = searchIntent.getIntent(requireActivity())
startActivityForResult(intent, SearchIntent.SEARCH_REQUEST_CODE)
}
Java:
private void showSiteSearchFragment(){
Intent intent = searchIntent.getIntent(requireActivity());
startActivityForResult(intent, SearchIntent.SEARCH_REQUEST_CODE);
}
Kotlin:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (SearchIntent.SEARCH_REQUEST_CODE == requestCode) {
if (SearchIntent.isSuccess(resultCode)) {
val site = searchIntent.getSiteFromIntent(data)
val latLng = LatLng(site.location.lat, site.location.lng)
huaweiMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18f))
saveAndShowAddress(latLng)
}
}
}
private fun saveAndShowAddress(latLng: LatLng) {
fragmentViewBinding.searchAddressText.text = homeViewModel.getAddress(latLng)
}
Java:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(SearchIntent.SEARCH_REQUEST_CODE == requestCode){
Site site = searchIntent.getSiteFromIntent(data);
LatLng latLng = new LatLng(site. location.lat, site.location.lng);
huaweiMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18f));
saveAndShowAddress(latLng);
}
}
private void saveAndShowAddress(LatLng latLng) {
fragmentViewBinding.searchAddressText.setText(homeViewModel.getAddress(latLng));
}
<com.huawei.hms.maps.MapView
android:id="@+id/huaweiMap"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="41.009314"
map:cameraTargetLng="29.003253"
map:cameraZoom="10"
map:mapType="normal"
map:uiCompass="true"
map:uiZoomControls="true" />
Kotlin:
override fun setupUi() {
super.setupUi()
lottieDialog = LottieDialog.Builder().setContext(requireContext())
.setLottieRawId(R.raw.route_animation).build()
locationDialog = LottieDialog.Builder().setContext(requireContext())
.setLottieRawId(R.raw.taxi_animation).build()
fragmentViewBinding.huaweiMap.apply {
onCreate(null)
getMapAsync(this@HomeFragment)
setupBookingBottomSheet()
}
}
Java:
@Override
public void setupUi() {
super.setupUi();
lottieDialog = new LottieDialog(R.raw.route_animation, requireContext());
locationDialog = new LottieDialog(R.raw.taxi_animation, requireContext());
fragmentViewBinding.huaweiMap.onCreate(null);
fragmentViewBinding.huaweiMap.getMapAsync(this);
setupBookingBottomSheet();
}
Kotlin:
fun addTaxi(latLng: LatLng) {
if (marker != null) {
marker!!.remove()
}
val startLat = latLng.latitude - 0.001
val endLat = latLng.latitude + 0.001
val startLng = latLng.longitude - 0.001
val endLng = latLng.longitude + 0.001
for (i in 0..5) {
marker = huaweiMap.addMarker(
MarkerOptions().position(
LatLng(
Random.nextDouble(startLat, endLat),
Random.nextDouble(startLng, endLng)
)
)
.anchor(0.5f, 0.9f)
.title("HiTaxi")
.icon(
BitmapDescriptorFactory.fromBitmap(
ContextCompat.getDrawable(
requireContext(),
R.drawable.ic_taxi
)?.toBitmap()
)
)
)
}
}
Java:
private void addTaxi(LatLng latLng) {
if (marker != null) {
marker.remove();
}
double startLat = latLng.latitude - 0.001;
double endLat = latLng.latitude + 0.001;
double startLng = latLng.longitude - 0.001;
double endLng = latLng.longitude + 0.001;
for (int i = 0; i <= 5; i++) {
double random = new Random().nextDouble();
double randomLat = startLat + (random * (endLat - startLat));
double randomLng = startLng + (random * (endLng - startLng));
Bitmap bitmap = BitmapFactory.decodeResource(requireContext().getResources(), R.drawable.ic_taxi);
MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(randomLat, randomLng))
.anchor(0.5f, 0.9f)
.title("HiTaxi")
.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
marker = huaweiMap.addMarker(
markerOptions);
}
}
Note: In this demo app, taxis are added as markers and randomly added close to user's location.
Kotlin:
private fun observeAndAddTaxi() {
homeViewModel.lastKnownLocation.observe(viewLifecycleOwner) {
it?.let { latLang ->
if (homeViewModel.isDestinationSelectedBefore.value == false) {
huaweiMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLang, 18f))
huaweiMap.clear()
addTaxi(latLang)
taxiFinalLocation = latLang
}
}
}
}
Java:
private void observeAndAddTaxi() {
homeViewModel.getLastKnownLocation().observe(getViewLifecycleOwner(), latLng -> {
if (homeViewModel.isDestinationSelectedBefore().getValue() == false) {
huaweiMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18f));
huaweiMap.clear();
addTaxi(latLng);
taxiFinalLocation = latLng;
}
});
}
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Kotlin:
fun checkPermission(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return false
}
}
return true
}
Java:
public boolean checkPermission(){
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
}
} else {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
Kotlin:
fun getLastLocation(lastKnownLocation: (LatLng) -> Unit) {
var mFusedLocationProviderClient: FusedLocationProviderClient? = null
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
var latLng: LatLng
try {
val lastLocation: Task = mFusedLocationProviderClient!!.lastLocation
lastLocation.addOnSuccessListener {
if (it == null) {
latLng = LatLng(0.0, 0.0)
lastKnownLocation(latLng)
} else {
latLng = LatLng(it.latitude, it.longitude)
lastKnownLocation(latLng)
}
}.addOnFailureListener {
Log.e(TAG, "getLastLocation exception:" + it.message)
}
} catch (e: Exception) {
Log.e(TAG, "getLastLocation exception:" + e.message)
}
}
Java:
public LatLng getLastLocation() {
LatLng lastKnownLocation = new LatLng(0, 0);
try {
Task<Location> lastLocation = mFusedLocationProviderClient.getLastLocation();
lastLocation.addOnSuccessListener(new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location == null) {
lastKnownLocation.latitude = 0;
lastKnownLocation.longitude = 0;
} else {
lastKnownLocation.latitude = location.getLatitude();
lastKnownLocation.longitude = location.getLongitude();
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "getLastLocation exception:" + e.getMessage());
}
});
} catch (Exception e) {
Log.e(TAG, "getLastLocation exception:" + e.getMessage());
}
return lastKnownLocation;
}
Kotlin:
fun checkLocationSettings(lastKnownLocation: (LatLng) -> Unit) {
val settingsClient = LocationServices.getSettingsClient(context)
val fusedLocationProviderClient: FusedLocationProviderClient
val mLocationRequest: LocationRequest
var latLng: LatLng
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
val mLocationCallback: LocationCallback
mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
latLng = LatLng(
locationResult.lastHWLocation.latitude,
locationResult.lastHWLocation.longitude
)
lastKnownLocation(latLng)
}
}
val builder = LocationSettingsRequest.Builder()
mLocationRequest = LocationRequest()
builder.addLocationRequest(mLocationRequest)
val locationSettingsRequest = builder.build()
settingsClient.checkLocationSettings(locationSettingsRequest)
.addOnSuccessListener {
fusedLocationProviderClient
.requestLocationUpdates(
mLocationRequest,
mLocationCallback,
Looper.getMainLooper()
)
}
.addOnFailureListener { e ->
val statusCode = (e as ApiException).statusCode
when (statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {
val rae = e as ResolvableApiException
rae.startResolutionForResult(context, 0)
lastKnownLocation(LatLng(0.0, 0.0))
} catch (sie: IntentSender.SendIntentException) {
lastKnownLocation(LatLng(0.0, 0.0))
}
}
}
}
Java:
public void checkLocationSettings(){
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
mLocationRequest = new LocationRequest();
builder.addLocationRequest(mLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
LatLng lastKnownLocation = new LatLng(0, 0);
LocationCallback mLocationCallback;
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
lastKnownLocation.latitude = locationResult.getLastLocation().getLatitude();
lastKnownLocation.longitude = locationResult.getLastLocation().getLongitude();
}
}
};
settingsClient.checkLocationSettings(locationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
mFusedLocationProviderClient
.requestLocationUpdates(
mLocationRequest,
mLocationCallback,
Looper.getMainLooper());
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(this, 0);
} catch (IntentSender.SendIntentException sie) {
}
break;
}
}
});
}
Kotlin:
private fun stopLocationUpdates() {
fusedLocationProviderClient.removeLocationUpdates(locationCallback)
}
Java:
public void stopLocationUpdates() {
mFusedLocationProviderClient.removeLocationUpdates(locationCallback);
}
Upon completing the essential parts of the code, connect your mobile device to the PC and enable the USB debugging mode. In the Android Studio window, click
icon to run the project you have created in Android Studio to generate an APK. Then install the APK on the mobile device.


|
|
|
|
|


Well done. You have successfully completed this codelab and learned:
For more information, please click the following links:
To download the sample code, please click the button below:
Download