[Gradle, Java, Kotlin, Разработка мобильных приложений, Разработка под Android] Встраиваем геолокацию от Huawei в Android приложение
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В предыдущих статьях мы создавали аккаунт разработчика для использования Huawei Mobile Services и подготавливали проект к их использованию. И использовали аналитику от Huawei вместо аналога от Google. В этой статье мы будем встраивать определение геолокации от Huawei.
Вот полный список статей из цикла:
- Создаём аккаунт разработчика, подключаем зависимости, подготавливаем код к внедрению. тык
- Встраиваем Huawei Analytics. тык
- Используем геолокацию от Huawei. ← вы тут
- Huawei maps. Используем вместо Google maps для AppGallery.
С геолокацией немного сложнее, т.к. надо нюансы учитывать. О них, конечно, тоже расскажем.
Как должен выглядеть код в уже готовом проекте
Исходить будем, опять таки, из того, что у вас геолокация для гугла сделана примерно так:
1) Для проверки разрешения пользователя на доступ к его местоположению использована библиотека RxPermissions примерно так:
class PermissionsHelper {
private var rxPermissions: RxPermissions? = null
/**
* Вызываем в Activity#onCreate
*/
fun attach(activity: FragmentActivity) {
rxPermissions = RxPermissions(activity)
}
/**
* Вызываем в Activity#onDestroy
*/
fun detach() {
rxPermissions = null
}
fun requestPermission(vararg permissionName: String): Single<Boolean> {
return rxPermissions?.request(*permissionName)
?.firstOrError()
?: Single.error(
IllegalStateException("PermissionHelper is not attached to Activity")
)
}
}
2) Создан свой класс для местоположения:
data class Location(
val latitude: Double,
val longitude: Double
) {
companion object {
val DEFAULT_LOCATION = Location(59.927752, 30.346944)
}
}
3) Создана абстракция над поставщиком местоположения:
interface FusedLocationClient {
fun checkPermissions(): Single<Boolean>
fun getLastLocation(): Single<Location>
fun requestLastLocation(): Single<Location>
}
4) И используется она примерно так:
class LocationGateway(
private val fusedLocationClient: FusedLocationClient
) {
fun requestLastLocation(): Single<Location> {
return fusedLocationClient.checkPermissions()
.flatMap { granted ->
if (granted) {
fusedLocationClient.getLastLocation()
.onErrorResumeNext(fusedLocationClient.requestLastLocation())
} else {
Single.just(Location.DEFAULT_LOCATION) // или ошибку кидаем какую-то
}
}
}
}
Используем разные реализации определения геолокации
Если вышеописанное верно для вашего случая, то как и в случае с аналитикой нам понадобятся 2 разные реализации FusedLocationClient — FusedLocationClientImpl:
1) В папке src/huawei/kotlin/com/example:
class FusedLocationClientImpl(
private val permissionsHelper: PermissionsHelper,
context: Context
) : FusedLocationClient {
private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
override fun checkPermissions(): Single<Boolean> {
val permissions = mutableListOf(Manifest.permission.ACCESS_FINE_LOCATION)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
// for huawei we need this permission too after API=28
permissions += Manifest.permission.ACCESS_BACKGROUND_LOCATION
}
return permissionsHelper.requestPermission(*permissions.toTypedArray())
}
override fun getLastLocation(): Single<Location> {
return Single.create { singleEmitter ->
fusedLocationClient.lastLocation
.addOnFailureListener {
if (singleEmitter.isDisposed) return@addOnFailureListener
singleEmitter.onError(it)
}
.addOnSuccessListener { newLocation ->
if (singleEmitter.isDisposed) return@addOnSuccessListener
if (newLocation == null) {
singleEmitter.onError(UnknownLocationException())
} else {
singleEmitter.onSuccess(
Location(
newLocation.latitude,
newLocation.longitude
)
)
}
}
}
}
override fun requestLastLocation(): Single<Location> {
return Single.create { singleEmitter ->
val locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(5000)
.setSmallestDisplacement(5.5F)
.setNumUpdates(1)
val callback = object : LocationCallback() {
override fun onLocationResult(result: LocationResult) {
if (singleEmitter.isDisposed) return
singleEmitter.onSuccess(
Location(
result.lastLocation.latitude,
result.lastLocation.longitude
)
)
}
}
fusedLocationClient.requestLocationUpdates(locationRequest, callback, null)
singleEmitter.setCancellable {
fusedLocationClient.removeLocationUpdates(callback)
}
}
}
}
2) В папке src/google/kotlin/com/example:
class FusedLocationClientImpl(
private val permissionsHelper: PermissionsHelper,
context: Context
) : FusedLocationClient {
private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
override fun checkPermissions(): Single<Boolean> {
return permissionsHelper.requestPermission(Manifest.permission.ACCESS_FINE_LOCATION)
}
@SuppressLint("MissingPermission")
override fun getLastLocation(): Single<Location> {
return Single.create { singleEmitter ->
fusedLocationClient.lastLocation
.addOnFailureListener {
if (singleEmitter.isDisposed) return@addOnFailureListener
singleEmitter.onError(it)
}
.addOnSuccessListener { newLocation ->
if (singleEmitter.isDisposed) return@addOnSuccessListener
if (newLocation == null) {
singleEmitter.onError(UnknownLocationException())
} else {
singleEmitter.onSuccess(
Location(
newLocation.latitude,
newLocation.longitude
)
)
}
}
}
}
@SuppressLint("MissingPermission")
override fun requestLastLocation(): Single<Location> {
return Single.create { singleEmitter ->
val locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(5000)
.setSmallestDisplacement(5.5F)
.setNumUpdates(1)
val callback = object : LocationCallback() {
override fun onLocationResult(result: LocationResult) {
if (singleEmitter.isDisposed) return
singleEmitter.onSuccess(
Location(
result.lastLocation.latitude,
result.lastLocation.longitude
)
)
}
}
fusedLocationClient.requestLocationUpdates(locationRequest, callback, null)
singleEmitter.setCancellable {
fusedLocationClient.removeLocationUpdates(callback)
}
}
}
}
В итоге реализации отличаются 2 вещами: импортами и тем, что в случае Huawei надо запрашивать разрешение на запрос геолокации в фоне на API>28.
Аналогично с аналитикой, в DI биндим для типа FusedLocationClient экземпляр FusedLocationClientImpl. Для разных сборок будет взята та или иная реализация.
Ну и не забываем, конечно, зависимости в скрипте сборки прописать:
dependencies {
huaweiImplementation 'com.huawei.agconnect:agconnect-core:1.3.1.300'
huaweiImplementation 'com.huawei.hms:location:5.0.0.301'
googleImplementation 'com.google.android.gms:play-services-location:17.0.0'
}
И не забудьте добавить разрешение на доступ к местоположению в фоне для Huawei сборки! Если такое разрешение уже есть в основном файле AndroidManifest.xml — то можете этот пункт пропустить. Если нет — то создайте ещё один файл манифеста в папке src/huawei/ с таким содержимым:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example">
<!-- huawei location throws error without this permission -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>
Подводные камни
Надо иметь в виду, что геолокация от Huawei будет работать при следующих условиях:
- У вас установлены Huawei Mobile Services на девайсе.
- Им выданы нужные разрешения.
- Юзер согласился на определение местоположения в фоне, а не только во время использования.
Дальше — встраиваем карты
С геолокацией мы разобрались, в следующей статье покажем как встроить карты от Huawei в приложение, которое уже использует аналог от Google.
Весь код, который есть в этом цикле статей вы можете посмотреть в репозитории на GitHub. Вот ссылка: https://github.com/MobileUpLLC/huawei_and_google_services.
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, Java, Конференции, Микросервисы] 29 октября приглашаем на онлайн-митап Hot Java
- [Разработка мобильных приложений, Разработка под Android, Kotlin, Учебный процесс в IT] Android Academy Fundamentals: теперь прямо у тебя дома
- [Разработка веб-сайтов, JavaScript, VueJS] Отдаем корректный код 404 в связке VUE SPA + SSR
- [Программирование, Разработка под Android] Избегайте внедрения внешних библиотек в свой проект
- Доступен пакетный менеджер NPM 7.0
- [Ненормальное программирование, JavaScript, Графический дизайн] QR-художество
- [Тестирование IT-систем, Java, Тестирование веб-сервисов] Flame-графики: «огонь» из всех движков (перевод)
- [Разработка веб-сайтов, CSS, JavaScript, Canvas, ReactJS] 24 октября приглашаем на онлайн-митап Hot Frontend в Казани
- [Разработка под iOS, Разработка мобильных приложений, Swift, Аналитика мобильных приложений] Автоматизация тестирования продуктовой аналитики в мобильных приложениях
- [Java] Получение Method из Method Reference в Java
Теги для поиска: #_gradle, #_java, #_kotlin, #_razrabotka_mobilnyh_prilozhenij (Разработка мобильных приложений), #_razrabotka_pod_android (Разработка под Android), #_gradle, #_java, #_kotlin, #_razrabotka_mobilnyh_prilozhenij (Разработка мобильных приложений), #_razrabotka_pod_android (Разработка под Android), #_gradle, #_java, #_kotlin, #_razrabotka_mobilnyh_prilozhenij (
Разработка мобильных приложений
), #_razrabotka_pod_android (
Разработка под Android
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:58
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В предыдущих статьях мы создавали аккаунт разработчика для использования Huawei Mobile Services и подготавливали проект к их использованию. И использовали аналитику от Huawei вместо аналога от Google. В этой статье мы будем встраивать определение геолокации от Huawei. Вот полный список статей из цикла:
С геолокацией немного сложнее, т.к. надо нюансы учитывать. О них, конечно, тоже расскажем. Как должен выглядеть код в уже готовом проекте Исходить будем, опять таки, из того, что у вас геолокация для гугла сделана примерно так: 1) Для проверки разрешения пользователя на доступ к его местоположению использована библиотека RxPermissions примерно так: class PermissionsHelper {
private var rxPermissions: RxPermissions? = null /** * Вызываем в Activity#onCreate */ fun attach(activity: FragmentActivity) { rxPermissions = RxPermissions(activity) } /** * Вызываем в Activity#onDestroy */ fun detach() { rxPermissions = null } fun requestPermission(vararg permissionName: String): Single<Boolean> { return rxPermissions?.request(*permissionName) ?.firstOrError() ?: Single.error( IllegalStateException("PermissionHelper is not attached to Activity") ) } } 2) Создан свой класс для местоположения: data class Location(
val latitude: Double, val longitude: Double ) { companion object { val DEFAULT_LOCATION = Location(59.927752, 30.346944) } } 3) Создана абстракция над поставщиком местоположения: interface FusedLocationClient {
fun checkPermissions(): Single<Boolean> fun getLastLocation(): Single<Location> fun requestLastLocation(): Single<Location> } 4) И используется она примерно так: class LocationGateway(
private val fusedLocationClient: FusedLocationClient ) { fun requestLastLocation(): Single<Location> { return fusedLocationClient.checkPermissions() .flatMap { granted -> if (granted) { fusedLocationClient.getLastLocation() .onErrorResumeNext(fusedLocationClient.requestLastLocation()) } else { Single.just(Location.DEFAULT_LOCATION) // или ошибку кидаем какую-то } } } } Используем разные реализации определения геолокации Если вышеописанное верно для вашего случая, то как и в случае с аналитикой нам понадобятся 2 разные реализации FusedLocationClient — FusedLocationClientImpl: 1) В папке src/huawei/kotlin/com/example: class FusedLocationClientImpl(
private val permissionsHelper: PermissionsHelper, context: Context ) : FusedLocationClient { private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context) override fun checkPermissions(): Single<Boolean> { val permissions = mutableListOf(Manifest.permission.ACCESS_FINE_LOCATION) if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { // for huawei we need this permission too after API=28 permissions += Manifest.permission.ACCESS_BACKGROUND_LOCATION } return permissionsHelper.requestPermission(*permissions.toTypedArray()) } override fun getLastLocation(): Single<Location> { return Single.create { singleEmitter -> fusedLocationClient.lastLocation .addOnFailureListener { if (singleEmitter.isDisposed) return@addOnFailureListener singleEmitter.onError(it) } .addOnSuccessListener { newLocation -> if (singleEmitter.isDisposed) return@addOnSuccessListener if (newLocation == null) { singleEmitter.onError(UnknownLocationException()) } else { singleEmitter.onSuccess( Location( newLocation.latitude, newLocation.longitude ) ) } } } } override fun requestLastLocation(): Single<Location> { return Single.create { singleEmitter -> val locationRequest = LocationRequest.create() .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval(5000) .setSmallestDisplacement(5.5F) .setNumUpdates(1) val callback = object : LocationCallback() { override fun onLocationResult(result: LocationResult) { if (singleEmitter.isDisposed) return singleEmitter.onSuccess( Location( result.lastLocation.latitude, result.lastLocation.longitude ) ) } } fusedLocationClient.requestLocationUpdates(locationRequest, callback, null) singleEmitter.setCancellable { fusedLocationClient.removeLocationUpdates(callback) } } } } 2) В папке src/google/kotlin/com/example: class FusedLocationClientImpl(
private val permissionsHelper: PermissionsHelper, context: Context ) : FusedLocationClient { private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context) override fun checkPermissions(): Single<Boolean> { return permissionsHelper.requestPermission(Manifest.permission.ACCESS_FINE_LOCATION) } @SuppressLint("MissingPermission") override fun getLastLocation(): Single<Location> { return Single.create { singleEmitter -> fusedLocationClient.lastLocation .addOnFailureListener { if (singleEmitter.isDisposed) return@addOnFailureListener singleEmitter.onError(it) } .addOnSuccessListener { newLocation -> if (singleEmitter.isDisposed) return@addOnSuccessListener if (newLocation == null) { singleEmitter.onError(UnknownLocationException()) } else { singleEmitter.onSuccess( Location( newLocation.latitude, newLocation.longitude ) ) } } } } @SuppressLint("MissingPermission") override fun requestLastLocation(): Single<Location> { return Single.create { singleEmitter -> val locationRequest = LocationRequest.create() .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) .setInterval(5000) .setSmallestDisplacement(5.5F) .setNumUpdates(1) val callback = object : LocationCallback() { override fun onLocationResult(result: LocationResult) { if (singleEmitter.isDisposed) return singleEmitter.onSuccess( Location( result.lastLocation.latitude, result.lastLocation.longitude ) ) } } fusedLocationClient.requestLocationUpdates(locationRequest, callback, null) singleEmitter.setCancellable { fusedLocationClient.removeLocationUpdates(callback) } } } } В итоге реализации отличаются 2 вещами: импортами и тем, что в случае Huawei надо запрашивать разрешение на запрос геолокации в фоне на API>28. Аналогично с аналитикой, в DI биндим для типа FusedLocationClient экземпляр FusedLocationClientImpl. Для разных сборок будет взята та или иная реализация. Ну и не забываем, конечно, зависимости в скрипте сборки прописать: dependencies {
huaweiImplementation 'com.huawei.agconnect:agconnect-core:1.3.1.300' huaweiImplementation 'com.huawei.hms:location:5.0.0.301' googleImplementation 'com.google.android.gms:play-services-location:17.0.0' } И не забудьте добавить разрешение на доступ к местоположению в фоне для Huawei сборки! Если такое разрешение уже есть в основном файле AndroidManifest.xml — то можете этот пункт пропустить. Если нет — то создайте ещё один файл манифеста в папке src/huawei/ с таким содержимым: <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example"> <!-- huawei location throws error without this permission --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> </manifest> Подводные камни Надо иметь в виду, что геолокация от Huawei будет работать при следующих условиях:
Дальше — встраиваем карты С геолокацией мы разобрались, в следующей статье покажем как встроить карты от Huawei в приложение, которое уже использует аналог от Google. Весь код, который есть в этом цикле статей вы можете посмотреть в репозитории на GitHub. Вот ссылка: https://github.com/MobileUpLLC/huawei_and_google_services. =========== Источник: habr.com =========== Похожие новости:
Разработка мобильных приложений ), #_razrabotka_pod_android ( Разработка под Android ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:58
Часовой пояс: UTC + 5