【问题标题】:Location permission callback being called again and again位置权限回调被一次又一次调用
【发布时间】:2018-03-17 13:21:09
【问题描述】:

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

在这个显示NecessaryMsgForLocationPermissionDenied() 函数中,我放置了一个日志,在我的logcat 中我看到这个函数被一次又一次地调用。如何阻止它?这是 logcat 屏幕截图

我想在用户拒绝权限时显示此对话框。但是对于上述问题,我无法顺利绘制。

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

【问题讨论】:

  • 同样的事情发生在我身上。在 LocationSettingsRequest 之前使用旧版本,但从未遇到过这个问题。
  • 请看下面的答案。放一个布尔值。或使用 Dexter 库。虽然它会被调用,但图书馆会管理它。你需要添加布尔值。如果显示您的对话框
  • 使用布尔值。您还应该将以下答案标记为已接受:-)

标签: android runtime-permissions


【解决方案1】:

基于Activity.requestPermissions的文档

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

在这段代码中,您在onResume() 中调用checkLocationPermission()。然后从checkLocationPermission() 调用到requestPermissions,它接受onPasue() 中的活动。在onRequestPermissionsResult() 之后,再次调用onResume(),创建无限循环。

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

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

    updateUI()
}

然后在showingNecessaryMsgForLocationPermissionDenied()之前将isRequestRequired更新为false

isRequestRequired = false
showingNecessaryMsgForLocationPermissionDenied()

这将阻止onResume() 一次又一次地调用checkLocationPermission()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    相关资源
    最近更新 更多