简介

定位服务(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能力,需要完成以下准备工作:

具体操作请按照《HUAWEI HMS Core集成准备》中详细说明来完成。

配置SDK的Maven仓地址

Android Studio的代码库配置在Gradle插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请根据您当前的Gradle插件版本,选择对应的配置过程。

7.0以下版本 7.0版本 7.1及以上版本

7.0以下版本

7.0版本

7.1及以上版本

添加编译依赖

  1. 打开应用级“build.gradle”文件。
  2. 在相应的app模块中添加SDK依赖。
  3. dependencies { implementation 'com.huawei.hms:location:6.4.0.300' }

您编译APK前需要配置混淆配置文件,避免混淆HMS Core SDK导致功能异常。

  1. 打开Android工程的混淆配置文件"proguard-rules.pro"。
  2. 添加用于排除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.**{*;}
  3. 如果您使用了AndResGuard,需要在混淆配置文件中加入AndResGuard允许清单。
    "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. (可选)当您集成Location 6.0.0.xxx版本时,此系列版本使用了so加固,加固后的so不能压缩优化,为了保证您的App可以正常运行,需要您在应用级的“build.gradle”文件中添加如下声明:
    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开发过程中涉及到的文件均取自示例中源码,建议您先下载示例代码

  1. 申请定位权限。
    1. 在工程的“AndroidManifest.xml”文件中添加精准位置权限和粗略位置权限。
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    2. 在Android 10版本中,如果您需要应用程序在后台执行时也具备持续定位能力,需要在“AndroidManifest.xml”文件中添加ACCESS_BACKGROUND_LOCATION权限。
      <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
    3. 动态申请相关权限
      Java示例代码如下:
      // 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) } }
    4. 权限申请结果回调。
      Java示例代码如下:
      @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”文件。

  2. 创建位置信息提供者客户端和设备设置客户端。
    Java示例代码如下:
    // 定位交互接入对象 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)
  3. 创建位置信息请求体。
    Java示例代码如下:
    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 }
  4. 创建结果回调类。
    Java示例代码如下:
    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") } } } }
  5. 请求位置更新。
    Java示例代码如下:
    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}") } }
  6. 移除位置信息更新请求。
    Java示例代码如下:
    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并学到了:

您可以阅读定位服务指南文档,了解更多相关的信息。
您还可以点击下载源码

已复制代码