简体   繁体   English

Facebook Android SDK 3.0在登录时始终返回OPENING

[英]Facebook Android SDK 3.0 always returns OPENING when logging in

I followed the instructions at https://developers.facebook.com/docs/howtos/androidsdk/3.0/login-with-facebook/ . 我按照https://developers.facebook.com/docs/howtos/androidsdk/3.0/login-with-facebook/上的说明进行操作。 When I touch the "Log In"-button, the session state is OPENING - always. 当我触摸“登录”按钮时,会话状态是打开 - 始终。 When I try to post a story to the user's wall I get an error stating 当我尝试将故事发布到用户的墙上时,我收到错误消息

"Session: an attempt was made to request new permissions for a session that has a pending request." “会话:尝试为具有待处理请求的会话请求新权限。”

Here is my code: 这是我的代码:

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();
        }

    }
}

What's wrong? 怎么了?

Edit: I'd also like to mention that the text on the "Log In"-Button doesn't change. 编辑:我还想提一下“登录”-Button上的文字不会改变。 I don't get an error while authenticating, but as far as I read it should change to "Log Out". 我在验证时没有收到错误,但据我所知,它应该更改为“Log Out”。

It wasn't easy to figure this out. 弄清楚这一点并不容易。 :-) :-)

If you actually check out exception in onSessionStateChange() , you'll see that it's not really simply stuck in OPENING . 如果您实际检查onSessionStateChange() exception ,您会发现它并非真正停留在OPENING That exception contains: java.lang.UnsupportedOperationException: Session: an attempt was made to open a session that has a pending request. 该异常包含: java.lang.UnsupportedOperationException:Session:尝试打开具有挂起请求的会话。

The reason I finally found was that onActivityResult() wasn't called. 我最终发现的原因是没有调用onActivityResult() It's its responsibility to call back to uiHelper and that call will call the finishing part of the login, so it if isn't called, the state stays OPENING forever. 它有责任回电给uiHelper并且该呼叫将调用登录的完成部分,因此如果没有被调用,状态将永远保持OPENING状态。 Apart from the obvious pieces of advice above, this is what I found and they are all needed for the login to work: 除上述建议的明显的碎片,这是我发现了什么,他们需要登录到工作:

Make sure you use both a fragment and an activity, as described in the FB documentation. 确保同时使用片段和活动,如FB文档中所述。 Even if the doc hints at an activity being enough, it isn't. 即使文档暗示某项活动足够,但事实并非如此。 You need both even if the activity has nothing else but calling the single fragment. 即使活动只有调用单个片段,你也需要两者。

Make sure you have no history set for the activity (neither in the manifest nor in code). 确保没有为活动设置历史记录(清单和代码中都没有)。

Make sure you override the fragment's onActivityResult() as per the documentation. 确保根据文档覆盖片段的onActivityResult() And make sure you override the same in the activity as well: 并确保在活动中覆盖相同的内容:

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

Yes, this seems strange but it doesn't work without it. 是的,这看起来很奇怪但没有它就行不通。

Finally this works for me. 最后这对我有用。 The key points was to add 关键点是补充

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

and

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

Code inside Fragment: 片段内的代码:

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();
                }
            }
        });
    }
}

I had the same issue. 我遇到过同样的问题。 The state was always OPENING . 国家总是OPENING Turns out that @Gabor was wright. 事实证明@Gabor是怀疑的。

When the session state is OPENING a method onActivityResult gets called, that's for sure. 当会话状态为OPENING一个方法onActivityResult被调用, 这是肯定的。

If you are using a fragment, onActivityResult is called in the ACTIVITY that holds the fragment, and not in the fragment. 如果您正在使用片段,则在包含片段的ACTIVITY中调用onActivityResult ,而不是在片段中调用。 That is due to the passed context etc. 那是由于传递的背景等。

So i did it like this: 所以我这样做了:

  1. Check what onActivityResults gets called (by logcat) - just to make sure 检查onActivityResults被调用的内容(通过logcat) - 只是为了确保

  2. In that method add a line Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data); 在该方法中添加一行Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data); Notice that the parameter this is an activity context. 请注意,参数this是活动上下文。

    OR 要么

    Use the UiLifecycleHelper 's onActivityResult method, like this: UiHelper.onActivityResult(requestCode, resultCode, data); 使用UiLifecycleHelperonActivityResult方法,如下所示: UiHelper.onActivityResult(requestCode, resultCode, data); More about it here 更多关于它的信息

If anyone else is still having this issue it can be caused by overriding onActivityResult in the Activity and not calling the super method. 如果其他人仍然遇到此问题,可能是由于重写了Activity中的onActivityResult而没有调用super方法。

Activity 活动

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

Fragment 分段

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

You should implement onActivityResult in the activity not in the fragment. 您应该在不在片段中的活动中实现onActivityResult Worked for me. 为我工作。

Yet another reason this might occur (as it has for me) is when you're using getChildFragmentManager() - onActivityResult is not passed to nested Fragments, due to a bug . 这可能发生的另一个原因(就像它对我来说)是当你使用getChildFragmentManager() - 由于一个bug ,onActivityResult没有传递给嵌套的Fragments。 This (having the hosting Fragment pass its received onActivityResult to all children) is what helped me. 这个 (托管片段将其收到的onActivityResult传递给所有孩子)对我有所帮助。

My Activity's onActivityResult is being invoked... So I did a very very bad hacking there: 正在调用我的Activity的onActivityResult ...所以我在那里做了非常糟糕的黑客攻击:

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

df is my fragment. df是我的片段。 That made the session get open... this is friggin crazy. 这使得会议开放......这太疯狂了。 Very interested to find a better solution for this. 非常有兴趣为此找到更好的解决方案。

In my case, I was trying to change the fragment class from android.support.v4.app.Fragment to android.app.Fragment (I was not supporting pre API-11 Android versions) and omitted the FBAuthButton.setFragment(this); 在我的例子中,我试图将片段类从android.support.v4.app.Fragment更改为android.app.Fragment (我不支持API-11之前的Android版本)并省略了FBAuthButton.setFragment(this); statement. 声明。 That was actually causing the problem. 这实际上是造成了这个问题。

我遇到了同样的问题,我卸载了我的应用程序并重新安装,它工作了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM