定位权限回调一次又一次被调用
Location permission callback being called again and again
我已经实现了运行时权限。出于测试目的,我拒绝了位置权限,然后我又用 "Never to ask again" 复选框拒绝了权限。
现在有问题了。系统一次又一次地调用 OnRequestPermissionResult。为此,我无法在屏幕上正确显示对话框或小吃栏。这是我的实现。问题出在哪里?
正在检查位置权限
override fun onResume() {
super.onResume()
if (checkLocationPermission())
startLocationUpdates()
updateUI()
}
这是我的位置更新电话
@SuppressLint("MissingPermission")
private fun startLocationUpdates() {
// Begin by checking if the device has the necessary location settings.
mLocationSettingsClient.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(this, {
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.myLooper());
updateUI()
})
.addOnFailureListener(this, {
handlingLocationClientSettingsFailure(it)
});
}
private fun handlingLocationClientSettingsFailure(it: Exception) {
val apiException = it as ApiException
when (apiException.statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
try {
Lg.d(TAG, "Inside start location update method FAILURE: REQUIRED")
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
val rae = it as ResolvableApiException
rae.startResolutionForResult(this@MainActivity, REQUEST_CHECK_SETTINGS);
} catch (sie: IntentSender.SendIntentException) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
}
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
val errorMessage = "Location settings are inadequate, and cannot be " +
"fixed here. Fix in Settings.";
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
mRequestingLocationUpdates = false;
}
}
updateUI()
}
override fun onStop() {
super.onStop()
stopLocationUpdates()
}
private fun stopLocationUpdates() {
if (!mRequestingLocationUpdates) {
Lg.d(TAG, "Permission Denied! So No op!!!")
return
}
mFusedLocationClient.removeLocationUpdates(mLocationCallback)
.addOnCompleteListener(this) { mRequestingLocationUpdates = false }
}
private val MY_PERMISSIONS_REQUEST_LOCATION = 99;
private fun startLocationPermissionRequest() {
ActivityCompat.requestPermissions(this@MainActivity,
arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION),
MY_PERMISSIONS_REQUEST_LOCATION);
}
private fun checkLocationPermission(): Boolean {
if (ContextCompat.checkSelfPermission(this@MainActivity, ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this@MainActivity, ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)) {
showSnackbar(R.string.location_permission_rationale,
android.R.string.ok,
View.OnClickListener {
startLocationPermissionRequest()
})
} else {
// No explanation needed, we can request the permission.
startLocationPermissionRequest()
}
return false
} else {
// Permission has already been granted
return true
}
}
@SuppressLint("NeedOnRequestPermissionsResult")
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
MY_PERMISSIONS_REQUEST_LOCATION -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(this@MainActivity, ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this@MainActivity, ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
) {
setLocationEnabled()
startLocationUpdates()
}
} else {
val showRationale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
shouldShowRequestPermissionRationale(permissions[0])
} else {
TODO("VERSION.SDK_INT < M")
}
if (!showRationale) {
// user also CHECKED "never ask again"
// you can either enable some fall back,
// disable features of your app
// or open another dialog explaining
// again the permission and directing to
// the app setting
showingNecessaryMsgForLocationPermissionDenied()
} else {
// user did NOT check "never ask again"
// this is a good place to explain the user
// why you need the permission and ask if he wants
// to accept it (the rationale)
}
}
return
}
// other 'case' lines to check for other
// permissions this app might request
}
}
private fun showingNecessaryMsgForLocationPermissionDenied() {
Lg.d("TestTag", "Called")
MaterialDialog.Builder(this)
.title("Permission")
.content(R.string.permission_denied_explanation)
.onPositive { dialog, which ->
// Build intent that displays the App settings screen.
val intent = Intent().apply {
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
data = Uri.fromParts("package", APPLICATION_ID, null)
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
startActivity(intent)
}
.positiveText(R.string.ok)
.show()
}
在这个 showingNecessaryMsgForLocationPermissionDenied() 函数中,我放置了一个日志,在我的 logcat 中,我看到这个函数被一次又一次地调用。如何阻止它?这是 logcat 屏幕截图
我想在用户拒绝权限时显示此对话框。但是对于上面的问题,我并不能顺利的画出这个。
注意:我已经测试了位置更新项目的 google 存储库。同样的问题
基于 Activity.requestPermissions
的文档
此方法可能会启动一个 activity 允许用户选择授予和拒绝哪些权限。因此,您应该做好准备,您的 activity 可能会暂停和恢复 。 此外,授予某些权限可能需要重新启动您的应用程序。
在此代码中,您将在 onResume()
中调用 checkLocationPermission()
。然后从 checkLocationPermission()
调用转到 requestPermissions
,在 onPasue()
中调用 Activity。在 onRequestPermissionsResult()
之后,onResume()
再次被调用,创建无限循环。
我建议使用一个布尔变量来决定是否需要调用 checkLocationPermission()
。
var isRequestRequired = true;
override fun onResume() {
super.onResume()
if (isRequestRequired && checkLocationPermission())
startLocationUpdates()
updateUI()
}
然后在 showingNecessaryMsgForLocationPermissionDenied()
之前将 isRequestRequired
更新为 false
isRequestRequired = false
showingNecessaryMsgForLocationPermissionDenied()
这将阻止 onResume()
一次又一次地调用 checkLocationPermission()
我已经实现了运行时权限。出于测试目的,我拒绝了位置权限,然后我又用 "Never to ask again" 复选框拒绝了权限。 现在有问题了。系统一次又一次地调用 OnRequestPermissionResult。为此,我无法在屏幕上正确显示对话框或小吃栏。这是我的实现。问题出在哪里?
正在检查位置权限
override fun onResume() {
super.onResume()
if (checkLocationPermission())
startLocationUpdates()
updateUI()
}
这是我的位置更新电话
@SuppressLint("MissingPermission")
private fun startLocationUpdates() {
// Begin by checking if the device has the necessary location settings.
mLocationSettingsClient.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(this, {
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.myLooper());
updateUI()
})
.addOnFailureListener(this, {
handlingLocationClientSettingsFailure(it)
});
}
private fun handlingLocationClientSettingsFailure(it: Exception) {
val apiException = it as ApiException
when (apiException.statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
try {
Lg.d(TAG, "Inside start location update method FAILURE: REQUIRED")
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
val rae = it as ResolvableApiException
rae.startResolutionForResult(this@MainActivity, REQUEST_CHECK_SETTINGS);
} catch (sie: IntentSender.SendIntentException) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
}
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
val errorMessage = "Location settings are inadequate, and cannot be " +
"fixed here. Fix in Settings.";
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
mRequestingLocationUpdates = false;
}
}
updateUI()
}
override fun onStop() {
super.onStop()
stopLocationUpdates()
}
private fun stopLocationUpdates() {
if (!mRequestingLocationUpdates) {
Lg.d(TAG, "Permission Denied! So No op!!!")
return
}
mFusedLocationClient.removeLocationUpdates(mLocationCallback)
.addOnCompleteListener(this) { mRequestingLocationUpdates = false }
}
private val MY_PERMISSIONS_REQUEST_LOCATION = 99;
private fun startLocationPermissionRequest() {
ActivityCompat.requestPermissions(this@MainActivity,
arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION),
MY_PERMISSIONS_REQUEST_LOCATION);
}
private fun checkLocationPermission(): Boolean {
if (ContextCompat.checkSelfPermission(this@MainActivity, ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this@MainActivity, ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)) {
showSnackbar(R.string.location_permission_rationale,
android.R.string.ok,
View.OnClickListener {
startLocationPermissionRequest()
})
} else {
// No explanation needed, we can request the permission.
startLocationPermissionRequest()
}
return false
} else {
// Permission has already been granted
return true
}
}
@SuppressLint("NeedOnRequestPermissionsResult")
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
MY_PERMISSIONS_REQUEST_LOCATION -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(this@MainActivity, ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this@MainActivity, ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
) {
setLocationEnabled()
startLocationUpdates()
}
} else {
val showRationale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
shouldShowRequestPermissionRationale(permissions[0])
} else {
TODO("VERSION.SDK_INT < M")
}
if (!showRationale) {
// user also CHECKED "never ask again"
// you can either enable some fall back,
// disable features of your app
// or open another dialog explaining
// again the permission and directing to
// the app setting
showingNecessaryMsgForLocationPermissionDenied()
} else {
// user did NOT check "never ask again"
// this is a good place to explain the user
// why you need the permission and ask if he wants
// to accept it (the rationale)
}
}
return
}
// other 'case' lines to check for other
// permissions this app might request
}
}
private fun showingNecessaryMsgForLocationPermissionDenied() {
Lg.d("TestTag", "Called")
MaterialDialog.Builder(this)
.title("Permission")
.content(R.string.permission_denied_explanation)
.onPositive { dialog, which ->
// Build intent that displays the App settings screen.
val intent = Intent().apply {
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
data = Uri.fromParts("package", APPLICATION_ID, null)
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
startActivity(intent)
}
.positiveText(R.string.ok)
.show()
}
在这个 showingNecessaryMsgForLocationPermissionDenied() 函数中,我放置了一个日志,在我的 logcat 中,我看到这个函数被一次又一次地调用。如何阻止它?这是 logcat 屏幕截图
我想在用户拒绝权限时显示此对话框。但是对于上面的问题,我并不能顺利的画出这个。
注意:我已经测试了位置更新项目的 google 存储库。同样的问题
基于 Activity.requestPermissions
此方法可能会启动一个 activity 允许用户选择授予和拒绝哪些权限。因此,您应该做好准备,您的 activity 可能会暂停和恢复 。 此外,授予某些权限可能需要重新启动您的应用程序。
在此代码中,您将在 onResume()
中调用 checkLocationPermission()
。然后从 checkLocationPermission()
调用转到 requestPermissions
,在 onPasue()
中调用 Activity。在 onRequestPermissionsResult()
之后,onResume()
再次被调用,创建无限循环。
我建议使用一个布尔变量来决定是否需要调用 checkLocationPermission()
。
var isRequestRequired = true;
override fun onResume() {
super.onResume()
if (isRequestRequired && checkLocationPermission())
startLocationUpdates()
updateUI()
}
然后在 showingNecessaryMsgForLocationPermissionDenied()
isRequestRequired
更新为 false
isRequestRequired = false
showingNecessaryMsgForLocationPermissionDenied()
这将阻止 onResume()
一次又一次地调用 checkLocationPermission()