原文发表于Unity中国论坛 ,如果对你有帮助请关注我!

Unity游戏如何在iOS上调用Facebook原生对话框分享图片 - Unity​unity.cn

手头上的一个游戏项目需要实现截屏并分享到Facebook的功能,但Facebook Unity SDK提供的两个接口:FB.FeedShare() 和 FB.ShareLink,前者会弹出一个Web登录提示框,用户需要登录后才能分享,用户体验流程繁琐。后者虽然不需要登录就可以调用Facebook原生的分享对话框,但只能分享链接不能直接分享本地图片。这意味着如何要实现将屏幕截图分享到Facebook的功能,我们需要先将本地截屏的图片上传到某个图床,获取图片的链接然后再调用FB.ShareLink() 才行。这个方法虽然勉强也可以实现分享图片的功能,但过程仍然繁琐,而且分享到Facebook的图片是以外链网页的缩略图方式展示的,要查看全图还要再次点击打开,也不大符合我们的要求。进一步研究了Facebook SDK的文档,发现iOS SDK提供了直接调用Facebook原生对话框分享图片的功能,于是有了下面的Objectiv-C插件的解决方案。

开始之前

本文中的代码在Unity3D 2019.3.6f 以及Xcode 11.3.1中调试通过

开始之前,请下载并导入最新版本的Facebook SDK for Unity https://developers.facebook.com/docs/unity/downloads/

在Assets/Plugins/iOS目录下创建Objective-C插件

我们需要创建三个文件放在Assets/Plugins/iOS目录下,这样在Unity打包输出xcode工程项目时会自动将文件拷贝到工程的Libraries/Plugins/iOS目录并添加正确的引用。这三个文件的作用分别如下:

  • NativeFBShareDelegate.h : 定义继承自FBSDKSharingDelegate的回调接口,接受Facebook原生对话框分享成功、取消、错误消息回调。
  • NativeFBShareDelegate.m:回调接口的实现代码,收到Facebook原生对话框分享的消息回调后,使用UnitySendMessage() 方法把结果发送给Unity C#脚本。
  • NativeFBShare.mm:定义C#中调用的Native Plugin接口方法,调用Facebook iOS SDK打开原生分享对话框(注意这个文件的后缀名要使用.mm)

NativeFBShareDelegate.h 源代码

#import <FBSDKShareKit/FBSDKShareKit.h>@interface NativeFBShareDelegate : NSObject<FBSDKSharingDelegate>+ (instancetype)instanceWithRequestID:(int)requestID;@end

NativeFBShareDelegate.m 源代码

#import <Foundation/Foundation.h>
#import "NativeFBShareDelegate.h"
#import "FBUnityUtility.h"
#import "UnityInterface.h"//Unity 中接收回调消息的游戏对象名称
const char* const GAME_OBJECT_NAME = "FBShareButton";
//Unity 中处理回调消息的方法名称
const char* const FBUnityMethodName_OnFacebookShareNativeCallback = "OnFacebookShareNativeCallback"; static NSMutableArray *g_instances;@implementation NativeFBShareDelegate {int _requestID;
}+ (void)initialize
{if (self == [NativeFBShareDelegate class]) {g_instances = [NSMutableArray array];}
}- (void)complete
{[g_instances removeObject:self];
}+ (instancetype)instanceWithRequestID:(int)requestID
{NativeFBShareDelegate *instance = [[NativeFBShareDelegate alloc] init];instance->_requestID = requestID;[g_instances addObject:instance];return instance;
}#pragma mark - FBSDKSharingDelegate- (void)sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results
{NSLog(@"FBShareComplete");//分享成功,返回字符串“success”UnitySendMessage(GAME_OBJECT_NAME, FBUnityMethodName_OnFacebookShareNativeCallback, "success");[self complete];
}- (void)sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error
{NSLog(@"FBShareError");//分享发生错误时,返回字符串“error”UnitySendMessage(GAME_OBJECT_NAME, FBUnityMethodName_OnFacebookShareNativeCallback, "error");[self complete];
}- (void)sharerDidCancel:(id<FBSDKSharing>)sharer
{NSLog(@"FBShareCancelled");//用户取消了分享,返回字符串“cancelled”UnitySendMessage(GAME_OBJECT_NAME, FBUnityMethodName_OnFacebookShareNativeCallback, "cancelled");[self complete];
}@end

NativeFBShare.mm 源代码

