You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Fragment结合Navigation Component实现Facebook登录异常排查

Facebook登录在Navigation Component的Fragment中回调失效问题

问题描述

在Activity中实现Facebook登录功能完全正常,但迁移到使用Navigation Component的Fragment后出现异常:点击Facebook登录按钮能弹出授权界面,但点击「继续」后,loginWithFacebook()方法内的Log.i()日志没有触发,回调逻辑未执行。

Fragment代码

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    binding = FragmentLoginBinding.inflate(inflater, container, false);
    // facebook callback
    callbackManager = CallbackManager.Factory.create();

    LoginManager.getInstance().registerCallback(callbackManager,
            new FacebookCallback<LoginResult>() {
                @Override
                public void onSuccess(LoginResult loginResult) {
                    // App code
                    loginWithFacebook(loginResult);
                }

                @Override
                public void onCancel() {
                    // App code
                }

                @Override
                public void onError(FacebookException exception) {
                    // App code
                    Log.e("Login With facebook", "onError: ", exception);
                }
            });
    binding.btnRegisterFacebook.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            LoginManager.getInstance().logInWithReadPermissions(requireActivity(), Arrays.asList("public_profile"));
        }
    });
    return binding.getRoot();
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    callbackManager.onActivityResult(requestCode, resultCode, data);
    super.onActivityResult(requestCode, resultCode, data);
}

private void loginWithFacebook(LoginResult loginResult) {
    // here we will get access token and save data to server
    AccessToken accessToken = loginResult.getAccessToken();
    GraphRequest request = GraphRequest.newMeRequest(
            accessToken,
            new GraphRequest.GraphJSONObjectCallback() {
                @Override
                public void onCompleted(
                        JSONObject object,
                        GraphResponse response) {
                    try {
                        String name = object.getString("name");
                        String id = object.getString("id");
                        // save to server
                        Log.i("Facebook auth",id);
                        Log.i("Facebook auth",name);
                    } catch (JSONException e) {
                        Log.e("Login With facebook", "onCompleted: ", e);
                        throw new RuntimeException(e);
                    }
                    // Application code
                }
            });
    Bundle parameters = new Bundle();
    parameters.putString("fields", "id,name,link");
    request.setParameters(parameters);
    request.executeAsync();
}

宿主Activity代码

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
   Fragment navhost = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
   navhost.onActivityResult(requestCode,resultCode,data);
   super.onActivityResult(requestCode, resultCode, data);
}

排查与解决

问题核心是Activity到Fragment的onActivityResult结果分发逻辑错误,以及Fragment回调的生命周期稳定性问题,按以下步骤修复:

  • 修正宿主Activity的结果分发逻辑
    直接调用navhost.onActivityResult()无法将结果传递到当前显示的子Fragment,需要通过NavHostFragment的子Fragment管理器分发。同时要先调用super.onActivityResult():

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Fragment navHost = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
        if (navHost != null) {
            // 遍历NavHost下的子Fragment,分发结果
            for (Fragment fragment : navHost.getChildFragmentManager().getFragments()) {
                fragment.onActivityResult(requestCode, resultCode, data);
            }
        }
    }
    
  • 确保CallbackManager是Fragment成员变量
    避免在onCreateView中局部声明callbackManager,防止Fragment重建时回调实例丢失,将其声明为Fragment的全局成员:

    public class LoginFragment extends Fragment {
        private FragmentLoginBinding binding;
        // 全局成员变量
        private CallbackManager callbackManager;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            binding = FragmentLoginBinding.inflate(inflater, container, false);
            callbackManager = CallbackManager.Factory.create();
            // 后续注册回调逻辑...
            return binding.getRoot();
        }
    }
    
  • 改用LoginButton的Fragment绑定方式(推荐)
    对于Fragment场景,Facebook官方推荐直接使用LoginButton并调用setFragment(this),无需手动处理onActivityResult分发,简化逻辑:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        binding = FragmentLoginBinding.inflate(inflater, container, false);
        callbackManager = CallbackManager.Factory.create();
    
        LoginButton loginButton = binding.btnRegisterFacebook;
        // 将按钮与当前Fragment绑定
        loginButton.setFragment(this);
        loginButton.setReadPermissions(Arrays.asList("public_profile"));
        loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                loginWithFacebook(loginResult);
            }
    
            @Override
            public void onCancel() {}
    
            @Override
            public void onError(FacebookException exception) {
                Log.e("Login With facebook", "onError: ", exception);
            }
        });
    
        return binding.getRoot();
    }
    

内容的提问来源于stack exchange,提问作者Mohamed Hossam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:05:33