自定义Facebook登录按钮 - Android

54

我正在学习这个教程,但到目前为止,我还无法使其正常工作,尽管这是大约一年前的内容...

我正在使用Android Studio 1.2.2和FacebookSDK 4。

我想要通过一个自定义按钮简单地登录Facebook,就像在这张图片中所示:

Example

现在,在教程的示例中,我遇到了Session变量的问题,它说无法解决它,也无法解决getActivity()

有人已经在FacebookSDK4.0上尝试过吗?

这是正确的方法,还是可能有更更新的东西吗?


1
新版Facebook SDK中已删除Session。您不能在新版Facebook SDK中使用Session或UiLifecycleHelper。 - Harvi Sirja
1
请查看下面的第二个答案,我认为所选的答案并不完全正确。 - Shehabic
教程链接已过期。 - Jeff T.
8个回答

169

步骤1: 首先添加FrameLayout并使Facebook按钮visibility="gone",然后添加自定义按钮。 不要忘记在主布局中加入xmlns:facebook="http://schemas.android.com/apk/res-auto"

<FrameLayout
        android:id="@+id/FrameLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

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

        <Button
            android:id="@+id/fb"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="#416BC1"
            android:onClick="onClick"
            android:text="FaceBook"
            android:textColor="#ffffff"
            android:textStyle="bold" />
    </FrameLayout>

第二步:在设置布局前,在 onCreate 方法中初始化 FacebookSdk

FacebookSdk.sdkInitialize(this.getApplicationContext());

第三步:将此代码添加到您的 Java 文件中。

callbackManager = CallbackManager.Factory.create();

fb = (Button) findViewById(R.id.fb);
loginButton = (LoginButton) findViewById(R.id.login_button);

List < String > permissionNeeds = Arrays.asList("user_photos", "email",
    "user_birthday", "public_profile", "AccessToken");
