Unity

【UnityAsset】SocialWorker – Twitter、Facebook、Line、Instagram、メールへの個別連携

ここではSocialWorkerの紹介を行いたいと思います。

SocialWorkerとは

SocialWorkerは、iOS/AndroidでのTwitter、Facebook、Line、Instagram、メールへの連携を簡単に行うことが出来るAssetです。

  • 連携可能データ:メッセージ/画像
  • OAuth認証:なし

SocialWorkerは各種SNSへの簡単なデータの受け渡しをサポートしています。連携可能なデータはメッセージと画像のみです。
連携方法は、iOSではURLSchemeを主に使用しており、AndroidではIntentによるデータの受け渡しの方法を取っています。

動作環境

Unity5.5.0+
iOS 6.0+
Android 2.3+

使用方法

SocialWorker Prefab の設置

Project「SocialWorker/Prefabs/SocialWorker」をHierarchyに設置。

スクリプトから連携メソッドを呼ぶ

SocialWorker.PostTwitter(string message, string url, string imagePath, Action<SocialWorkerResult> onResult = null)
SocialWorker.PostFacebook(string imagePath, Action<SocialWorkerResult> onResult = null)
SocialWorker.PostLine(string message, string imagePath, Action<SocialWorkerResult> onResult = null)
SocialWorker.PostInstagram(string imagePath, Action<SocialWorkerResult> onResult = null)
SocialWorker.PostMail(string[] to, string[] cc, string[] bcc, string subject, string message, string imagePath, Action<SocialWorkerResult> onResult = null)
SocialWorker.CreateChooser(string message, string imagePath, Action<SocialWorkerResult> onResult = null)

解説

次に各種SNSのサポート内容を解説します。どのように連携を行っているかネイティブプラグインのコードを載せていますが、SocialWorker使用時にこれらのコードを操作する必要はありません。ご注意下さい。

Twitter連携

メッセージ、URL、画像の投稿をサポート。

iOSではSocial.frameworkを使用し、AndroidではIntentによる方法です。iOS/Android共にFacebookと処理を共通化しています。
全てのSNS連携に共通する処理としてアプリの存在判定を行っています。アプリが存在しなかった場合はUnity側にNotAvailableの結果が返るので、その値を見て処理することになります。
投稿可能な画像はPNG/JPGのみです。それと、画像は予めSDカードに保存しておく必要があります(Gmailに画像を添付する場合、SDカードに保存されていないと添付されない)。

SceneDemo.cs

string message   = "message";
string url       = "http://yedo-factory.co.jp/";
string imagePath = Application.persistentDataPath + "/image.png";
SocialWorker.PostTwitter(message, url, imagePath);

SocialWorker.mm

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <Social/Social.h>

static const char *kUnitySendGameObject = "SocialWorker";
static const char *kUnitySendCallback   = "OnSocialWorkerResult";

static const char *kResultSuccess      = "0";
static const char *kResultNotAvailable = "1";
static const char *kResultError        = "2";

@interface SocialWorker : NSObject
@end

