android Facebook登录 接入文档

0 阅读5分钟

Facebook 登录接入文档

一、准备工作

1.1 Facebook Developers 后台配置

  1. 前往 Facebook Developers 注册并创建应用
  2. 获取以下信息:
    • App ID(应用编号)
    • Client Token(客户端令牌)
  3. 在「设置 > 基本」中配置:
    • 包名(Package Name)
    • 默认 Activity 类名
    • Key Hash(密钥哈希)

1.2 获取 Key Hash

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.Base64;
import java.security.MessageDigest;

public void getKeyHash(Context context) {
    try {
        PackageInfo info = context.getPackageManager().getPackageInfo(
                context.getPackageName(), PackageManager.GET_SIGNATURES);
        for (Signature signature : info.signatures) {
            MessageDigest md = MessageDigest.getInstance("SHA");
            md.update(signature.toByteArray());
            String keyHash = Base64.encodeToString(md.digest(), Base64.DEFAULT);
            Log.d("KeyHash", keyHash);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

注意: 需要将 Debug 和 Release 的 Key Hash 都配置到 Facebook 后台。


二、Gradle 依赖配置

app/build.gradle 中添加 Facebook SDK 依赖:

dependencies {
    // Facebook 登录
    implementation 'com.facebook.android:facebook-login:latest.release'
    
    // Facebook 分享(可选)
    implementation 'com.facebook.android:facebook-share:latest.release'
    
    // Facebook App Links(可选)
    implementation 'com.facebook.android:facebook-applinks:13.0.0'
}

最小依赖配置(仅登录功能):

dependencies {
    implementation 'com.facebook.android:facebook-login:latest.release'
}

三、strings.xml 配置

app/src/main/res/values/strings.xml 中添加:

<resources>
    <!-- Facebook App ID -->
    <string name="facebook_app_id" translatable="false">你的_FACEBOOK_APP_ID</string>
    
    <!-- Facebook Client Token -->
    <string name="facebook_client_token" translatable="false">你的_FACEBOOK_CLIENT_TOKEN</string>
    
    <!-- Facebook Login Protocol Scheme: fb + App ID -->
    <string name="fb_login_protocol_scheme" translatable="false">fb你的_FACEBOOK_APP_ID</string>
</resources>

示例(App ID 为 1424623392511798):

<resources>
    <string name="facebook_app_id" translatable="false">1424623392511798</string>
    <string name="facebook_client_token" translatable="false">fb16d4fe6a4dbeabbc050478a66b12d2</string>
    <string name="fb_login_protocol_scheme" translatable="false">fb1424623392511798</string>
</resources>

四、AndroidManifest.xml 配置

4.1 添加 Meta-data 配置

<application>
    <!-- Facebook App ID -->
    <meta-data
        android:name="com.facebook.sdk.ApplicationId"
        android:value="@string/facebook_app_id" />

    <!-- Facebook Client Token -->
    <meta-data
        android:name="com.facebook.sdk.ClientToken"
        android:value="@string/facebook_client_token" />
</application>

4.2 配置 ContentProvider(分享功能需要)

<application>
    <!-- Facebook Content Provider(分享功能必需) -->
    <!-- authorities 格式:com.facebook.app.FacebookContentProvider + App ID -->
    <provider
        android:name="com.facebook.FacebookContentProvider"
        android:authorities="com.facebook.app.FacebookContentProvider你的_APP_ID"
        android:exported="true" />
</application>

示例(App ID 为 1424623392511798):

<provider
    android:name="com.facebook.FacebookContentProvider"
    android:authorities="com.facebook.app.FacebookContentProvider1424623392511798"
    android:exported="true" />

4.3 添加网络权限

<manifest>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

五、SDK 初始化与登录控制器

5.1 完整控制器实现

package com.example.myapplication;

import android.app.Activity;
import android.content.Intent;
import android.util.Log;

import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;

import java.util.Arrays;

/**
 * Facebook 登录控制器
 */
public class GameFbController {

    private static final String TAG = "GameFbController";
    
    // 回调管理器
    private CallbackManager callbackManager;
    
    // 登录类型常量
    public static final int LOGIN_TYPE = 1;  // 登录
    public static final int BIND_TYPE = 2;   // 绑定
    
    private int currentType = 0;
    
    // 单例
    private static GameFbController instance = null;
    
    private GameFbController() {}
    
    public static GameFbController getInstance() {
        if (instance == null) {
            synchronized (GameFbController.class) {
                if (instance == null) {
                    instance = new GameFbController();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化 Facebook SDK
     * @param activity Activity 上下文
     */
    public void init(Activity activity) {
        try {
            // 创建回调管理器
            callbackManager = CallbackManager.Factory.create();
            
            // 注册登录回调
            registerLoginCallback(activity);
        } catch (Exception e) {
            Log.e(TAG, "初始化失败", e);
        }
    }

    /**
     * 注册登录回调
     */
    private void registerLoginCallback(final Activity activity) {
        if (callbackManager != null) {
            LoginManager.getInstance().registerCallback(callbackManager,
                new FacebookCallback<LoginResult>() {
                    @Override
                    public void onSuccess(LoginResult loginResult) {
                        AccessToken accessToken = loginResult.getAccessToken();
                        Log.i(TAG, "登录成功,Token: " + accessToken.getToken());
                        Log.i(TAG, "用户ID: " + accessToken.getUserId());
                        
                        // 处理登录成功
                        handleLoginSuccess(accessToken);
                    }

                    @Override
                    public void onCancel() {
                        Log.w(TAG, "用户取消登录");
                    }

                    @Override
                    public void onError(FacebookException exception) {
                        Log.e(TAG, "登录失败", exception);
                        handleError(exception);
                    }
                });
        }
    }

    /**
     * 发起 Facebook 登录
     * @param activity Activity
     * @param loginType 登录类型(LOGIN_TYPE 或 BIND_TYPE)
     */
    public void login(Activity activity, int loginType) {
        try {
            this.currentType = loginType;
            
            // 检查是否已有有效 Token
            AccessToken accessToken = AccessToken.getCurrentAccessToken();
            if (accessToken != null && !accessToken.isExpired()) {
                // Token 有效,直接使用
                handleLoginSuccess(accessToken);
            } else {
                // 需要重新登录
                LoginManager.getInstance().logInWithReadPermissions(
                    activity,
                    Arrays.asList("public_profile", "email")
                );
            }
        } catch (Exception e) {
            Log.e(TAG, "登录异常", e);
        }
    }

    /**
     * 处理登录成功
     */
    private void handleLoginSuccess(AccessToken accessToken) {
        if (currentType == BIND_TYPE) {
            // 处理绑定逻辑
            Log.i(TAG, "执行绑定操作");
        } else {
            // 处理登录逻辑
            Log.i(TAG, "执行登录操作");
        }
    }

    /**
     * Facebook 登出
     */
    public void logout() {
        try {
            AccessToken accessToken = AccessToken.getCurrentAccessToken();
            if (accessToken != null && !accessToken.isExpired()) {
                LoginManager.getInstance().logOut();
                Log.i(TAG, "登出成功");
            }
        } catch (Exception e) {
            Log.e(TAG, "登出异常", e);
        }
    }

    /**
     * 处理 Activity 回调(必须在 Activity.onActivityResult 中调用)
     */
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (callbackManager != null) {
            callbackManager.onActivityResult(requestCode, resultCode, data);
        }
    }

    /**
     * 处理登录错误
     */
    private void handleError(FacebookException exception) {
        try {
            // Token 失效时登出
            if (AccessToken.getCurrentAccessToken() != null) {
                LoginManager.getInstance().logOut();
            }
        } catch (Exception e) {
            Log.e(TAG, "错误处理异常", e);
        }
    }

    /**
     * 检查是否已登录
     */
    public boolean isLoggedIn() {
        AccessToken accessToken = AccessToken.getCurrentAccessToken();
        return accessToken != null && !accessToken.isExpired();
    }

    /**
     * 获取当前 Access Token
     */
    public AccessToken getCurrentAccessToken() {
        return AccessToken.getCurrentAccessToken();
    }
}

六、Activity 中集成

6.1 初始化

public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 初始化 Facebook 控制器
        GameFbController.getInstance().init(this);
    }
}

6.2 处理回调(必需)

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    
    // 传递给 Facebook CallbackManager
    GameFbController.getInstance().onActivityResult(requestCode, resultCode, data);
}

6.3 登录调用

// 登录
btnFbLogin.setOnClickListener(v -> {
    GameFbController.getInstance().login(this, GameFbController.LOGIN_TYPE);
});

// 绑定
btnFbBind.setOnClickListener(v -> {
    GameFbController.getInstance().login(this, GameFbController.BIND_TYPE);
});

// 登出
btnFbLogout.setOnClickListener(v -> {
    GameFbController.getInstance().logout();
});

七、获取用户信息

登录成功后可获取用户详细信息:

import com.facebook.GraphRequest;
import com.facebook.GraphResponse;
import org.json.JSONObject;

public void fetchUserInfo(AccessToken accessToken) {
    GraphRequest request = GraphRequest.newMeRequest(
        accessToken,
        new GraphRequest.GraphJSONObjectCallback() {
            @Override
            public void onCompleted(JSONObject object, GraphResponse response) {
                try {
                    String id = object.getString("id");
                    String name = object.getString("name");
                    String email = object.optString("email", "");
                    String picture = object.getJSONObject("picture")
                            .getJSONObject("data")
                            .getString("url");
                    
                    Log.i(TAG, "用户ID: " + id);
                    Log.i(TAG, "用户名: " + name);
                    Log.i(TAG, "邮箱: " + email);
                    Log.i(TAG, "头像: " + picture);
                } catch (Exception e) {
                    Log.e(TAG, "解析用户信息失败", e);
                }
            }
        });
    
    Bundle parameters = new Bundle();
    parameters.putString("fields", "id,name,email,picture.type(large)");
    request.setParameters(parameters);
    request.executeAsync();
}

八、权限说明

权限说明是否需要审核
public_profile基本公开信息(ID、名字、头像)
email用户邮箱
user_friends好友列表
user_birthday生日

注意: public_profileemail 是基础权限,无需审核。其他权限需要提交 Facebook 审核。


九、常见问题

Q1: 登录时闪退或无响应

  1. 检查 strings.xml 中的 facebook_app_id 是否正确
  2. 检查 AndroidManifest.xml 中的 meta-data 配置
  3. 确保 Key Hash 已配置到 Facebook 后台

Q2: onActivityResult 未回调

确保在 Activity 中正确调用:

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

Q3: 分享功能不可用

检查 ContentProvider 配置:

  • authorities 必须是 com.facebook.app.FacebookContentProvider + App ID
  • 无空格、无其他字符

Q4: 混淆配置

proguard-rules.pro 中添加:

# Facebook SDK
-keep class com.facebook.** { *; }
-keepattributes Signature

Q5: "Invalid key hash" 错误

  1. 确保 Debug 和 Release 的 Key Hash 都已添加到 Facebook 后台
  2. 使用上述代码获取正确的 Key Hash
  3. 注意:不同签名文件生成的 Key Hash 不同

十、SDK 配置文件说明

项目中 game_sdk_config.json 相关配置:

{
    "FacebookAppId": "1424623392511798",
    "FacebookHomePage": "https://www.facebook.com/profile.php?id=xxx",
    "FacebookSocietyPage": "https://www.facebook.com/groups/xxx",
    "FacebookPageId": "xxx",
    "FbH5Url": "https://sdk-web.xxx.com/fb/"
}
字段说明
FacebookAppIdFacebook 应用 ID
FacebookHomePageFacebook 主页链接
FacebookSocietyPageFacebook 群组链接
FacebookPageIdFacebook 页面 ID
FbH5UrlFacebook H5 页面地址

十一、参考链接