Overview

Location Kit combines the GNSS, Wi-Fi, and base station location functionalities into your app to build up global positioning capabilities, allowing you to provide flexible location-based services for global users. In this codelab, you will learn how to call capabilities of Location Kit to create an Android app (codelab app).
The following figure shows the basic architecture of the app. The codelab app will use the integrated Location SDK to call the location service in HMS Core (APK).

What You Will Create

In this codelab, you will create an app for obtaining device location information.

What You Will Learn

In this codelab, you will learn how to:

Hardware Requirements

Software Requirements

To integrate Location Kit, you must complete the following preparations:

For details, please refer to Preparations for Integrating HUAWEI HMS Core.

You need to open your project in Android Studio.

  1. Open the build.gradle file in the root directory of your Android Studio project.
  2. Go to allprojects > repositories and configure the Maven repository address for the HMS Core SDK.
    allprojects { repositories { maven { url 'https://developer.huawei.com/repo/' } google() jcenter() } }
  3. Go to buildscript > repositories and configure the Maven repository address for the HMS Core SDK.
    buildscript { repositories { maven { url 'https://developer.huawei.com/repo/' } google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.5.4' classpath 'com.huawei.agconnect:agcp:1.6.0.300' } }
  4. Open the build.gradle directory in the app's root directory of your project.
  5. Add dependency on the Location SDK.
    dependencies { implementation 'com.huawei.hms:location:6.2.0.300' }

Before building the APK, configure the obfuscation configuration file to prevent the HMS Core SDK from being obfuscated.

  1. Open the obfuscation configuration file proguard-rules.pro of your Android project.
  2. Add the following configuration to exclude the HMS Core SDK from obfuscation:
    -ignorewarnings -keepattributes *Annotation* -keepattributes Exceptions -keepattributes InnerClasses -keepattributes Signature -keepattributes SourceFile,LineNumberTable -keep class com.huawei.hianalytics.**{*;} -keep class com.huawei.updatesdk.**{*;} -keep class com.huawei.hms.**{*;} -keep class * extends com.huawei.location.router.LocationApiRequest{ *; } -keep class * extends com.huawei.hms.core.aidl.IMessageEntity{ *; } -keep public class com.huawei.location.nlp.network.** {*; } -keep class com.huawei.wisesecurity.ucs.**{*;}
  3. If you are using AndResGuard, add its trustlist to the obfuscation configuration file.
    "R.string.hms*", "R.string.connect_server_fail_prompt_toast", "R.string.getting_message_fail_prompt_toast", "R.string.no_available_network_prompt_toast", "R.string.third_app_*", "R.string.upsdk_*", "R.layout.hms*", "R.layout.upsdk_*", "R.drawable.upsdk*", "R.color.upsdk*", "R.dimen.upsdk*", "R.style.upsdk*"
  4. If you integrate Location Kit 6.0.0 or later and enable compression for your app, add the following information to the app-level build.gradle file in your project. This is to avoid loading failure of some compressed dynamic hardening libraries during app running, which may cause function exception.
    android { buildTypes { release { packagingOptions { // If the CPU architecture is ARMv7 or ARMv8, add the following configuration: doNotStrip "*/arm64-v8a/libucs-credential.so" doNotStrip "*/armeabi-v7a/libucs-credential.so" // If the CPU architecture is x86, add the following configuration: doNotStrip "*/x86/libucs-credential.so" doNotStrip "*/x86_64/libucs-credential.so" } } debug { packagingOptions { // If the CPU architecture is ARMv7 or ARMv8, add the following configuration: doNotStrip "*/arm64-v8a/libucs-credential.so" doNotStrip "*/armeabi-v7a/libucs-credential.so" // If the CPU architecture is x86, add the following configuration: doNotStrip "*/x86/libucs-credential.so" doNotStrip "*/x86_64/libucs-credential.so" } } } }

You can click here to download the demo source code and obtain the xxx.java file used during the demo development.

  1. Apply for location permissions.
    1. Declare the following permissions in the AndroidManifest.xml file of your project:
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    2. If your app needs to continuously locate the device when it runs in the background in Android Q, also declare the ACCESS_BACKGROUND_LOCATION permission in the AndroidManifest.xml file.
      <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
    3. Dynamically apply for required permissions.
      Java sample code:
      if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) { Log.i(TAG, "sdk < 28 Q"); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { String[] strings = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}; ActivityCompat.requestPermissions(this, strings, 1); } } else { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, "android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED){ String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION, "android.permission.ACCESS_BACKGROUND_LOCATION"}; ActivityCompat.requestPermissions(this, strings, 2); } }
      Kotlin sample code:
      // check location permission if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) { Log.i(TAG, "sdk < 28 Q") if (checkSelfPermission( this, ACCESS_FINE_LOCATION ) != PERMISSION_GRANTED && checkSelfPermission( this, ACCESS_COARSE_LOCATION ) != PERMISSION_GRANTED ) { val strings = arrayOf( ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION ) requestPermissions(this, strings, 1) } } else { if (checkSelfPermission(this@RequestLocationUpdatesWithCallbackActivity, ACCESS_FINE_LOCATION) != PERMISSION_GRANTED && checkSelfPermission( this@RequestLocationUpdatesWithCallbackActivity, ACCESS_COARSE_LOCATION ) != PERMISSION_GRANTED && checkSelfPermission( this@RequestLocationUpdatesWithCallbackActivity, "android.permission.ACCESS_BACKGROUND_LOCATION" ) != PERMISSION_GRANTED ) { val strings = arrayOf( ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, "android.permission.ACCESS_BACKGROUND_LOCATION" ) requestPermissions(this, strings, 2) } }
    4. Configure permission application result callback.
      Java sample code:
      @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1) { if (grantResults.length > 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSION successful"); } else { Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSION failed"); } } if (requestCode == 2) { if (grantResults.length > 2 && grantResults[2] == PackageManager.PERMISSION_GRANTED && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION successful"); } else { Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION failed"); } } }
      Kotlin sample code:
      override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == 1) { if (grantResults.size > 1 && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED ) { Log.i( TAG, "onRequestPermissionsResult: apply LOCATION PERMISSION successful" ) } else { Log.i( TAG, "onRequestPermissionsResult: apply LOCATION PERMISSSION failed" ) } } if (requestCode == 2) { if (grantResults.size > 2 && grantResults[2] == PERMISSION_GRANTED && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED ) { Log.i( TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION successful" ) } else { Log.i( TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION failed" ) } } }
    5. You can refer to the RequestLocationUpdatesWithCallbackActivity.java or RequestLocationUpdatesWithCallbackActivity.kt file to complete subsequent steps.
  2. Create a location provider client and device setting client.
    Java sample code:
    // Define a location provider client. private FusedLocationProviderClient fusedLocationProviderClient; // Define a device setting client. private SettingsClient settingsClient; fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this); settingsClient = LocationServices.getSettingsClient(this);
    Kotlin sample code:
    // Define a location provider client. private lateinit var fusedLocationProviderClient: FusedLocationProviderClient // Define a device setting client. private lateinit var settingsClient: SettingsClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this) settingsClient = LocationServices.getSettingsClient(this)
  3. Create the location request body.
    Java sample code:
    LocationRequest mLocationRequest; mLocationRequest = new LocationRequest(); // Set the interval for requesting location updates (unit: ms). mLocationRequest.setInterval(10000); // Set the location type. mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    Kotlin sample code:
    var mLocationRequest: LocationRequest? = null // Set the interval for requesting location updates (unit: ms). // Set the location type. mLocationRequest = LocationRequest().apply { interval = 1000 needAddress = true priority = LocationRequest.PRIORITY_HIGH_ACCURACY }
  4. Create a location result callback.
    Java sample code:
    LocationCallback mLocationCallback; mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult != null) { List<Location> locations = locationResult.getLocations(); if (!locations.isEmpty()) { for (Location location : locations) { Log.i(TAG,"onLocationResult location[Longitude,Latitude,Accuracy]:" + location.getLongitude() + "," + location.getLatitude() + "," + location.getAccuracy()); } } } } @Override public void onLocationAvailability(LocationAvailability locationAvailability) { if (locationAvailability != null) { boolean flag = locationAvailability.isLocationAvailable(); Log.i(TAG, "onLocationAvailability isLocationAvailable:" + flag); } } };
    Kotlin sample code:
    var mLocationCallback: LocationCallback? = null if (null == mLocationCallback) { mLocationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult?) { if (locationResult != null) { val locations: List<Location> = locationResult.locations if (locations.isNotEmpty()) { for (location in locations) { Log.i( TAG, "onLocationResult location[Longitude,Latitude,Accuracy]:${location.longitude} , ${location.latitude} , ${location.accuracy}" ) } } } } override fun onLocationAvailability(locationAvailability: LocationAvailability?) { locationAvailability?.let { val flag: Boolean = locationAvailability.isLocationAvailable Log.i(TAG, "onLocationAvailability isLocationAvailable:$flag") } } } }
  5. Request location updates.
    Java sample code:
    private void requestLocationUpdatesWithCallback() { try { LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); builder.addLocationRequest(mLocationRequest); LocationSettingsRequest locationSettingsRequest = builder.build(); // Check the device settings before requesting location updates. settingsClient.checkLocationSettings(locationSettingsRequest) .addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() { @Override public void onSuccess(LocationSettingsResponse locationSettingsResponse) { Log.i(TAG, "check location settings success"); // Request location updates. fusedLocationProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper()).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { Log.i(TAG, "requestLocationUpdatesWithCallback onSuccess"); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { Log.e(TAG, "requestLocationUpdatesWithCallback onFailure:" + e.getMessage()); } }); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { Log.e(TAG, "checkLocationSetting onFailure:" + e.getMessage()); int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: try { ResolvableApiException rae = (ResolvableApiException) e; rae.startResolutionForResult(RequestLocationUpdatesWithCallbackActivity.this, 0); } catch (IntentSender.SendIntentException sie) { Log.e(TAG, "PendingIntent unable to execute request."); } break; } } }); } catch (Exception e) { Log.e(TAG, "requestLocationUpdatesWithCallback exception:" + e.getMessage()); } }
    Kotlin sample code:
    private fun requestLocationUpdatesWithCallback() { try { val builder = LocationSettingsRequest.Builder() builder.addLocationRequest(mLocationRequest) val locationSettingsRequest = builder.build() // Check the device settings before requesting location updates. val locationSettingsResponseTask: Task<LocationSettingsResponse> = settingsClient.checkLocationSettings(locationSettingsRequest) locationSettingsResponseTask.addOnSuccessListener { locationSettingsResponse: LocationSettingsResponse? -> Log.i(TAG, "check location settings success {$locationSettingsResponse}") // Request location updates. fusedLocationProviderClient.requestLocationUpdates( mLocationRequest, mLocationCallback, Looper.getMainLooper() ) .addOnSuccessListener { Log.i(TAG, "requestLocationUpdatesWithCallback onSuccess") } .addOnFailureListener { e -> Log.e( TAG, "requestLocationUpdatesWithCallback onFailure:${e.message}" ) } } .addOnFailureListener { e: Exception -> Log.e(TAG, "checkLocationSetting onFailure:${e.message}") when ((e as ApiException).statusCode) { LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try { val rae = e as ResolvableApiException rae.startResolutionForResult( this@RequestLocationUpdatesWithCallbackActivity, 0 ) } catch (sie: SendIntentException) { Log.e(TAG, "PendingIntent unable to execute request.") } } } } catch (e: Exception) { Log.e(TAG, "requestLocationUpdatesWithCallback exception:${e.message}") } }
  6. Stop requesting location updates.
    Java sample code:
    private void removeLocationUpdatesWithCallback() { try { fusedLocationProviderClient.removeLocationUpdates(mLocationCallback) .addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { Log.i(TAG, "removeLocationUpdatesWithCallback onSuccess"); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { Log.e(TAG, "removeLocationUpdatesWithCallback onFailure:" + e.getMessage()); } }); } catch (Exception e) { Log.e(TAG, "removeLocationUpdatesWithCallback exception:" + e.getMessage()); } }
    Kotlin sample code:
    private fun removeLocationUpdatesWithCallback() { try { fusedLocationProviderClient.removeLocationUpdates(mLocationCallback) .addOnSuccessListener { Log.i( TAG, "removeLocationUpdatesWithCallback onSuccess" ) } .addOnFailureListener { e -> Log.e( TAG, "removeLocationUpdatesWithCallback onFailure:${e.message}" ) } } catch (e: Exception) { Log.e( TAG, "removeLocationUpdatesWithCallback exception:${e.message}" ) } }

Tap requestLocationUpdates with callback in the demo app. The obtained location information will be displayed on the app screen.

Well done. You have successfully completed this codelab and learned how to:

For more information, please read related documents.
You can click here to download the source code.

已复制代码