@implementation SocialWorker
/**
 * Twitter or Facebook 投稿。ただしFacebookは画像の投稿のみ許可しており、テキストの投稿は無視されることに注意。
 * @param isTwitter true:Twitter、false:Facebook
 * @param message メッセージ
 * @param url URL。空文字の場合は処理されない。
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
- (void)postTwitterOrFacebook:(BOOL)isTwitter message:(NSString *)message url:(NSString *)url imagePath:(NSString *)imagePath {
    NSString *type = (isTwitter) ? SLServiceTypeTwitter : SLServiceTypeFacebook;
    if ([SLComposeViewController isAvailableForServiceType:type]) {
        SLComposeViewController *vc = [SLComposeViewController composeViewControllerForServiceType:type];
        [vc setInitialText:message];
        if([url length] != 0) {
            [vc addURL:[NSURL URLWithString:url]];
        }
        if([imagePath length] != 0) {
            [vc addImage:[UIImage imageWithContentsOfFile:imagePath]];
        }
        [vc setCompletionHandler:^(SLComposeViewControllerResult result) {}];
        [UnityGetGLViewController() presentViewController:vc animated:YES completion:nil];
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultSuccess);
    } else {
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultNotAvailable);
    }
}
@end

SocialWorker.java

public class SocialWorker {
    public static final String TAG = SocialWorker.class.getSimpleName();

    public static final String UNITY_SEND_GAMEOBJECT = "SocialWorker";
    public static final String UNITY_SEND_CALLBACK   = "OnSocialWorkerResult";

    public static final String RESULT_SUCCESS       = "0";
    public static final String RESULT_NOT_AVAILABLE = "1";
    public static final String RESULT_ERROR         = "2";

    /**
     * Twitter or Facebook 投稿。ただしFacebookは画像の投稿のみ許可しており、テキストの投稿は無視されることに注意。
     * @param isTwitter true:Twitter、false:Facebook
     * @param message メッセージ
     * @param url URL。空文字の場合は処理されない。
     * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
     */
    public void postTwitterOrFacebook(boolean isTwitter, String message, String url, String imagePath) {
        try {
            String name = (isTwitter) ? "com.twitter" : "com.facebook";
            String type = (imagePath.equals("")) ? "text/plain" : getIntentTypeForImage(imagePath);
            Intent intent = createAppIntent(name, Intent.ACTION_SEND, type);
            if(intent != null) {
                intent.putExtra(Intent.EXTRA_TEXT, message + System.getProperty("line.separator") + url);
                if(!imagePath.equals("")) {
                    intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(imagePath)));
                }
                UnityPlayer.currentActivity.startActivity(intent);
                UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_SUCCESS);
            } else {
                UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_NOT_AVAILABLE);
            }
        } catch(Exception e) {
            Log.e(TAG, "postTwitterOrFacebook", e);
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_ERROR);
        }
    }

    /**
     * 画像のIntentタイプを取得
     * @param imagePath 画像パス(PNG/JPGのみ)
     * @return Intentタイプ
     */
    private String getIntentTypeForImage(String imagePath) {
        String extension = imagePath.substring(imagePath.lastIndexOf(".") + 1).toLowerCase(Locale.getDefault()) ;
        return (extension == ".png") ? "image/png" : "image/jpg";
    }

    /**
     * 特定のアプリを起動させるためのIntentを生成
     * @param name アプリパッケージ名。null or 空文字 で無視する。
     * @param action Intentアクション
     * @param type Intentタイプ
     * @return Intent。アプリがない場合は null
     */
    private Intent createAppIntent(String name, String action, String type) throws Exception {
        try {
            Intent intent = new Intent(action);
            intent.setType(type);

            List<ResolveInfo> ris = UnityPlayer.currentActivity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
            if(name == "" || name == null) {
                return (!ris.isEmpty()) ? intent : null;
            } else {
                for (ResolveInfo ri : ris) {
                    if (ri.activityInfo.name.contains(name)) {
                        intent.setClassName(ri.activityInfo.packageName, ri.activityInfo.name);
                        return intent;
                    }
                }
            }
            return null;
        } catch (Exception e) {
            throw e;
        }
    }
}

Facebook連携

画像の投稿をサポート。FacebookはFacebook Platform Policyで投稿画面での自動挿入文を許可していません。なので、画像の投稿のみを許可しています。

SceneDemo.cs

string imagePath = Application.persistentDataPath + "/image.png";
SocialWorker.PostFacebook(imagePath);

SocialWorker.mm

#import <Social/Social.h>

@interface SocialWorker : NSObject
@end

