一次又一次地调用位置权限回调

时间:2018-03-17 13:21:09

标签: android runtime-permissions

我已经实现了运行时权限。出于测试目的,我已经拒绝了位置许可,然后我再次拒绝了“永不再问”复选框的权限。 现在有问题了。正在从系统中反复调用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()
}

在这个showsNecessaryMsgForLocationPermissionDenied()函数中我放了一个日志,在我的logcat中我看到这个函数一次又一次地调用。怎么阻止它?这是logcat screentshot Method called again and again. see this Logcat

我想在用户拒绝权限时显示此对话框。但是我不能顺利地解决上述问题。 Permission denied message

注意:我已经测试了位置更新项目的Google存储库。同样的问题

1 个答案:

答案 0 :(得分:4)

基于Activity.requestPermissions

的文档

此方法可以启动一项活动,允许用户选择授予哪些权限以及拒绝哪些权限。因此,您应该准备好您的活动可以暂停和恢复此外,授予某些权限可能需要重新启动您的应用

在此代码中,您在checkLocationPermission()中呼叫onResume()。然后从checkLocationPermission()来电requestPermissions进入onPasue()中的活动。在onRequestPermissionsResult()之后,再次调用onResume(),创建infinte循环。

我建议使用布尔变量来决定是否需要调用checkLocationPermission()

var isRequestRequired = true;
override fun onResume() {
    super.onResume()
    if (isRequestRequired && checkLocationPermission())
        startLocationUpdates()

    updateUI()
}

然后在isRequestRequired

之前将showingNecessaryMsgForLocationPermissionDenied()更新为false
isRequestRequired = false
showingNecessaryMsgForLocationPermissionDenied()

这会阻止onResume()一次又一次地呼叫checkLocationPermission()