定位权限回调一次又一次被调用

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()