@implementation SocialWorker
/**
 * Twitter or Facebook 投稿。ただしFacebookは画像の投稿のみ許可しており、テキストの投稿は無視されることに注意。
 * @param isTwitter true:Twitter、false:Facebook
 * @param message メッセージ
 * @param url URL。空文字の場合は処理されない。
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
- (void)postTwitterOrFacebook:(BOOL)isTwitter message:(NSString *)message url:(NSString *)url imagePath:(NSString *)imagePath {
    NSString *type = (isTwitter) ? SLServiceTypeTwitter : SLServiceTypeFacebook;
    if ([SLComposeViewController isAvailableForServiceType:type]) {
        SLComposeViewController *vc = [SLComposeViewController composeViewControllerForServiceType:type];
        [vc setInitialText:message];
        if([url length] != 0) {
            [vc addURL:[NSURL URLWithString:url]];
        }
        if([imagePath length] != 0) {
            [vc addImage:[UIImage imageWithContentsOfFile:imagePath]];
        }
        [vc setCompletionHandler:^(SLComposeViewControllerResult result) {}];
        [UnityGetGLViewController() presentViewController:vc animated:YES completion:nil];
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultSuccess);
    } else {
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultNotAvailable);
    }
}
@end

SocialWorker.java

/**
 * Twitter or Facebook 投稿。ただしFacebookは画像の投稿のみ許可しており、テキストの投稿は無視されることに注意。
 * @param isTwitter true:Twitter、false:Facebook
 * @param message メッセージ
 * @param url URL。空文字の場合は処理されない。
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
public void postTwitterOrFacebook(boolean isTwitter, String message, String url, String imagePath) {
    try {
        String name = (isTwitter) ? "com.twitter" : "com.facebook";
        String type = (imagePath.equals("")) ? "text/plain" : getIntentTypeForImage(imagePath);
        Intent intent = createAppIntent(name, Intent.ACTION_SEND, type);
        if(intent != null) {
            intent.putExtra(Intent.EXTRA_TEXT, message + System.getProperty("line.separator") + url);
            if(!imagePath.equals("")) {
                intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(imagePath)));
            }
            UnityPlayer.currentActivity.startActivity(intent);
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_SUCCESS);
        } else {
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_NOT_AVAILABLE);
        }
    } catch(Exception e) {
        Log.e(TAG, "postTwitterOrFacebook", e);
        UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_ERROR);
    }
}

Line連携

メッセージと画像の投稿をサポート。ただしメッセージと画像の同時投稿は行えません。

iOS/Android共にURLSchemeを使用しています。Line側の使用についてはこちらを参考に。
画像投稿の際、iOSではLine側の仕様に則りUIPasteboardを使用しています。iOS7からUIPasteboardの仕様が変更されたようなので、ご注意下さい。

SceneDemo.cs

string message   = "message";
string imagePath = Application.persistentDataPath + "/image.png";
SocialWorker.PostLine(message, imagePath);

SocialWorker.mm

@interface SocialWorker : NSObject
@end

@implementation SocialWorker
/**
 * Line投稿。Lineはメッセージと画像の同時投稿は行えないことに注意。
 * @param message メッセージ
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
- (void)postLine:(NSString *)message imagePath:(NSString *)imagePath {
    NSString *url;
    if([imagePath length] == 0) {
        // メッセージ投稿
        url = [NSString stringWithFormat:@"line://msg/text/%@", message];
    } else {
        // 画像投稿
        UIPasteboard *pasteboard;
        if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0f) { // Pasteboardの仕様がiOS7から変更された
            pasteboard = [UIPasteboard generalPasteboard];
        } else {
            pasteboard = [UIPasteboard pasteboardWithUniqueName];
        }

        NSString *extension = [[@"." stringByAppendingString:[imagePath pathExtension]] lowercaseString];
        if([extension rangeOfString:@".png"].location != NSNotFound) {
            [pasteboard setData:UIImagePNGRepresentation([UIImage imageWithContentsOfFile:imagePath]) forPasteboardType:@"public.png"];
        } else {
            [pasteboard setData:UIImageJPEGRepresentation([UIImage imageWithContentsOfFile:imagePath], 1.0f) forPasteboardType:@"public.jpeg"];
        }
        url = [NSString stringWithFormat:@"line://msg/image/%@", pasteboard.name];
    }

    NSURL *urlData = [NSURL URLWithString:url];
    if ([[UIApplication sharedApplication] canOpenURL:urlData]) {
        [[UIApplication sharedApplication] openURL:urlData];
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultSuccess);
    } else {
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultNotAvailable);
    }
}
@end

SocialWorker.java

/**
 * Line投稿。Lineはメッセージと画像の同時投稿は行えないことに注意。
 * @param message メッセージ
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
public void postLine(String message, String imagePath) {
    try {
        Intent intent = createAppIntent("jp.naver.line", Intent.ACTION_SEND, "text/plain");
        if(intent != null) {
            if(imagePath.equals("")) {
                intent = new Intent(Intent.ACTION_VIEW, Uri.parse("line://msg/text/" + URLEncoder.encode(message, "UTF-8")));
            } else {
                intent = new Intent(Intent.ACTION_VIEW, Uri.parse("line://msg/image/" + imagePath));
            }
            UnityPlayer.currentActivity.startActivity(intent);
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_SUCCESS);
        } else {
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_NOT_AVAILABLE);
        }
    } catch(Exception e) {
        Log.e(TAG, "postLine", e);
        UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_ERROR);
    }
}

Instagram連携

画像の投稿をサポート。

iOSではUIDocumentInteractionControllerを使用し、AndroidではIntentによる方法です。Instagramの仕様についてはこちら
iOSではUIDocumentInteractionControllerを使用してる関係でInstagramアプリを直接起動することが出来ません。1度アプリ選択のウィンドウを挟んで、その選択後にInstagramが起動します。InstagramはURLSchemeにも対応してるようなのですが、上記の公式仕様にはデータやり取りの際はUIDocumentInteractionControllerを使ったやり取りを指定していて、何かちょっとスマートじゃない感じです。UIDocumentInteractionControllerを使用する場合、ファイル拡張子によってアプリが自動で複数出てしまうので、Instagramだけに限定するために、拡張子を「.igo」に変換しています。

SceneDemo.cs

string imagePath = Application.persistentDataPath + "/image.png";
SocialWorker.PostInstagram(imagePath);

SocialWorker.mm

@interface SocialWorker : NSObject<UIDocumentInteractionControllerDelegate>
@property(nonatomic, retain) UIDocumentInteractionController *_dic;
@end

@implementation SocialWorker
@synthesize _dic;

/**
 * Instagram投稿。Instagramは画像の投稿のみ行える。
 * @param imagePath 画像パス(PNG/JPGのみ)
 */
