【发布时间】:2021-03-28 11:00:07
【问题描述】:
我在片段中遇到了一个关于 onRequestPermissionsResult 的奇怪问题。基本上,fragment 在 onCreate 中要求相机许可:
override fun onCreate(savedInstanceState: Bundle?) {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
super.onCreate(savedInstanceState)
if(!permissionsGranted){
requestPermissions(arrayOf(Manifest.permission.CAMERA),
PermissionsDelegateUtil.REQUEST_PERMISSIONS_CAMERA
)
}
}
然后我在 onRequestPermissionsResult 中处理权限:
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
val resultResponse = permissionsDelegateUtil.resultGranted(requestCode=requestCode, permissions = permissions, grantResults = grantResults)
when(resultResponse){
PermissionResult.PermissionGranted -> {
setupCameraX()
}
PermissionResult.PermissionNotGrantedRetryAuto -> {
//retrying again
requestPermissions(arrayOf(Manifest.permission.CAMERA),
PermissionsDelegateUtil.REQUEST_PERMISSIONS_CAMERA
)
}
PermissionResult.PermissionNotGrantedCantRetry -> {
//show a screen that user must enabled permission
}
PermissionResult.PermissionNotGrantedDontAsk -> {
//Don't do anything, because you can't retry here, otherwise it will cause infinite loop.
}
}
}
然后权限委托类处理权限逻辑:
fun resultGranted(requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray): PermissionResult {
if (requestCode != REQUEST_PERMISSIONS_CAMERA) {
return PermissionResult.PermissionNotGrantedDontAsk
}
if (grantResults.isEmpty()) {
return PermissionResult.PermissionNotGrantedDontAsk
}
if(permissions[0] != Manifest.permission.CAMERA){
return PermissionResult.PermissionNotGrantedDontAsk
}
return if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
PermissionResult.PermissionGranted
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (fragment.shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
PermissionResult.PermissionNotGrantedRetryAuto
} else{
///User selected don't show again checkbox.
PermissionResult.PermissionNotGrantedCantRetry
}
} else{
PermissionResult.PermissionNotGrantedRetryAuto
}
}
}
在我强制进程死亡(我在开发人员工具中选择不保留活动复选框)之前,此代码运行良好。之后,我从后台返回,权限对话框仍然存在(因为再次触发 onCreate 并再次执行权限检查)。
问题是,在我按下权限对话框中的任何按钮后,onRequestPermissionsResult 方法 没有在片段中触发。我查看了logcat,发现权限结果应该是传递的,因为这些日志:
2020-12-17 18:48:17.816 22496-22496/? V/GrantPermissionsActivity: Logged buttons presented and clicked permissionGroupName=android.permission-group.CAMERA uid=10135 package=com.test.app presentedButtons=25 clickedButton=8
2020-12-17 18:48:17.821 22496-22496/? V/GrantPermissionsActivity: Permission grant result requestId=-2584100455717644829 callingUid=10135 callingPackage=com.test.app permission=android.permission.CAMERA isImplicit=false result=6
我还尝试在 PermissionResult.PermissionNotGrantedDontAsk 返回后重试调用权限。它会起作用,但它会导致权限请求和响应的无限循环触发,从而导致应用程序崩溃。
编辑
我在不使用 backstack 的情况下添加了一个片段:
fun addCameraSessionFragment(supportFragmentManager: FragmentManager) {
val fragment = supportFragmentManager.findFragmentByTag(CAMERA_SESSION_FRAGMENT_TAG)
if (fragment == null) {
val cameraSessionFragment =
CameraSessionFragment()
val fragmentTransaction = supportFragmentManager.beginTransaction()
fragmentTransaction.replace(getTranscationRootId(), cameraSessionFragment, CAMERA_SESSION_FRAGMENT_TAG).commitNow()
}
}
问题是这个添加逻辑是由 ViewModel 作为 LiveData 事件触发的。进程死亡发生后,加法实际上发生了两次。第一个是因为它是最后一个片段,它在进程死亡后恢复。第二个是由 ViewModel 动作触发的。
编辑
我创建了一个新项目,即使没有使用片段,仅使用活动,也可以再次重现此问题。这是存储库: https://github.com/wellbranding/AndroidPermissionIssue 尝试在权限对话框打开时强制进程死亡。返回应用程序后,对话框存在,但如果您按下任何按钮,onRequestPermissionsResult 仍然不会被触发,但应该会。
【问题讨论】:
-
片段是怎么添加的
-
可能是内存泄漏,因此您在内存中有多个主要活动或片段的实例。如果您可以提供演示项目,我可以帮助调试。
-
@HarisDautović 谢谢。我创建了一个新的 android 项目,粘贴了此代码,并且可以重现该问题。 gist.github.com/wellbranding/a2cb6f31130ffc19d6e93a8177781ad5
-
@ViktorVostrikov。我做了研究并对为什么会发生这种情况有一些假设,但还没有任何解决方案。以防万一,你能检查一下你是否有同样的行为吗?这是一个视频:gofile.io/d/34Cg4o(我正在使用:Android API 29,Android Studio 4.4.1)
-
@HarisDautović 是的,我有同样的行为。通过在 Android Studio 中按下终止按钮,即使拒绝响应,它也可以正常工作。但是,如果我在设备设置中启用不保留活动,并在它之后转到后台/返回,问题仍然存在。
标签: android android-fragments android-camera android-permissions