#import <FBSDKShareKit/FBSDKShareKit.h>
#import "FBUnitySDKDelegate.h"
#import "FBUnityUtility.h"
#import "NativeFBShareDelegate.h"#ifdef UNITY_4_0 || UNITY_5_0
#import "iPhone_View.h"
#else
extern UIViewController* UnityGetGLViewController();
#endifextern "C" void _NativeFacebookShare( const char* imagePath )
{NSString *imgPath = [[NSString alloc]initWithUTF8String:imagePath];NSLog(@"_NativeFacebookShare local image path: %@", imgPath);UIImage *image = [UIImage imageWithContentsOfFile:imgPath];FBSDKSharePhoto *photo = [[FBSDKSharePhoto alloc] init];photo.image = image;photo.userGenerated = YES;FBSDKSharePhotoContent *content = [[FBSDKSharePhotoContent alloc] init];content.photos = @[photo];UIViewController *rootViewController = UnityGetGLViewController();FBSDKShareDialog *dialog = [[FBSDKShareDialog alloc] init];dialog.fromViewController = rootViewController;dialog.shareContent = content;dialog.mode = FBSDKShareDialogModeAutomatic;NativeFBShareDelegate *delegate = [NativeFBShareDelegate instanceWithRequestID:1];dialog.delegate = delegate;NSError *error;if (![dialog validateWithError:&error]) {[FBUnityUtility sendErrorToUnity:FBUnityMessageName_OnShareLinkComplete error:error requestId:1];}if (![dialog show]) {[FBUnityUtility sendErrorToUnity:FBUnityMessageName_OnShareLinkComplete errorMessage:@"Failed to show share dialog_" requestId:1];}}

在Unity 中调用Facebook的原生分享对话框

在Unity中,可以用下面的C#代码调用刚才实现的iOS原生插件接口:

#if UNITY_IOS || UNITY_IPHONE
[System.Runtime.InteropServices.DllImport( "__Internal" )]
private static extern bool _NativeFacebookShare(string localImagePath);
#endif

我们在Unity中创建一个Button,如下图:

注意Button命名为FBShareButton,这个GameObject名字我们稍后还会用到),挂上下面的脚本,即可实现截屏并分享到Facebook的功能。

