Как получить профиль, например пол, из входа в Google на Android?

Я хочу интегрировать вход Google в свое приложение, когда пользователь впервые войдет в систему, я создам учетную запись, привязанную к этому, поэтому мне нужны некоторые профили, такие как пол, локаль и т. д., и я попытался использовать документ для входа в Google и быстро -start пример показывает:

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();

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

когда нажмите, чтобы войти, я позвоню:

  Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);

войти успешно, я могу получить структуру данных GoogleSignInResult в onActivityResult, из GoogleSignInResult я могу получить GoogleSignInAccount, который содержит только DisplayName, адрес электронной почты и идентификатор. но когда в https://developers.google.com/apis-explorer/#p/, я могу получить такие профили, как пол, регион. Я что-то пропустил?

и я попробовал google plus api, кажется, я могу получить то, что хочу. но не знаю, как использовать, в документе говорится, что создайте клиент следующим образом:

mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(Plus.API)
            .addScope(new Scope(Scopes.PLUS_LOGIN))
            .addScope(new Scope(Scopes.PLUS_ME))
            .build();

но когда я использую это, нажатие кнопки входа вызовет сбой приложения.

Обновление: проблемы при обновлении до новой версии входа в Google Отсутствует ключ API_key/текущий ключ в Службах Google 3.0.0


person dx3906    schedule 24.11.2015    source источник
comment
вы нашли что-нибудь или нет??   -  person aman verma    schedule 26.11.2015
comment
@amanverma Я прочитал твой новый вопрос. ИМО, вы должны прочитать комментарии между ОП и мной ниже моего ответа на этот вопрос.   -  person BNK    schedule 19.12.2015
comment
нет, на самом деле я думаю, что вход в Google работает нормально, поэтому в моем хранилище ключей все в порядке, я думаю, проблема где-то еще ??   -  person aman verma    schedule 19.12.2015
comment
@amanverma, у ОП была та же проблема, что и у вас. Пожалуйста, прочитайте весь его вопрос еще раз.   -  person BNK    schedule 20.12.2015
comment
что ты имеешь в виду под ОП??   -  person aman verma    schedule 20.12.2015
comment
@amanverma в SO, OP для обозначения человека, задавшего вопрос.   -  person BNK    schedule 20.12.2015
comment
Что касается Missing api_key/current key with Google Services 3.0.0, вам следует повторно создать файл конфигурации на странице developers.google.com. /cloud-messaging/android/client#get-config или вручную добавить ключ API в существующий файл конфигурации вашего приложения, выглядит как "api_key": [ { "current_key": "AIzaS.....BeQK6Q" } ],   -  person BNK    schedule 24.06.2016


Ответы (5)


ОБНОВЛЕНИЕ:

Поскольку Plus.PeopleApi устарел в службах Google Play 9.4 как примечания к декларации Google, вместо этого обратитесь к следующим решениям, использующим API Google People:

Получить сведения о человеке в новый вход в Google Play Services 8.3 (ответ Изабеллы Чен);

Не удается получить частный день рождения из учетной записи 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.i(TAG, "--------------------------------");
            Log.i(TAG, "Display Name: " + person.getDisplayName());
            Log.i(TAG, "Gender: " + person.getGender());
            Log.i(TAG, "AboutMe: " + person.getAboutMe());
            Log.i(TAG, "Birthday: " + person.getBirthday());
            Log.i(TAG, "Current Location: " + person.getCurrentLocation());
            Log.i(TAG, "Language: " + person.getLanguage());
        }
    }

Внутри build.gradle файла

// Dependency for Google Sign-In
compile 'com.google.android.gms:play-services-auth:8.3.0'
compile 'com.google.android.gms:play-services-plus:8.3.0'

Вы можете ознакомиться с моим примером проекта GitHub. Надеюсь это поможет!

