Открытие FBSession в последовательных запусках (FB SDK для SDK 3.0)

Я пытаюсь интегрировать новый SDK для Facebook для iOS и имел проблемы с пониманием некоторых концепций.

  • Я аутентифицируюсь с помощью диалогового окна [FBSession sessionOpenWithPermissions:...] auth и я возвращаю приложение. Auth успешно.

  • Затем выключите приложение, снова перезапустите. [[FBSession activeSession] accessToken] успешно возвращает ранее сохраненный токен.

  • Однако в то же время [[FBSession activeSession] isOpen] возвращает NO. (Это означает, что сеанс не готов к использованию.)

  • Кроме того, [[FBSession activeSession] state] - FBSessionStateCreatedTokenLoaded в это время. Учебное пособие здесь использует вызов isOpen для проверки активного сеанса загрузки и открытия с помощью токена.

Итак, что мы вызываем, чтобы открыть сеанс, загруженный токеном, без перенаправления пользователя на диалог auth?

Подсказка:

В FBSessionState enum, для FBSessionStateOpen он говорит:

Открыто состояние сеанса, указывающее, что пользователь зарегистрировался или доступен кеш-ключ.

Однако FBSessionStateCreatedTokenLoaded описывается как:

Одно из двух начальных состояний сеанса, указывающее, что загружен кешированный токен; когда сеанс находится в этом состоянии, вызов для открытия * приведет к открытому сеансу без использования UX или приложения

Не могли бы вы помочь мне разобраться в понимании этих сеансовых переходов?

Ответ 1

Я включаю в себя класс утилиты Facebook, который я написал, который помогает с пониманием состояния входа в систему, потому что я предоставляю пользователю сообщение "вошел в систему" ​​/ "не вошел в систему" ​​в моем собственном пользовательском интерфейсе настроек, в дополнение к использованию фактического "FBLoginView", когда приходит время, чтобы пользователь мог переключать состояние авторизации.

Код ниже также доступен через gist.

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

Ключевое замечание, о котором говорили другие, заключается в том, что иногда у вас есть кеш-авторизация авторизации, которую вы не можете использовать сразу, но если вы сделаете вызов Facebook open, вы можете получить ее быть повторно используемым (обновляется). Этот открытый вызов работает за кулисами, не вызывая переключения UI/jarring OAuth/приложения (если у вас есть кешированный токен).

См. мои комментарии в методе isLoggedInAfterOpenAttempt. Обратите внимание, как я проверяю состояние FBSessionStateCreatedTokenLoaded и только тогда, сделайте вызов

-openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error).

Другие лакомые кусочки об этом классе:

  • У меня есть свойство кэшировать зарегистрированного пользователя, типа, соответствующего протоколу FBGraphUser. Тем не менее, он не используется ни в одном из методов входа, показанных здесь.
  • В SDK 3.0 для кода примера iOS предлагается создать свой собственный класс для управления этими видами операций, если у вас есть что-то большее, чем простое приложение. Этот мой класс ниже - это начало этой идеи для моего приложения.
  • Вы можете заменить мои макросы "log4Info" и "log4Debug" на NSLog, чтобы заставить это работать.
#import "UWFacebookService.h"

@implementation UWFacebookService

// Static
static const int ddLogLevel = LOG_LEVEL_DEBUG;

// Strong
@synthesize facebookGraphUser = _facebookGraphUser;


#pragma mark - Inquiries

- (BOOL)isSessionStateEffectivelyLoggedIn:(FBSessionState)state {
    BOOL effectivelyLoggedIn;

    switch (state) {
        case FBSessionStateOpen:
            log4Info(@"Facebook session state: FBSessionStateOpen");
            effectivelyLoggedIn = YES;
            break;
        case FBSessionStateCreatedTokenLoaded:
            log4Info(@"Facebook session state: FBSessionStateCreatedTokenLoaded");
            effectivelyLoggedIn = YES;
            break;
        case FBSessionStateOpenTokenExtended:
            log4Info(@"Facebook session state: FBSessionStateOpenTokenExtended");
            effectivelyLoggedIn = YES;
            break;
        default:
            log4Info(@"Facebook session state: not of one of the open or openable types.");
            effectivelyLoggedIn = NO;
            break;
    }

    return effectivelyLoggedIn;
}

