rxLocationManager 循环

rxLocationManager looping

我制作了一个 LocationManager 来处理权限问题,return 来自 FusedLocationProviderClient 的 lastLocation。它大量使用 RxJava 来避免回调地狱。这是代码:

object LocationManager {

    // using coarse location to not ask for GPS enabling
    // after changing to ACCESS_FINE_LOCATION don't forget to check GPS settings
    private const val LOCATION_PERMISSION = Manifest.permission.ACCESS_COARSE_LOCATION

    private var permissionSubject = AsyncSubject.create<Boolean>()

    fun loadLastLocation(activity: Activity): Observable<Location?> =
            checkPermission(activity).flatMap { hasPermission ->
                // check permission, then request last location
                Log.d("qwerty", "hasPermission=$hasPermission")
                if (hasPermission) requestLastLocation(activity)
                else Observable.error<Location>(Exception("Permission not granted"))
            }

    private fun checkPermission(activity: Activity): Observable<Boolean> =
            if (activity.hasPermission(LOCATION_PERMISSION)) Observable.just(true)
            else requestPermission(activity)

    private fun requestPermission(activity: Activity): Observable<Boolean> = permissionSubject.apply {
        // result will be posted to subject later
        Log.d("qwerty", "requestPermission $LOCATION_PERMISSION")
        ActivityCompat.requestPermissions(activity, arrayOf(LOCATION_PERMISSION), RequestCode.LOCATION_PERMISSION)
    }

    // call this from hosting activity or you can never get lastLocation
    fun onRequestPermissionsResult(requestCode: Int, grantResults: IntArray) {
        if (requestCode == RequestCode.LOCATION_PERMISSION) {
            permissionSubject.apply {
                val granted = grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED
                Log.d("qwerty", "onRequestPermissionsResult=$granted")
                onNext(granted)
                onComplete()
            }
        }
        // skip other request codes
    }

    @SuppressLint("MissingPermission")
    // check ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION before calling this
    private fun requestLastLocation(activity: Activity): Observable<Location?> = PublishSubject.create<Location>().apply {
        Log.d("qwerty", "requestLastLocation")
        LocationServices.getFusedLocationProviderClient(activity).lastLocation
                .addOnSuccessListener { location ->
                    Log.d("qwerty", "lastLocation=$location")
                    onNext(location)
                    onComplete()
                }
                .addOnFailureListener { error ->
                    Log.d("qwerty", "lastLocation error: ${error.message}")
                    onError(error)
                }
    }
}

然后片段像这样调用 LocationManager:

    LocationManager.loadLastLocation(activity!!)
            .subscribe(
                    { location -> Log.d("qwerty", "fragment got location $location")},
                    { error -> error.printStackTrace() }
            )

问题是 Observable 卡在无限循环中试图获得许可。这是我在日志中得到的,无限次:

qwerty: requestPermission android.permission.ACCESS_COARSE_LOCATION
qwerty: hasPermission=false
System.err: java.lang.Exception: Permission not granted...
qwerty: onRequestPermissionsResult=false

有人能告诉我这段代码有什么问题吗?

据我从这段代码中所见,它应该可以正常工作。请检查您的清单,它的标签包含您请求的相同权限。第二个,请检查您的位置管理器导入,导入正确的清单 class(android.Manifest 而不是 your.app.package.Manifest)。