【问题标题】:How to get gender and birthday from Google provider using FirebaseAuth?如何使用 FirebaseAuth 从 Google 提供商处获取性别和生日?
【发布时间】: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,但它只包括idpSecretidpToken。如何访问其他要求的个人资料字段,例如性别和生日?我可以使用

访问常用字段电子邮件、姓名、照片等
FirebaseAuth.getInstance().getCurrentUser();

【问题讨论】:

    标签: android firebase firebase-authentication google-signin


    【解决方案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_idclient_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.emailAddress‌​es,person.genders,pe‌​rson.birthdays").exe‌​cute();
    

    感谢@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 你好,我在颤振上有同样的问题。你能帮我吗?这是我的问题的链接。 stackoverflow.com/questions/69217255/…
    猜你喜欢
    • 2011-11-01
    • 2018-03-06
    • 2013-09-07
    • 2017-12-21
    • 2018-07-07
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    相关资源
    最近更新 更多