使用 Google 登录 Android 获取用户的出生日期和性别

Posted

技术标签:

【中文标题】使用 Google 登录 Android 获取用户的出生日期和性别【英文标题】:Get User's Birthdate & Gender using Google Sign-In Android 【发布时间】:2017-08-31 06:41:34 【问题描述】:

我已将Google Sign-In 集成到我的应用程序中。我可以得到用户的EmailDisplayName。现在,我想获取用户的BirthdateGender

我已将所有必需的requestsScopes 添加到GoogleApiClient 中,所有这些都由API 授予。这是代码。

    // [START configure_signin]
    // 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()
            .requestProfile() <- This
            .requestScopes(
                    new Scope(Scopes.PLUS_ME), new Scope(Scopes.PROFILE) <- This
            )
            .build();
    // [END configure_signin]

    // [START build_client]
    // Build a GoogleApiClient with access to the Google Sign-In API and the
    // options specified by gso.
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, new GoogleApiClient.OnConnectionFailedListener() 
                @Override
                public void onConnectionFailed(@NonNull ConnectionResult connectionResult) 
                    // An unresolvable error has occurred and Google APIs (including Sign-In) will not
                    // be available.
                    Log.d(TAG, "onConnectionFailed:" + connectionResult);
                
             /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .addScope(new Scope(Scopes.PLUS_ME)) <- This
            .addScope(new Scope(Scopes.PROFILE)) <- This
            .build();
    // [END build_client]

这是GoogleSignInAccount 中授予的范围

private void setupUserData(GoogleSignInAccount acct) 
    if (acct != null) 
        mPrefs.setName(acct.getDisplayName());
        mPrefs.setEmail(acct.getEmail());
        if (acct.getPhotoUrl() != null) 
            mPrefs.setPicURL(acct.getPhotoUrl().toString());
        
        Set<Scope> scopes = acct.getGrantedScopes(); <- This
        for (Scope scope : scopes) 
            Log.d(TAG, "setupUserData: " + scope.toString()); <- This
        
    

这是授予scopes的日志

D/SplashActivity: setupUserData: GrantedScopes size 6
D/SplashActivity: setupUserData: https://www.googleapis.com/auth/plus.me
D/SplashActivity: setupUserData: https://www.googleapis.com/auth/userinfo.email
D/SplashActivity: setupUserData: https://www.googleapis.com/auth/userinfo.profile
D/SplashActivity: setupUserData: email
D/SplashActivity: setupUserData: profile
D/SplashActivity: setupUserData: openid

这是我的 Google 移动服务的依赖项

compile 'com.google.android.gms:play-services-auth:10.2.0'
compile 'com.google.android.gms:play-services-plus:10.2.0'

现在,我不知道如何访问user's profile information

【问题讨论】:

你是如何实现这个的? 我建议您使用Facebook SDK 而不是Google Plus。 Facebook SDK 比 Google Plus 提供更多支持。 【参考方案1】:

如Getting people and profile information 中所述,要获取其他个人资料信息和用户的联系人,请使用People API。您必须在用户登录时通过请求额外的scopes 获得用户的同意才能访问此信息。

您可以调用people.get,并传入资源名称,以获取每个人的私人联系人和公共个人资料数据。如果您的请求成功,则响应包含 Person 的实例,包括 birthday 和 gender。

您可能需要访问我提供的链接以获取更多信息。

【讨论】:

【参考方案2】:

这是完整的工作示例,希望对以后的读者有所帮助。该应用程序所做的是首先登录(登录 API 包括姓名和电子邮件),然后请求生日和性别(人员 API)身份验证,并将其保存到 SharedPreferences 以供下次启动时重复使用。最后它将打印基本信息和高级(性别和生日)信息。

