Facebook Android SDK 3.0 всегда возвращает OPENING при входе в систему

Я выполнил инструкции на https://developers.facebook.com/docs/howtos/androidsdk/3.0/login-with-facebook/ . Когда я прикасаюсь к кнопке «Вход», состояние сеанса – ОТКРЫТИЕ – всегда. Когда я пытаюсь опубликовать историю на стене пользователя, я получаю сообщение об ошибке

«Сессия: была сделана попытка запросить новые разрешения для сеанса с ожидающим запрос».

Вот мой код:

public class MainFragment extends Fragment { private static final String TAG = "MainFragment"; private UiLifecycleHelper uiHelper; private Session.StatusCallback callback = new Session.StatusCallback() { @Override public void call(Session session, SessionState state, Exception exception) { onSessionStateChange(session, state, exception); } }; private void onSessionStateChange(Session session, SessionState state, Exception exception) { if (state.isOpened()) { Log.d(TAG, "Logged in..."); } else if (state.isClosed()) { Log.d(TAG, "Logged out..."); } else { Log.d(TAG, "Unknown state: " + state); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); uiHelper = new UiLifecycleHelper(getActivity(), callback); uiHelper.onCreate(savedInstanceState); } @Override public 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's open/closed. Session session = Session.getActiveSession(); if (session != null && (session.isOpened() || session.isClosed())) { onSessionStateChange(session, session.getState(), null); } uiHelper.onResume(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); uiHelper.onActivityResult(requestCode, resultCode, data); } @Override public void onPause() { super.onPause(); uiHelper.onPause(); } @Override public void onDestroy() { super.onDestroy(); uiHelper.onDestroy(); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); uiHelper.onSaveInstanceState(outState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.facebook_login, container, false); LoginButton authButton = (LoginButton) view .findViewById(R.id.authButton); authButton.setFragment(this); return view; } private boolean isSubsetOf(Collection<String> subset, Collection<String> superset) { for (String string : subset) { if (!superset.contains(string)) { return false; } } return true; } private static final List<String> PERMISSIONS = Arrays .asList("publish_actions"); private static final String PENDING_PUBLISH_KEY = "pendingPublishReauthorization"; private boolean pendingPublishReauthorization = false; public void publishStory() { Session session = Session.getActiveSession(); if (session != null) { // Check for publish permissions List<String> permissions = session.getPermissions(); if (!isSubsetOf(PERMISSIONS, permissions)) { pendingPublishReauthorization = true; Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest( this, PERMISSIONS); session.requestNewPublishPermissions(newPermissionsRequest); return; } Bundle postParams = new Bundle(); postParams.putString("name", "Facebook SDK for Android"); postParams.putString("caption", "Build great social apps and get more installs."); postParams .putString( "description", "The Facebook SDK for Android makes it easier and faster to develop Facebook integrated Android apps."); postParams.putString("link", "https://developers.facebook.com/android"); postParams .putString("picture", "https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png"); Request.Callback callback = new Request.Callback() { public void onCompleted(Response response) { JSONObject graphResponse = response.getGraphObject() .getInnerJSONObject(); String postId = null; try { postId = graphResponse.getString("id"); } catch (JSONException e) { Log.i(TAG, "JSON error " + e.getMessage()); } FacebookRequestError error = response.getError(); if (error != null) { Toast.makeText(getActivity().getApplicationContext(), error.getErrorMessage(), Toast.LENGTH_SHORT) .show(); } else { Toast.makeText(getActivity().getApplicationContext(), postId, Toast.LENGTH_LONG).show(); } } }; Request request = new Request(session, "me/feed", postParams, HttpMethod.POST, callback); RequestAsyncTask task = new RequestAsyncTask(request); task.execute(); } } } 

Что не так?

Edit: Я также хотел бы упомянуть, что текст в «Log In» -Button не изменяется. Я не получаю сообщение об ошибке при аутентификации, но, насколько я понимаю, он должен измениться на «Выход».

Solutions Collecting From Web of "Facebook Android SDK 3.0 всегда возвращает OPENING при входе в систему"

Это было нелегко понять. 🙂

Если вы действительно проверяете exception в onSessionStateChange() , вы увидите, что на самом деле это не просто застряло в OPENING . Это исключение содержит: java.lang.UnsupportedOperationException: сеанс: была предпринята попытка открыть сеанс с ожидающим запрос.

Причина, по которой я наконец нашел, заключалась в том, что onActivityResult() не был вызван. Это его обязанность перезвонить uiHelper и этот вызов вызовет окончательную часть входа, поэтому, если он не вызывается, состояние остается OPENING навсегда. Помимо очевидных советов выше, это то, что я нашел, и все они необходимы для входа в систему:

Убедитесь, что вы используете как фрагмент, так и действие, как описано в документации FB. Даже если док намекает на активность, это не так. Вам нужны оба, даже если активность не имеет ничего, кроме вызова одного фрагмента.

Убедитесь, что у вас нет истории для активности (ни в манифесте, ни в коде).

Убедитесь, что вы переопределили onActivityResult() в соответствии с документацией. И убедитесь, что вы переопределяете то же самое в своей деятельности:

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

Да, это кажется странным, но без него это не сработает.

Наконец, это работает для меня. Ключевыми моментом было добавить

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

а также

