Обратный вызов Facebook SDK 3.0 срабатывает дважды

У меня есть следующее действие, и я использую Facebook LoginButton. onSessionStateChange вызывается несколько раз. У меня есть asynctask, которую я хочу запустить после успешного входа в систему, который также открывает новую активность после завершения. Сейчас это запускает несколько асинхронных задач. Как я могу найти последнее состояние, чтобы он не срабатывал дважды? Ive просмотрел все примеры, и Facebook говорит, что session.isOpened() должен работать, но он все еще срабатывает несколько раз.

UPDATE:

После удаления кода сеанса из onResume он получает только один раз, но согласно https://developers.facebook.com/docs/howtos/androidsdk/3.0/login-with-facebook/#step3 Мне нужен этот код в OnResume для определенных ситуаций.

public class LoginActivity extends SherlockActivity {

private static final String TAG = "LoginActivity";

private Context context;
private int statusCode;
private String emailAddress = null;
private String password = null;
private GraphUser fbUser;

private UiLifecycleHelper uiHelper;

private Session.StatusCallback callback = new Session.StatusCallback() {
    @Override
    public void call(Session session, SessionState state,
            Exception exception) {
        onSessionStateChange(session, state, exception);
    }
};

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);

    context = getApplicationContext();

    uiHelper = new UiLifecycleHelper(this, callback);
    uiHelper.onCreate(savedInstanceState);

    final LoginButton fbBtn = (LoginButton) findViewById(R.id.facebook_login);
    fbBtn.setReadPermissions(Arrays.asList("basic_info", "email"));
    /*
     * fbBtn.setOnClickListener(new View.OnClickListener() {
     * 
     * @Override public void onClick(View v) {
     * 
     * Intent intent = new Intent(context, MainActivity.class);
     * startActivity(intent);
     * 
     * finish();
     * 
     * } });
     */
}

@Override
protected void onPause() {
    super.onPause();
    uiHelper.onPause();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    uiHelper.onDestroy();
}

@Override
protected void onResume() {
    super.onResume();

    // For scenarios where the main activity is launched and user
    // session is not null, the session state change notification
    // may not be triggered. Trigger it if it open/closed.
    Session session = Session.getActiveSession();
    if (session != null && (session.isOpened() || session.isClosed())) {
        onSessionStateChange(session, session.getState(), null);
    }
    uiHelper.onResume();
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    uiHelper.onSaveInstanceState(outState);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Log.d("FbLogin", "Result Code is - " + resultCode +"");
    uiHelper.onActivityResult(requestCode, resultCode, data);

}

private void onSessionStateChange(Session session, SessionState state,
        Exception exception) {
    if (session != null && session.isOpened()) {
        Log.i(TAG, "Logged in...");
        Log.i(TAG, "Access Token" + session.getAccessToken());

        if (state == SessionState.OPENED) {
        Request.executeMeRequestAsync(session,
                new Request.GraphUserCallback() {
                    @Override
                    public void onCompleted(GraphUser user,
                            Response response) {
                        if (user != null) {
                            Log.i(TAG, "User ID " + user.getId());
                            Log.i(TAG, "Email " + user.asMap().get("email"));

                            fbUser = user;

                            //FbRegisterTask fbReg = new FbRegisterTask(LoginActivity.this, user);
                            //fbReg.execute();
                            //finish();
                        }
                    }
                });
        }

    } else if (session.isClosed()) {
        Log.i(TAG, "Logged out...");
    }
}
}

Ответ 1

У меня была такая же проблема.

Один вызов происходит из UiLifecycleHelper, когда он вызывает обратный вызов:

UiLifecycleHelper callback
onSessionStateChange()

Другое происходит из Activity, возобновляющего LoginFragment.

LoginActivity.onResumeFragments()
LoginFragment.onResume()
onSessionStateChange()

Во многих случаях это нормально, но в вашем случае это явно проблема из-за AsyncTask.

Вы можете кэшировать сеанс, полученный в onSessionStateChange(), и посмотреть, изменилось ли его состояние и токенInfo, и только затем вызвать вашу задачу async. Необходимо проверить комбинацию состояния сеанса и tokenInfo:

private void onSessionStateChange(Session session, SessionState state, Exception exception) {
    if (state.isOpened()) {
        if (mSession == null || isSessionChanged(session)) {
            mSession = session;
            LogUtils.LOGFB(TAG, "Logged in using facebook");
            LogUtils.LOGFB(TAG, "Access Token: " + session.getAccessToken());
            // Run your AsyncTask
        }

    } else if (state.isClosed()) {
        LogUtils.LOGFB(TAG, "Logged out from facebook");
        // Display your non-authenticated UI
    }
}

private boolean isSessionChanged(Session session) {

    // Check if session state changed
    if (mSession.getState() != session.getState())
        return true;

    // Check if accessToken changed
    if (mSession.getAccessToken() != null) {
        if (!mSession.getAccessToken().equals(session.getAccessToken()))
            return true;
    }
    else if (session.getAccessToken() != null) {
        return true;
    }

    // Nothing changed
    return false;
}