public class MainActivity extends AppCompatActivity 

    static final private int RC_SIGN_IN = 1;
    static final private String TAG = "hole";
    private WeakReference<MainActivity> weakAct = new WeakReference<>(this);
    private GoogleSignInClient mGoogleSignInClient;
    private GoogleSignInAccount account;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Scope myScope = new Scope("https://www.googleapis.com/auth/user.birthday.read");
        Scope myScope2 = new Scope(Scopes.PLUS_ME);
        Scope myScope3 = new Scope(Scopes.PROFILE); //get name and id
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestScopes(myScope, myScope2)
                .requestEmail()
                .requestProfile()
                .build();

        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

        account = GoogleSignIn.getLastSignedInAccount(this);
        if (account == null) 
            reqPerm();
         else 
            SharedPreferences sharedPref = getSharedPreferences(account.getId(), MODE_PRIVATE);
            if (sharedPref.contains("gender")) 
                printBasic();
                printAdvanced();
             else 
                new GetProfileDetails(account, weakAct, TAG).execute();
            
        
    

    private void reqPerm() 
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    

    private void printBasic() 
        account = GoogleSignIn.getLastSignedInAccount(this);
        if (account != null) 
            Log.d(TAG, "latest sign in: "
                    + "\n\tPhoto url:" + account.getPhotoUrl()
                    + "\n\tEmail:" + account.getEmail()
                    + "\n\tDisplay name:" + account.getDisplayName()
                    + "\n\tFamily(last) name:" + account.getFamilyName()
                    + "\n\tGiven(first) name:" + account.getGivenName()
                    + "\n\tId:" + account.getId()
                    + "\n\tIdToken:" + account.getIdToken()
            );
         else 
            Log.w(TAG, "basic info is null");
        
    

    private void saveAdvanced(Person meProfile) 
        account = GoogleSignIn.getLastSignedInAccount(this);
        if (account != null) 
            SharedPreferences sharedPref = getSharedPreferences(account.getId(), MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPref.edit();

            if (n.size() > 0) 
                try 
                    Log.d("hole", "g name: " + n);
                    editor.putString("givenName", n.get(0).getGivenName());
                    editor.putString("familyName", n.get(0).getFamilyName());
                    editor.putString("id", n.get(0).getMetadata().getSource().getId());
                  catch (Exception e) 
                    e.printStackTrace();
                    //this one should act as fallback priority since it got problem to get name without wait for ~1 minute
                    // ... when create new account will get empty name
                    editor.putString("id", account.getId());
                    editor.putString("givenName", account.getGivenName());
                    editor.putString("familyName", account.getFamilyName());
            
        
            List<Gender> genders = meProfile.getGenders();
            if (genders != null && genders.size() > 0) 
                String gender = genders.get(0).getValue();
                Log.d(TAG, "onPostExecute gender: " + gender);
                editor.putString("gender", gender);
             else 
                Log.d(TAG, "onPostExecute no gender if set to private ");
                editor.putString("gender", ""); //save as main key to know pref saved
            
            List<Birthday> birthdays = meProfile.getBirthdays();
            if (birthdays != null && birthdays.size() > 0) 
                for (Birthday b : birthdays)  //birthday still able to get even private, unlike gender
                    Date bdate = b.getDate();
                    if (bdate != null) 
                        String bday, bmonth, byear;
                        if (bdate.getDay() != null) bday = bdate.getDay().toString();
                        else bday = "";
                        if (bdate.getMonth() != null) bmonth = bdate.getMonth().toString();
                        else bmonth = "";
                        if (bdate.getYear() != null) byear = bdate.getYear().toString();
                        else byear = "";
                        editor.putString("bday", bday);
                        editor.putString("bmonth", bmonth);
                        editor.putString("byear", byear);
                    
                
             else 
                Log.w(TAG, "saveAdvanced no birthday");
            
            editor.commit();  //next instruction is print from pref, so don't use apply()
         else 
            Log.w(TAG, "saveAdvanced no acc");
        
    

    private void printAdvanced() 
        account = GoogleSignIn.getLastSignedInAccount(this);
        if (account != null) 
            SharedPreferences sharedPref = getSharedPreferences(account.getId(), MODE_PRIVATE);
            if (sharedPref.contains("gender"))  //this checking works since null still saved
                String gender = sharedPref.getString("gender", "");
                Log.d(TAG, "gender: " + gender);
                if (sharedPref.contains("bday"))  //this checking works since null still saved
                    String bday = sharedPref.getString("bday", "");
                    String bmonth = sharedPref.getString("bmonth", "");
                    String byear = sharedPref.getString("byear", "");
                    Log.d(TAG, bday + "/" + bmonth + "/" + byear);
                 else 
                    Log.w(TAG, "failed ot get birthday from pref");
                
                String givenName = sharedPref.getString("givenName", "");
                String familyName = sharedPref.getString("familyName", "");
                String id = sharedPref.getString("id", "");
             else 
                Log.w(TAG, "failed ot get data from pref -2");
            

         else 
            Log.w(TAG, "failed ot get data from pref -1");
        
    

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RC_SIGN_IN) 
            if (resultCode == Activity.RESULT_OK) 
                Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
                handleSignInResult(task);
             else 
                Log.w(TAG, "failed, user denied OR no network OR jks SHA1 not configure yet at play console android project");
            
        
    

    private void handleSignInResult(Task<GoogleSignInAccount> completedTask) 
        try 
            GoogleSignInAccount account = completedTask.getResult(ApiException.class);
            // Signed in successfully, show authenticated UI.
            new GetProfileDetails(account, weakAct, TAG).execute();
         catch (ApiException e)  //cancel choose acc will come here with status code 12501 if not check RESULT_OK
            // , more status code at:
            //https://developers.google.com/android/reference/com/google/android/gms/auth/api/signin/GoogleSignInStatusCodes
            Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
        
    

    static class GetProfileDetails extends AsyncTask<Void, Void, Person> 

        private PeopleService ps;
        private int authError = -1;
        private WeakReference<MainActivity> weakAct;
        private String TAG;

        GetProfileDetails(GoogleSignInAccount account, WeakReference<MainActivity> weakAct, String TAG) 
            this.TAG = TAG;
            this.weakAct = weakAct;
            GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(
                    this.weakAct.get(), Collections.singleton(Scopes.PROFILE));
            credential.setSelectedAccount(
                    new Account(account.getEmail(), "com.google"));
            HttpTransport HTTP_TRANSPORT = AndroidHttp.newCompatibleTransport();
            JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
            ps = new PeopleService.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                    .setApplicationName("Google Sign In Quickstart")
                    .build();
        

        @Override
        protected Person doInBackground(Void... params) 
            Person meProfile = null;
            try 
                meProfile = ps
                        .people()
                        .get("people/me")
                        .setPersonFields("names,genders,birthdays")
                        .execute();
             catch (UserRecoverableAuthIOException e) 
                e.printStackTrace();
                authError = 0;
             catch (GoogleJsonResponseException e) 
                e.printStackTrace();
                authError = 1;
             catch (IOException e) 
                e.printStackTrace();
                authError = 2;
            
            return meProfile;
        

        @Override
        protected void onPostExecute(Person meProfile) 
            MainActivity mainAct = weakAct.get();
            if (mainAct != null) 
                mainAct.printBasic();
                if (authError == 0)  //app has been revoke, re-authenticated required.
                    mainAct.reqPerm();
                 else if (authError == 1) 
                    Log.w(TAG, "People API might not enable at" +
                            " https://console.developers.google.com/apis/library/people.googleapis.com/?project=<project name>");
                 else if (authError == 2) 
                    Log.w(TAG, "API io error");
                 else 
                    if (meProfile != null) 
                        mainAct.saveAdvanced(meProfile);
                        mainAct.printAdvanced();
                    
                
            
        
    