person BNK    schedule 25.11.2015
comment
mGoogleApiClient.isConnected() возвращает true, но Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) возвращает null, я использую хранилище ключей в C:\Users\xxx\.android\debug.keystore для создания sha1, а в вашем проекте отсутствует google-service.json . - person dx3906; 25.11.2015
comment
Если вы используете мой пример проекта, конечно, вы должны обновить свой идентификатор приложения и файл google-service.json. - person BNK; 25.11.2015
comment
я не знаю почему, но когда я использую ключ отладки, я получаю нуль, как в вашем, так и в моем примере проекта, когда я интегрирую его в свое выпущенное приложение и использую хранилище ключей с пользовательской подписью, я получаю правильный результат. - person dx3906; 25.11.2015
comment
Ключ отладки, который вы создали как документацию Google? Мой пример проекта работает с моим ключом отладки. Пароль по умолчанию - android. - person BNK; 25.11.2015
comment
это было вызвано несоответствием sha1, документ Google указывает, что код оболочки - это sha1 %USERPROFILE%\.android\debug.keystore, а ключ mydefalut - %ANDROID_SDK_HOME%\.android\debug.keystore. см. второй ответ здесь stackoverflow.com/questions/16622528/ - person dx3906; 26.11.2015
comment
да, в консоли разработчика я регистрирую sha1 %USERPROFILE%\.android\debug.keystore, но когда сборка AS использует %ANDROID_SDK_HOME%\.android\debug.keystore, несоответствие вызвало возврат getPerson null . - person dx3906; 26.11.2015
comment
эй @BNK предположим, что у одного пользователя есть учетная запись в google, но нет в google plus, тогда скажите вам, что произойдет ?? - person aman verma; 26.11.2015
comment
@amanverma: я встречал такой случай, приложение вылетает с какой-то значимой информацией, вам нужно исключение try-catch - person BNK; 26.11.2015
comment
просто скажите мне еще одну вещь, что файл, который вы мне отправляете, в котором вы используете только один API, который является плюсом, но здесь, в вашем ответе, вы используете оба API, теперь вы можете сказать мне, что правильно ????? - person aman verma; 26.11.2015
comment
@amanverma: Файл, который я тебе отправил? Какой файл? Я отправляю вам не какой-либо файл, а ссылку на мой пример проекта в GitHub - person BNK; 26.11.2015
comment
извините, вы можете написать здесь свою ссылку на github ?? - person aman verma; 26.11.2015
comment
нет, это не работает, когда я вхожу в результат активности, он возвращает -1 в качестве кода результата ?? - person aman verma; 26.11.2015
comment
@amanverma Вы должны обновить свой идентификатор приложения и файл google-services.json в качестве руководства Google. - person BNK; 26.11.2015
comment
не могли бы вы, пожалуйста, сказать мне, как я могу это сделать и что вы, мужчины, под ap_id имеете в виду sha1 или что я также использую Android Studio ?? - person aman verma; 26.11.2015
comment
нет, все еще не работает, получая -1 в качестве кода результата, я добавил google-services.json d, что такое app_id ?? - person aman verma; 26.11.2015
comment
@amanverma В своем вопросе вы сказали, что ваше приложение хорошо работает с входом в Google, поэтому вы знаете, что такое идентификатор приложения. Теперь вам нужно только обновить рабочее приложение с помощью моего кода в MainActivity.java. Если все еще не работает, разместите свое приложение на github или google drive, я проверю завтра - person BNK; 26.11.2015
comment
Давайте продолжим это обсуждение в чате. - person aman verma; 26.11.2015
comment
эй, не могли бы вы сказать мне, какое здесь название приложения developers.google.com /мобильный/ - person aman verma; 20.12.2015
comment
также в google-services.json мне нужно отредактировать что-то вроде ключа API и все такое, и если да, то где, пожалуйста, скажите мне ?? - person aman verma; 20.12.2015
comment
Имя приложения @amanverma можно задать любое, только обратите внимание на Android package name, которое должно совпадать с applicationId в файле build.gradle и package в AndroidManifest.xml, например, в моем примере проекта вы найдете applicationId "com.example.googlesignindemo" и <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.googlesignindemo" >. Не редактируйте google-services.json - person BNK; 20.12.2015
comment
@amanverma Я предлагаю вам загрузить ваш полный проект на Google Drive или github ... чтобы завтра утром я проверил больше. - person BNK; 21.12.2015
comment
Plus.PeopleApi.getCurrentPerson( gac ) теперь устарело... есть решение? - person injecteer; 21.01.2016
comment
@injecteer Я думаю, вы можете найти решение по этой ссылке stackoverflow.com/questions/34412157/ - person BNK; 21.01.2016
comment
но не у всех пользователей есть google plus, так что это может привести к нулю, верно? - person Nasz Njoka Sr.; 01.02.2016
comment
@NaszNjokaSr. Думаю да, можно попробовать :) - person BNK; 01.02.2016
comment
@suku посмотрите мой проект на Github, обратите внимание на if (mGoogleApiClient.hasConnectedApi... и if (person != null) - person BNK; 03.04.2016
comment
спасибо!! Я пропустил .requestScopes(new Scope(Scopes.PLUS_LOGIN)), поэтому у меня всегда был 0 для пола. - person Beeing Jk; 15.07.2016
comment
Что такое ТАГ? у меня в красном - person Nicolas Schmidt; 18.07.2016
comment
@NicolasSchmidt это строка, например TAG=MyAndroid :) - person BNK; 19.07.2016
comment
@NicolasSchmidt это просто переменная строкового типа. Вы можете использовать Log.i (MyAndroid, содержимое вашего сообщения); вместо - person BNK; 19.07.2016
comment
Этот метод устарел! - person Ram Suthakar; 20.11.2018