/**
* Determines if the Facebook session has an authorized state. It might still need to be opened if it is a cached
* token, but the purpose of this call is to determine if the user is authorized at least that they will not be
* explicitly asked anything.
*/
- (BOOL)isLoggedIn {
    FBSession *activeSession = [FBSession activeSession];
    FBSessionState state = activeSession.state;
    BOOL isLoggedIn = activeSession && [self isSessionStateEffectivelyLoggedIn:state];

    log4Info(@"Facebook active session state: %d; logged in conclusion: %@", state, (isLoggedIn ? @"YES" : @"NO"));

    return isLoggedIn;
}


/**
* Attempts to silently open the Facebook session if we have a valid token loaded (that perhaps needs a behind the scenes refresh).
* After that attempt, we defer to the basic concept of the session being in one of the valid authorized states.
*/
- (BOOL)isLoggedInAfterOpenAttempt {
    log4Debug(@"FBSession.activeSession: %@", FBSession.activeSession);

    // If we don't have a cached token, a call to open here would cause UX for login to
    // occur; we don't want that to happen unless the user clicks the login button over in Settings, and so
    // we check here to make sure we have a token before calling open
    if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) {
        log4Info(@"We have a cached token, so we're going to re-establish the login for the user.");
        // Even though we had a cached token, we need to login to make the session usable:
        [FBSession.activeSession openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
            log4Info(@"Finished opening login session, with state: %d", status);
        }];
    }
    else {
        log4Info(@"Active session wasn't in state 'FBSessionStateCreatedTokenLoaded'. It has state: %d", FBSession.activeSession.state);
    }

    return [self isLoggedIn];
}

@end

Ответ 2

Это означает, что если у вас есть сохраненный (кэшированный) токен или иным образом уже доступный, библиотека iOS Facebook по-прежнему требует использования открытого метода для повторной инициализации сеанса.

Выполнение этого будет, если оно сможет повторно использовать существующий токен (и это ваш случай), и в этом случае UX (пользовательский интерфейс - например, переключение приложений или всплывающее окно входа в Facebook) не будет запущен.

Попытка пользователя состоит в том, что он никогда не выходил из системы, но в приложении происходит то, что вы связываетесь с Facebook, чтобы открыть сеанс.

Причина этого заключается в том, что в случае, когда токен доступен, но истек, библиотека Facebook скажет вам: "Истек срок действия маркера, считайте, что вы вышли из системы, если у вас нет нового токена".

Надеюсь, что это поможет.

Ответ 3

Попробуйте выполнить следующий пример кода:

/////////////////////////////////

-(void)CallBackOpenURLFromDelegate:(NSURL *)url
{
    [FBSession.activeSession handleOpenURL:url];
}

-(id)init
{
    self = [super init];
    FBSessionTokenCachingStrategy* pToken = [[[FBSessionTokenCachingStrategy alloc]initWithUserDefaultTokenInformationKeyName:@"STokenInfoX"]autorelease];
    FBSession.activeSession = [[FBSession alloc] initWithAppID:FACEBOOK_AppId
                                                   permissions:[NSArray arrayWithObject:@"status_update"]
                                               urlSchemeSuffix:@""
                                            tokenCacheStrategy: pToken];
    return self;
}


-(void)dealloc
{
    [FBSession.activeSession close];
    [super dealloc];
}

-(void) UploadImpl:(NSString*)strImagePath
{
    FBRequest *photoUploadRequest = [FBRequest requestForUploadPhoto: [UIImage imageWithContentsOfFile:strImagePath ]];
    [photoUploadRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error)
    {
        NSLog(@"%@",[error description]);
        //self.delegate
    }];
}

Ответ 4

Это может быть старый поток, но теперь все, что вам нужно сделать, это вызов handleDidBecomeActive в вашем объекте FBSession из приложения (void) applicationDidBecomeActive: (UIApplication *) в вашем делете приложения.

Например:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [[[MLSocialNetworksManager sharedManager] MLFacebook] handleDidBecomeActive];
}

Где MLFacebook - мой объект FBSession.

Ответ 5

просто позвоните в контроллер инициализации.

self.FBloginView = [[FBLoginView alloc] init];