- (void)postInstagram:(NSString *)imagePath {
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"instagram://app"]]) {
        // 拡張子「.igo」にすることでアプリを特定させるため、ファイル名を変更して新たに保存
        UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
        NSString *extension = [[@"." stringByAppendingString:[imagePath pathExtension]] lowercaseString];
        imagePath = [imagePath stringByReplacingOccurrencesOfString:extension withString:@".igo"];
        if([extension rangeOfString:@".png"].location != NSNotFound) {
            [UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
        } else {
            [UIImageJPEGRepresentation(image, 1.0f) writeToFile:imagePath atomically:YES];
        }

        UIViewController *unityView = UnityGetGLViewController();
        _dic = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:imagePath]];
        _dic.UTI = @"com.instagram.exclusivegram";
        _dic.delegate = self;
        if ([_dic presentOpenInMenuFromRect:unityView.view.frame inView:unityView.view animated:YES]) {
            UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultSuccess);
        } else {
            UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultError);
        }
    } else {
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultNotAvailable);
    }
}

/**
 * UIDocumentInteractionController起動
 */
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application {}

/**
 * UIDocumentInteractionController送信完了
 */
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application {
    self._dic = nil;
}

/**
 * UIDocumentInteractionControllerキャンセル
 */
- (void)documentInteractionControllerDidDismissOpenInMenu: (UIDocumentInteractionController *) controller {
    self._dic = nil;
}
@end

SocialWorker.java

/**
 * Instagram投稿。Instagramは画像の投稿のみ行える。
 * @param imagePath 画像パス(PNG/JPGのみ)
 */
public void postInstagram(String imagePath) {
    try {
        Intent intent = createAppIntent("com.instagram", Intent.ACTION_SEND, getIntentTypeForImage(imagePath));
        if(intent != null) {
            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(imagePath)));
            UnityPlayer.currentActivity.startActivity(intent);
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_SUCCESS);
        } else {
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_NOT_AVAILABLE);
        }
    } catch(Exception e) {
        Log.e(TAG, "postInstagram", e);
        UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_ERROR);
    }
}

メール連携

メッセージと画像の投稿をサポート。

iOSではMFMailComposeViewControllerを使用し、AndroidではIntentによる方法です。
AndroidではIntentタイプにmessage/rfc822を使用することで、メールアプリのみを選択表示出来るようにしています。選択可能なアプリは端末にインストールされているメールアプリが全て出てくる形ですが、数が膨大なため、その全てで動作確認は取っていないのでご注意下さい(Gmailのみ動作確認済みです)。個人的な見解ですが、メールアプリ毎にIntentでどのように処理されるか微妙に違うため、ある程度、使用出来るメーラーは限定した方がいいかもしれません。

SceneDemo.cs

string[] to      = new string[] { "to@hoge.com" };
string[] cc      = new string[] { "cc@hoge.com" };
string[] bcc     = new string[] { "bcc@hoge.com" };
string subject   = "subject";
string message   = "message";
string imagePath = Application.persistentDataPath + "/image.png";
SocialWorker.PostMail(to, cc, bcc, subject, message, imagePath);

SocialWorker.mm

#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>

@interface SocialWorker : NSObject<MFMailComposeViewControllerDelegate>
@end