loginButton.registerCallback(callbackManager,
new FacebookCallback < LoginResult > () {@Override
    public void onSuccess(LoginResult loginResult) {

        System.out.println("onSuccess");

        String accessToken = loginResult.getAccessToken()
            .getToken();
        Log.i("accessToken", accessToken);

        GraphRequest request = GraphRequest.newMeRequest(
        loginResult.getAccessToken(),
        new GraphRequest.GraphJSONObjectCallback() {@Override
            public void onCompleted(JSONObject object,
            GraphResponse response) {

                Log.i("LoginActivity",
                response.toString());
                try {
                    id = object.getString("id");
                    try {
                        URL profile_pic = new URL(
                            "http://graph.facebook.com/" + id + "/picture?type=large");
                        Log.i("profile_pic",
                        profile_pic + "");

                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
                    name = object.getString("name");
                    email = object.getString("email");
                    gender = object.getString("gender");
                    birthday = object.getString("birthday");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
        Bundle parameters = new Bundle();
        parameters.putString("fields",
            "id,name,email,gender, birthday");
        request.setParameters(parameters);
        request.executeAsync();
    }

    @Override
    public void onCancel() {
        System.out.println("onCancel");
    }

    @Override
    public void onError(FacebookException exception) {
        System.out.println("onError");
        Log.v("LoginActivity", exception.getCause().toString());
    }
});

第四步:不要忘记添加以下代码。

@Override
protected void onActivityResult(int requestCode, int responseCode,
Intent data) {
    super.onActivityResult(requestCode, responseCode, data);
    callbackManager.onActivityResult(requestCode, responseCode, data);
}

第五步:将自定义按钮点击事件设置为Facebook登录按钮的点击事件。

public void onClick(View v) {
    if (v == fb) {
        loginButton.performClick();
    }
 }

步骤6: 要进行编程登出,请使用以下代码。

LoginManager.getInstance().logOut();

步骤7:您可以通过个人资料查找用户是否已登录。

profile = Profile.getCurrentProfile().getCurrentProfile();
if (profile != null) {
    // user has logged in
} else {
    // user has not logged in
}

2
太棒了!我正在实现它,但是在这一行上出现了一个错误:'loginButton.registerCallback(callbackManager,' 'Cannot resolve method' :( 是否有什么遗漏? - NeoVe
2
我将为这个错误开一个新的问题,非常感谢。 - NeoVe
2
很好..可以给一个例子来制作自定义的登出按钮。 - Vishal
2
非常感谢,这篇文章非常有帮助...讲解得非常清楚。 - Krupa Kakkad
2
loginButton.performClick(); 这是答案的核心,谢谢伙计 :) - Biskrem Muhammad
显示剩余11条评论

104

依我看,所选答案中的部分是一种“变通方法”,而不是正确的解决方案。因此,要使其正确,需要进行以下更改:

  1. 从您的XML中删除“com.facebook.login.widget.LoginButton”

    <com.facebook.login.widget.LoginButton
            android:id="@+id/login_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone" />
    
  2. 在你的Java代码中清除所有有关"LoginButton"的引用

  3. 使用Facebook的"LoginManager"类,该类专门用于此目的,操作如下:

  4. @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Some code
        callbackManager = CallbackManager.Factory.create();
        LoginManager.getInstance().registerCallback(
            callbackManager,
            new FacebookCallback < LoginResult > () {
                @Override
                public void onSuccess(LoginResult loginResult) {
                    // Handle success
                }
    
                @Override
                public void onCancel() {
                }
    
                @Override
                public void onError(FacebookException exception) {
                } 
           }
       );
    }
    
    public void onClick(View v) {
       if (v == fb) {
           LoginManager.getInstance().logInWithReadPermissions(
               this,
               Arrays.asList("user_photos", "email", "user_birthday", "public_profile")
           );
       }
    }
    
    // this part was missing thanks to wesely
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        callbackManager.onActivityResult(requestCode, resultCode, data);
    }
    

1
嗨@Shehabix,这是几年前的事了,但我会尽快检查您的代码并回复!保证!实际上,另一个答案并不是最终解决方案。 - NeoVe
1
这是一个干净的解决方案。比那个被接受的答案变通方法好多了。 - ViliusK
1
此外,根据 LoginManager 的状态,您可能希望将按钮的标签从“登录”更新为“注销”。 - ViliusK
10
应该接受此回答,因为它提供了一种干净合法的方法来操作登录按钮。 - aB9
1
已接受的答案! - Asad
显示剩余5条评论

16

这很简单。在布局文件中添加一个按钮,例如:

<Button
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:text="Login with facebook"
    android:textColor="#ffff"
    android:layout_gravity="center"
    android:textStyle="bold"
    android:onClick="fbLogin"
    android:background="@color/colorPrimary"/>

在onClick事件中,放置LoginManager的registercallback()方法。由于该方法会自动执行,因此需要这么做。

例如:

  public void fbLogin(View view)
{
    // Before Edit:
    // LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("user_photos", "email", "public_profile", "user_posts" , "AccessToken"));

    LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("user_photos", "email", "public_profile", "user_posts"));
    LoginManager.getInstance().logInWithPublishPermissions(this, Arrays.asList("publish_actions"));
    LoginManager.getInstance().registerCallback(callbackManager,
            new FacebookCallback<LoginResult>()
            {
                @Override
                public void onSuccess(LoginResult loginResult)
                {
                    // App code
                }

                @Override
                public void onCancel()
                {
                    // App code
                }

                @Override
                public void onError(FacebookException exception)
                {
                    // App code
                }
            });
}

玩得开心


13

(没有足够的声望来添加评论...)

我尝试了@Shehabix的答案,但在添加以下内容之前无法接收回调

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

那么它正常工作。


2
我将在今晚更新我的答案,谢谢。 - Shehabic

10
简单的答案是在“cutomBtn.setOnClickListener”中添加“facebookButton.performClick()”。
    <!-- connect with Facebook -->
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <com.facebook.login.widget.LoginButton
            android:id="@+id/fb_connect"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:textSize="@dimen/login_fb_font_size"
            android:visibility="invisible" />

        <LinearLayout
            android:id="@+id/mfb_connect"
            style="@style/facebook_button">

            <ImageView
                style="@style/login_connect_icon"
                android:src="@drawable/ic_facebook" />

            <TextView
                style="@style/login_connect_text"
                android:text="@string/login_connect_facebook" />
        </LinearLayout>
    </RelativeLayout>

...

private LoginButton fb_connect;
private LinearLayout mfb_connect;

...

    // the button from facebook sdk
    fb_connect = (LoginButton) findViewById(R.id.fb_connect);
    // handle the click from my custom button to perfrom action click on facebook sdk button
    mfb_connect = (LinearLayout) findViewById(R.id.mfb_connect);
    mfb_connect.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            fb_connect.performClick();
        }
    });