提醒:

    在 AndroidManifest.xml 中添加 &lt;uses-permission android:name="android.permission.INTERNET" /&gt;。 在dependencies build.gradle 中添加implementation 'com.google.android.gms:play-services-auth:12.0.1'implementation 'com.google.apis:google-api-services-people:v1-rev255-1.23.0'implementation 'com.google.api-client:google-api-client-android:1.23.0'。 就我而言,我将 compileSdkVersiontargetSdkVersionappcompat-v7 从 27 降级到 26,因为我在添加 #2 依赖项后收到警告。 添加 signingConfigs debug storeFile file('<path to jks file>') keyAlias '<your key alias>' keyPassword '<your key password>' storePassword '<your store password>' build.gradle,由Build生成的jks文件->Generated Signed APK...->Create new... keytool -exportcert -keystore &lt;path to jks file&gt; -list -v获取SHA1 hex key,然后访问play console,填写项目名、app包名、SHA1 hex key。 Enable People API at https://console.developers.google.com/apis/library/people.googleapis.com/?project=[your project id]",该项目 id 可以从游戏控制台获取。请注意,它不是项目名称。 我注意到库中没有这样的Scopes.BIRTHDAY,因此我必须对生日端点 URL"https://www.googleapis.com/auth/user.birthday.read" 进行硬编码,该链接可以从 https://developers.google.com/people/v1/how-tos/authorizing#profile-scopes 或“Try it API”面板中的“Show Scopes”获取https://developers.google.com/people/api/rest/v1/people/get 生日是一个列表,它可能会循环 2 个日期项目,在我的情况下,一个项目缺少年份。我的代码总是替换以保存这两项。可能有更好的方法来处理它。 只有在不是私有的情况下才能返回性别。生日没有这个限制。 由于 Android 设备需要大约 1 分钟的延迟才能获取新创建的帐户名称,因此您可能需要使用 PROFILE 范围而不是简单的 account.getGivenName()account.getFamilyName()

