Когда запрашивать разрешения с помощью нового Android SDK 3.0 от Facebook?

В новом Android SDK 3.0 от Facebook (который был выпущен несколько дней назад) процесс аутентификации изменился.

Так как же запросить разрешение на чтение, такое как «friends_hometown»?

Следующий код - это то, как я пытаюсь это сделать, но я совершенно уверен, что это не так, как вы должны это делать:

Версия 1:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Session.openActiveSession(this, true, new Session.StatusCallback() { // start Facebook login
        @Override
        public void call(Session session, SessionState state, Exception exception) { // callback for session state changes
            if (session.isOpened()) {
                List<String> permissions = new ArrayList<String>();
                permissions.add("friends_hometown");
                session.requestNewReadPermissions(new Session.NewPermissionsRequest(FBImport.this, permissions));
                Request.executeGraphPathRequestAsync(session, "me/friends/?access_token="+session.getAccessToken()+"&fields=id,name,hometown", new Request.Callback() {
                    ...
                });
            }
        }
    });
}

Версия 2:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Session currentSession = Session.getActiveSession();
    if (currentSession == null || currentSession.getState().isClosed()) {
        Session session = Session.openActiveSession(this, true, fbStatusCallback); // PROBLEM: NO PERMISSIONS YET BUT CALLBACK IS EXECUTED ON OPEN
        currentSession = session;
    }
    if (currentSession != null && !currentSession.isOpened()) {
        OpenRequest openRequest = new OpenRequest(this).setCallback(fbStatusCallback); // HERE IT IS OKAY TO EXECUTE THE CALLBACK BECAUSE WE'VE GOT THE PERMISSIONS
        if (openRequest != null) {
            openRequest.setDefaultAudience(SessionDefaultAudience.FRIENDS);
            openRequest.setPermissions(Arrays.asList("friends_hometown"));
            openRequest.setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK);
            currentSession.openForRead(openRequest);
        }
    }
}

Что я делаю, так это запрашиваю разрешение, как только сеанс открыт, но в этот момент код уже запускает запрос Graph API, поэтому запрос разрешения приходит с опозданием...

Разве вы не можете запросить разрешение одновременно с инициализацией сеанса?


person caw    schedule 15.12.2012    source источник
comment
stackoverflow.com/q/17878417/1503130 У меня возникла проблема с использованием этого метода, я опубликовал с ним тему.   -  person Prateek    schedule 26.07.2013


Ответы (4)


Я рекомендую вам прочитать наше руководство по входу в систему здесь особенно на шаге 3. Использование кнопки входа, которую мы предоставляем, является наиболее удобным методом (см. authButton.setReadPermissions())

РЕДАКТИРОВАТЬ:

Установить разрешения без использования кнопки входа в систему сложнее, так как вам придется выполнять все управление сеансом вручную. Копаясь в исходном коде кнопки входа, этот строка кода, вероятно, то, что вам нужно. Похоже, вам нужно будет создать свой собственный Session.OpenRequest и установить его атрибуты, такие как разрешения, аудитория и поведение при входе в систему, а затем получить текущий сеанс и вызвать openForRead() на вашем Session.OpenRequest.

person Jesse Chen    schedule 17.12.2012
comment
Спасибо, Джесси, я прочитал этот урок, но я искал способ сделать это без кнопки. Как указано в вашем руководстве, вы также можете войти в систему напрямую. И я думаю, что-то вроде кода, опубликованного в моем вопросе, должно быть решением. - person caw; 18.12.2012
comment
Спасибо! Также обновил мой вопрос (версия 2): это то, что вы хотели? Я вижу здесь проблему, которую я отметил комментариями: как только открывается новая сессия, выполняется данный метод обратного вызова (где обычно выполняются запросы). Но на данный момент в некоторых случаях у нас еще нет необходимых разрешений. - person caw; 18.12.2012
comment
Марко, я сейчас пытаюсь решить ту же проблему. Я как раз собирался опубликовать свой вопрос, когда увидел ваш. У меня была та же логика, что и вы. Я также вижу проблему в том, что метод обратного вызова выполняется немедленно. - person KevinM; 18.12.2012
comment
@JesseChen, привет, я просто хочу знать, могу ли я как-нибудь зарегистрироваться в Facebook в своем приложении для Android? - person Muhammad Babar; 29.04.2013
comment
@JesseChen Я вижу, вы работаете в Facebook: вам действительно следует исправить это, чтобы оно было таким же, как в SDK для iOS, почти каждое приложение, чувствительное к дизайну, будет иметь собственную кнопку Facebook. - person Yosi Taguri; 03.07.2013

