如何使用 FirebaseAuth 从 Google 提供商处获取性别和生日?
Posted
技术标签:
【中文标题】如何使用 FirebaseAuth 从 Google 提供商处获取性别和生日?【英文标题】:How to get gender and birthday from Google provider using FirebaseAuth? 【发布时间】:2020-12-18 06:25:17 【问题描述】:我正在尝试使用 Firebase AuthUI 从 Google 提供商处获取性别和生日。这是我的代码。
AuthUI.IdpConfig googleIdp = new AuthUI.IdpConfig.Builder(AuthUI.GOOGLE_PROVIDER)
.setPermissions(Arrays.asList(Scopes.EMAIL, Scopes.PROFILE, Scopes.PLUS_ME))
.build();
startActivityForResult(
AuthUI.getInstance().createSignInIntentBuilder()
.setLogo(R.drawable.firebase_auth_120dp)
.setProviders(Arrays.asList(
new AuthUI.IdpConfig.Builder(AuthUI.EMAIL_PROVIDER).build(),
googleIdp))
.setIsSmartLockEnabled(false)
.setTheme(R.style.AppTheme_Login)
.build(),
RC_SIGN_IN);
在 onActivityResult 中:
IdpResponse idpResponse = IdpResponse.fromResultIntent(data);
我得到了idpResponse
,但它只包括idpSecret
和idpToken
。如何访问其他要求的个人资料字段,例如性别和生日?我可以使用
FirebaseAuth.getInstance().getCurrentUser();
【问题讨论】:
【参考方案1】:很遗憾,Firebase 没有任何内置功能可以在成功登录后获取用户的性别/出生日期。您必须自己从每个提供者那里检索这些数据。
以下是使用 Google People API 从 Google 获取用户性别的方法
public class SignInActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_google_sign_in);
// We can only get basic information using FirebaseAuth
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener()
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth)
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null)
// User is signed in to Firebase, but we can only get
// basic info like name, email, and profile photo url
String name = user.getDisplayName();
String email = user.getEmail();
Uri photoUrl = user.getPhotoUrl();
// Even a user's provider-specific profile information
// only reveals basic information
for (UserInfo profile : user.getProviderData())
// Id of the provider (ex: google.com)
String providerId = profile.getProviderId();
// UID specific to the provider
String profileUid = profile.getUid();
// Name, email address, and profile photo Url
String profileDisplayName = profile.getDisplayName();
String profileEmail = profile.getEmail();
Uri profilePhotoUrl = profile.getPhotoUrl();
else
// User is signed out of Firebase
;
// Google sign-in button listener
findViewById(R.id.google_sign_in_button).setOnClickListener(this);
// Configure GoogleSignInOptions
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.server_client_id))
.requestServerAuthCode(getString(R.string.server_client_id))
.requestEmail()
.requestScopes(new Scope(PeopleScopes.USERINFO_PROFILE))
.build();
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addOnConnectionFailedListener(this)
.addConnectionCallbacks(this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
@Override
public void onClick(View v)
switch (v.getId())
case R.id.google_sign_in_button:
signIn();
break;
private void signIn()
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN)
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess())
// Signed in successfully
GoogleSignInAccount acct = result.getSignInAccount();
// execute AsyncTask to get gender from Google People API
new GetGendersTask().execute(acct);
// Google Sign In was successful, authenticate with Firebase
firebaseAuthWithGoogle(acct);
class GetGendersTask extends AsyncTask<GoogleSignInAccount, Void, List<Gender>>
@Override
protected List<Gender> doInBackground(GoogleSignInAccount... googleSignInAccounts)
List<Gender> genderList = new ArrayList<>();
try
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance();
//Redirect URL for web based applications.
// Can be empty too.
String redirectUrl = "urn:ietf:wg:oauth:2.0:oob";
// Exchange auth code for access token
GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(
httpTransport,
jsonFactory,
getApplicationContext().getString(R.string.server_client_id),
getApplicationContext().getString(R.string.server_client_secret),
googleSignInAccounts[0].getServerAuthCode(),
redirectUrl
).execute();
GoogleCredential credential = new GoogleCredential.Builder()
.setClientSecrets(
getApplicationContext().getString(R.string.server_client_id),
getApplicationContext().getString(R.string.server_client_secret)
)
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.build();
credential.setFromTokenResponse(tokenResponse);
People peopleService = new People.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("My Application Name")
.build();
// Get the user's profile
Person profile = peopleService.people().get("people/me").execute();
genderList.addAll(profile.getGenders());
catch (IOException e)
e.printStackTrace();
return genderList;
@Override
protected void onPostExecute(List<Gender> genders)
super.onPostExecute(genders);
// iterate through the list of Genders to
// get the gender value (male, female, other)
for (Gender gender : genders)
String genderValue = gender.getValue();
您可以找到有关访问 Google API 的更多信息
【讨论】:
嗨,毗湿奴感谢您的回复。你能告诉我 HttpTransport、JacksonFactory 和这里使用的任何其他的导入吗? 嗨威廉添加以下依赖项,编译 'com.google.api-client:google-api-client:1.20.0' 编译 'com.google.firebase:firebase-auth:10.0.1 ' 编译 'com.google.android.gms:play-services-auth:10.0.1' ,添加类路径 classpath 'com.google.gms:google-services:3.0.0' 并添加应用插件:'com.google .gms.google-services' 在依赖项下【参考方案2】:Firebase 不支持该功能,但您可以通过以下方式实现:
首先你需要 client_id 和 client_secret。
您可以通过以下步骤从 Firebase 面板获取这两个:
身份验证 >> 登录方法。点击 Google 并展开 Web SDK 配置。
Gradle 依赖项:
compile 'com.google.apis:google-api-services-people:v1-rev63-1.22.0'
在您的登录活动中添加以下方法。
private void setupGoogleAdditionalDetailsLogin()
// Configure sign-in to request the user's ID, email address, and basic profile. ID and
// basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestIdToken(GOOGLE_CLIENT_ID)
.requestServerAuthCode(GOOGLE_CLIENT_ID)
.requestScopes(new Scope("profile"))
.build();
// Build a GoogleApiClient with access to GoogleSignIn.API and the options above.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, new GoogleApiClient.OnConnectionFailedListener()
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
Log.d(TAG, "onConnectionFailed: ");
)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
public void googleAdditionalDetailsResult(Intent data)
Log.d(TAG, "googleAdditionalDetailsResult: ");
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess())
// Signed in successfully
GoogleSignInAccount acct = result.getSignInAccount();
// execute AsyncTask to get data from Google People API
new GoogleAdditionalDetailsTask().execute(acct);
else
Log.d(TAG, "googleAdditionalDetailsResult: fail");
startHomeActivity();
private void startGoogleAdditionalRequest()
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_GOOGLE);
异步任务以获取更多详细信息
public class GoogleAdditionalDetailsTask extends AsyncTask<GoogleSignInAccount, Void, Person>
@Override
protected Person doInBackground(GoogleSignInAccount... googleSignInAccounts)
Person profile = null;
try
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance();
//Redirect URL for web based applications.
// Can be empty too.
String redirectUrl = "urn:ietf:wg:oauth:2.0:oob";
// Exchange auth code for access token
GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(
httpTransport,
jsonFactory,
GOOGLE_CLIENT_ID,
GOOGLE_CLIENT_SECRET,
googleSignInAccounts[0].getServerAuthCode(),
redirectUrl
).execute();
GoogleCredential credential = new GoogleCredential.Builder()
.setClientSecrets(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.build();
credential.setFromTokenResponse(tokenResponse);
People peopleService = new People.Builder(httpTransport, jsonFactory, credential)
.setApplicationName(App.getInstance().getString(R.string.app_name))
.build();
// Get the user's profile
profile = peopleService.people().get("people/me").execute();
catch (IOException e)
Log.d(TAG, "doInBackground: " + e.getMessage());
e.printStackTrace();
return profile;
@Override
protected void onPostExecute(Person person)
if (person != null)
if (person.getGenders() != null && person.getGenders().size() > 0)
profileGender = person.getGenders().get(0).getValue();
if (person.getBirthdays() != null && person.getBirthdays().get(0).size() > 0)
// yyyy-MM-dd
Date dobDate = person.getBirthdays().get(0).getDate();
if (dobDate.getYear() != null)
profileBirthday = dobDate.getYear() + "-" + dobDate.getMonth() + "-" + dobDate.getDay();
profileYearOfBirth = DateHelper.getYearFromGoogleDate(profileBirthday);
if (person.getBiographies() != null && person.getBiographies().size() > 0)
profileAbout = person.getBiographies().get(0).getValue();
if (person.getCoverPhotos() != null && person.getCoverPhotos().size() > 0)
profileCover = person.getCoverPhotos().get(0).getUrl();
Log.d(TAG, String.format("googleOnComplete: gender: %s, birthday: %s, about: %s, cover: %s", profileGender, profileBirthday, profileAbout, profileCover));
startHomeActivity();
像这样改变你的 onActivityResult:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_GOOGLE) // result for addition details request
googleAdditionalDetailsResult(data);
return;
else if (requestCode == RC_SIGN_IN && resultCode == RESULT_OK) //logged in with firebase
if (FirebaseAuth.getInstance().getCurrentUser().getProviders().get(0).equals("google.com"))
// user logged in with google account using firebase ui
startGoogleAdditionalRequest();
else
// user logged in with google
startHomeActivity();
else
// handle error
更新:如果代码出错
personFields 掩码是必需的
然后使用以下代码:
profile = peopleService.people().get("people/me"). setRequestMaskIncludeField("person.names,person.emailAddresses,person.genders,person.birthdays").execute();
感谢@AbrahamGharyali。
【讨论】:
此代码给出错误 personFields 掩码是必需的。我是这样修好的。希望能帮助到你。// Get the user's profile profile = peopleService.people().get("people/me"). setRequestMaskIncludeField("person.names,person.emailAddresses,person.genders,person.birthdays").execute();
@AbrahamGharyali 感谢您建议我更新它。
我得到:com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found when I using person.genders and person.birthdays
@Sabeeh 你好,我在颤振上有同样的问题。你能帮我吗?这是我的问题的链接。 ***.com/questions/69217255/…以上是关于如何使用 FirebaseAuth 从 Google 提供商处获取性别和生日?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 FirebaseAuth 从 Google 提供商处获取性别和生日?
我们可以从 FirebaseAuth 获取 FacebookAccessToken 吗?
如何在颤振中从 FirebaseAuth 电话验证方法返回变量?