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).
In this codelab, you will create an app for obtaining device location information.
In this codelab, you will learn how to:
To integrate Location Kit, you must complete the following preparations:
The procedure for configuring the Maven repository address in Android Studio is different for Gradle plugin earlier than 7.0, Gradle plugin 7.0, and Gradle plugin 7.1 or later. Click a relevant link below to find the configuration procedure for the specific Gradle plugin version.
Gradle plugin earlier than 7.0 | Gradle plugin 7.0 | Gradle plugin 7.1 or later |
Gradle plugin earlier than 7.0
buildscript {
repositories {
google()
jcenter()
// Configure the Maven repository address for the HMS Core SDK.
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
...
// Add the AppGallery Connect plugin configuration. Please refer to AppGallery Connect Plugin Dependency to select a proper plugin version.
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
allprojects {
repositories {
google()
jcenter()
// Configure the Maven repository address for the HMS Core SDK.
maven {url 'https://developer.huawei.com/repo/'}
}
}
Gradle plugin 7.0
buildscript {
repositories {
google()
jcenter()
// Configure the Maven repository address for the HMS Core SDK.
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
...
// Add the Android Gradle plugin configuration. You need to replace {version} with the actual Gradle plugin version, for example, 7.0.1.
classpath 'com.android.tools.build:gradle:{version}'
// Add the AppGallery Connect plugin configuration. Please refer to AppGallery Connect Plugin Dependency to select a proper plugin version.
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
dependencyResolutionManagement {
...
repositories {
google()
jcenter()
// Configure the Maven repository address for the HMS Core SDK.
maven {url 'https://developer.huawei.com/repo/'}
}
}
buildscript {
dependencies {
...
// Add the Android Gradle plugin configuration. You need to replace {version} with the actual Gradle plugin version, for example, 7.1.1.
classpath 'com.android.tools.build:gradle:{version}'
// Add the AppGallery Connect plugin configuration. Please refer to AppGallery Connect Plugin Dependency to select a proper plugin version.
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
// Configure the Maven repository address for the HMS Core SDK.
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencyResolutionManagement {
...
repositories {
google()
mavenCentral()
// Configure the Maven repository address for the HMS Core SDK.
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencies {
implementation 'com.huawei.hms:location:6.4.0.300'
}
Before building the APK, configure the obfuscation configuration file to prevent the HMS Core SDK from being obfuscated.
-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.hms.core.aidl.IMessageEntity{ *; }
-keep public class com.huawei.location.nlp.network.** {*; }
-keep class com.huawei.wisesecurity.ucs.**{*;}
"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*"
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.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
// check location permission
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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
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, 3);
}else{
if (ActivityCompat.checkSelfPermission(this,
"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
String[] permission = {"android.permission.ACCESS_BACKGROUND_LOCATION"};
ActivityCompat.requestPermissions(this, permission, 0);
}
}
} 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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (checkSelfPermission(
this,
ACCESS_FINE_LOCATION
) != PERMISSION_GRANTED
&& checkSelfPermission(
this,
ACCESS_COARSE_LOCATION
) != PERMISSION_GRANTED
) {
val strings = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)
ActivityCompat.requestPermissions(this, strings, 3)
} else {
if (checkSelfPermission(
this,
"android.permission.ACCESS_BACKGROUND_LOCATION"
) != PERMISSION_GRANTED
) {
val permission = arrayOf("android.permission.ACCESS_BACKGROUND_LOCATION")
ActivityCompat.requestPermissions(this, permission, 0)
}
}
} 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)
}
}
@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");
}
}
if (requestCode == 3) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
|| grantResults[1] == PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.checkSelfPermission(this,
"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
String[] permission = {"android.permission.ACCESS_BACKGROUND_LOCATION"};
ActivityCompat.requestPermissions(this, permission, 0);
}
} else {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSION failed");
}
}
}
Kotlin sample code:
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array, 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 PERMISSION 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"
)
}
}
if (requestCode == 3) {
if (grantResults.isNotEmpty() && grantResults[0] == PERMISSION_GRANTED
|| grantResults[1] == PERMISSION_GRANTED
) {
if (checkSelfPermission(
this,
"android.permission.ACCESS_BACKGROUND_LOCATION"
) != PERMISSION_GRANTED
) {
val permission = arrayOf("android.permission.ACCESS_BACKGROUND_LOCATION")
ActivityCompat.requestPermissions(this, permission, 0)
}
} else {
Log.i(
TAG,
"onRequestPermissionsResult: apply LOCATION PERMISSSION failed"
)
}
}
}
// 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)
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
}
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")
}
}
}
}
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() {
@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() {
@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());
}
});
} 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 =
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}")
}
} catch (e: Exception) {
Log.e(TAG, "requestLocationUpdatesWithCallback exception:${e.message}")
}
}
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.