Facebook 集成指南
For the C++ version of cocos2d-x v3.x - (all other versions)
集成
用如下命令来集成 SDKBOX Facebook 插件,请确保您可以正常执行的 SDKBOX 安装器.
sdkbox import facebook
重点注意事项
如果您升级到了 Xcode7, 则需要以下额外步骤来确保插件工作正常:
禁用应用程序安全传输策略
添加以下项到 plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
添加后的文件内容看起来就像这样:
禁止 Bitcode 支持
您必须禁止 Bitcode 的支持,否则将会编译失败。
游戏全屏配置
如果您的游戏不同时支持横竖屏,则必须在 Xcode 中选中 Requires full screen
,否则将不会通过 Apple 的审核。
canOpenURL 白名单
取决于您使用哪些插件。需要在 info.plist
的 LSApplicationQueriesSchemes
下添加名单。
关于 Creator 工程
Creator 导出工程会修改工程的配置, 这可能会影响 SDKBox 对工程的配置修改. 所以可以有以下做法(任选其一):
- 保存导出工程中的修改, 对于 SDKBox 来说可能有这些文件(mk, gradle, gradle.properties, AppDelegate.cpp, ...), 导出后再恢复对应该文件
- 在每一次 Creator 导出工程后, 重新 import 插件.
推荐第一种, 但是第一种的麻烦点在于, 对于第一次(或很久没接触的人)可能会有露掉某个文件 第二种, 很方便, 它的麻烦点在于, 如果你对工程有自己的修改, SDKBox 的重新 import 不能帮你恢复.
FAQ
- 切换 Facebook 登录方式,使用应用、浏览器方式登录, 清理 Safari Cookie
- 切换 Facebook 登录账号, 清理 Safari Cookie
额外的步骤
下面的步骤假定您已经注册为 Facbbook 开发者,并创建了一个 APP
iOS的步骤
- 依iOS快速指导 来配置您的 APP
- 在
AppController.mm
中修改如下代码,不是AppDelegate.cpp
中
- (void)applicationDidBecomeActive:(UIApplication *)application {
[FBSDKAppEvents activateApp];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ...
//
// **************************
// !! 非常重要,非常重要,非常重要 !!
// **************************
//
// 在 app->run() 前调用
// [[FBSDKApplicationDelegate sharedInstance] application:didFinishLaunchingWithOptions
[[FBSDKApplicationDelegate sharedInstance] application:application
didFinishLaunchingWithOptions:launchOptions];
app->run();
return YES;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
BOOL handled = [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]
];
// Add any custom logic here.
return handled;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
BOOL handled = [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation
];
// Add any custom logic here.
return handled;
}
在 Xcode8 iOS10 模拟器上,不能登录:
Go to the `Project Target` and then `Capabilities` and switch `Keychain Sharing ON`.
http://stackoverflow.com/a/39788102/5443510
Android的步骤
- 确保您的
java -version
>= 1.7 - 依Android快速指导 来配置您的 APP
- 在
res/values/strings.xml
中给facebook_app_id
赋值为您的Facebook App ID
- 在
AndroidManifest.xml
中给_replace_with_your_app_id_
赋值为您的Facebook App ID
- 在
project.properties
中给 target 赋值为target=android-15
JSON 配置
SDKBOX 安装器会为您自动生成一个 sdkbox_config.json
配置文件
下面给出一个例子,您可以打开/关闭Facebook的调试模式
"Facebook":
{
"debug":true
}
~~邀请朋友~~
- http://discuss.cocos2d-x.org/t/solved-invite-friends-with-using-cocos2dx-layer/34450
https://developers.facebook.com/docs/ios/change-log-4x/
The App Invites feature has been deprecated. (4.28.0 - November 7, 2017)
使用
初始化 Facebook
在您的代码合适的地方初始化插件, 我们建议您在 AppDelegate::applicationDidFinishLaunching()
或 AppController:didFinishLaunchingWithOptions()
中完成初始化. 请确保您包含了对应的头文件:
#include "PluginFacebook/PluginFacebook.h"
AppDelegate::applicationDidFinishLaunching()
{
sdkbox::PluginFacebook::init();
}
使用 Facebook
登录
用户在使用前需要登录到 Facebook.
sdkbox::PluginFacebook::login();
用户不想使用 Facebook 时,可以注销.
sdkbox::PluginFacebook::logout();
您可以检查是否已经登录
sdkbox::PluginFacebook::isLoggedIn();
注意: 用户只需要登录一次, 除非他们注销
权限
Facebook 要求您在使用前去询问用户要相应的权限,比如 posting 相关的权益 就有两类权限, read and publish 您也可以通过这里得到完整的信息
SDKBOX 提供最常用的几种权限:
- FB_PERM_READ_PUBLIC_PROFILE
- FB_PERM_READ_EMAIL
- FB_PERM_READ_USER_FRIENDS
- FB_PERM_PUBLISH_POST
要获取权限,您可以指定您想要权限,比如:
sdkbox::PluginFacebook::requestReadPermissions({FB_PERM_READ_PUBLIC_PROFILE, FB_PERM_READ_USER_FRIENDS});
sdkbox::PluginFacebook::requestPublishPermissions({FB_PERM_PUBLISH_POST});
分享
提供了两种分享方式.
- 分享 会自动发布到用户的信息流中 分享联接:
sdkbox::FBShareInfo info;
info.type = FB_LINK;
info.link = "http://www.cocos2d-x.org";
info.title = "cocos2d-x";
info.text = "Best Game Engine";
info.image = "http://cocos2d-x.org/images/logo.png";
sdkbox::PluginFacebook::share(info);
分享图片:
sdkbox::FBShareInfo info;
info.type = FB_PHOTO;
info.title = "My Photo";
info.image = __path to image__;
sdkbox::PluginFacebook::share(info);
- dialog 会显示一个对话框,让用户可以添加他们自己想说的话:
显一个分享对话框:
sdkbox::FBShareInfo info;
info.type = FB_LINK;
info.link = "http://www.cocos2d-x.org";
info.title = "cocos2d-x";
info.text = "Best Game Engine";
info.image = "http://cocos2d-x.org/images/logo.png";
sdkbox::PluginFacebook::dialog(info);
分享一个带有文字注解的图片:
sdkbox::FBShareInfo info;
info.type = FB_PHOTO;
info.title = "My Photo";
info.image = __path to image__;
sdkbox::PluginFacebook::dialog(info);
注意: 分享带有文字注解的图片需要用户的手机上已安装了 Facebook 应用.
图谱API
您可以通过 api
函数 执行图谱API
比如,取好友列表:
sdkbox::PluginFacebook::FBAPIParam params;
sdkbox::PluginFacebook::api("/me/friendlists", "GET", params, "/me/friendlists");
Facebook 事件
您可以接收 Facebook
事件,以对不同事件做不同的处理.
- 让您的类继承
sdkbox::FacebookListener
并重写下面的函数:
#include "PluginFacebook/PluginFacebook.h"
class MyClass : public sdkbox::FacebookListener
{
private:
void onLogin(bool isLogin, const std::string& msg);
void onPermission(bool isLogin, const std::string& msg);
void onAPI(const std::string& tag, const std::string& jsonData);
void onSharedSuccess(const std::string& message);
void onSharedFailed(const std::string& message);
void onSharedCancel();
};
- 创建一个 listener 监听事件:
sdkbox::PluginFacebook::setListener(this);
API Reference
Methods
static void init ( ) ;
initialize the plugin instance.
static void setListener ( FacebookListener * listener ) ;
Set listener to listen for facebook events
static FacebookListener * getListener ( ) ;
Get the listener
static void removeListener ( ) ;
Remove the listener, and can't listen to events anymore
static void login ( ) ;
log in
static void login ( std::vector <std::string> & permissions ) ;
static void requestReadPermissions ( const std::vector <std::string> & permissions ) ;
log in with specific read permissions, conflict with publish permissions https://developers.facebook.com/docs/facebook-login/permissions
static void requestPublishPermissions ( const std::vector <std::string> & permissions ) ;
log in with specific public permissions https://developers.facebook.com/docs/facebook-login/permissions
static void logout ( ) ;
log out
static bool isLoggedIn ( ) ;
Check whether the user logined or not
static std::string getUserID ( ) ;
get UserID
static std::string getAccessToken ( ) ;
get AccessToken
static std::vector <std::string> getPermissionList ( ) ;
get permissoin list
static void share ( const FBShareInfo & info ) ;
share
static void dialog ( const FBShareInfo & info ) ;
open a dialog of Facebook app or WebDialog (dialog with photo only avaible with native Facebook app)
static std::string getSDKVersion ( ) ;
return the version of Facebook SDK
static void api ( const std::string & path ,
const std::string & method ,
const FBAPIParam & params ,
const std::string & tag ) ;
use Facebook Open Graph api https://developers.facebook.com/docs/ios/graph
static void fetchFriends ( ) ;
fetch friends data from Facebook
Only friends who has installed the app are returned in API v2.0 and higher of Facebook. The "total_count" in summary represents the total number of friends, including those who haven't installed the app. https://developers.facebook.com/docs/apps/changelog#v2_0
static std::vector <FBGraphUser> getFriends ( ) ;
get friends info
static bool canPresentWithFBApp ( const FBShareInfo & info ) ;
check whether can present Facebook App
static void requestInvitableFriends ( const FBAPIParam & ) ;
Get a vector of invitable friends info which can be used to build a custom friends invite dialog.
static void inviteFriendsWithInviteIds ( const std::vector <std::string> & invite_ids ,
const std::string & title ,
const std::string & invite_text ) ;
Invite friends based on the result obtained from a call to
requestInvitableFriends
static void inviteFriends ( const std::string & app_link_url ,
const std::string & preview_image_url ) ;
Use the default FB dialog to invite friends.
static void setAppId ( const std::string& appId );
Set the Facebook App ID to be used by the FB SDK.
static void setAppURLSchemeSuffix ( const std::string & appURLSchemeSuffix );
Set the app url scheme suffix used by the FB SDK.
Listeners
void onLogin ( bool isLogin , const std::string & msg );
void onSharedSuccess ( const std::string & message );
void onSharedFailed ( const std::string & message );
void onSharedCancel ( );
void onAPI ( const std::string & key , const std::string & jsonData );
void onPermission ( bool isLogin , const std::string & msg );
void onFetchFriends ( bool ok , const std::string & msg );
void onRequestInvitableFriends ( const FBInvitableFriendsInfo & friends );
void onInviteFriendsWithInviteIdsResult ( bool result ,
const std::string & msg );
void onInviteFriendsResult ( bool result , const std::string & msg );
void onGetUserInfo ( const FBGraphUser & userInfo );
手动集成
如果 SDKBOX 安装器 安装插件失败了,那么需要手动集成插件.如果安装器安装插件成功了,那么不需要,也没必要,按文档再手动集成一次.
下面列出的的步骤一般很少用到.如果你按下面的步骤完成了集成,请在完成集成后,再按步骤检查一次.
iOS 平台手动集成
拖拽下列 framework 从 Facebook
插件包的 plugins/ios 目录到您的 Xcode 工程中,在添加 frameworks 的时候,请勾选 Copy items if needed
。
sdkbox.framework
PluginFacebook.framework
上面的 frameworks 依赖于大量其他 frameworks。如果您没有添加它们,您也需要添加下列这些 frameworks:
Security.framework
Android 平台手动集成
拷贝文件
从插件安装包中的 plugin/android/libs
目录拷贝下列 jar 文件到您的工程的 proj.android/libs 目录。
PluginFacebook.jar
sdkbox.jar
-
如果你使用 cocos2d-x 源码,拷贝 jar 文件到:
Android command-line:
cocos2d/cocos/platform/android/java/libs
Android Studio:
cocos2d/cocos/platform/android/libcocos2dx/libs
-
如果你使用 cocos2d-js 或者 lua ,拷贝 jar 文件到:
Android command-line:
frameworks/cocos2d-x/cocos/platform/android/java/libs
Android Studio:
frameworks/cocos2d-x/cocos/platform/android/libcocos2dx/libs
-
如果你使用 cocos2d-x 预编译包,拷贝 jar 文件到:
Android command-line:
proj.android/libs
从 plugin/android/jni
目录拷贝 pluginfacebook
以及 sdkbox
目录到您的工程的 proj.android/jni
目录。如果 sdkbox
目录在工程中已经存在,请覆盖它。
从 plugin/android/libs
拷贝 facebook_lib
目录到您的 proj.android/libs/
目录。
编辑 AndroidManifest.xml
在标签 application tag 上添加下列权限:
<uses-permission android:name="android.permission.INTERNET" />
还有一些必要的元数据标签需要添加:
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:label="@string/app_name" />
<provider android:authorities="com.facebook.app.FacebookContentProvider__replace_with_your_app_id__"
android:name="com.facebook.FacebookContentProvider"
android:exported="true" />
编辑 strings.xml
打开 res/values/strings.xml
,添加一个新的名为 facebook_app_id
的字串,其值是您的 Facebook App ID。比如:
xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">facebook</string>
<string name="facebook_app_id">280194012150923</string>
</resources>
编辑 Android.mk
编辑 proj.android/jni/Android.mk
:
为 LOCAL_STATIC_LIBRARIES 添加额外的库:
LOCAL_STATIC_LIBRARIES += PluginFacebook
LOCAL_STATIC_LIBRARIES += sdkbox
在所有 import-module 语句之前添加一条 call 语句:
$(call import-add-path,$(LOCAL_PATH))
在最后添加额外的 import-module 语句:
$(call import-module, ./sdkbox)
$(call import-module, ./pluginfacebook)
这意味着您的语句顺序看起来像是这样:
$(call import-add-path,$(LOCAL_PATH))
$(call import-module, ./sdkbox)
$(call import-module, ./pluginfacebook)
Note: 如果您使用的是 cocos2d-x 预编译库,那么保证这些语句在已有的 $(call import-module,./prebuilt-mk)
语句之上非常重要。
编辑 Application.mk
(只限 Cocos2d-x v3.0 到 v3.2 版本)
编辑 proj.android/jni/Application.mk
保证 APP_STL 的定义正确。如果 Application.mk
包含了 APP_STL := c++_static
语句,那么这条语句应该被改为:
APP_STL := gnustl_static
修改 AppActivity.java
插件版本 >= 2.4.0.3
- 找到 AppActivity.java 文件
find . -name "AppActivity.java"
- 把
extends Cocos2dxActivity
替换为extends com.sdkbox.plugin.SDKBoxActivity
以下是 AppActivity.java 不同版本的引擎所在的目录:
cpp
- proj.android/src/org/cocos2dx/cpp/AppActivity.java
- proj.android-studio/app/src/org/cocos2dx/cpp/AppActivity.java
- proj.android/app/src/org/cocos2dx/cpp/AppActivity.java ( from cocos2d-x 3.17)
lua
- frameworks/runtime-src/proj.android/src/org/cocos2dx/lua/AppActivity.java
- frameworks/runtime-src/proj.android-studio/app/src/org/cocos2dx/lua/AppActivity.java
- frameworks/runtime-src/proj.android/app/src/org/cocos2dx/lua/AppActivity.java (from cocos2d-x 3.17)
js
- frameworks/runtime-src/proj.android/src/org/cocos2dx/javascript/AppActivity.java
- frameworks/runtime-src/proj.android/app/src/org/cocos2dx/javascript/AppActivity.java ( from cocos2d-x 3.17)
插件版本 < 2.4.0.3
-
如果您使用 cocos2d-x 源代码,假设您在
proj.android
目录下,那么您可以在如下位置找到Cocos2dxActivity.java
文件:../../cocos2d-x/cocos/platform/android/java/src/org/cocos2dx/ lib/Cocos2dxActivity.java
-
如果您使用 cocos2dx-x 预编译库, 假设您在
proj.android
目录下,那么您可以在如下位置找到Cocos2dxActivity.java
文件:./src/org/cocos2dx/lib/Cocos2dxActivity.java
Note: 当你使用 cocos2d-x 源代码时,不同的版本中 Cocos2dxActivity.java
文件的位置也不同。一个确定该文件位置的方法是查看 proj.android/project.properties
。比如:
android.library.reference.1=../../cocos2d-x/cocos/platform/android/java
在这个例子中, Cocos2dxActivity.java
文件应该在如下位置:
../../cocos2d-x/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxActivity.java
- 修改
Cocos2dxActivity.java
文件,导入如下包:
import android.content.Intent;
import com.sdkbox.plugin.SDKBox;
- 然后,修改
Cocos2dxActivity
类的onCreate(final Bundle savedInstanceState)
函数,添加一个调用语句SDKBox.init(this);
。添加的位置非常重要,必须在调用onLoadNativeLibraries();
之后。如下:
onLoadNativeLibraries();
SDKBox.init(this);
-
最后, 我需要提供合适的 overrides 方法的代码。这里有一些约定如下。
-
如果这个被列出的方法没有在
SDKBox
中定义,那么__定义它__。 -
如果这个被列出的方法已经被定义在
SDKBox
中,那么请调用这个在SDKBox
中的__同名方法__。
-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(!SDKBox.onActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
protected void onStart() {
super.onStart();
SDKBox.onStart();
}
@Override
protected void onStop() {
super.onStop();
SDKBox.onStop();
}
@Override
protected void onResume() {
super.onResume();
SDKBox.onResume();
}
@Override
protected void onPause() {
super.onPause();
SDKBox.onPause();
}
@Override
public void onBackPressed() {
if(!SDKBox.onBackPressed()) {
super.onBackPressed();
}
}
混淆 (release模式下可选)
- 编辑
project.properties
指定Proguard
到一个配置文件. 比如:
proguard.config=proguard.cfg
- 编辑这个配置文件,包含以下内容:
-libraryjars libs/facebook_lib/libs/android-support-v4.jar
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
注意: 混淆只在 Release 模式下有效 (比如 cocos run -m release
), 在 debug 模式下,不会调到混淆规则.
Facebook 编译问题
目前 SDKBox 使用的是 Facebook iOS SDK 7.1.1 的静态库.
Facebook iOS SDK 7.1.1 的静态库与 Other Linker Flags
-> -ObjC
存在冲突.
如果编译遇到以下类似错误, 那很有可能是冲突引起的
Could not find or use auto-linked library 'swiftCompatibilityDynamicReplacements'
Could not find or use auto-linked library 'swiftCore'
Could not find or use auto-linked library 'swiftQuartzCore'
Could not find or use auto-linked library 'swiftDispatch'
Could not find or use auto-linked library 'swiftAVFoundation'
Could not find or use auto-linked library 'swiftCoreMedia'
Could not find or use auto-linked library 'swiftCoreAudio'
Could not find or use auto-linked library 'swiftPhotos'
Could not find or use auto-linked library 'swiftCoreMIDI'
Could not find or use auto-linked library 'swiftCoreLocation'
Undefined symbol: protocol descriptor for Foundation._ErrorCodeProtocol
Undefined symbol: associated conformance descriptor for Foundation._ErrorCodeProtocol._ErrorType: Foundation._BridgedStoredNSError
Undefined symbol: base conformance descriptor for Foundation._BridgedStoredNSError: Foundation.CustomNSError
Undefined symbol: base conformance descriptor for Foundation._BridgedStoredNSError: Swift.Hashable
Undefined symbol: base conformance descriptor for Foundation._ErrorCodeProtocol: Swift.Equatable
Undefined symbol: associated conformance descriptor for Foundation._BridgedStoredNSError.Code: Foundation._ErrorCodeProtocol
Undefined symbol: associated conformance descriptor for Foundation._BridgedStoredNSError.Code: Swift.RawRepresentable
Undefined symbol: method descriptor for Foundation._BridgedStoredNSError.init(_nsError: __C.NSError) -> A
Undefined symbol: base conformance descriptor for Foundation.CustomNSError: Swift.Error
Undefined symbol: method descriptor for static Foundation.CustomNSError.errorDomain.getter : Swift.String
Undefined symbol: method descriptor for Foundation._ObjectiveCBridgeableError.init(_bridgedNSError: __shared __C.NSError) -> A?
Undefined symbol: method descriptor for Swift.Error._code.getter : Swift.Int
Undefined symbol: method descriptor for Swift.Error._userInfo.getter : Swift.AnyObject?
Undefined symbol: method descriptor for Swift.Error._getEmbeddedNSError() -> Swift.AnyObject?
Undefined symbol: protocol conformance descriptor for Swift.Int : Swift.FixedWidthInteger in Swift
Undefined symbol: type metadata for Swift.Int
Undefined symbol: protocol descriptor for Foundation.CustomNSError
Undefined symbol: static Swift._DictionaryStorage.allocate(capacity: Swift.Int) -> Swift._DictionaryStorage<A, B>
Undefined symbol: __swiftEmptyDictionarySingleton
解决方法A
- 去掉
Project Setting
->Build Settings
->Linking
->Other Linker Flags
->-ObjC
就可以解决这些错误
解决方法B
-
如果你的工程不能去掉
-ObjC
, 那你需要将 Facebook 静态库替换为动态库 -
解压并替换工程中的 Facebook 相关的文件
FBSDK*.framework
文件. -
调整 Xcode 设置,
Project Setting
->General
->Frameworks, Libraries, and Embedded Content
下的FBSDK*.framework
设置为Embed & Sign
Facebook 编译问题
如果编译遇到以下类似错误
dyld: Library not loaded: @rpath/libswiftCore.dylib
可以尝试这个方法, 调整 Xcode 设置, Project
-> target
-> Build Setting/All
-> Always Embed Swift Standard Libraries
设置为 YES
Facebook Crash 问题
如果你遇到了如下错误:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSError fbErrorFromReturnURLParameters:]: unrecognized selector sent to class 0x1e0bdf480'
可以尝试添加如下设置到 Other Linker Flags
:
-ObjC
-force_load
${PROJECT_DIR}/Frameworks/FBSDKLoginKit.framework/FBSDKLoginKit
-force_load
${PROJECT_DIR}/Frameworks/FBSDKCoreKit.framework/FBSDKCoreKit
Facebook 登录界面
现象: iOS 13 中, 横屏调用 FB 登录, 当弹出 “在Facebook中打开” 对话框时, 点击无效.
在 Info.plist
中的 LSApplicationQueriesSchemes
中的不应该包含 fb-messenger-api20140430
.
fb-messenger-api20140430
是旧版FBSDK使用的. 新版可能应该是 fb-messenger-share-api