在没有登录按钮的情况下进行Facebook身份验证

52

我已经跟随一些Facebook API 3.0教程,包括登录/注销和发布到Feed的示例。所以登录方式如下:

  1. 应用程序打开,显示一个片段,其中显示登录按钮
  2. 用户点击登录,通过引用的FacebookSDK库(com.facebook.widget.LoginActivity)和提供的代码使用会话进行身份验证。
  3. 用户被重定向到下一个屏幕

我不想让用户以这种方式登录。我希望他们在没有任何登录/注册的情况下使用我的应用程序,然后如果他们点击Facebook特定功能,例如在Facebook上分享笔记,则应用程序应该询问他们是否允许Facebook使用他们的应用程序或其他内容(通常都会出现)。如果没有这个操作,因为没有进行登录,publishFeedDialog()函数将返回nullpointer。

那么我的问题是,我如何忽略带有登录按钮的SplashFragment,因此当用户在我的应用程序中单击Facebook功能时,不会显示新屏幕并显示登录按钮,而只会出现用户习惯的默认Facebook身份验证窗口?


你找到解决方案了吗?我也遇到了同样的问题。 - Anirudh
我也是,请问 @erdomester 有什么新消息吗? - akohout
我认为我们做了一些变通,但我已经不再参与那个项目了。 - erdomester
7个回答

99

@erdomester, @sromku

Facebook发布了新的SDK版本4.x,其中Session已过时

现在有一种新的Facebook登录概念

LoginManager和AccessToken - 这些新类执行Facebook登录

所以,现在您可以在没有登录按钮的情况下访问Facebook身份验证

layout.xml

    <Button
            android:id="@+id/btn_fb_login"
            .../>

主活动界面.java

private CallbackManager mCallbackManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    FacebookSdk.sdkInitialize(this.getApplicationContext());

    mCallbackManager = CallbackManager.Factory.create();

    LoginManager.getInstance().registerCallback(mCallbackManager,
            new FacebookCallback<LoginResult>() {
                @Override
                public void onSuccess(LoginResult loginResult) {
                    Log.d("Success", "Login");

                }

                @Override
                public void onCancel() {
                    Toast.makeText(MainActivity.this, "Login Cancel", Toast.LENGTH_LONG).show();
                }

                @Override
                public void onError(FacebookException exception) {
                    Toast.makeText(MainActivity.this, exception.getMessage(), Toast.LENGTH_LONG).show();
                }
            });

    setContentView(R.layout.activity_main);

    Button btn_fb_login = (Button)findViewById(R.id.btn_fb_login);

    btn_fb_login.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
              LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile", "user_friends"));
        }
    });

}

编辑

如下内容未添加,此方法将无法正常工作(由@Daniel Zolnai在下面的评论中指出):

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(mCallbackManager.onActivityResult(requestCode, resultCode, data)) {
        return;
    }
}

我几天前发现了新的SDK,我必须说这真是一件解脱的事情,终于Facebook团队开发了可以使用的东西。每个人都应该更新到新的SDK。 - erdomester
7
这对我来说运作良好。如果您的回调未被调用,请检查是否已添加以下内容:@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); callbackManager.onActivityResult(requestCode, resultCode, data); } - Daniel Zolnai
你能否添加完整的代码,包括登录、注销和获取个人资料信息。我需要那个。 - Android Dev
谢谢@Sufian。现在我的回答已经完成了。 - TejaDroid
4
请注意将MainActivity.this设置为logInWithReadPermissions()的属性。否则,this将指代View.OnClickListener而非Activity - lagos
大家好,这个答案很好,但我能在片段中使用它而不是在活动中吗?我需要做出哪些更改? - Ganpat Kaliya

9

类似这样的东西

private void performFacebookLogin()
{
    Log.d("FACEBOOK", "performFacebookLogin");
    final Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(this, Arrays.asList("email"));
    Session openActiveSession = Session.openActiveSession(this, true, new Session.StatusCallback()
    {
        @Override
        public void call(Session session, SessionState state, Exception exception)
        {
            Log.d("FACEBOOK", "call");
            if (session.isOpened() && !isFetching)
            {
                Log.d("FACEBOOK", "if (session.isOpened() && !isFetching)");
                isFetching = true;
                session.requestNewReadPermissions(newPermissionsRequest);
                Request getMe = Request.newMeRequest(session, new GraphUserCallback()
                {
                    @Override
                    public void onCompleted(GraphUser user, Response response)
                    {
                        Log.d("FACEBOOK", "onCompleted");
                        if (user != null)
                        {
                            Log.d("FACEBOOK", "user != null");
                            org.json.JSONObject graphResponse = response.getGraphObject().getInnerJSONObject();
                            String email = graphResponse.optString("email");
                            String id = graphResponse.optString("id");
                            String facebookName = user.getUsername();
                            if (email == null || email.length() < 0)
                            {
                                Logic.showAlert(
                                        ActivityLogin.this,
                                        "Facebook Login",
                                        "An email address is required for your account, we could not find an email associated with this Facebook account. Please associate a email with this account or login the oldskool way.");
                                return;
                            }
                        }
                    }
                });
                getMe.executeAsync();
            }
            else
            {
                if (!session.isOpened())
                    Log.d("FACEBOOK", "!session.isOpened()");
                else
                    Log.d("FACEBOOK", "isFetching");

            }
        }
    });

确实就是这样。对我来说它完美地工作。


1
我有自定义的按钮“分享到Facebook”。当用户点击它时,它会检查用户的登录状态。如果用户已经登录,则会在墙上发布文本,否则会提示登录。我想添加publish_stream权限。请帮我实现这个功能。你是如何做到的? - Ajay S
你能解释一下如何定义isFetching吗? - user1851212
布尔型变量isFetching = false; 声明为成员变量,在获取数据时将其设置为true。 - WIllJBD
这会打开一个黑色背景的进度条,我该如何使用自己的进度条? - jmhostalet
你能否添加完整的登录、注销和获取个人资料信息的代码,使用最新的SDK,但不包括FB登录按钮?我尝试了一些例子,但是不正常工作。或者 请推荐一个可行的例子。@WIllJBD - Android Dev
会话不再存在了... Facebook从其SDK中删除了它。 - Erçin Dedeoğlu

3
这对我有用。
    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Intent;
    import android.widget.TextView;
    import com.facebook.*;
    import com.facebook.model.*;

    public class MainActivity extends Activity {

      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // start Facebook Login
        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) {
                  if (user != null) {
                    TextView welcome = (TextView) findViewById(R.id.welcome);
                    welcome.setText("Hello " + user.getName() + "!");
                  }
                }
              }).executeAsync();
            }
          }
        });
      }

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

    }

