registerForActivityResult回调未触发,AppAuth授权码获取失败
问题分析与解决
核心问题点
你的代码存在几个关键问题,导致ActivityResultLauncher的回调无法执行、authCode始终为null:
1. ActivityResultLauncher初始化时机错误
在Fragment中直接通过private val authLauncher = registerAuthResultLauncher()初始化时,Fragment尚未依附到Activity,不符合registerForActivityResult要求的组件生命周期注册时机,会导致Launcher无法正确绑定到Fragment生命周期,回调自然不会触发。
2. 同步返回authCode的逻辑错误
obtainAuthCode中调用authLauncher.launch(authIntent)是异步操作,授权需要用户交互后才会返回结果,但你直接同步返回authCode,此时结果还未生成,必然返回null。
3. RedirectUriReceiverActivity配置潜在问题
tools:node="replace"可能覆盖AppAuth库中该Activity的默认配置,导致跳转逻辑异常;- 需确保
authRequest中设置的redirectUri与Manifest里的<data>配置完全一致(包括scheme、host、path,大小写也要匹配)。
修复方案
1. 修正ActivityResultLauncher初始化时机
改用lazy延迟初始化,确保Fragment依附到Activity后再注册:
private val authLauncher by lazy { registerAuthResultLauncher() }
或者在onAttach方法中初始化:
private lateinit var authLauncher: ActivityResultLauncher<Intent> override fun onAttach(context: Context) { super.onAttach(context) authLauncher = registerAuthResultLauncher() }
2. 重构异步结果处理逻辑
放弃同步返回authCode,改用LiveData传递授权结果(也可用回调、Flow实现):
private val authCodeLiveData = MutableLiveData<AuthorizationResponse?>() private fun registerAuthResultLauncher(): ActivityResultLauncher<Intent> { return registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { val exception = AuthorizationException.fromIntent(result.data) if (exception == null) { val response = result.data?.let { AuthorizationResponse.fromIntent(it) } authCodeLiveData.postValue(response) } else { Timber.e(exception, "授权失败") authCodeLiveData.postValue(null) } } else { Timber.e("请求失败: ${result.resultCode}") authCodeLiveData.postValue(null) } } } // 调整obtainAuthCode,不再返回值 private fun obtainAuthCode() { val authIntent = authService.getAuthorizationRequestIntent(authRequest) val packageManager = requireContext().packageManager if (authIntent.resolveActivity(packageManager) != null) { authLauncher.launch(authIntent) } else { Timber.e("没有可用的Intent处理授权请求") } } // 在Fragment中观察结果 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) authCodeLiveData.observe(viewLifecycleOwner) { response -> response?.let { // 拿到授权码,执行换取令牌逻辑 exchangeToken(it.authorizationCode) } ?: run { // 处理授权失败或取消的情况 } } }
3. 修正Manifest配置
将tools:node="replace"改为tools:node="merge",避免覆盖默认配置:
<activity android:name="net.openid.appauth.RedirectUriReceiverActivity" android:exported="true" tools:node="merge"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="https" android:host="myapp.example.com" android:path="/oauth2redirect"/> </intent-filter> </activity>
同时严格检查authRequest中的redirectUri是否与上述配置完全一致,示例:
val redirectUri = Uri.parse("https://myapp.example.com/oauth2redirect") val authRequest = AuthorizationRequest.Builder( serviceConfiguration, clientId, ResponseTypeValues.CODE, redirectUri ).build()
内容的提问来源于stack exchange,提问作者ArkadiuszZiemian
相关产品推荐
相关产品推荐