Материал Plus people устарел, не используйте его больше. Это можно сделать с помощью API Google People. Включите этот API в своем проекте. . Если вы этого не сделаете, исключение, созданное в Studio, будет содержать прямую ссылку на ваш проект, чтобы включить его (приятно).

Включите следующие зависимости в build.gradle вашего приложения:

compile 'com.google.api-client:google-api-client:1.22.0'
compile 'com.google.api-client:google-api-client-android:1.22.0'
compile 'com.google.apis:google-api-services-people:v1-rev4-1.22.0'

Выполните авторизованный GoogleSignIn, как обычно. Ему не нужны какие-либо Scopes или API, кроме основных учетных записей, например.

GoogleSignInOptions.DEFAULT_SIGN_IN

.addApi(Auth.GOOGLE_SIGN_IN_API, gso)

и запросы на электронную почту и профиль - все, что вам нужно.

Теперь, когда у вас есть успешный результат входа в систему, вы можете получить учетную запись, включая адрес электронной почты (возможно, это можно сделать и с идентификатором).

final GoogleSignInAccount acct = googleSignInResult.getSignInAccount();

Теперь новая часть: создайте и выполните AsyncTask для вызова API Google People после вы получаете счет по электронной почте.

// get Cover Photo Asynchronously
new GetCoverPhotoAsyncTask().execute(Prefs.getPersonEmail());

Вот асинхронная задача:

// Retrieve and save the url to the users Cover photo if they have one
private class GetCoverPhotoAsyncTask extends AsyncTask<String, Void, Void> {
    HttpTransport httpTransport = new NetHttpTransport();
    JacksonFactory jsonFactory = new JacksonFactory();

    // Retrieved from the sigin result of an authorized GoogleSignIn
    String personEmail;

    @Override
    protected Void doInBackground(String... params) {
        personEmail = params[0];
        Person userProfile = null;
        Collection<String> scopes = new ArrayList<>(Collections.singletonList(Scopes.PROFILE));

        GoogleAccountCredential credential =
                GoogleAccountCredential.usingOAuth2(SignInActivity.this, scopes);
        credential.setSelectedAccount(new Account(personEmail, "com.google"));

        People service = new People.Builder(httpTransport, jsonFactory, credential)
                .setApplicationName(getString(R.string.app_name)) // your app name
                .build();

        // Get info. on user
        try {
            userProfile = service.people().get("people/me").execute();
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }

        // Get whatever you want
        if (userProfile != null) {
            List<CoverPhoto> covers = userProfile.getCoverPhotos();
            if (covers != null && covers.size() > 0) {
                CoverPhoto cover = covers.get(0);
                if (cover != null) {
                    // save url to cover photo here, load at will
                    //Prefs.setPersonCoverPhoto(cover.getUrl());
                }
            }
        }

        return null;
    }
}

