最近项目需要更改分享方式,以前接入各种SKD去分享的,现在要求直接使用IOS原生分享的接口!
一开始去网上找,发现并没有人直接写代码使用,但是在Unity的AssetStore中我找到了一个插件,也就是IOSNative插件,但是插件带的功能比较多,我自己基本用不到,然后就自己写了一个和IOS交互的oc类,只调用系统自带的分享框,并且拿到是否点击了分享还是取消的回调。
先在导出的xcode工程中创建一个类GJCSocialShare, 我在参考了IOSNative插件的基础上,修改了下显示位置,使Ipad也能显示在屏幕下方
.h文件内容
#import <UIKit/UIKit.h>
@interface GJCSocialShare : NSObject
+ (id) sharedInstance;
- (void) nativeShare:(NSString*)text media: (NSString*) media;
@end
@interface GJC_DataConvertor : NSObject
+ (NSString*) charToNSString: (char*)value;
+ (const char*) NSIntToChar: (NSInteger) value;
+ (const char*) NSStringToChar: (NSString*) value;
+ (NSArray*) charToNSArray: (char*)value;
+ (const char*) serializeErrorWithData:(NSString*)description code: (int) code;
+ (const char*) serializeError:(NSError*)error;
+ (NSMutableString*) serializeErrorWithDataToNSString:(NSString*)description code: (int) code;
+ (NSMutableString*) serializeErrorToNSString:(NSError*)error;
+ (const char*) NSStringsArrayToChar:(NSArray*) array;
+ (NSString*) serializeNSStringsArray:(NSArray*) array;
@end
这其中的DataConvertor是参考的IOSNative插件里面,为了更方便的使用数据
.mm文件内容
#import "GJCSocialShare.h"
#import <Social/Social.h>
NSString* const STR_SPLITTER = @"|";
NSString* const STR_EOF = @"endofline";
NSString* const STR_ARRAY_SPLITTER = @"%%%";
@implementation GJCSocialShare
static GJCSocialShare* gjc_sharedInstance;
+ (id)sharedInstance {
if (gjc_sharedInstance == nil) {
gjc_sharedInstance = [[self alloc] init];
}
return gjc_sharedInstance;
}
-(void) nativeShare:(NSString*)text media:(NSString*)media {
NSLog(@"==============>nativeShare");
UIActivityViewController *controller;
if(media.length != 0) {
NSData* imageData = [[NSData alloc]initWithBase64EncodedString:media options:0];
UIImage* image = [[UIImage alloc] initWithData:imageData];
NSLog(@"==============>image added");
if(text.length != 0) {
NSLog(@"==============>text added");
controller = [[UIActivityViewController alloc] initWithActivityItems:@[text, image] applicationActivities:nil];
} else {
NSLog(@"==============>no text");
controller = [[UIActivityViewController alloc] initWithActivityItems:@[image] applicationActivities:nil];
}
} else {
NSLog(@"==============>no image");
controller = [[UIActivityViewController alloc] initWithActivityItems:@[text] applicationActivities:nil];
}
UIViewController* vc = UnityGetGLViewController();
NSArray* vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
if ([[vComp objectAtIndex:0] intValue] >= 8) {
UIPopoverPresentationController *presentationController = [controller popoverPresentationController];
presentationController.sourceView = vc.view;
presentationController.sourceRect = CGRectMake(vc.view.bounds.origin.x+vc.view.bounds.size.width/2,
vc.view.bounds.origin.y+vc.view.bounds.size.height,
0, 0);
presentationController.permittedArrowDirections = 0;
}
[vc presentViewController:controller animated:YES completion:nil];
controller.completionWithItemsHandler = ^(UIActivityType _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) {
// NSLog(@"activityType :%@", activityType);
if (completed){
UnitySendMessage("GJCNativeShare", "OnNativeShareSuccess", [GJC_DataConvertor NSStringToChar:activityType]);
// NSLog(@"completed!");
}else{
if (activityType != nil){
UnitySendMessage("GJCNativeShare", "OnNativeShareCancel", [GJC_DataConvertor NSStringToChar:activityType]);
}else{
UnitySendMessage("GJCNativeShare", "OnNativeShareCancel", [GJC_DataConvertor NSStringToChar:@""]);
}
// NSLog(@"cancel!");
}
};
}
@end
@implementation GJC_DataConvertor
+(NSString*) charToNSString:(char*)value {
if (value != NULL) {
return [NSString stringWithUTF8String: value];
} else {
return [NSString stringWithUTF8String: ""];
}
}
+(const char*)NSIntToChar:(NSInteger)value {
NSString* tmp = [NSString stringWithFormat:@"%ld", (long)value];
return [tmp UTF8String];
}
+ (const char*) NSStringToChar:(NSString*)value {
return [value UTF8String];
}
+ (NSArray*)charToNSArray:(char*)value {
NSString* strValue = [GJC_DataConvertor charToNSString:value];
NSArray* array;
if([strValue length] == 0) {
array = [[NSArray alloc] init];
} else {
array = [strValue componentsSeparatedByString:STR_ARRAY_SPLITTER];
}
return array;
}
+ (const char*) NSStringsArrayToChar:(NSArray*) array {
return [GJC_DataConvertor NSStringToChar:[GJC_DataConvertor serializeNSStringsArray:array]];
}
+ (NSString*) serializeNSStringsArray:(NSArray*) array {
NSMutableString* data = [[NSMutableString alloc] init];
for(NSString* str in array) {
[data appendString:str];
[data appendString: STR_ARRAY_SPLITTER];
}
[data appendString: STR_EOF];
NSString* str = [data copy];
#if UNITY_VERSION < 500
[str autorelease];
#endif
return str;
}
+ (NSMutableString*)serializeErrorToNSString:(NSError*)error {
NSString* description = @"";
if(error.description != nil) {
description = error.description;
}
return [self serializeErrorWithDataToNSString:description code: (int) error.code];
}
+ (NSMutableString*)serializeErrorWithDataToNSString:(NSString*)description code:(int)code {
NSMutableString* data = [[NSMutableString alloc] init];
[data appendFormat:@"%i", code];
[data appendString: STR_SPLITTER];
[data appendString: description];
return data;
}
+ (const char*) serializeErrorWithData:(NSString*)description code: (int) code {
NSString* str = [GJC_DataConvertor serializeErrorWithDataToNSString:description code:code];
return [GJC_DataConvertor NSStringToChar:str];
}
+ (const char*) serializeError:(NSError*)error {
NSString* str = [GJC_DataConvertor serializeErrorToNSString:error];
return [GJC_DataConvertor NSStringToChar:str];
}
@end
extern "C" {
void _GJC_NativeShare(char* text, char* encodedMedia) {
NSString* status = [GJC_DataConvertor charToNSString:text];
NSString* media = [GJC_DataConvertor charToNSString:encodedMedia];
[[GJCSocialShare sharedInstance] nativeShare:status media:media];
}
}
这两个文件放在Assets的Plugins/iOS下面,另外还需要写一个C#端的使用方法和回调:
.cs文件,注意文件的名称,以及挂在场景中对象的名称,如果和我的不一样,你需要把.mm中使用UnitySendMessage方法中添加的第一个参数的字符串名字保持一致
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_IPHONE && !UNITY_EDITOR
using System.Runtime.InteropServices;
#endif
public class GJCNativeShare : MonoBehaviour {
#if UNITY_IPHONE && !UNITY_EDITOR
[DllImport ("__Internal")]
private static extern void _GJC_NativeShare(string text, string encodedMedia);
#endif
public delegate void OnShareSuccess(string platform);
public delegate void OnShareCancel(string platform);
public OnShareSuccess onShareSuccess = null;
public OnShareCancel onShareCancel = null;
private static GJCNativeShare _instance = null;
public static GJCNativeShare Instance {
get {
if (_instance == null) {
_instance = GameObject.FindObjectOfType(typeof(GJCNativeShare)) as GJCNativeShare;
if (_instance == null) {
_instance = new GameObject ().AddComponent<GJCNativeShare> ();
_instance.gameObject.name = _instance.GetType ().FullName;
}
}
return _instance;
}
}
public void NativeShare(string text, Texture2D texture = null) {
Debug.Log("NativeShare");
#if UNITY_IPHONE && !UNITY_EDITOR
if(texture != null) {
Debug.Log("NativeShare: Texture");
byte[] val = texture.EncodeToPNG();
string bytesString = System.Convert.ToBase64String (val);
_GJC_NativeShare(text, bytesString);
} else {
Debug.Log("NativeShare: No Texture");
_GJC_NativeShare(text, "");
}
#endif
}
private void OnNativeShareSuccess(string result){
// Debug.Log("success: " + result);
if (onShareSuccess!=null){
onShareSuccess(result);
}
}
private void OnNativeShareCancel(string result){
// Debug.Log("cancel: " + result);
if (onShareCancel != null){
onShareCancel(result);
}
}
}
接下来就是使用,本方法可以传递一个分享的字符串和一个屏幕截屏:
在Init中添加回调:
public void Init(){
blnInitNativeShare = true;
GJCNativeShare.Instance.onShareSuccess = OnShareSuccess;
GJCNativeShare.Instance.onShareCancel = OnShareCancel;
}
void OnShareSuccess(string platform){
//...your code
}
void OnShareCancel(string platform){
//...your code
}
然后是调用
public void ShareWithNative(){
StartCoroutine(TakeScreenshot());
}
private IEnumerator TakeScreenshot()
{
yield return new WaitForEndOfFrame();
var width = Screen.width;
var height = Screen.height;
var tex = new Texture2D(width, height, TextureFormat.RGB24, false);
// Read screen contents into the texture
tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
tex.Apply();
GJCNativeShare.Instance.NativeShare(shareDefaultText, tex);
Destroy(tex);
}
另外,需要在unity中选中.mm文件,现在可以直接在Unity编辑器中选中需要添加的IOS framework包,把Social勾上即可在xcode中添加这个framework
看看效果图:弹出框
分享文字
分享带截图文字