【讨论】:

这个代码仍然有效吗?还是不推荐使用 People API? @Coeus Google 以及相关 API 已弃用,但 People API 本身已弃用。 AsyncTask 已弃用。【参考方案3】:

分级

implementation "com.google.android.gms:play-services-auth:$google_play_service_version"
implementation 'com.google.apis:google-api-services-people:v1-rev354-1.25.0'
implementation ('com.google.api-client:google-api-client-android:1.23.0') 
    exclude group: 'org.apache.httpcomponents'

认证

private void setupGoogleLogin() 
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestScopes(new Scope(PeopleApi.CONTACT_SCOPE), new Scope(PeopleApi.BIRTHDAY_SCOPE))
                .requestEmail()
                .build();

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this, mOnConnectionFailedListener)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();
    

人物接口

public class PeopleApi 
    public static final String CONTACT_SCOPE = "https://www.googleapis.com/auth/contacts.readonly";
    public static final String BIRTHDAY_SCOPE = "https://www.googleapis.com/auth/user.birthday.read";
    private static PeopleService mInstance;

    private static PeopleService getService() 
        if (mInstance == null) mInstance = initializeService();
        return mInstance;
    

    private static PeopleService initializeService() 
        Context context = BHApp.getContext();
        GoogleAccountCredential credential =
                GoogleAccountCredential.usingOAuth2(context, Arrays.asList(CONTACT_SCOPE, BIRTHDAY_SCOPE));
        credential.setSelectedAccount(GoogleSignIn.getLastSignedInAccount(context).getAccount());

        return new PeopleService.Builder(AndroidHttp.newCompatibleTransport(), JacksonFactory.getDefaultInstance(), credential)
                .setApplicationName(context.getString(R.string.app_name)).build();
    

    public static Person getProfile() 
        try 
            return getService().people().get("people/me")
                    .setPersonFields("genders,birthdays,addresses")
                    .execute();
         catch (Exception e) 
            Utils.handleException(e);
            return null;
        
    

    public static String getBirthday(Person person) 
        try 
            List<Birthday> birthdayList = person.getBirthdays();
            if (birthdayList == null) return Utils.EMPTY_STRING;
            Date date = null;
            for (Birthday birthday : birthdayList) 
                date = birthday.getDate();
                if (date != null && date.size() >= 3) break;
                else date = null;
            
            if (date == null) return Utils.EMPTY_STRING;
            Calendar calendar = Calendar.getInstance();
            calendar.set(date.getYear(), date.getMonth() - 1, date.getDay());
            return Utils.convertDateToString(calendar);
         catch (Exception e) 
            Utils.handleException(e);
            return Utils.EMPTY_STRING;
        
    

    private static final String CITY_SUFFIX = " city";
    public static android.location.Address getLocation(Person person) 
        try 
            List<Address> addressList = person.getAddresses();
            if (addressList == null) return null;
            String city = null;
            for (Address add : addressList) 
                city = add.getCity();
                if (!TextUtils.isEmpty(city)) break;
            
            if (TextUtils.isEmpty(city)) return null;

            Geocoder geocoder = new Geocoder(BHApp.getContext());

            List<android.location.Address> addresses =  geocoder.getFromLocationName(city + CITY_SUFFIX, 1);
            if (addresses == null || addresses.isEmpty()) return null;
            return addresses.get(0);
         catch (Exception e) 
            Utils.handleException(e);
            return null;
        
    

    public static String getGender(Person person) 
        List<Gender> genders = person.getGenders();
        if (genders == null || genders.isEmpty()) return null;
        Gender gender = genders.get(0);
        return String.valueOf(Enum.Gender.getEnumByValue(gender.getValue()).getId());
    