Вот материалы, которые можно получить у Person.

Если вы вставляете код в свой проект, убедитесь, что импорт разрешен правильно. Есть перекрывающиеся имена классов с некоторыми из старых API.

person Michael Updike    schedule 23.01.2017

После входа выполните:

 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);

            LogUtil.d("googleuser: getGivenName " + (person.getName().getGivenName()));
            LogUtil.d("googleuser: getFamilyName " + (person.getName().getFamilyName()));
            LogUtil.d("googleuser: getDisplayName " + (person.getDisplayName()));
            LogUtil.d("googleuser: getGender " + (person.getGender() + ""));
            LogUtil.d("googleuser: getBirthday " + (person.getBirthday() + ""));
        }
    });
person Frank    schedule 07.03.2016
comment
Этот метод устарел - person RJFares; 19.02.2017

Создайте параметры входа в Google, как показано ниже. Это работает идеально для меня

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestProfile()
            .requestScopes(new Scope(Scopes.PLUS_ME))
            .requestScopes(new Scope(Scopes.PLUS_LOGIN))
            .build();
person Jiju Induchoodan    schedule 21.12.2015
comment
Вариант подписи для чего? Вы должны определить клиент API - person Vahe Gharibyan; 14.11.2017

Я потратил некоторое время, чтобы найти решение, поэтому позвольте мне поделиться текущим способом его достижения.

Вам необходимо расширить параметры входа в Google следующим образом:

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.google_client_id)) //like: '9241xyz.apps.googleusercontent.com'
            .requestEmail()
            .requestProfile()
            .requestServerAuthCode(getString(R.string.google_client_id))
            .build();

Затем в ответ вы получаете объект GoogleSignInResult с GoogleSignInAccount. Вы извлекаете из него как идентификатор токена, так и код авторизации.

private void handleGoogleSignInResult(GoogleSignInResult result) {
    if (result.isSuccess()) {
        GoogleSignInAccount acct = result.getSignInAccount();
        String authCode = acct.getServerAuthCode();
        String idToken = acct.getIdToken();
    }
}

Далее вам нужно получить access_token с помощью POST-запроса:

POST https://www.googleapis.com/oauth2/v4/token
Body (x-www-form-urlencoded):
grant_type authorization_code
client_id 9241xyz.apps.googleusercontent.com
client_secret MNw...fMO
redirect_uri ""
code auth_code_from_google_account
id_token id_token_from_google_account

Запрос можно сделать в Android-приложении, но я рекомендую делать это на стороне сервера, так как хранить client_secret в Android-приложении небезопасно. Но это зависит от вас. Ответ на такой запрос выглядит так:

{
"access_token": "ya29.GluIBuHTXZ...kTglmCceBG",
"expires_in": 3552,
"scope": "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/plus.me",
"token_type": "Bearer",
"id_token": "eyJhbGciOiJSUzI1NiIsImt....V6EAlQd3-Y9CQ"
}

Затем вы можете запросить конечную точку профиля пользователя для получения сведений о пользователе:

GET https://www.googleapis.com/oauth2/v3/userinfo
Headers:
Authorization : Bearer ya29.GluIBuHTXZ...kTglmCceBG

Ответ выглядит так:

{
"sub": "107...72",
"name": "Johny Big",
"given_name": "Johny",
"family_name": "Big",
"profile": "https://plus.google.com/107417...990272",
"picture": "https://lh3.googleusercontent.com/-....IxRQ/mo/photo.jpg",
"email": "[email protected]",
"email_verified": true,
"gender" : "male",
"locale": "en"
}

Однако, если пользователь не имеет публичного доступа к информации о себе, поле пола здесь может отсутствовать. Возможно, вам нужно запросить дополнительную область в запросе входа в Google, но я не проверял. (параметры совместного доступа находятся на странице учетной записи Google: https://myaccount.google.com/personal-info)

person pkleczko    schedule 05.01.2019