如何使用FB SDK 4.0 for Android检查用户是否已登录?

67

几天前我在我的应用中实现了FB登录,今天发现我实现的大部分功能都已经过时。

之前,我使用Session来查看用户是否已登录。然而,这在新的SDK中不起作用。

根据他们的文档,我们可以使用 AccessToken.getCurrentAccessToken()Profile.getCurrentProfile()来检查用户是否已登录,但我无法利用它们。

我尝试了类似这样的东西:

if(AccessToken.getCurrentAccessToken() == null)

我想知道如果我能在这个(也由FB提供)内部使用它,那是否会起作用:

LoginManager.getInstance().registerCallback(callbackManager, new LoginManager.Callback() {...});

然而,我遇到了"Cannot resolve symbol 'Callback'"的问题。

编辑!!!!

好的,我能够通过以下方式检查用户是否已登录:

在onCreate中:

accessTokenTracker = new AccessTokenTracker() {
        @Override
        protected void onCurrentAccessTokenChanged(AccessToken oldAccessToken, AccessToken newAccessToken) {
            updateWithToken(newAccessToken);
        }
    };

然后,调用了我的updateWithToken方法:

private void updateWithToken(AccessToken currentAccessToken) {
    if (currentAccessToken != null) {

            LOAD ACTIVITY A!

    } else {

            LOAD ACTIVITY B!
    }
}

现在的问题是:如果用户以前使用过应用程序并已登录,我可以检查到这一点!但是,如果用户第一次使用该应用程序,则我的AccessTokenTracker从未调用updateWithToken

如果有人能帮忙,我会非常感激。

谢谢!


你尝试过 Session.getActiveSession() 方法吗? - Heshan Sandeepa
2
SDK 4.0 中已经移除了 Session。=/ - Felipe
1
你可以根据更新后的文档尝试使用 AccessTokenTracker。 - Heshan Sandeepa
我知道我必须使用访问令牌,但就像我在问题中提到的那样:我不知道怎么做。 - Felipe
你解决了用户是新用户的问题吗?如果解决了,能告诉我怎么做吗? :) - Dor Dadush
6个回答

142

对于我的情况,有一个更简单的解决方案(我不知道这是否是更优雅的方式):

public boolean isLoggedIn() {
    AccessToken accessToken = AccessToken.getCurrentAccessToken();
    return accessToken != null;
}

8
这应该是被接受的解决方案。同时,我已经仔细确认它没有过期(.isExpired())。 - Andre Figueiredo
8
这对我似乎没有用 —— 即使我已经登录,它仍然是null - u3l
即使我已登录,这仍然是null。 - S-K'
2
有时候 AccessToken.getCurrentAccessToken() 为空的原因是 onCurrentAccessTokenChanged 是异步调用的。你必须等待第一次调用完成后才能使用 AccessToken.getCurrentAccessToken()。 - klimat
如果为空,你需要跟踪访问令牌。https://developers.facebook.com/docs/facebook-login/android/v2.2 - SpyZip
显示剩余2条评论

35

我明白了!

首先,请确保您已初始化您的FB SDK。其次,添加以下内容:

accessTokenTracker = new AccessTokenTracker() {
        @Override
        protected void onCurrentAccessTokenChanged(AccessToken oldAccessToken, AccessToken newAccessToken) {
            updateWithToken(newAccessToken);
        }
    };

当当前访问令牌发生更改时,将调用此方法。这意味着,只有在用户已经登录时,此方法才会对您有所帮助。

接下来,我们将其添加到我们的onCreate()方法中:

updateWithToken(AccessToken.getCurrentAccessToken());

当然,我们的updateWithToken()方法:

private void updateWithToken(AccessToken currentAccessToken) {

    if (currentAccessToken != null) {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                Intent i = new Intent(SplashScreen.this, GeekTrivia.class);
                startActivity(i);

                finish();
            }
        }, SPLASH_TIME_OUT);
    } else {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                Intent i = new Intent(SplashScreen.this, Login.class);
                startActivity(i);

                finish();
            }
        }, SPLASH_TIME_OUT);
    }
}

那对我来说就可以了!=]


2
我正在使用一个不同的片段进行登录,另一个片段用于发布内容,我想知道是否需要将访问令牌保存为全局状态。 - Skynet
这对我不起作用。我正在使用LoginButton,但无法接收任何FB回调。 - Konstantin Konopko
@sirvon 通过将FB登录活动设置为启动活动,问题得到解决。 - Konstantin Konopko
谢谢 - 我在尝试获取FB登录accessToken时遇到了一些问题,而这段代码使其记住我已经登录。 - Simon
在onCreate()之前必须添加accessTokenTracker代码,并且在setContentView()之前必须初始化FB SDK。 - Tara

9

我在使用AccessToken和AccessTokenTracker检查登录状态时遇到了困境,因为当AccessToken准备好并且跟踪器的回调函数被调用时,个人资料可能尚未准备好,因此我无法立即获取或显示Facebook用户的姓名。

我的解决方案是检查当前个人资料!= null,并使用其跟踪器同时获取Facebook用户的姓名:

    ProfileTracker fbProfileTracker = new ProfileTracker() {
        @Override
        protected void onCurrentProfileChanged(Profile oldProfile, Profile currentProfile) {
            // User logged in or changed profile
        }
    };

检查登录状态,然后获取用户名:

Profile profile = Profile.getCurrentProfile();
if (profile != null) {
    Log.v(TAG, "Logged, user name=" + profile.getFirstName() + " " + profile.getLastName());
}

谢谢。Profile.getCurrentProfile(); 对我来说运行良好 :) - Thom

3

您可以使用Felipe在其答案中提到的相同方式,或者使用其他两种方式。但似乎AccessTokenTracker是方便的方法,因为它帮助您跟踪访问令牌(与ProfileTracker类一起使用)

  1. 如果您正在使用自定义按钮进行登录,请使用LoginManager回调函数

例如:

在您的布局xml中

    <Button
        android:id="@+id/my_facebook_button"
        android:background="@drawable/btnfacebook"
        android:onClick="facebookLogin"/>

在你的Activity中
    //Custom Button
    Button myFacebookButton = (Button) findViewById(R.id.my_facebook_button);

按钮 onclick 监听器
public void facebookLogin(View view) {
        LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile", "user_friends"));
    }

在LoginManager回调函数的结尾处

 //Create callback manager to handle login response
        CallbackManager callbackManager = CallbackManager.Factory.create();

       LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
           @Override
           public void onSuccess(LoginResult loginResult) {
               Log.i(TAG, "LoginManager FacebookCallback onSuccess");
               if(loginResult.getAccessToken() != null) {
                   Log.i(TAG, "Access Token:: " + loginResult.getAccessToken());
                   facebookSuccess();
               }
           }

           @Override
           public void onCancel() {
               Log.i(TAG, "LoginManager FacebookCallback onCancel");
           }

           @Override
           public void onError(FacebookException e) {
               Log.i(TAG, "LoginManager FacebookCallback onError");
           }
       });
  1. 如果你正在使用SDK中提供的按钮(com.facebook.login.widget.LoginButton),请使用LoginButton回调函数(这在他们的参考文档中非常详细地说明了-https://developers.facebook.com/docs/facebook-login/android/v2.3)。

例如:

在你的布局xml中:

<com.facebook.login.widget.LoginButton
                android:id="@+id/login_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"/>

在你的活动中
    //Facebook SDK provided LoginButton
    LoginButton loginButton = (LoginButton) findViewById(R.id.login_button);
    loginButton.setReadPermissions("user_friends");
    //Callback registration
    loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
        @Override
        public void onSuccess(LoginResult loginResult) {
            // App code
            Log.i(TAG, "LoginButton FacebookCallback onSuccess");
            if(loginResult.getAccessToken() != null){
                Log.i(TAG, "Access Token:: "+loginResult.getAccessToken());
                facebookSuccess();
            }

        }

        @Override
        public void onCancel() {
            // App code
            Log.i(TAG, "LoginButton FacebookCallback onCancel");
        }

        @Override
        public void onError(FacebookException exception) {
            // App code
            Log.i(TAG, "LoginButton FacebookCallback onError:: "+exception.getMessage());
            Log.i(TAG,"Exception:: "+exception.getStackTrace());
        }
    });