如果您需要在验证会话已打开后获取授权,请按如下方式添加:
List<String> permissions = session.getPermissions();             
                 Session.NewPermissionsRequest newPermissionsRequest = new         Session.NewPermissionsRequest(getActivity(), Arrays.asList("read_mailbox"));
                 session.requestNewReadPermissions(newPermissionsRequest);

1
你的 permissions 变量是用来做什么的?它似乎在下一条语句中没有被使用。 - Konrad Morawski
@KonradMorawski 有点晚了,但这是用于获取 Facebook 个人资料中所需数据类型的(例如 public_profile、user_friends、email)。 - Jeongbebs

2
不使用LoginButton访问FB详细信息的方法是:

1)隐藏您的LoginButton UI

2)添加您自己的自定义按钮

Button signup = (Button) view.findViewById(R.id.btn_signup);
        signup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loginButton.performClick();//Where loginButton is Facebook UI
            }
        });

但我建议使用LoginManager


2
这个简单的库可以帮助你:https://github.com/sromku/android-simple-facebook

只需将此库添加到您的项目中,并从该库引用 Facebook SDK 3.0.x 并从您的应用程序引用该库。
然后,您可以在没有 LoginButton 的情况下登录,并执行诸如发布动态、获取个人资料/好友、发送邀请等简单操作。
这就是登录页面的样子:
OnLoginOutListener onLoginOutListener = new SimpleFacebook.OnLoginOutListener()
{

    @Override
    public void onFail()
    {
        Log.w(TAG, "Failed to login");
    }

    @Override
    public void onException(Throwable throwable)
    {
        Log.e(TAG, "Bad thing happened", throwable);
    }

    @Override
    public void onThinking()
    {
        // show progress bar or something to the user while login is happening
        Log.i(TAG, "In progress");
    }

    @Override
    public void onLogout()
    {
        // change the state of the button or do whatever you want
        Log.i(TAG, "Logged out");
    }

    @Override
    public void onLogin()
    {
        // change the state of the button or do whatever you want
        Log.i(TAG, "Logged in");
    }
};

// set login/logut listener
mSimpleFacebook.setLogInOutListener(onLoginOutListener);

// do the login action
mSimpleFacebook.login(MainActivity.this);

然后,在onLogin()回调方法中,您可以像这样发布动态:
// build feed
Feed feed = new Feed.Builder()
    .setMessage("Clone it out...")
    .setName("Simple Facebook for Android")
    .setCaption("Code less, do the same.")
    .setDescription("The Simple Facebook library project makes the life much easier by coding less code for being able to login, publish feeds and open graph stories, invite friends and more.")
    .setPicture("https://raw.github.com/sromku/android-simple-facebook/master/Refs/android_facebook_sdk_logo.png")
    .setLink("https://github.com/sromku/android-simple-facebook")
    .build();

// publish the feed
mSimpleFacebook.publish(feed);

希望它可以帮到你。

1
SimpleFacebook现在已经过时了。 - Trần Thị Diệu My

0

您可以使用基于Node的facebook-proxy模块绕过登录对话框。使用一键部署按钮在Heroku上创建自己的实例。

它的基本功能如下:

  1. 从Facebook请求access_token
  2. 使用express-http-proxy打开代理服务器
  3. 允许您请求API的所有端点

0

您可以更改放置Facebook按钮的位置并调整其可见性。例如:

<FrameLayout
            android:id="@+id/frameLayout_facebook"
            android:layout_width="0dp"
            android:layout_height="wrap_content">

            <com.google.android.material.button.MaterialButton
                android:id="@+id/button_continue_facebook"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/continue_with_facebook" />

            <com.facebook.login.widget.LoginButton
                android:id="@+id/loginButton_facebook"
                android:visibility="gone"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

 </FrameLayout>

在你的代码中(这里是Kotlin),当有人点击你的按钮时,你可以调用Facebook SDK的onClick()方法:
 button_continue_facebook.setOnClickListener {
            binding.loginButton_facebook.callOnClick()
}

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