希望对你有帮助:)

【讨论】:

【参考方案4】:

以下是我的回答,希望对你有所帮助。

Google 的声明说明,Google Play 服务 9.4 已弃用 Plus.PeopleAPI,请参考以下使用 Google People API 的解决方案:

在 Play Services 8.3 的新 google 登录中获取人员详细信息(Isabella Chen 的回答);

尽管明确要求,但无法从 Google Plus 帐户获取私人生日

更新结束

首先,确保您已为自己的 Google 帐户创建了 Google+ 个人资料。然后可以参考以下代码:

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)             
            .requestScopes(new Scope(Scopes.PLUS_LOGIN))
            .requestEmail()
            .build();

mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .addApi(Plus.API)
            .build();

然后

@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);
        handleSignInResult(result);

        // G+
        Person person  = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
        Log.e(TAG, "--------------------------------");
        Log.e(TAG, "Display Name: " + person.getDisplayName());
        Log.e(TAG, "Gender: " + person.getGender());
        Log.e(TAG, "AboutMe: " + person.getAboutMe());
        Log.e(TAG, "Birthday: " + person.getBirthday());
        Log.e(TAG, "Current Location: " + person.getCurrentLocation());
        Log.e(TAG, "Language: " + person.getLanguage());
    

在 build.gradle 文件中

// Google 登录的依赖项

   compile 'com.google.android.gms:play-services-auth:8.3.0'
   compile 'com.google.android.gms:play-services-plus:8.3.0'

您可以查看 belo GitHub 示例项目。希望这对您有所帮助并解决了您的问题。

https://github.com/ngocchung/GoogleSignInDemo

如果您想要最新的集成,请点击下面的链接,该链接有一个很好的文档以及关于代码的简要说明,这都是参数。

https://developers.google.com/identity/sign-in/android/start-integrating

GoogleSignInAccount acct = GoogleSignIn.getLastSignedInAccount(getActivity());
if (acct != null) 
  String personName = acct.getDisplayName();
  String personGivenName = acct.getGivenName();
  String personFamilyName = acct.getFamilyName();
  String personEmail = acct.getEmail();
  String personId = acct.getId();
  Uri personPhoto = acct.getPhotoUrl();

【讨论】:

'PLUS_LOGIN' 已弃用 请按照上面的链接和代码为我工作并解决您的问题。 请查看以下链接:developers.google.com/+/mobile/android/api-deprecation 链接已使用 2 年,我想要更新版本的答案 我只想要出生和性别的数据【参考方案5】:

将此添加到您的 build.gradle 依赖项中

implementation 'com.google.android.gms:play-services-auth:11.8.0'

试试这个

import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;


import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.plus.People;
import com.google.android.gms.plus.Plus;
import com.google.android.gms.plus.model.people.Person;

public class MainActivity extends AppCompatActivity implements  GoogleApiClient.OnConnectionFailedListener

private SignInButton signInButton;
private GoogleSignInOptions gso;
private GoogleApiClient mGoogleApiClient;
private int SIGN_IN = 30;

@Override
    protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();
    signInButton = (SignInButton) findViewById(R.id.sign_in_button);
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .addApi(Plus.API)
            .build();

signInButton.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
            startActivityForResult(signInIntent, SIGN_IN);
        
    );



@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    //If signin
    if (requestCode == SIGN_IN) 
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        //Calling a new function to handle signin
        handleSignInResult(result);
    


