Русский
Русский
English
Статистика
Реклама

Встраиваем геолокацию от Huawei в Android приложение

image


В предыдущих статьях мы создавали аккаунт разработчика для использования Huawei Mobile Services и подготавливали проект к их использованию. И использовали аналитику от Huawei вместо аналога от Google. В этой статье мы будем встраивать определение геолокации от Huawei.


Вот полный список статей из цикла:


  1. Создаём аккаунт разработчика, подключаем зависимости, подготавливаем код к внедрению. тык
  2. Встраиваем Huawei Analytics. тык
  3. Используем геолокацию от Huawei. вы тут
  4. 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://personeltest.ru/away/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 будет работать при следующих условиях:


  1. У вас установлены Huawei Mobile Services на девайсе.
  2. Им выданы нужные разрешения.
  3. Юзер согласился на определение местоположения в фоне, а не только во время использования.

Дальше встраиваем карты


С геолокацией мы разобрались, в следующей статье покажем как встроить карты от Huawei в приложение, которое уже использует аналог от Google.


Весь код, который есть в этом цикле статей вы можете посмотреть в репозитории на GitHub. Вот ссылка: https://github.com/MobileUpLLC/huawei_and_google_services.

Источник: habr.com
К списку статей
Опубликовано: 14.10.2020 16:16:12
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Gradle

Java

Kotlin

Разработка мобильных приложений

Разработка под android

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru