如何在不使用Facebook登录/注销按钮的情况下,以编程方式从Facebook SDK 3.0中注销?

80

标题已经说明了一切。我正在使用自定义按钮来获取用户的Facebook信息(用于“注册”目的)。然而,我不希望应用程序记住上一个已注册的用户,也不希望通过Facebook原生应用程序当前登录的人员。我希望Facebook登录活动每次都会弹出。这就是为什么我想编程方式注销任何先前的用户。

我该怎么做?这是我登录的方式:

private void signInWithFacebook() {

    SessionTracker sessionTracker = new SessionTracker(getBaseContext(), new StatusCallback() 
    {
        @Override
        public void call(Session session, SessionState state, Exception exception) { 
        }
    }, null, false);

    String applicationId = Utility.getMetadataApplicationId(getBaseContext());
    mCurrentSession = sessionTracker.getSession();

    if (mCurrentSession == null || mCurrentSession.getState().isClosed()) {
        sessionTracker.setSession(null);
        Session session = new Session.Builder(getBaseContext()).setApplicationId(applicationId).build();
        Session.setActiveSession(session);
        mCurrentSession = session;
    }

    if (!mCurrentSession.isOpened()) {
        Session.OpenRequest openRequest = null;
        openRequest = new Session.OpenRequest(RegisterActivity.this);

        if (openRequest != null) {
            openRequest.setPermissions(null);
            openRequest.setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK);

            mCurrentSession.openForRead(openRequest);
        }
    }else {
        Request.executeMeRequestAsync(mCurrentSession, new Request.GraphUserCallback() {
              @Override
              public void onCompleted(GraphUser user, Response response) {
                  fillProfileWithFacebook( user );
              }
            });
    }
}

理想情况下,我会在这个方法的开头打电话注销任何以前的用户。

9个回答

161

最新SDK更新:

现在针对Facebook SDK v4.7+,@zeuter的答案是正确的:

LoginManager.getInstance().logOut();

原始回答:

请勿使用SessionTracker。它是一个内部(包私有)类,不应作为公共API的一部分被使用。因此,它的API可能随时更改,而没有任何向后兼容性的保证。您应该能够摆脱所有SessionTracker的实例,并仅使用活动会话。

回答您的问题,如果您不想保留任何会话数据,请在应用程序关闭时调用closeAndClearTokenInformation


3
你只需要调用Session.getActiveSession方法,如果它返回null,那么你可以选择1.)使用Session.Builder创建一个新的Session并调用Session.setActiveSession方法,或者2.)调用其中一个Session.openActiveSession方法(静态方法,同时为你打开和设置活动会话)。 - Ming Li
24
你需要打开一个会话才能注销,这表明Facebook SDK的设计非常糟糕...它没有提供简单的公共API和标准回调函数,而是使用了一个糟糕的机制...真让人惊讶。 - Martin Marconcini
18
Facebook的SDK和文档糟糕透了! - Skynet
3
官方Facebook文档中的示例代码已经过时,我们需要参考旧版堆栈以取消使其过时。 - Skynet
1
与其添加没有贡献的评论,你应该给出具体的例子来说明文档缺失(与问题/答案有关),或者你可以到开发者门户网站上特定文档页面的底部,点击“否”按钮以表示“这篇文档有帮助吗?” - Ming Li
显示剩余4条评论

87

这种方法将帮助你在安卓设备上以编程方式注销 Facebook。

/**
 * Logout From Facebook 
 */
public static void callFacebookLogout(Context context) {
    Session session = Session.getActiveSession();
    if (session != null) {

        if (!session.isClosed()) {
            session.closeAndClearTokenInformation();
            //clear your preferences if saved
        }
    } else {

        session = new Session(context);
        Session.setActiveSession(session);

        session.closeAndClearTokenInformation();
            //clear your preferences if saved

    }

}

3
在我使用片段而不是活动的情况下,这是唯一可行的工作解决方案! - Roger Alien
为什么代码中要有else部分?如果用户没有登录,为什么需要再次登录然后注销? - Vihaan Verma
1
出现错误java.lang.NullPointerException:参数“applicationId”不能为空。 - Krunal Shah
我认为初始化会话的适当方式是 new Session.Builder(context).build();。 - hasan

66

自从Facebook的Android SDK v4.0(详见变更日志),您需要执行以下操作:

LoginManager.getInstance().logOut();

