Jintin / FancyLocationProvider

Wrapper of FusedLocationProviderClient for Android to support modern usage like LiveData and Flow
MIT License
66 stars 5 forks source link

Support for Huawei HMS Location service #5

Closed zcelaloglu closed 3 years ago

zcelaloglu commented 3 years ago

it would be better to bring an implementation for HMS services as well

Jintin commented 3 years ago

Well, it's a good suggestion but still out of my original scope of this project. Found some interesting discussion on stackoverflow: https://stackoverflow.com/questions/59974428/have-both-gms-and-hms-in-the-project

Without any experience on Huawei HMS I found it seems have every same class and function as GMS have and we can use convertor if we want to? Second approach is create a platform independent layer to support different vendor. But this approach will make the usage a bit unfriendly for most use case. Third approach is like Retrofit to support different convertor, but need some adjustment on the structure.

What do you think, any idea on this three approach?

zcelaloglu commented 3 years ago

I think this lib should take couple of parameters in order to be able to provide location . LocationRequest should be located in lib and lazy while getting location and all we have to do is providing intervals and priority and this libs needs to get location by using available API by checking which location API is suitable.

Jintin commented 3 years ago

Here is one of the way #7 to support custom location provider:

    // Can change the implementation here
    private val locationProvider: ILocationProvider = LocationProvider(context, locationRequest) 

And then we can get LiveData and Flow via the extension.

    @ExperimentalCoroutinesApi
    val locationFlow = locationProvider.asFlow()
    val locationLiveData = locationProvider.asLiveData()

And this is also backward compatible for current version.

How to create location provider is like this:

class LocationProvider(
    private val context: Context,
    private val locationRequest: LocationRequest
) : ILocationProvider {

    private val fusedLocationProviderClient by lazy {
        LocationServices.getFusedLocationProviderClient(context)
    }
    private val locationListener by lazy {
        LocationListener()
    }
    private var locationObserver: ILocationObserver? = null

    @RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
    override fun requestLocationUpdates(locationObserver: ILocationObserver) {
        this.locationObserver = locationObserver
        fusedLocationProviderClient.requestLocationUpdates(
            locationRequest,
            locationListener,
            Looper.getMainLooper()
        )
    }

    override fun removeLocationUpdates() {
        fusedLocationProviderClient.removeLocationUpdates(locationListener)
    }

    inner class LocationListener : LocationCallback() {
        override fun onLocationResult(result: LocationResult?) {
            result?.lastLocation?.let {
                locationObserver?.onLocationResult(it)
            }
        }

        override fun onLocationAvailability(availability: LocationAvailability?) {
            if (availability?.isLocationAvailable == false) {
                locationObserver?.onLocationFailed()
            }
        }
    }
}

Later we can also provide something like HMSLocationProvider in separate module if this works. Let me know if you have any other comment, thanks.

zcelaloglu commented 3 years ago

Pr looks good 👍

Jintin commented 3 years ago

Updated README section according to the change. https://github.com/Jintin/FancyLocationProvider#custom-location-provider Feel free to submit pr to create the HMS module if you're interested in. I'll close the issue for now. Thanks for bring this up.