Unity3D-调用IOS原生分享的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pz789as/article/details/74526775

连接

最近项目需要更改分享方式,以前接入各种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

看看效果图:

弹出框



分享文字



分享带截图文字



连接

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试