@implementation SocialWorker
/**
 * メール投稿
 * @param to 宛先。カンマ区切りの配列。
 * @param cc CC。カンマ区切りの配列。
 * @param bcc BCC。カンマ区切りの配列。
 * @param subject タイトル
 * @param message メッセージ
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
- (void)postMail:(NSString *)to cc:(NSString *)cc bcc:(NSString *)bcc subject:(NSString *)subject message:(NSString *)message imagePath:(NSString *)imagePath {
    if([MFMailComposeViewController canSendMail]) {
        MFMailComposeViewController *vc = [[MFMailComposeViewController alloc] init];
        vc.mailComposeDelegate = self;
        [vc setToRecipients:[to componentsSeparatedByString:@","]];
        [vc setCcRecipients:[cc componentsSeparatedByString:@","]];
        [vc setBccRecipients:[bcc componentsSeparatedByString:@","]];
        [vc setSubject:subject];
        [vc setMessageBody:message isHTML:NO];
        if([imagePath length] != 0) {
            NSString *extension = [[@"." stringByAppendingString:[imagePath pathExtension]] lowercaseString];
            if([extension rangeOfString:@".png"].location != NSNotFound) {
                [vc addAttachmentData:UIImagePNGRepresentation([UIImage imageWithContentsOfFile:imagePath]) mimeType:@"image/png" fileName:@"image.png"];
            } else {
                [vc addAttachmentData:UIImageJPEGRepresentation([UIImage imageWithContentsOfFile:imagePath], 1.0f) mimeType:@"image/jpeg" fileName:@"image.jpeg"];
            }
        }
        [UnityGetGLViewController() presentViewController:vc animated:YES completion:nil];
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultSuccess);
    } else {
        UnitySendMessage(kUnitySendGameObject, kUnitySendCallback, kResultNotAvailable);
    }
}

/**
 * メール結果
 */
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
    [UnityGetGLViewController() dismissViewControllerAnimated:YES completion:nil];
}
@end

SocialWorker.java

/**
 * メール投稿
 * @param to 宛先。カンマ区切りの配列。
 * @param cc CC。カンマ区切りの配列。
 * @param bcc BCC。カンマ区切りの配列。
 * @param subject タイトル
 * @param message メッセージ
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
public void postMail(String to, String cc, String bcc, String subject, String message, String imagePath) {
    try {
        Intent intent = createAppIntent(null, Intent.ACTION_SEND, "message/rfc822");
        if(intent != null) {
            intent.putExtra(Intent.EXTRA_EMAIL, to.split(","));
            intent.putExtra(Intent.EXTRA_CC, cc.split(","));
            intent.putExtra(Intent.EXTRA_BCC, bcc.split(","));
            intent.putExtra(Intent.EXTRA_SUBJECT, subject);
            intent.putExtra(Intent.EXTRA_TEXT, message);
            if(!imagePath.equals("")) {
                intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(imagePath)));
            }
            UnityPlayer.currentActivity.startActivity(intent);
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_SUCCESS);
        } else {
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_NOT_AVAILABLE);
        }
    } catch(Exception e) {
        Log.e(TAG, "postMail", e);
        UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_ERROR);
    }
}
/**
 * メール投稿
 * @param to 宛先。カンマ区切りの配列。
 * @param cc CC。カンマ区切りの配列。
 * @param bcc BCC。カンマ区切りの配列。
 * @param subject タイトル
 * @param message メッセージ
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
public void postMail(String to, String cc, String bcc, String subject, String message, String imagePath) {
    try {
        Intent intent = createAppIntent(null, Intent.ACTION_SEND, "message/rfc822");
        if(intent != null) {
            intent.putExtra(Intent.EXTRA_EMAIL, to.split(","));
            intent.putExtra(Intent.EXTRA_CC, cc.split(","));
            intent.putExtra(Intent.EXTRA_BCC, bcc.split(","));
            intent.putExtra(Intent.EXTRA_SUBJECT, subject);
            intent.putExtra(Intent.EXTRA_TEXT, message);
            if(!imagePath.equals("")) {
                intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(imagePath)));
            }
            UnityPlayer.currentActivity.startActivity(intent);
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_SUCCESS);
        } else {
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_NOT_AVAILABLE);
        }
    } catch(Exception e) {
        Log.e(TAG, "postMail", e);
        UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_ERROR);
    }
}

アプリ選択式の連携

メッセージと画像の投稿をサポート。

これだけ少し特殊ですが、投稿するデータタイプに応じて自動的に起動できるアプリを選択表示します。この機能は付属機能と捉えて下さい。簡単に実装出来そうだったのでついでに入れたものです。
iOSではUIActivityViewControllerを使用し、AndroidではIntent.createChooserを使用しています。
iOSではUIActivityViewControllerのapplicationActivitiesに現状nilが設定されていますが、ここに追加したいアプリを指定すれば、選択表示にアプリを追加することが可能です(iOSのUIActivityViewControllerにカスタムアクティビティを追加する)。

SceneDemo.cs

string message   = "message";
string imagePath = Application.persistentDataPath + "/image.png";
SocialWorker.CreateChooser(message, imagePath);

SocialWorker.mm

@interface SocialWorker : NSObject
@end

@implementation SocialWorker
/**
 * アプリ選択式での投稿
 * @param message メッセージ
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
- (void)createChooser:(NSString *)message imagePath:(NSString *)imagePath {
    NSArray *activities = [NSArray arrayWithObjects:message, nil];
    if([imagePath length] != 0) {
        activities = [activities arrayByAddingObject:[UIImage imageWithContentsOfFile:imagePath]];
    }

    UIActivityViewController *vc = [[UIActivityViewController alloc] initWithActivityItems:activities applicationActivities:nil];
    if ([[UIDevice currentDevice].systemVersion floatValue] > 7.1f) {
        vc.popoverPresentationController.sourceView = UnityGetGLViewController().view;
    }
    [UnityGetGLViewController() presentViewController:vc animated:YES completion:nil];
}
@end

SocialWorker.java

/**
 * アプリ選択式での投稿
 * @param message メッセージ
 * @param imagePath 画像パス(PNG/JPGのみ)。空文字の場合は処理されない。
 */
