Токен доступа Facebook потерян после перезапуска приложения

Я работаю с Facebook SDK 4.0 и использую встроенную кнопку LoginButton. У меня есть Fragment, который содержит LoginButton, и другой, который просто содержит TextBox.

Вот фрагмент кода из Fragment :

public class LoginFragment extends Fragment {

private OnLoginFragmentInteractionListener mListener;
LoginButton loginButton;
CallbackManager callbackManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
    }

    callbackManager = CallbackManager.Factory.create();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_login, container, false);

    loginButton = (LoginButton) view.findViewById(R.id.login_button);

    // If using in a fragment
    loginButton.setFragment(this);

    // Callback registration
    loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
        @Override
        public void onSuccess(LoginResult loginResult) {
            Toast.makeText(getActivity(), "Logged in successfully.", Toast.LENGTH_SHORT).show();
            onLoginEvent(true);
        }
        @Override
        public void onCancel() {
            Toast.makeText(getActivity(), "Login canceled.", Toast.LENGTH_SHORT).show();
            onLoginEvent(false);
        }
        @Override
        public void onError(FacebookException exception) {
            Toast.makeText(getActivity(), "Failed to log in. Please try again.", Toast.LENGTH_SHORT).show();
            onLoginEvent(false);
        }
    });

    return view;
}

public void onLoginEvent(boolean loginSuccess) {
    if (mListener != null) {
        mListener.onLoginFragmentInteraction(loginSuccess);
    }
}

public interface OnLoginFragmentInteractionListener {
    public void onLoginFragmentInteraction(boolean onLoginSuccess);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    callbackManager.onActivityResult(requestCode, resultCode, data);
}
}

Активность выглядит примерно так:

public class LoginActivity extends ActionBarActivity implements
    LoginFragment.OnLoginFragmentInteractionListener, TestFragment.OnFragmentInteractionListener {

static final String TAG = "LoginActivity";

private LoginFragment loginFragment;
private TestFragment testFragment;
private AccessToken accessToken;
private AccessTokenTracker accessTokenTracker;
private Profile fbProfile;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);

    FacebookSdk.sdkInitialize(getApplicationContext());

    if (savedInstanceState == null) {
        // Add the fragment on initial activity setup
        Log.d(TAG, "Bundle = null, isLoggedIn() = " + isLoggedIn());
        if (isLoggedIn()) {
            testFragment = new TestFragment();
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, testFragment).commit();
        } else {
            loginFragment = new LoginFragment();
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, loginFragment).commit();
        }
    } else {
        // Or set the fragment from restored state info
        Fragment frag = getSupportFragmentManager()
                .findFragmentById(R.id.fragment_container);
        if (frag instanceof LoginFragment) {
            Log.d(TAG, "Bundle != null, fragment = LoginFragment");
            loginFragment = (LoginFragment) frag;
        }
        else if (frag instanceof TestFragment) {
            Log.d(TAG, "Bundle != null, fragment = TestFragment");
            testFragment = (TestFragment) frag;
        }
    }
}


@Override
public void onLoginFragmentInteraction(boolean loginSuccess) {
    updateUI(loginSuccess);
}

public void updateUI(boolean loggedIn) {
    // User is logged in, show the main fragment
    if (loggedIn) {
        testFragment = new TestFragment();
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, testFragment).commit();
    }
    // User is logged out, show the login fragment
    else {
        loginFragment = new LoginFragment();
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, loginFragment).commit();
    }
}

public boolean isLoggedIn() {
    accessToken = AccessToken.getCurrentAccessToken();
    if (accessToken != null && !accessToken.isExpired())
        return true;
    else
        return false;
}
}

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

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

Когда пользователь впервые входит в систему, он работает как положено. Но проблема, с которой я сталкиваюсь, заключается в том, что если я убью приложение или удалю его из списка «Недавние», я потеряю токен доступа. AccessToken.getCurrentAccessToken() всегда возвращает ноль. Разве это не правильный способ справиться с этим?


person akshayt23    schedule 17.05.2015    source источник


Ответы (2)


Как вы упомянули в своем комментарии. Вы должны проверить, что пользователь вошел в систему, когда FacebookSDK завершил инициализацию.
Проблема в вашем случае заключается в том, что вы проверили AccessToken, когда SDK еще не завершил инициализацию. Чтобы решить эту проблему, проверьте AcessToken в методе onInitialized() FacebookSdk.InitializeCallback, который вызывается при инициализации SDK.

FacebookSdk.sdkInitialize(getApplicationContext(), new FacebookSdk.InitializeCallback() {
    @Override
    public void onInitialized() {
        if (isLoggedIn()) {
            ..............
        }
    }
});
person Jason Vo    schedule 18.10.2015
comment
Пожалуйста, попробуйте ответить на весь вопрос. Как насчет Но проблема, с которой я столкнулся, заключается в том, что если я убью приложение или удалю его из списка «Недавние», я потеряю токен доступа. ? - person Bö macht Blau; 18.10.2015
comment
Я тестировал и даже перезапускал эмулятор, и этот код работал. Вы пробовали это? - person Jason Vo; 18.10.2015
comment
Я думаю, хорошо, что вы протестировали свое решение. Гораздо лучше, чем попробовать этот вариант :) Сказав это, я вижу, что вы ввели обратный вызов там, где его раньше не было. Моя проблема остается: ссылка от пользователя 2558050 больше похожа на исходный код проблемы (без обратного вызова), поэтому, если бы вы могли объяснить свое решение в дополнение к публикации фрагмента кода, тогда люди вроде меня (никогда ничего не делали с facebook SDK) поняли бы лучше, почему они могут сделать это по-твоему. - person Bö macht Blau; 18.10.2015
comment
В комментарии пользователя @user2558050 здесь stackoverflow.com/a/30288238/5460059. Вы можете увидеть, как FacebookSDK сохраняет и устанавливает AccessToken и Profile во время инициализации. Проблема в данном случае в том, что он проверил AccessToken, когда SDK еще не закончил инициализацию. Чтобы решить эту проблему, проверьте AcessToken в методе onInitialized() FacebookSdk.InitializeCallback, который вызывается при инициализации SDK. - person Jason Vo; 19.10.2015
comment
Кроме того, если вы используете более новую версию модуля входа в систему (инициализация неявна при запуске приложения) и проверяете вход в систему на чем-то вроде заставки, вы можете захотеть отложить проверку того, действителен ли токен доступа, на пару сотен миллисекунд. . - person Karan Modi; 12.12.2019

Когда вход в систему будет успешным, сохраните токен доступа где-нибудь. В базу данных или в общие настройки. Когда ваше приложение запускается, проверьте, есть ли токен доступа и действителен ли он.

person ferdinand    schedule 17.05.2015
comment
Согласно официальной документации: FacebookSDK сохраняет эти данные в общих настройках и устанавливает их во время инициализации SDK. Вы можете увидеть, вошел ли человек уже в систему, проверив AccessToken.getCurrentAccessToken(). developers.facebook.com/docs/facebook-login/android/ Разве это не должно обрабатываться автоматически? - person akshayt23; 17.05.2015