using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;public class FacebookShareButton : MonoBehaviour
{void Awake() {GetComponent<Button>().onClick.AddListener(_OnButtonClick);}private void _OnButtonClick(){this.transform.localScale = Vector3.zero;StartCoroutine(_ShareOnFacebook());      }private IEnumerator _ShareOnFacebook(){string screenshotFileName = "screenshot.png";string screenshotFilePath = Path.Combine(Application.persistentDataPath,screenshotFileName);;if(File.Exists(screenshotFilePath)){File.Delete(screenshotFilePath);}yield return new WaitForEndOfFrame();ScreenCapture.CaptureScreenshot(screenshotFileName);while(!File.Exists(screenshotFilePath)){yield return null;}#if UNITY_IOS || UNITY_IPHONE_NativeFacebookShare(screenshotFilePath);#elif UNITY_ANDROID//TODO: Calling Android native plugin to share on Facebook#endif}#if UNITY_IOS || UNITY_IPHONE[System.Runtime.InteropServices.DllImport( "__Internal" )]private static extern bool _NativeFacebookShare(string localImagePath);#endif

下面是在iPhone真机上运行的结果

获取分享结果的回调通知

有时我们需要知道Facebook分享的结果来实现一些功能,比如如果用户分享失败,则弹出对话框让用户重试一遍。为了实现这个功能,我们在NativeFBShareDelegate.hNativeFBShareDelegate.m中定义并实现了FBSDKSharingDelegate的回调接口,并在NativeFBShare.mm中创建了这个delegate的实例并注册到FBSDKShareDialog,在收到Facebook原生对话框分享的消息回调后,再使用UnitySendMessage() 方法把结果发送给Unity C#脚本。

UnitySendMessage是Unity提供的一个工具方法,可以从iOS Native Plugin向Unity 游戏对象发送消息。这个方法的签名如下:

void UnitySendMessage(const char* obj, const char* method, const char* msg);

其中第一个参数是接受这个消息的游戏对象名称,第二个参数是这个对象上所绑定的脚本接受回调的方法名称,第三个参数是发送的消息内容,只能是字符串。

在本文前面给出的示例代码中

  • 我们接收消息的游戏对象名字为FBShareButton
  • 处理回调消息的方法名称是OnFacebookShareNativeCallback(string)
  • 用户分享成功返回“success”,发生错误返回“error”,取消返回“cancelled”

我们给FacebookShareButton.cs脚本添加OnFacebookShareNativeCallback(string)方法来接收分享结果的回调消息。

private Text m_ResultText;
void Start()
{m_ResultText = this.transform.Find("Text").GetComponent<Text>();m_ResultText.text = "";
}public void OnFacebookShareNativeCallback(string result)
{Text shareResult = GetComponent<Text>();if(string.Equals(result, "success")){shareResult.text = "FB Share Result: Succeed";}else if(string.Equals(result, "cancelled")){shareResult.text = "FB Share Result: Cancelled";}else{shareResult.text = "FB Share Result: Error";}
}

下面是在iPhone上运行的结果

参考资料

Unity3D关于构建iOS上Native Plugin的官方文档

Facebook Sharing on iOS

web dialog 内嵌 图片_Unity游戏如何在iOS上调用Facebook原生对话框分享图片相关推荐

  1. Qt for Android 调用android原生接口分享图片或文字

    在用Qt开发android应用的时候,有一个需求是通过调用android原生接口去实现图片分享功能,原理很简单,首先在java文件中用android接口封装一个分享功能的方法,然后在C++中调用QAn ...

  2. 苹果状态栏HTML,webview内嵌的html页面,在ios系统上12以上版本和12以下版本状态栏效果不一样...

    详细问题描述 (DCloud产品不会有明显的bug,所以你遇到的问题大都是在特定环境下才能重现的问题,请仔细描述你的环境和重现方式,否则DCloud很难排查解决你的问题) [内容] 重现步骤 在vue ...

  3. 嵌入式:ARM内嵌汇编及C和ARM汇编相互调用

    内嵌汇编 在C程序中嵌入汇编程序可以实现一些高级语言没有的功能,并可以提高执行效率.armcc和armcpp内嵌汇编器支持完整的ARM指令集:tcc和tcpp用于Thumb指集.但是内嵌汇编器并不支持 ...

  4. STM32如何在LCD上显示单词、文字、图片等

    本文将介绍STM32F103R6如何在LCD12864上显示文字图片 注:本文中用到的字模软件,我放在了文章末尾,点击链接即可下载,是绿色版软件,解压即可使用! 点击下载LCD12864上显示文字图片 ...

  5. 13.tornado操作之增加用户喜欢的图片展示页+同时展示用户上传的所有图片增加展示图片有多少用户喜欢的功能

    目录: 第一部分:增加用户喜欢的图片展示页 1.基本步骤先走起来--视图+接口+前端模板 (1)编写视图ProfileHandler: (2)编写接口:(app.py文件中加入以下接口) (3)编写前 ...

  6. linux安装2048游戏,如何在CentOS上安装一个2048小游戏

    如何在centos上安装一个2048小游戏 最近在学习CentOS系统,就琢磨着玩点什么,然后我看到有人在玩2048小游戏,所有我就在想,为啥不装一个2048小游戏搞一下嘞,于是乎,我就开始工作啦 由 ...

  7. 识别图片文字转换成word文字真的很难吗?分享图片转文字的技巧

    在我们日常办公中,图片转文字.图片转 word 文字运营的十分广泛,并且使用起来非常节约时间,但要是说如何快速的实现图片转文字,相信很多人就不知道了,下面分享便捷的图片转文字的方法介绍,有需要的朋友可 ...

  8. android dialog内嵌listview样式,android 開發dialog 嵌套listview布局

    示例代碼: 示例:public void setDialog(){ LayoutInflater inflater=LayoutInflater.from(this);//將xml布局轉換為view ...

  9. android app 内嵌h5小游戏

    layabox打包android APP 原理: 其实就是在app内部放置一个浏览器内核,这个内核可以是浏览器的系统内核,也可以是腾讯的x5内核,一般使用腾讯浏览器的x5内核,如果环境不允许,则使用默 ...

最新文章

  1. VC屏幕截图并保存为bmp文件
  2. [Algorithm] Good Fibonacci
  3. Apache多网站虚拟目录域名
  4. 64位有符号与无符号类型的整数
  5. 【旧文章搬运】无Device的驱动如何通信
  6. 1.3 使用电脑测试MC20的电话语音功能
  7. Shopify 入门 (英文)
  8. Collection与Map
  9. vdbench和fio
  10. Java日期时间格式转换
  11. 人才管理是什么意思_hr是什么意思(HR到底是干什么的?)
  12. 云通讯im怎么做php回调,腾讯云IM接入案列(一)
  13. php抓取关键词排名,如何 用php抓取google关键词排名?
  14. XCELSIUS例子(CX钻取).
  15. Excel的25个知识~边看边操作
  16. LCEDA-国产PCB设计工具
  17. NLP之NER:商品标题属性识别探索与实践
  18. 中学计算机社团活动计划,社团活动方案
  19. C#实现jQuery的方法连缀
  20. 2D降噪3D降噪(NR:Noise Reduce)

热门文章

  1. java的断点条件,java – 非行依赖的条件断点
  2. linux入门 适合初学者_经过慎重考虑,我拿出这套适合初学者入门的Java基础完整版视频...
  3. python查看包的路径_获取python及三方包的版本,安装路径等信息
  4. 《Essential C++》笔记之设计一个泛型算法(一)
  5. 如何自建微信外卖平台_外卖平台高抽成的背后,看小程序如何玩转餐饮外卖?...
  6. php++背景自适应屏幕宽度,背景图片+自适应屏幕
  7. Java三层结构的概念_Java中的mvc和三层结构究竟是什么关系
  8. git出现红字说明什么_怀孕的第一个月会出现什么变化?若有7种表现,说明可能怀上了...
  9. php 如何保存录像文件,如何录制屏幕并保存下来?
  10. vue webpack压缩代码_webpack不混淆、不压缩指定js文件