private void handleSignInResult(GoogleSignInResult result) 

    if (result.isSuccess()) 

        final GoogleSignInAccount acct = result.getSignInAccount();


        String name = acct.getDisplayName();
        final String mail = acct.getEmail();
        // String photourl = acct.getPhotoUrl().toString();

        final String givenname="",familyname="",displayname="",birthday="";

        Plus.PeopleApi.load(mGoogleApiClient, acct.getId()).setResultCallback(new ResultCallback<People.LoadPeopleResult>() 
            @Override
            public void onResult(@NonNull People.LoadPeopleResult loadPeopleResult) 
                Person person = loadPeopleResult.getPersonBuffer().get(0);

                Log.d("GivenName ", person.getName().getGivenName());
                Log.d("FamilyName ",person.getName().getFamilyName());
                Log.d("DisplayName ",person.getDisplayName());
                Log.d("gender ", String.valueOf(person.getGender())); //0 = male 1 = female
                String gender="";
                if(person.getGender() == 0)
                    gender = "Male";
                else 
                    gender = "Female";
                
                    Log.d("Gender ",gender);
                if(person.hasBirthday())
                    Log.d("Birthday ",person.getBirthday());
                


            
        );
     else 

        Toast.makeText(this, "Login Failed", Toast.LENGTH_LONG).show();
    


@Override
public void onConnectionFailed(ConnectionResult connectionResult) 



【讨论】:

此方法已弃用【参考方案6】:

使用 People api,您可以检索出生日期和性别详细信息。

在 gradle 中使用依赖项 'com.google.apis:google-api-services-people:v1-rev4-1.22.0' 来包含人员的 api。

public void fetchProfileDetails() 
    GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(context, Collections.singleton(Scopes.PROFILE));
    credential.setSelectedAccount(
            new Account(gsr.getSignInAccount().getEmail(), "com.google"));
    /** Global instance of the HTTP transport. */
    HttpTransport HTTP_TRANSPORT = AndroidHttp.newCompatibleTransport();
    /** Global instance of the JSON factory. */
    JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    People service = new People.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
            .setApplicationName("AppName")
            .build();
    try 
        meProfile = service.people().get("people/me").execute();
        List<Gender> genders = meProfile.getGenders();
        if (genders != null && genders.size() > 0) 
            String gender = genders.get(0).getValue();
        
        List<Birthday> birthdays = meProfile.getBirthdays();
        if (birthdays != null && birthdays.size() > 0) 
            String birthday = birthdays.get(0).getText();
        
     catch (IOException e) 
        e.printStackTrace();
    

【讨论】:

【参考方案7】:
//Global instance of the HTTP transport.
private val HTTP_TRANSPORT: HttpTransport = AndroidHttp.newCompatibleTransport()

//Global instance of the JSON factory.
private val JSON_FACTORY: JsonFactory = JacksonFactory.getDefaultInstance()

Thread 
        var meProfile: Person? = null
        try 
            val googleAccountCredential: GoogleAccountCredential = GoogleAccountCredential.usingOAuth2(
                context, Collections.singleton(Scopes.PROFILE)
            )
            googleAccountCredential.selectedAccount = Account(googleSignInAccount.email, "com.google")
            val service: People = People.Builder(HTTP_TRANSPORT, JSON_FACTORY, googleAccountCredential)
                .setApplicationName("Google Sign In Quickstart")
                .build()

            meProfile = service
                .people()
                .get("people/me")
                .set("personFields", "genders")
                .execute()
         catch (e: UserRecoverableAuthIOException) 
            e.printStackTrace()
         catch (e: GoogleJsonResponseException) 
            e.printStackTrace()
         catch (e: IOException ) 
            e.printStackTrace()
        

        if (meProfile != null && !meProfile.genders.isNullOrEmpty()) 
            Log.d(TAG, "Gender: $meProfile.genders[0]["value"]")
         else 
            Log.d(TAG, "Gender only able to return if it's not private.")
        

    .start()

重要:

googleSignInAccount 是要获取性别的账号。 在 Google 个人资料的版本中,必须公开流派的隐私,以便获取数据。

GL

来源

Contact list Scopes

【讨论】:

以上是关于使用 Google 登录 Android 获取用户的出生日期和性别的主要内容,如果未能解决你的问题,请参考以下文章

Android:如何通过 Google 登录 API 获取刷新令牌?

Android FirebaseUI 登录时使用 Google 错误获取发布密钥

Android Google 登录:检查用户是不是已登录

在 Android 上集成 Google 登录时如何在 ID 令牌过期后刷新?

如何通过用于下载应用程序的 Google Play 商店帐户获取 Firebase 用户?

iOS Google 登录无法获取用户个人资料图片?(不是 Google 加号登录)