为什么在进程终止后,片段中没有触发onRequestPermissionsResult



我在片段中遇到一个onRequestPermissionsResult的奇怪问题。基本上片段请求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后重试调用权限。这是可行的,但它会导致权限请求和响应的无限循环触发,结果导致应用程序崩溃。

编辑

我添加了一个片段,而不使用反包装:

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 still,但应该触发。

权限请求与用户的交互可能会中断。在这种情况下,您将收到空的权限和结果数组,应将其视为取消。

解决方案:android:launchMode="singleInstance"用于主要活动。

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.StackOverflowSolutions">
<activity android:name="dh.sos.MainActivity" android:launchMode="singleInstance">>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

默认模式为standard。具有standardsingleTop启动模式的活动可以被实例化多次。

当CCD_ 5模式与安卓权限对话框+"组合使用时;不要保持活动"我们失去了警报和应用程序之间的连接(案例1)。

情况1:android:launchMode="default"

  • 启用"不保留活动">
  • 运行应用程序并请求权限
  • 将应用程序置于后台
  • 打开应用程序
  • 权限对话框将再次显示
  • 在与Android权限对话框交互后,我们在onRequestPermissionsResult函数内没有得到任何回调

情况2android:launchMode="singleInstance"

  • 启用"不保留活动">
  • 运行应用程序并请求权限
  • 将应用程序置于后台
  • 打开应用程序
  • 调用了onRequestPermissionsResult,但我们看不到权限对话框。这种情况被认定为许可被取消,这是正常行为

更新:发现了一个新的案例,其中上述解决方案不够。更具体地说:当用户从最近的活动屏幕返回应用程序时

添加android:excludeFromRecents="true"是一个部分解决方案,但在用户直接从应用程序转到最近的屏幕,然后返回应用程序时不起作用。

解决方法:返回到上一个savedInstanceState中可见权限对话框的应用程序时重新创建MainActivity。

源代码:https://github.com/dautovicharis/sos_android/tree/q_65346039

您提供的代码是不完整的(即使是在要点中),因为没有提供Fragment。但没有什么奇怪的。如果我理解正确的话,您请求的是活动级别的权限,而不是片段级别的权限。因此,触发的方法是来自活动的onRequestPermissionsResult,而不是片段。看看这个关于如何实现它的答案:https://stackoverflow.com/a/35996955/1827254

摘录:

我认为您混淆了碎片和活动的方法。上个月我的项目也遇到了类似的问题。请检查您是否最终拥有以下内容:

在AppCompatActivity中,使用ActivityCompt.requestpermissions方法在v4支持片段中,您应该使用requestpermissionsCatch是,如果您在片段中调用AppcompatActivity.requestpermissions,则回调将指向活动,而不是片段请确保从活动的onRequestPermissionsResult调用super.onRequestPermissions Result。

相关内容

  • 没有找到相关文章

最新更新