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

8a989018f97850c4ba960ceb870d2cfa.png

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

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

手头上的一个游戏项目需要实现截屏并分享到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();
#endif

extern "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,如下图:

eb5573dfab7a82b8ec2b28f42e567cd7.png

注意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真机上运行的结果

6cea2c474dac351ff15fe615e147563e.png

获取分享结果的回调通知

有时我们需要知道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上运行的结果

06b80d18edc7025fe5b4da207be147a3.png

参考资料

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

Facebook Sharing on iOS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值