定位服务(Location
Kit)采用GNSS、Wi-Fi、基站等多途径的混合定位模式进行定位,赋予您的应用快速、精准地获取用户位置信息的能力,构建全球定位服务能力,助力您发展全球业务。您将通过本Codelab学习如何调用Location
Kit定位服务能力创建一款Android 应用程序(Codelab App)。
此应用程序的基本架构如图所示:Codelab
App将集成Location SDK,然后通过Location SDK去调用HMS Core
(APK)的定位服务能力。
在这个Codelab中,您将创建一个获取设备位置信息的App。
集成HUAWEI HMS Core能力,需要完成以下准备工作:
Android Studio的代码库配置在Gradle插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请根据您当前的Gradle插件版本,选择对应的配置过程。
7.0以下版本 | 7.0版本 | 7.1及以上版本 |
7.0以下版本
buildscript {
repositories {
google()
jcenter()
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
...
// 增加AGC插件配置,请您参见AGC插件依赖关系选择合适的AGC插件版本。
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
allprojects {
repositories {
google()
jcenter()
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}
}
}
7.0版本
buildscript {
repositories {
google()
jcenter()
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
...
// 增加Android Gradle插件版本号配置,{version}为实际的Gradle插件版本号,例如7.0.1。
classpath 'com.android.tools.build:gradle:{version}'
// 增加AGC插件配置,请您参见AGC插件依赖关系选择合适的AGC插件版本。
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
dependencyResolutionManagement {
...
repositories {
google()
jcenter()
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}
}
}
buildscript {
dependencies {
...
// 增加Android Gradle插件版本号配置,{version}为实际的Gradle插件版本号,例如7.1.1。
classpath 'com.android.tools.build:gradle:{version}'
// 增加AGC插件配置,请您参见AGC插件依赖关系选择合适的AGC插件版本。
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
// 配置HMS Core SDK的Maven仓地址。
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencyResolutionManagement {
...
repositories {
google()
mavenCentral()
// 配置HMS Core SDK的Maven仓地址。
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencies {
implementation 'com.huawei.hms:location:6.4.0.300'
}
您编译APK前需要配置混淆配置文件,避免混淆HMS Core SDK导致功能异常。
-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 {
// 如果CPU架构为ARMv7、ARMv8时,需增加如下配置。
doNotStrip "*/arm64-v8a/libucs-credential.so"
doNotStrip "*/armeabi-v7a/libucs-credential.so"
// 如果CPU架构为x86时,需增加如下配置。
doNotStrip "*/x86/libucs-credential.so"
doNotStrip "*/x86_64/libucs-credential.so"
}
}
debug {
packagingOptions {
// 如果CPU架构为ARMv7、ARMv8时,需增加如下配置。
doNotStrip "*/arm64-v8a/libucs-credential.so"
doNotStrip "*/armeabi-v7a/libucs-credential.so"
// 如果CPU架构为x86时,需增加如下配置。
doNotStrip "*/x86/libucs-credential.so"
doNotStrip "*/x86_64/libucs-credential.so"
}
}
}
}
Demo开发过程中涉及到的文件均取自示例中源码,建议您先下载示例代码。
<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示例代码如下:
// 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 PERMISSSION 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 PERMISSSION failed");
}
}
}
Kotlin示例代码如下:
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 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"
)
}
}
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"
)
}
}
}
后续步骤均可参考“RequestLocationUpdatesWithCallbackActivity.java”或“RequestLocationUpdatesWithCallbackActivity.kt”文件。
// 定位交互接入对象
private FusedLocationProviderClient fusedLocationProviderClient;
//位置相关设置检查对象
private SettingsClient settingsClient;
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
settingsClient = LocationServices.getSettingsClient(this);
Kotlin示例代码如下:
// 定位交互接入对象
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
//位置相关设置检查对象
private lateinit var settingsClient: SettingsClient
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
settingsClient = LocationServices.getSettingsClient(this)
LocationRequest mLocationRequest;
mLocationRequest = new LocationRequest();
// 设置位置更新的间隔(单位:毫秒)
mLocationRequest.setInterval(10000);
// 设置定位类型
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
Kotlin示例代码如下:
var mLocationRequest: LocationRequest? = null
// 设置位置更新的间隔(单位:毫秒)
// 设置定位类型
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示例代码如下:
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();
// 请求位置更新前检查设备设置。
settingsClient.checkLocationSettings(locationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.i(TAG, "check location settings success");
// 请求位置更新
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示例代码如下:
private fun requestLocationUpdatesWithCallback() {
try {
val builder = LocationSettingsRequest.Builder()
builder.addLocationRequest(mLocationRequest)
val locationSettingsRequest = builder.build()
// 请求位置更新前检查设备设置。
val locationSettingsResponseTask: Task =
settingsClient.checkLocationSettings(locationSettingsRequest)
locationSettingsResponseTask.addOnSuccessListener { locationSettingsResponse: LocationSettingsResponse? ->
Log.i(TAG, "check location settings success {$locationSettingsResponse}")
// 请求位置更新
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示例代码如下:
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}"
)
}
}
您可以点击请求位置更新按钮,并将位置信息打印到当前界面。
干得好,您已经成功完成了Codelab并学到了: