1. 程式人生 > >Unity3D-呼叫IOS原生分享的實現

Unity3D-呼叫IOS原生分享的實現

連線

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

看看效果圖:

彈出框


分享文字


分享帶截圖文字


連線

相關推薦

Unity3D-呼叫IOS原生分享實現

連線 最近專案需要更改分享方式,以前接入各種SKD去分享的,現在要求直接使用IOS原生分享的介面! 一開始去網上找,發現並沒有人直接寫程式碼使用,但是在Unity的AssetStore中我找到了一個外掛,也就是IOSNative外掛,但是外掛帶的功能比較多,我自己基本用不到

Unity3D 嵌入iOS原生程式碼,並實現unity iOS之間的互動

Unity iOS嵌入 互動 傳值 專案需要用到iOS和Unity之間的互動, 就捯飭了一下 我專案是Unity工程大, iOS工程小, 所以在是Unity匯出的xcode工程裡嵌入iOS

Unity呼叫iOS原生內購

Unity在5.x以後的版本,都附帶了各種平臺的IAP(內購),網上一搜Unity IAP,就一大堆如何如何接入的教程,據說還挺方便的。本人也是用Unity 5.x,也曾經用了一下Unity的IAP,那為何現在還要討論呼叫iOS原生的IAP呢? 在這裡不得不吐槽一下Unity的IAP,雖然它目的

React Native呼叫Android原生程式碼實現車牌識別功能【附效果圖附原始碼】

        這段時間研究了下React Native,Facebook推出的,結合了Web應用和Native應用的優勢,可以使用JavaScript來開發iOS和Android原生應用,決定簡單研究下,於是開始搭建環境,編寫HelloWorld,完成後又覺得HelloWo

iOS開發(OC)——iOS原生API實現檔案下載

新建繼承NSObject類Downloader Downloader.h程式碼 #import <Foundation/Foundation.h> #import <UIKit

[iOS 原生程式碼實現掃描二維碼/條形碼] AVCaptureDevice

//參照別人的教程的作業貼 記錄一下注意點 掃碼的主要原生程式碼如下 這裡比較關鍵的是對掃碼作用範圍的確定,metdataOutput.rectOfInterest 如果不設定,那麼預設就

React Native 呼叫iOS原生功能—直播

專案 中 採用React Native 開發 ,觀看直播呼叫iOS 原生介面 RN程式碼 import React, { Component } from 'react'; import { Platform, StyleSheet, Text, V

Unity3D呼叫iOS攝像頭全屏旋轉,ZXing測試

在測試Unity3D ZXing程式碼時,呼叫iOS攝像頭的效果總不令我滿意,你會發現用WebCamTexture呼叫的攝像頭畫面跟iOS自帶相簿呼叫的效果不一樣,焦距有點問題。雖然這不影響ZXing的呼叫,但我還是搜了下,解決了這個問題,還可以適應螢幕旋轉。參

Unity3D 呼叫Android原生方法2

記一次Unity通過Android系統函式獲取記憶體資訊的過程,感謝河馬爸爸指導。 Unity原生方法沒有獲取當前可用記憶體的方法,系統記憶體資訊android底層肯定有方法獲取,於是我搜到了這篇文章(http://blog.csdn.net/sxwyf248/articl

ios webView怎麼實現原生呼叫JS?

在iOS 7之後,apple添加了一個新的庫JavaScriptCore,用來做JS互動,因此JS與原生OC互動也變得簡單了許多。 第一種方法 首先匯入JavaScriptCore庫, 然後在OC中獲取JS的上下文 JSContext *context = [self.web

vue 實現 ios 原生picker 效果(實現思路分析)

sta 效果 cursor touchend orm dex tex sub alt 以前最早實現了一個類似的時間選擇插件,但是適用範圍太窄,索性最近要把這個實現方式發布出來,就重寫了一個高復用的vue組件。 支持安卓4.0以上,safari 7以上 效果預覽 gitHu

WebViewJavascriptBridge實現js與android和ios原生交互

WebViewJavascriptB Android IOS js 1、實現原生與js交互 <!-- 申明交互 這段代碼固定必須有 --> function setupWebViewJavascriptBridge(callback) { //android使用

ios webView怎麼實現JS調原生

1)在方法- (void)webViewDidFinishLoad:(UIWebView *)webView 中 self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScr

在微擎呼叫微信JSSDK實現分享功能

最近遇到一個專案是基於微擎框架做一個分享功能的,微擎本身是自帶分享功能的,只是這次想要實現自定義分享內容,故進行了以下程式碼處理 * $_W[‘account’][‘jssdkconfig’]是微擎封裝好的jssdk簽名包的內容 * php頁面程式碼 <?php if

JavaScript:使用原生JS實現Jsonp跨域,呼叫百度搜索介面完成聯想詞功能

Jsonp解釋 Jsonp這個術語聽起來很高大上,其實它的原理非常簡單,就是利用src不受同源策略限制這一點來實現的,很多標籤都有src特性。 你們可以想想為什麼img標籤能將不同源的百度logo拿過來? <img src="https://www.baidu.com/

呼叫微信介面實現網頁分享小功能

// 獲取access_token  *注意* 經過實際開發測試,微信分享不支援跨域請求,因此獲取access_token的請求必須從伺服器發起,否則無法獲取到access_token所以以下都是服務端操作 一、微信util類 public class Share

iOS原生實現二維碼拉近放大

http://www.cocoachina.com/ios/20180416/23033.html 2018-04-16 15:34 編輯: yyuuzhu 分類:iOS開發 來源:程式鵝 8 3008 iOS &nb

Unity3D 呼叫Android與IOS的剪貼簿

Unity3D剪貼簿 最近遇到一個需要呼叫Android與IOS裝置本身剪貼簿的需求,就是在Unity中,要將文字複製到裝置本身的剪貼簿中,然後在其他應用程式中都能貼上。 最開始在網上查到的方式是使用Unity3D本身自帶的TextEditor 類進行使用,使用方法如

基於ES6和原生nodejs實現自定義路由,靜態檔案伺服器和增刪查改的MVC架構分享

基於ES6和原生nodejs來實現一個基於MVC的增刪查改功能示例分享 自定義路由的解耦實現 首先分別處理不同方式的請求: const http = require('http'); const url = require('url')

cocos2d-x + Lua接入iOS原生SDK的實現方案

相信很多朋友在使用cocos2d-x+lua開發遊戲時都遇到過接入iOS原生SDK的問題,比如常見的接應用內支付SDK,廣告SDK或是一些社交平臺SDK等等,我也沒少接過這類SDK。這篇文章主要是對我做過專案中接入iOS原生SDK實現方案的一個總結,在這裡分享給大家,希望對自己和大家的開發工作都有幫