不要忘记在您的Activity的onActivityResult()方法中调用callbackManager.onActivityResult(requestCode, resultCode, data);

1
我已经按照选项2完成了所有步骤。当我点击FB登录按钮并在其活动中点击“确定”后,我的应用程序会重新启动。它首先进入我的闪屏界面,然后将我移动到登录按钮所在的活动界面。但是,FB登录按钮仍然显示为“使用Facebook登录”。有什么想法吗? - RogerSmith
但是当我尝试在从Facebook注销后隐藏按钮时,它没有起作用。 - Anshul Tyagi
@RogerSmith 也无法获取任何 FB 回调。 - Konstantin Konopko
不要忘记在你的 Activity 的 onActivityResult() 中调用 callbackManager.onActivityResult(requestCode, resultCode, data)。 - Mohamed ALOUANE

3
根据Facebook文档,您可以通过以下方式实现此目标:
AccessToken accessToken = AccessToken.getCurrentAccessToken();
boolean isLoggedIn = accessToken != null && !accessToken.isExpired();

1
在Facebook SDK的版本4.25.0中,现在有一个方法,尽管回复有点晚。
public void retrieveLoginStatus(Context context,
                                LoginStatusCallback responseCallback)

该状态说明:

检索用户的登录状态。如果用户已经登录了Facebook for Android应用程序,并且该用户以前登录过该应用程序,则这将返回一个应用访问令牌。如果检索到访问令牌,那么将显示一个消息框告诉用户他们已经登录。

可以像这样使用:

LoginManager.getInstance().retrieveLoginStatus( this, new LoginStatusCallback()
{
    @Override
    public void onCompleted( AccessToken accessToken )
    {
        GraphRequest request = GraphRequest.newMeRequest( accessToken, new GraphRequest.GraphJSONObjectCallback()
        {
            @Override
            public void onCompleted( JSONObject object, GraphResponse response )
            {
                Log.e( TAG, object.toString() );
                Log.e( TAG, response.toString() );

                try
                {
                    userId = object.getString( "id" );
                    profilePicture = new URL( "https://graph.facebook.com/" + userId + "/picture?width=500&height=500" );
                    Log.d( "PROFILE_URL", "url: " + profilePicture.toString() );
                    if ( object.has( "first_name" ) )
                    {
                        firstName = object.getString( "first_name" );
                    }
                    if ( object.has( "last_name" ) )
                    {
                        lastName = object.getString( "last_name" );
                    }
                    if ( object.has( "email" ) )
                    {
                        email = object.getString( "email" );
                    }
                    if ( object.has( "birthday" ) )
                    {
                        birthday = object.getString( "birthday" );
                    }
                    if ( object.has( "gender" ) )
                    {
                        gender = object.getString( "gender" );
                    }

                    Intent main = new Intent( LoginActivity.this, MainActivity.class );
                    main.putExtra( "name", firstName );
                    main.putExtra( "surname", lastName );
                    main.putExtra( "imageUrl", profilePicture.toString() );
                    startActivity( main );
                    finish();
                }
                catch ( JSONException e )
                {
                    e.printStackTrace();
                }
                catch ( MalformedURLException e )
                {
                    e.printStackTrace();
                }

            }
        } );
        //Here we put the requested fields to be returned from the JSONObject
        Bundle parameters = new Bundle();
        parameters.putString( "fields", "id, first_name, last_name, email, birthday, gender" );
        request.setParameters( parameters );
        request.executeAsync();
    }

    @Override
    public void onFailure()
    {
        Toast.makeText( LoginActivity.this, "Could not log in.", Toast.LENGTH_SHORT ).show();
    }

    @Override
    public void onError( Exception exception )
    {
        Toast.makeText( LoginActivity.this, "Could not log in.", Toast.LENGTH_SHORT ).show();
    }
} );

1
根据提供的文档,这似乎只在“用户已登录相同设备上的Facebook Android应用程序”时才有效。恐怕我们不能依赖这个事实。 - zelig74

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