Подтвердить что ты не робот

StatusCallback не вызывается после запросаNewReadPermissions, а затем requestNewPublishPermissions

Я разрабатываю приложение для Android, которое интегрируется с Facebook. Я бы хотел:

  • Позвольте пользователю войти в Facebook
  • Получить адрес электронной почты пользователя на Facebook (может быть проксированный адрес электронной почты, что хорошо)
  • Опубликовать на стене пользователя/временной шкале от его имени

Технически это будет:

  • Аутентификация пользователя
  • Запрос email
  • Запрос publish_stream

1. Аутентификация пользователя

Я назвал Session.openActiveSession() Session.StatusCallback (я уже проверял, что нет активных открытая сессия заранее):

final Session.StatusCallback sessionStatusCallback = new Session.StatusCallback() {
    public void call(final Session session, SessionState state, Exception exception) {
        // If there is an exception...
        if(exception != null)
        {
            // Handle fail case here.
            return;
        }

        // If session is just opened...
        if(state == SessionState.OPENED)
        {
            // Handle success case here.
            return;
        }
    };
};

// Start Facebook Login.
Session.openActiveSession(activity, true, sessionStatusCallback);

Мой обратный вызов вызывается после успешного входа в систему. Пока все хорошо.

2. Запросить email разрешение

Это мой статус-ответ:

new Session.StatusCallback() {
    public void call(final Session session, SessionState state, Exception exception) {
        // If there is an exception...
        if(exception != null)
        {
            // Handle fail case here.
            return;
        }

        // If token is just updated...
        if(state == SessionState.OPENED_TOKEN_UPDATED)
        {
            // Handle success case here.
            return;
        }
    };
};

Я запрашиваю разрешение с Session.requestNewReadPermissions():

final Session session = Session.getActiveSession();
final static String[] PERMISSION_ARRAY_READ = {"email"};
final List<String> permissionList = Arrays.asList(PERMISSION_ARRAY_READ);

// If all required permissions are available...
if(session.getPermissions().containsAll(permissionList))
{
    // Handle success case here.
    return;
}

// Request permissions.
session.requestNewReadPermissions(new Session.NewPermissionsRequest(activity, permissionList));

Мой callback вызывается после разрешения. Пока все хорошо.

3. Запросить publish_stream разрешение

Это мой статус-ответ:

new Session.StatusCallback() {
    public void call(final Session session, SessionState state, Exception exception) {
        // If there is an exception...
        if(exception != null)
        {
            // Handle fail case here.
            return;
        }

        // If token is just updated...
        if(state == SessionState.OPENED_TOKEN_UPDATED)
        {
            // Handle success case here.
            return;
        }
    };
};

Я запрашиваю разрешение с Session.requestNewPublishPermissions():

final Session session = Session.getActiveSession();
final static String[] PERMISSION_ARRAY_PUBLISH = {"publish_stream"};
final List<String> permissionList = Arrays.asList(PERMISSION_ARRAY_PUBLISH);

// If all required permissions are available...
if(session.getPermissions().containsAll(permissionList))
{
    // Handle success case here.
    return;
}

// Request permissions.
session.requestNewPublishPermissions(new Session.NewPermissionsRequest(activity, permissionList));

На этот раз мой обратный вызов не вызывается после разрешения.

Исследование

После дальнейшего расследования я обнаружил, что мой обратный вызов вызван com.facebook.Session#postStateChange(SessionState, SessionState, Exception):

void postStateChange(final SessionState oldState, final SessionState newState, final Exception exception) {
    if (oldState == newState && exception == null) {
        return;
    }

    /* ... */
}

Так как oldState и newState равны (оба являются SessionState.OPENED_TOKEN_UPDATED, мой обратный вызов не вызывается.

Вопрос

Как я могу получать уведомления после получения разрешения на второй раз? Предполагаю ли я close() сеанс и повторно открыть его из кеша?

Дополнительная информация

Мой Android Android SDK 3.0 загружается из здесь, о чем говорится в Facebook Начало работы с SDK для Android для Android.

4b9b3361

Ответ 1

Это ошибка.

[edit: Как указывает Гай в комментариях, это было исправлено в 3.0.1, поэтому это обходное решение больше не требуется]

Обходной путь, который вы упоминаете, в основном правильный, хотя вам не нужно звонить близко. Если вы используете один активный сеанс, перед вызовом requestNewPublishPermissions() просто вызовите:

Session.openActiveSessionFromCache(myContext);

Если вы используете несколько сеансов, вам нужно инициализировать новый сеанс с помощью TokenCachingStrategy, проверить, что он находится в состоянии CREATED_TOKEN_LOADED, и вызвать openForRead (null);

После выполнения одного из них requestNewPublishPermissions() должен вызывать ваше уведомление после его завершения.

Ответ 2

Рабочий код, основанный на правильном ответе

Прежде чем запрашивать разрешение во второй раз (т.е. до Session.requestNewPublishPermissions()), сделайте следующее:

// Re-initialize Facebook session.
session.removeCallback(sessionStatusCallback);          // Remove callback from old session.
session = Session.openActiveSessionFromCache(context);  // Create new session by re-opening from cache.
session.addCallback(sessionStatusCallback);             // Add callback to new session.

Код по-прежнему основан на Facebook Android SDK 3.0, как в вопросе.

Ответ 3

Еще одна вещь, с которой я столкнулся, заключалась в том, что мой requestCode для NewPermissionRequest не был настроен на тот же код запроса, который я использовал для открытия моего Session для чтения, тем самым мой Session.StatusCallback никогда не вызывался, когда новый разрешения были предоставлены.

Например, в моем onActivityResult у меня есть проверка для requestCode и делегирование вызова соответственно, потому что у меня есть другой материал, входящий в этот метод.

public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
    if (requestCode == FACEBOOK_AUTH_RESULT_CODE) {
        Session session = Session.getActiveSession();
        if(session != null) {
            session.onActivityResult(activity, requestCode, resultCode, data);
        }
    }       
}

Затем я открыл свой Session следующим кодом:

        Session.getActiveSession().openForRead(
            new Session.OpenRequest(activity).
                setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK).
                setRequestCode(FACEBOOK_AUTH_RESULT_CODE).
                setPermissions(MY_READ_PERMISSIONS));

Затем я забыл использовать тот же requestCode при построении моего NewPermissionRequest.

Вот что должно выглядеть правильно NewPermissionRequest:

        Session.getActiveSession().requestNewPublishPermissions(
            new NewPermissionsRequest(activity, MY_PUBLISH_PERMISSIONS)
                .setRequestCode(FACEBOOK_AUTH_RESULT_CODE));