Facebook 登录接入文档
一、准备工作
1.1 Facebook Developers 后台配置
- 前往 Facebook Developers 注册并创建应用
- 获取以下信息:
- App ID(应用编号)
- Client Token(客户端令牌)
- 在「设置 > 基本」中配置:
- 包名(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_profile 和 email 是基础权限,无需审核。其他权限需要提交 Facebook 审核。
九、常见问题
Q1: 登录时闪退或无响应
- 检查
strings.xml中的facebook_app_id是否正确 - 检查
AndroidManifest.xml中的 meta-data 配置 - 确保 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" 错误
- 确保 Debug 和 Release 的 Key Hash 都已添加到 Facebook 后台
- 使用上述代码获取正确的 Key Hash
- 注意:不同签名文件生成的 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/"
}
| 字段 | 说明 |
|---|---|
FacebookAppId | Facebook 应用 ID |
FacebookHomePage | Facebook 主页链接 |
FacebookSocietyPage | Facebook 群组链接 |
FacebookPageId | Facebook 页面 ID |
FbH5Url | Facebook H5 页面地址 |
十一、参考链接