Зацикливание rxLocationManager
Я создал LocationManager для обработки проблем с разрешениями и возврата lastLocation из FusedLocationProviderClient. Он интенсивно использует 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() }
)
Проблема в том, что наблюдаемые застряли в бесконечном цикле, пытаясь получить разрешение. Вот что я получаю в логах, бесконечные времена:
qwerty: requestPermission android.permission.ACCESS_COARSE_LOCATION
qwerty: hasPermission=false
System.err: java.lang.Exception: Permission not granted...
qwerty: onRequestPermissionsResult=false
Может кто-нибудь сказать мне, что не так с этим кодом?
1 ответ
Насколько я вижу из этого кода, он должен работать правильно. Пожалуйста, проверьте в своем манифесте, что тег содержит то же разрешение, которое вы запрашиваете. И второе, пожалуйста, проверьте, импортирует ли менеджер местоположений, импортируется ли соответствующий класс Manifest (android.Manifest
не your.app.package.Manifest
).