当前位置: 首页 > 知识库问答 >
问题:

为什么在进程死亡后不在片段中触发onRequestPermissionsResult?

严欣怡
2023-03-14
override fun onCreate(savedInstanceState: Bundle?) {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    super.onCreate(savedInstanceState)
    if(!permissionsGranted){
        requestPermissions(arrayOf(Manifest.permission.CAMERA),
                PermissionsDelegateUtil.REQUEST_PERMISSIONS_CAMERA
        )
    }
}
 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
        }
    }
}

这段代码工作得非常好,直到我强制流程死亡(我在开发人员工具中选择了Don't keep activities复选框)。之后,我从后台返回,权限对话框仍然存在(因为onCreate再次被触发,权限检查再次被执行)。

问题是,在我按下permission对话框中的任何按钮后,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
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()
    }
}

我创建了一个新项目,即使不使用片段,也可以再次复制这个问题,只是活动。下面是存储库:https://github.com/wellbranding/androidPermissionIssue尝试强制进程死亡,同时权限对话框打开。返回应用html" target="_blank">程序后,对话框出现了,但是如果您按下任何按钮,那么onRequestPermissionsResult仍然不会被触发,但它应该被触发。

共有1个答案

仲孙逸明
2023-03-14

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

解决方案:对主活动使用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>
    null
    null

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

添加android:excludefromrecents=“true”是一个部分解决方案,但如果用户直接从应用程序转到最近的屏幕,然后再回到应用程序,就不起作用了。

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

 类似资料:
  • 我的程序每次要处理某件事情时都会分叉,在每个分叉进程中,我都分离一个线程,以便从分叉进程中记录统计数据:这个线程循环收集数据,但它没有停止这个循环的实际条件。 程序的输出证实了每一个线程都随其工艺而死 当我使用运行这个程序时,引起了一些疑问:当每个分叉进程死亡时,会显示一些令人毛骨悚然的输出(13534是分叉进程PID): 相同的错误(警告?)每个分叉进程死亡时的消息。

  • 群集环境: Storm0.9.2 Zookeeper 3.4.6 Ubuntu 13.10

  • 主要问题: 我试图在网页上打印错误,如果连接到MySQL服务器不做。为此,我写了一个错误的库名

  • 问题内容: 假设我有一个进程,它恰好产生了一个子进程。现在,当父进程出于某种原因(正常或异常,通过kill,^ C,断言失败或其他任何原因)退出时,我希望子进程死亡。如何正确地做到这一点? 问题答案: 子进程可以通过在syscall中指定选项来要求父进程去世时内核发出(或其他信号),如下所示: 有关详细信息,请参见。 编辑:这是仅Linux

  • 问题内容: 在不让父进程等待子进程被杀死的情况下,我如何跟踪子进程的死亡? 我正在尝试一个客户端-服务器方案,其中服务器从客户端接受连接,并为它接受的每个连接派生一个新进程。 我忽略了SIGCHLD信号以防止僵尸创建。 上述情况下的问题是,如果子进程在函数中被杀死,则全局变量不会递减。 注意: 我正在寻找不使用SIGCHLD信号的解决方案…如果可能 问题答案: 通常,您编写一个调用pid 的处理程

  • 问题内容: 我有一个程序生成并与CPU繁重,不稳定的进程通信,而不是由我创建的。如果我的应用程序崩溃或被杀死,我也希望子进程也被杀死,因此用户不必跟踪它们并手动杀死它们。 我知道以前已经讨论过该主题,但是我已经尝试了所有描述的方法,但似乎没有一种方法能够经受住测试的考验。 我知道这是有可能的,因为终端一直在这样做。如果我在终端中运行某些程序并杀死该终端,则这些东西总是会死掉。 我试过了,双叉和。不