Я смог заставить его работать. Это модификация вашего образца версии 2. ссылка Джесси также очень помог.

Вот код, который я запускаю при аутентификации пользователя:

private void signInWithFacebook() {

    mSessionTracker = new SessionTracker(getBaseContext(), new StatusCallback() {

        @Override
        public void call(Session session, SessionState state, Exception exception) {
        }
    }, null, false);

    String applicationId = Utility.getMetadataApplicationId(getBaseContext());
    mCurrentSession = mSessionTracker.getSession();

    if (mCurrentSession == null || mCurrentSession.getState().isClosed()) {
        mSessionTracker.setSession(null);
        Session session = new Session.Builder(getBaseContext()).setApplicationId(applicationId).build();
        Session.setActiveSession(session);
        mCurrentSession = session;
    }

    if (!mCurrentSession.isOpened()) {
        Session.OpenRequest openRequest = null;
        openRequest = new Session.OpenRequest(SignUpChoices.this);

        if (openRequest != null) {
            openRequest.setDefaultAudience(SessionDefaultAudience.FRIENDS);
            openRequest.setPermissions(Arrays.asList("user_birthday", "email", "user_location"));
            openRequest.setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK);

            mCurrentSession.openForRead(openRequest);
        }
    }else {
        Request.executeMeRequestAsync(mCurrentSession, new Request.GraphUserCallback() {
              @Override
              public void onCompleted(GraphUser user, Response response) {
                  Log.w("myConsultant", user.getId() + " " + user.getName() + " " + user.getInnerJSONObject());
              }
            });
    }
}

Для тестирования я запустил его с помощью приведенного ниже кода после возврата из аутентификации Facebook:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);

  if (mCurrentSession.isOpened()) {
    Request.executeMeRequestAsync(mCurrentSession, new Request.GraphUserCallback() {

          // callback after Graph API response with user object
          @Override
          public void onCompleted(GraphUser user, Response response) {
              Log.w("myConsultant", user.getId() + " " + user.getName() + " " + user.getInnerJSONObject());
          }
        });
    }
}
person KevinM    schedule 18.12.2012
comment
Спасибо? Это работает во всех случаях? Вы проверили это? Я видел, что важно проверить, работает ли аутентификация Facebook при последующих вызовах, когда уже есть сеанс, и его необходимо повторно использовать. Кроме того, нужно поместить фактический запрос (который у вас есть в onActivityResult()) в метод обратного вызова кода авторизации. - person caw; 22.12.2012
comment
Да, я протестировал его с последующими вызовами существующих сеансов, и он работает. Я просто реорганизую свой код с вашим предложением. Спасибо - person KevinM; 22.12.2012
comment
@МаркоВ. Даже когда я очищаю данные для официального приложения facebook, мое приложение запоминает данные пользователя, как я могу этого избежать. Или было бы лучше, если бы я спросил, как мне выйти из самого приложения. - person Prateek; 27.01.2013
comment
@pKs: Вы даже можете изменить свой пароль Facebook, и пользователь не выйдет из системы. Это связано с тем, что сеанс создается и действует в течение некоторого времени (вероятно, несколько часов). - person caw; 27.01.2013
comment
@МаркоВ. Я понял смысл этого, но мое дело в том, как я мог выйти из своего приложения после того, как я вошел в систему в двух словах для sdk 3.0 - person Prateek; 27.01.2013
comment
Вы можете удалить токен доступа и потребовать от пользователя повторного входа в систему. - person caw; 27.01.2013
comment
Можете ли вы сказать мне, как я могу изменить ваш пример, чтобы я не использовал SessionTracker? Потому что SessionTracker — это внутренний класс, и они могут быть изменены в любое время без предупреждения. Какие-либо предложения? - person Karlis; 25.07.2013
comment
stackoverflow.com/q/17878417/1503130 У меня возникла проблема с использованием этого метода, я опубликовал с ним тему. - person Prateek; 26.07.2013
comment
У меня проблема в этом. Я использую это для публикации на временной шкале, но объект mcurrentSession всегда закрыт, поэтому он никогда не переходит в другую часть, когда я вызываю эту функцию. См. stackoverflow .com/questions/19191683/ - person Vyper; 05.10.2013

Я решил ту же проблему, реализовав свой собственный метод Session.openActiveSession():