8
谢谢,但我并没有看到这实际上清除了会话。LoginManager.logout()只是在内部调用“AccessToken.setCurrentAccessToken(null); Profile.setCurrentProfile(null);”。我发现用户仍然可以登录而无需在下次启动应用程序时重新输入凭据。你如何强制用户重新输入他们的凭据? - swooby
这个方法帮了我大忙。在调用它并尝试重新登录后,出现了一个输入凭据的屏幕,正如预期的那样。非常感谢。 - Zsolt Boldizsar
1
正如@swooby所指出的那样,这个解决方案不幸地不能在使用Facebook SDK v4.x的应用程序上运行。在进行了logOut之后,AccessToken变成了[{AccessToken token:ACCESS_TOKEN_REMOVED permissions:[public_profile]}],但是即使用户已经注销或撤销了对该应用程序的授权,AccessToken.getCurrentAccessToken().getToken()仍会返回有效的令牌字符串。 - Lisitso
@Lisitso,你现在有解决方案吗? - Jaec
1
@Jaec 我使用了“Aniket Thakur”提供的解决方案。你可以在其他回答中找到它。干杯! - Lisitso
@swooby 我在注销时也遇到了同样的问题。我想在从 Facebook 注销时删除凭据。你解决了这个问题吗? - sersem1

27

这是一个代码片段,它允许我从 Facebook 上编程注销。如果您发现任何需要改进的地方,请告诉我。

private void logout(){
    // clear any user information
    mApp.clearUserPrefs();
    // find the active session which can only be facebook in my app
    Session session = Session.getActiveSession();
    // run the closeAndClearTokenInformation which does the following
    // DOCS : Closes the local in-memory Session object and clears any persistent 
    // cache related to the Session.
    session.closeAndClearTokenInformation();
    // return the user to the login screen
    startActivity(new Intent(getApplicationContext(), LoginActivity.class));
    // make sure the user can not access the page after he/she is logged out
    // clear the activity stack
    finish();
}

什么是jpotter6 mApp? - Amitsharma
任何 Android 应用程序中都可用的 Application 类的实例。 - Eenvincible

14

自Facebook的Android SDK v4.0版本开始,您需要执行以下操作:

LoginManager.getInstance().logOut();

这还不够。这只会清除缓存的访问令牌和个人资料,以便AccessToken.getCurrentAccessToken()Profile.getCurrentProfile() 现在变成 null。

要完全注销登录,您需要撤销权限,然后调用 LoginManager.getInstance().logOut();。要撤销权限,请执行以下图形 API:

    GraphRequest delPermRequest = new GraphRequest(AccessToken.getCurrentAccessToken(), "/{user-id}/permissions/", null, HttpMethod.DELETE, new GraphRequest.Callback() {
        @Override
        public void onCompleted(GraphResponse graphResponse) {
            if(graphResponse!=null){
                FacebookRequestError error =graphResponse.getError();
                if(error!=null){
                    Log.e(TAG, error.toString());
                }else {
                    finish();
                }
            }
        }
    });
    Log.d(TAG,"Executing revoke permissions with graph path" + delPermRequest.getGraphPath());
    delPermRequest.executeAsync();

2
这是这个问题的正确答案。LoginManager.getInstance().logOut();只清除本地缓存,而GraphRequest调用以编程方式撤销应用程序对用户Facebook帐户的访问权限。两者都是必要的。单独使用任何一个都不足够。 - Yash Sampat
我们在哪里放置这个删除权限的代码?!我的代码没有起作用!您能提供完整的代码片段吗,先生?! - Akshay Shinde
代码可以运行,但是会出现警告:请求没有访问令牌,缺少应用程序ID或客户端令牌。我需要在上面的代码中添加一些内容到“/{user-id}/permissions/”吗? - zeeshan
@zeeshan,请将 {user-id} 替换为我。 - Amritpal singh

8

Session类已在SDK 4.0中删除。登录管理现在通过LoginManager类完成。因此:

mLoginManager = LoginManager.getInstance();
mLoginManager.logOut();

根据参考升级到SDK 4.0,文中表示:

Session Removed - AccessToken、LoginManager和CallbackManager类代替并取代了Session类的功能。


1
zeuter的回答更短,同时指出了同样的API调用。为什么会有重复? - rekire

3

是的,正如@luizfelippe所提到的那样,自从SDK 4.0以后Session类已经被移除了。我们需要使用LoginManager。

我刚刚查看了LoginButton类的注销方法。他们进行了这种检查。只有当accessToken不为空时才会注销。因此,我认为在我们的代码中也最好这样做。

AccessToken accessToken = AccessToken.getCurrentAccessToken();
if(accessToken != null){
    LoginManager.getInstance().logOut();
}

zeuter的回答更短,并且指出了相同的API调用。为什么会有重复? - rekire

0
private Session.StatusCallback statusCallback = new SessionStatusCallback();

logout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Session.openActiveSession(this, true, statusCallback);  
}
});

private class SessionStatusCallback implements Session.StatusCallback {
@Override
public void call(Session session, SessionState state,
Exception exception) {
session.closeAndClearTokenInformation();    
}
}

0

Facebook 提供了两种登录和注销帐户的方式。一种是使用 LoginButton,另一种是使用 LoginManager。LoginButton 只是一个按钮,点击后完成登录。而 LoginManager 则自动完成此操作。在您的情况下,您需要使用 LoginManager 自动注销。

LoginManager.getInstance().logout() 可以为您完成此操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接