public void createChooser(String message, String imagePath) {
    try {
        String type = (imagePath.equals("")) ? "text/plain" : getIntentTypeForImage(imagePath);
        Intent intent = createAppIntent(null, Intent.ACTION_SEND, type);
        if(intent != null) {
            intent.putExtra(Intent.EXTRA_TEXT, message);
            if(!imagePath.equals("")) {
                intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(imagePath)));
            }
            UnityPlayer.currentActivity.startActivity(Intent.createChooser(intent, "Share"));
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_SUCCESS);
        } else {
            UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_NOT_AVAILABLE);
        }
    } catch(Exception e) {
        Log.e(TAG, "createChooser", e);
        UnityPlayer.UnitySendMessage(UNITY_SEND_GAMEOBJECT, UNITY_SEND_CALLBACK, RESULT_ERROR);
    }
}

名前の由来

Unityで手軽にSNS連携するにはsocial-connectorが有名かと思います。かくいう自分もUnityでSNS連携を行うために最初に調査したAssetでした。しかし、social-connectorは投稿するアプリを限定出来ません。自分のアプリではTwitter、Facebook、Line、Instagram、メールにのみ投稿を許可したかったのです。

そのため、自作することにしました。それぞれのSNSに手軽に連携する方法を探し、それらをまとめました。そして、ふと思ったのです。せっかくまとめたのだから公開しとくか、と。

前置きが長くなりましたが、そんな経緯から、皆に親しみがあるsocialという単語をAsset名に組み込もうと考えました。

social何とか・・・social何とか・・・

自分がやったことと言ったらネットの情報をまとめて1つにしただけだしなぁ。すごい手軽っていう軽い感じ・・・

誰でも出来る・・・

蠅でも出来る・・・・・・???

Social・Workerだーーーッ!!

奴等の戦法は攻撃の後 すぐ呪文で逃げるっていう ヒットアンドアウェイ
攻撃された後 オレ達はすぐ別の場所へ移動してるのに すぐに場所がバレる

「ドップル」

「おう」

蠅の仕事 ~サイレントワーカー~

最後に

SocialWorkerですが、前述の通り、誰でも探せば分かるようなことを1つにまとめたにすぎないAssetです。Asset内にはiOS/Androidのネイティブプラグインのソースも付属していますので、細かい制御が必要な場合は自由に改変してもらって構いません。少しでも皆様の開発の手助けになれば・・・。

SocialWorkerを宜しくお願いします。

https://github.com/okamura0510/SocialWorker

【エビでもわかる】オセロプログラミング
〜オセロを作りながらゲームのプログラムを学ぼう〜
「Unityで初めてゲームを作ってみたい!」

そんな人のためにこの本を作りました。
オセロを一から作りながら実践形式でプログラムを学べる本です。
すでに完成したプロジェクトを説明するのではなく、実際に作りながら説明していきます。
一緒に手を動かしながら、プログラムを覚えていきましょう🌟