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
)。
我制作了一个 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
)。