private static Session openActiveSession(Activity activity, boolean allowLoginUI, StatusCallback callback, List<String> permissions) {
    OpenRequest openRequest = new OpenRequest(activity).setPermissions(permissions).setCallback(callback);
    Session session = new Builder(activity).build();
    if (SessionState.CREATED_TOKEN_LOADED.equals(session.getState()) || allowLoginUI) {
        Session.setActiveSession(session);
        session.openForRead(openRequest);
        return session;
    }
    return null;
}
person Pedro Oliveira    schedule 27.12.2012
comment
Спасибо большое, очень помог этот метод! - person caw; 31.12.2012
comment
вы имеете в виду, что копируете и вставляете частный метод из кода facebook-android-sdk :) - person tbruyelle; 04.04.2013
comment
Этот класс Builder является внутренним классом внутри класса Session для тех, кто спрашивает, откуда он. - person Raphael Oliveira; 18.04.2013
comment
@MuhammadBabar Я просто скопировал частный метод Session.openActiveSession и добавил параметр для получения разрешений. - person Pedro Oliveira; 30.04.2013
comment
@PedroOliveira, так что мы не можем сделать разрешение с помощью переопределенного openActiveSession() - person Muhammad Babar; 30.04.2013
comment
+1 у меня работает, спасибо. Однако это только для прав на чтение. Мое приложение разбилось, когда у меня было разрешение на публикацию вместе с разрешениями на чтение. Когда я удалил его, приложение работало нормально. Есть ли идея, как добавить разрешения на публикацию? - person Hesam; 04.05.2013
comment
@YogeshTatwal вы должны вызывать этот метод в том месте, где вы вызываете Session.openActiveSession с массивом разрешений. - person Vikram; 04.06.2013
comment
Очень элегантное решение, за него следует проголосовать как за правильное. - person Yosi Taguri; 03.07.2013
comment
Если вы используете веб-представление FB и у вас есть сеанс, но не все разрешения, появится всплывающий пользовательский интерфейс, даже если для параметра allowLoginUI установлено значение false. - person funkybro; 20.02.2014
comment
Сработало и для меня, мне просто было интересно, почему мой сеанс facebook все время пропускает разрешение, и это сделало его очень ясным и элегантным. - person Dr. aNdRO; 27.03.2014
comment
@Dr.aNdRO, потому что ваш пользователь уже предоставил разрешение, поэтому он все время пропускает разрешение. Вы можете перейти к настройке приложения пользователя и удалить приложение. Это заставит собственное приложение запрашивать разрешения для сеанса Facebook. - person AkshayT; 30.04.2014

Хотя первый вопрос был задан несколько месяцев назад, и есть принятые ответы, есть еще одно более элегантное решение для запроса дополнительных разрешений у пользователя во время аутентификации. Кроме того, недавно был выпущен Facebook SDK 3.5, и было бы неплохо обновить эту тему :)

Итак, элегантное решение поставляется с этой библиотекой с открытым исходным кодом: android-simple-facebook

Настройка

Просто добавьте следующие строки в свой класс Activity:

  1. Определите и выберите необходимые разрешения, например friends_hometown:

    Permissions[] permissions = new Permissions[]
    {
        Permissions.FRIENDS_HOMETOWN,
        Permissions.FRIENDS_PHOTOS,
        Permissions.PUBLISH_ACTION
    };
    

    Самое замечательное здесь с разрешениями заключается в том, что вам не нужно разделять разрешения на ЧТЕНИЕ и ПУБЛИКАЦИЯ. Вы просто указываете, что вам нужно, а библиотека позаботится обо всем остальном.

  2. Создайте и определите конфигурацию, поставив app_id, namespace и permissions:

    SimpleFacebookConfiguration configuration = new SimpleFacebookConfiguration.Builder()
            .setAppId("625994234086470")
            .setNamespace("sromkuapp")
            .setPermissions(permissions)
            .build();
    
  3. И создайте экземпляр SimpleFacebook и установите эту конфигурацию:

    SimpleFacebook simpleFacebook = SimpleFacebook.getInstance(Activity);
    simpleFacebook.setConfiguration(configuration);
    

Теперь вы можете запускать такие методы, как: войти, опубликовать ленту/историю, пригласить,…

Войти

mSimpleFacebook.login(OnLoginListener);

Выйти

mSimpleFacebook.logout(OnLogoutListener);

Для получения дополнительных примеров и использования посетите эту страницу: https://github.com/sromku/android-simple-facebook#actions-examples

person sromku    schedule 25.08.2013
comment
Спасибо, выглядит интересно! - person caw; 25.08.2013