如何从Firebase AuthUI的Facebook提供商获取额外用户信息
如何从Firebase AuthUI的Facebook提供商获取生日和性别信息
嘿,我懂你现在的困惑——你已经通过AuthUI请求了Facebook的生日和性别权限,但在Firebase User的ProviderData里找不到这些数据,反而调试时发现它们藏在一个叫zzdd的内部属性里。先给你敲个警钟:绝对不要直接用这个zzdd属性!它是Firebase Auth库的内部私有字段,Google随时可能改名字或者删掉它,到时候你的代码直接就崩了。
正确的做法是通过Facebook的Graph API来获取这些数据,毕竟这些信息本来就存储在Facebook那边,步骤很简单:
第一步:获取Facebook访问令牌
先从Firebase用户的提供商数据里提取Facebook的访问令牌:
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser(); String facebookAccessToken = null; // 遍历提供商数据,定位到Facebook的条目 for (UserInfo userInfo : mUser.getProviderData()) { if ("facebook.com".equals(userInfo.getProviderId())) { // 方式1:从Firebase用户的IdToken中获取 mUser.getIdToken(false) .addOnSuccessListener(result -> { facebookAccessToken = result.getToken(); // 拿到令牌后调用Graph API获取数据 fetchFacebookUserData(facebookAccessToken); }); // 方式2:如果集成了Facebook SDK,直接用官方API拿令牌 // facebookAccessToken = AccessToken.getCurrentAccessToken().getToken(); break; } }
第二步:调用Facebook Graph API获取目标数据
拿到令牌后,调用/me端点并指定需要的字段(birthday和gender)。这里给你两种常用的实现方式:
方式一:用OkHttp发起请求
如果你习惯用OkHttp,代码可以这么写:
private void fetchFacebookUserData(String token) { OkHttpClient client = new OkHttpClient(); String requestUrl = String.format("https://graph.facebook.com/me?fields=birthday,gender&access_token=%s", token); Request request = new Request.Builder().url(requestUrl).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 请求失败,处理错误逻辑 e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String jsonStr = response.body().string(); try { JSONObject userData = new JSONObject(jsonStr); String birthday = userData.optString("birthday"); String gender = userData.optString("gender"); // 注意:这里是子线程,要切回主线程处理UI或数据 runOnUiThread(() -> { // 在这里使用你的生日和性别数据 Log.d("FacebookUserData", "生日:" + birthday + ",性别:" + gender); }); } catch (JSONException e) { e.printStackTrace(); } } } }); }
方式二:用Facebook官方SDK的GraphRequest
如果已经集成了Facebook SDK,用GraphRequest会更省心:
private void fetchFacebookUserDataWithSDK() { AccessToken accessToken = AccessToken.getCurrentAccessToken(); if (accessToken != null && !accessToken.isExpired()) { GraphRequest request = GraphRequest.newMeRequest( accessToken, (jsonObject, response) -> { try { String birthday = jsonObject.optString("birthday"); String gender = jsonObject.optString("gender"); // GraphRequest默认在主线程回调,可直接处理数据 Log.d("FacebookUserData", "生日:" + birthday + ",性别:" + gender); } catch (Exception e) { e.printStackTrace(); } }); Bundle params = new Bundle(); params.putString("fields", "birthday,gender"); request.setParameters(params); request.executeAsync(); } }
为什么不能碰zzdd?
再强调一次:zzdd是Firebase Auth库的内部私有字段,完全没有公开的API承诺它会一直存在。Firebase团队在更新版本时,可能随便把它改名为zzde或者调整数据结构,你的代码要么拿不到数据,要么直接抛出反射异常(如果用反射访问的话),这绝对是不稳定的写法。
内容的提问来源于stack exchange,提问作者Bruno Neuman
相关产品推荐
相关产品推荐

