问题描述
限时送ChatGPT账号..我开始着手一个 100% 使用 Jetpack compose 编写的新项目,这意味着我们没有任何片段,而且我们也遵循单一活动模式.
I started working on a new project that is 100% written with Jetpack compose, meaning we don't have any fragments and we're also following the Single activity pattern.
现在我必须实现 Facebook 登录,但我被卡住了,因为他们仍在使用已弃用的 onActivityResult 而不是新的合同 API.
Now I have to implement the Facebook login but I'm stuck since they're still using the deprecated onActivityResult instead of the new contract api.
这是我正在尝试关注的文档,任何将不胜感激.
Here's the documentation that I'm trying to follow, any help would be greatly appreciated.
谢谢大家,
推荐答案
你必须等待 这个问题有待解决.
You have to wait this issue to be resolved.
现在,您可以使用 CompositionLocalProvider
将 callbackManager
从您的活动传递到 Compose 树,如下所示:
For now you can pass callbackManager
down from your activity to the Compose tree using CompositionLocalProvider
, like this:
val LocalFacebookCallbackManager =
staticCompositionLocalOf<CallbackManager> { error("No CallbackManager provided") }
class MainActivity : FragmentActivity() {
private var callbackManager = CallbackManager.Factory.create();
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Theme {
CompositionLocalProvider(
LocalFacebookCallbackManager provides callbackManager
) {
LoginScreen()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
callbackManager.onActivityResult(requestCode, resultCode, data)
super.onActivityResult(requestCode, resultCode, data)
}
}
@Composable
fun LoginScreen() {
val callbackManager = LocalFacebookCallbackManager.current
DisposableEffect(Unit) {
LoginManager.getInstance().registerCallback(
callbackManager,
object : FacebookCallback<LoginResult> {
override fun onSuccess(loginResult: LoginResult) {
println("onSuccess $loginResult")
}
override fun onCancel() {
println("onCancel")
}
override fun onError(exception: FacebookException) {
println("onError $exception")
}
}
)
onDispose {
LoginManager.getInstance().unregisterCallback(callbackManager)
}
}
val context = LocalContext.current
Button(onClick = {
LoginManager.getInstance()
.logInWithReadPermissions(context.findActivity(), Arrays.asList("public_profile"));
}) {
Text("FB Login")
}
}
fun Context.findActivity(): Activity? = when (this) {
is Activity -> this
is ContextWrapper -> baseContext.findActivity()
else -> null
}
更通用的解决方案是将 facebook 逻辑移动到视图模式,然后传递,然后您必须创建自己的回调管理器,如下所示:
More general solution is moving facebook logic into a view mode, and passing, then you have to create your own callback manager, something like this:
ActivityResultCallbackManager.kt
val LocalActivityResultCallbackManager =
staticCompositionLocalOf<ActivityResultCallbackManager> { error("No ActivityResultCallbackManager provided") }
interface ActivityResultCallbackI {
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean
}
class ActivityResultCallbackManager {
private val listeners = mutableListOf<ActivityResultCallbackI>()
fun addListener(listener : ActivityResultCallbackI) {
listeners.add(listener)
}
fun removeListener(listener : ActivityResultCallbackI) {
listeners.remove(listener)
}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) : Boolean =
listeners.any { it.onActivityResult(requestCode, resultCode, data) }
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private var callbackManager = ActivityResultCallbackManager()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
Theme {
CompositionLocalProvider(
LocalActivityResultCallbackManager provides callbackManager
) {
LoginScreen()
}
}
}
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
if (!callbackManager.onActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data)
}
}
}
FacebookLoginViewModel.kt
class FacebookLoginViewModel : ViewModel(), ActivityResultCallbackI {
sealed class LoginState {
object Initial: LoginState()
object Processing: LoginState()
data class Success(val loginResult: LoginResult): LoginState()
data class Error(val exception: FacebookException): LoginState()
}
private var callbackManager = CallbackManager.Factory.create()
var state by mutableStateOf<LoginState>(LoginState.Initial)
private set
init {
LoginManager.getInstance().registerCallback(
callbackManager,
object : FacebookCallback<LoginResult> {
override fun onSuccess(loginResult: LoginResult) {
state = LoginState.Success(loginResult)
}
override fun onCancel() {
state = LoginState.Initial
}
override fun onError(exception: FacebookException) {
state = LoginState.Error(exception)
}
}
)
}
override fun onCleared() {
super.onCleared()
LoginManager.getInstance().unregisterCallback(callbackManager)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean =
callbackManager.onActivityResult(requestCode, resultCode, data)
fun login(context: Context) {
state = LoginState.Processing
LoginManager.getInstance()
.logInWithReadPermissions(context.findActivity(), Arrays.asList("public_profile"));
}
}
LoginScreen.kt
@Composable
fun LoginScreen() {
val viewModel: FacebookLoginViewModel = viewModel()
val callbackManager = LocalActivityResultCallbackManager.current
DisposableEffect(Unit) {
callbackManager.addListener(viewModel)
onDispose {
callbackManager.removeListener(viewModel)
}
}
val context = LocalContext.current
Column {
Text(viewModel.state.toString())
Button(onClick = {
viewModel.login(context)
}) {
Text("FB Login")
}
}
}
您也可以尝试构建这个fork,它包含更改来自这个拉取请求.它增加了对合约 api 的支持,尚未被接受.仔细检查更改,这不是官方的!
Also you can try building this fork, it contains changes from this pull request. It adds support of contract api, and is not yet accepted. Check out changes carefully, it's not official!
这篇关于使用 Jetpack Compose 登录 Facebook的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论