  loginBtn.setFragment(this); loginBtn.setUserInfoChangedCallback(new LoginButton.UserInfoChangedCallback() { @Override public void onUserInfoFetched(GraphUser user) { graphUser = user; } }); 

Код внутри фрагмента:

 private GraphUser graphUser; private UiLifecycleHelper uiHelper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); uiHelper = new UiLifecycleHelper(getActivity(), callback); uiHelper.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.test_frame, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); view.findViewById(R.id.getMeBtn).setOnClickListener(this); LoginButton loginBtn = (LoginButton) view.findViewById(R.id.loginBtn); loginBtn.setFragment(this); loginBtn.setUserInfoChangedCallback(new LoginButton.UserInfoChangedCallback() { @Override public void onUserInfoFetched(GraphUser user) { graphUser = user; } }); } @Override public void onResume() { super.onResume(); uiHelper.onResume(); updateUI(); } @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); uiHelper.onActivityResult(requestCode, resultCode, data); } @Override public void onPause() { super.onPause(); uiHelper.onPause(); } @Override public void onDestroy() { super.onDestroy(); uiHelper.onDestroy(); } private Session.StatusCallback callback = new Session.StatusCallback() { @Override public void call(Session session, SessionState state, Exception exception) { onSessionStateChange(session, state, exception); } }; private void onSessionStateChange(Session session, SessionState state, Exception exception) { updateUI(); } private void updateUI() { if (graphUser != null) { Log.d("TEST", graphUser.getFirstName()); } } @Override public void onClick(View view) { Session session = Session.getActiveSession(); Log.d("TEST", "session.getState() = " + session.getState()); if (session.getState().isOpened()) { Request.executeMeRequestAsync(session, new Request.GraphUserCallback() { @Override public void onCompleted(GraphUser user, Response response) { if (user != null) { updateUI(); } } }); } } 

Я была такая же проблема. Государство всегда OPENING . Оказывается, @Gabor был против.

Когда состояние сеанса onActivityResult метод onActivityResult , это точно.

Если вы используете фрагмент, onActivityResult вызывается в ACTIVITY, который содержит фрагмент, а не в фрагменте. Это связано с принятым контекстом и т. Д.

Поэтому я сделал это так:

  1. Проверьте, какие onActivityResults вызываются (по logcat) – просто чтобы убедиться

  2. В этом методе добавьте строку Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data); Обратите внимание, что этот параметр является контекстом активности.

    ИЛИ

    Используйте метод UiLifecycleHelper для onActivityResult , например: UiHelper.onActivityResult(requestCode, resultCode, data); Подробнее об этом здесь

Если у кого-то еще есть эта проблема, это может быть вызвано переопределением onActivityResult в Activity и не вызовом метода super.

Мероприятия

 protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { /* other code here */ super.onActivityResult(requestCode, resultCode, data); } 

Фрагмент

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

Вы должны реализовать onActivityResult в активности, а не в фрагменте. Работал для меня.

Еще одна причина, по которой это может произойти (как это имеет место для меня), – это когда вы используете getChildFragmentManager() – onActivityResult не передается во вложенные фрагменты из- за ошибки . Это то, что помогло мне (имея хостинг Fragment передать его полученный onActivityResult для всех детей).

onActivityResult моей активности вызывается … Итак, я сделал очень плохой взлом:

 public void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == 64206) //Bad hacking if(df!=null) df.onActivityResult(requestCode, resultCode, data); 

Df – мой фрагмент. Это заставило сессию разобраться … это безумно безумно. Очень интересно найти лучшее решение для этого.

В моем случае я пытался изменить класс фрагмента из android.support.v4.app.Fragment в android.app.Fragment (я не поддерживал версии для Android версии до версии API-11) и опустил FBAuthButton.setFragment(this); заявление. Это фактически вызвало проблему.

У меня возникла та же проблема: я удалил приложение и переустановил его, и он сработал!