facebook login callback fires multiple times

2019-02-05 05:39发布

问题:

My app is having Share button to share story on users timeline. What I'm doing is, user taps on Share button, if user session is not present app forces to Login user with Facebook. When user do that, story directly need to be published. Here's my code.

onCreate Method

    isShared = false;
    uiHelper = new UiLifecycleHelper(this, statusCallback);
    uiHelper.onCreate(savedInstanceState);
    Settings.addLoggingBehavior(LoggingBehavior.INCLUDE_ACCESS_TOKENS);
    Session session = Session.getActiveSession();
    if (session == null) {

        if (savedInstanceState != null) {
            session = Session.restoreSession(this, null, statusCallback,
                    savedInstanceState);
        }
        if (session == null) {
            session = new Session(this);
        }
        Session.setActiveSession(session);
        if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
            session.openForRead(new Session.OpenRequest(this)
                    .setCallback(statusCallback));
        }
    }       

    if (savedInstanceState != null) {
        pendingPublishReauthorization = savedInstanceState.getBoolean(
                PENDING_PUBLISH_KEY, false);
    }

    shareBtn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View arg0) {
            doPostStory();                              
        }
    });

And remaining code is -

    private void doPostStory() {
    Session session = Session.getActiveSession();
    if (!session.isOpened() && !session.isClosed()) {
        session.openForRead(new Session.OpenRequest(this)
                .setCallback(statusCallback));
    } else {
        isShared = true;
        Session.openActiveSession(this, true, statusCallback);
        publishStory();         
    }
}

private class SessionStatusCallback implements Session.StatusCallback {
    @Override
    public void call(Session session, SessionState state,
            Exception exception) {
        if(!isShared){
            updateView();
            isShared = true;
        }
    }
}

private void updateView() {
    Session session = Session.getActiveSession();
    if (session.isOpened()) {
        if(!isShared){
            publishStory();
        }
        Log.i("Session State callback", "Logged in");
    } else {
        Log.i("Session State Callback", "Logged Out");                      
    }
}   

@Override
public void onStart() {
    super.onStart();
    Session.getActiveSession().addCallback(statusCallback);
}

@Override
public void onStop() {
    super.onStop();
    Session.getActiveSession().removeCallback(statusCallback);
}

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

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Session session = Session.getActiveSession();
    Session.saveSession(session, outState);
    outState.putBoolean(PENDING_PUBLISH_KEY, pendingPublishReauthorization);
    uiHelper.onSaveInstanceState(outState);
}

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

@Override
public void onResume() {
    super.onResume();
    uiHelper.onResume();
}

Code for publishStory()

    private 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", "Some");
        postParams.putString("caption",updateTitle);
        postParams.putString("description",updateText);
        postParams.putString("link","http://somedomain.com");
        postParams.putString("picture","someurl");

        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("asd", "JSON error " + e.getMessage());
                }
                FacebookRequestError error = response.getError();
                if (error != null) {
                    Toast.makeText(UpdateDetails.this,
                            error.getErrorMessage(), Toast.LENGTH_SHORT)
                            .show();
                } else {
                    Toast.makeText(UpdateDetails.this, postId,
                            Toast.LENGTH_LONG).show();
                }
            }
        };

        Request request = new Request(session, "me/feed", postParams,
                HttpMethod.POST, callback);

        RequestAsyncTask task = new RequestAsyncTask(request);
        task.execute();
    } else {
        Log.i("Session Sate", "close");
    }

}

Code does post story on users timeline. But it is posting multiple times. That means, statusCallbackgetting fired multiple times. I tried setting flags to check status of story post. But still it post several times.

Any ideas what's wrong with this code ? Help is highly appreciated.

PS : I don't need Login Button separately. What I want is, user taps on Share button, if logged in it need to post story else log in user and next directly post the story.

回答1:

remove all the publishStory() calling. in your callback do this:

public void call(Session session, SessionState state,
        Exception exception) {
    if(session != null && session.isOpened() && isShared){
       publishStory();
    }
}

in your UpdateDetails class declare isShared as boolean isShared = false; and when user tap on share button make it true, like:

shareBtn.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View arg0) {
        isShared = true;
        doPostStory();                              
    }
});

in your publishStorys onComplete make isShared false. like:

public void onCompleted(Response response) {
    isShared = false;
    ...................
    ...................
}

hope this will help.



回答2:

Create Facebook Session Object
Then Just Apply This in onCreate Method.

 Session.openActiveSession(this, true, new Session.StatusCallback() {

        // callback when session changes state
        @Override
        public void call(Session session, SessionState state,
                Exception exception) {
            if (session.isOpened()) {

                // make request to the /me API
                Request.newMeRequest(session,
                        new Request.GraphUserCallback() {

                            // callback after Graph API response with user
                            // object
                            @Override
                            public void onCompleted(GraphUser user,
                                    Response response) {
                                FacebookLoginActivity.this.progressDialog = ProgressDialog
                                        .show(YourActivity.this,
                                                "",
                                                "",
                                                true);
                                if (user != null) {

                                   Intent passIntent = new Intent(YourActivity.this,Second.class)
                                   startActivity(passIntent)
                                }
                            }
                        }).executeAsync();

            }
        }
    });