那将实现这个效果:

输入图像描述



2
非常有帮助 :) - Abhishek Batra

2
我只是从我的自定义按钮中调用 Facebook 默认按钮,并且每一行代码都按照文档进行了编写。结果非常成功。
public class SignInFragment extends Fragment implements
   FragmentChangeListener{
   private Button facebook



    private FirebaseAuth firebaseAuth;
    private CallbackManager mCallBackManager;
    private LoginButton loginButton;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View view =  inflater.inflate(R.layout.fragment_sign_in, container, false);

        facebook = view.findViewById(R.id.facebookButton);
        loginButton = view.findViewById(R.id.facebookBtn);

        firebaseAuth = FirebaseAuth.getInstance();

        facebook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loginButton.callOnClick();
            }
        });

        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCallBackManager = CallbackManager.Factory.create();
                loginButton.setFragment(SignInFragment.this);
                loginButton.setPermissions("email","public_profile");
                loginButton.registerCallback(mCallBackManager, new FacebookCallback<LoginResult>() {
                    @Override
                    public void onSuccess(LoginResult loginResult) {
                        handleFacebookAccessToken(loginResult.getAccessToken());
                    }

                    @Override
                    public void onCancel() {
                        Toast.makeText(getContext(),"Is Cancelled",Toast.LENGTH_LONG).show();
                    }

                    @Override
                    public void onError(FacebookException error) {
                        Toast.makeText(getContext(),error.getMessage(),Toast.LENGTH_LONG).show();
                    }
                });
            }
        });

        return view;
    }


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

        mCallBackManager.onActivityResult(requestCode, resultCode, data);
      
    }

    private void handleFacebookAccessToken(AccessToken token) {
        AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
        firebaseAuth.signInWithCredential(credential)
                .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            FirebaseUser user = firebaseAuth.getCurrentUser();
                            startActivity(new Intent(getContext(),MainActivity.class));
                        } else {
                            // If sign in fails, display a message to the user.
                            Toast.makeText(getContext(), task.getException().getMessage(),
                                    Toast.LENGTH_SHORT).show();
                        }

                    }
                });
    } 
 }

1
这在我的片段中完美地运行。我只是调用了默认的Facebook登录按钮,它在我的XML中保持不可见状态,从我的自定义按钮中调用。 - Emon Hossain Munna

1
在Harvi和Shehabix的回答中,我建议添加此方法,因为这会在Firebase Auth中注册身份验证。
应该在“LoginManager”的“On Success”中调用此方法。
private void handleFacebookAccessToken(AccessToken token) {

    AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {

                        //Toast.makeText(MainActivity.this, "Autenticando",Toast.LENGTH_SHORT).show();

                    } else {
                        // If sign in fails, display a message to the user.
                        Toast.makeText(MainActivity.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                        //updateUI(null);
                    }

                }
            });
}

0
try this 

// Facebook Button
LoginButton loginButton = findViewById(R.id.loginbtn);
loginButton.setVisibility(View.GONE)



// Your Custom Button

 binding.fbBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginButton.callOnClick();
            }
        });

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