アヒルのある日

株式会社AHIRUの社員ブログです。毎週更新!社員が自由に思いついたことを書きます。

Unityでギャラリーに保存してある画像をアップロードするPluginを作成してみる(#3)

こんにちは。ちゃらいプログラマです。
今回はiOS側の処理を紹介します。

PluginUpload.mmの記述

#import <UIKit/UIKit.h>
#import <Photos/Photos.h>
#import "UnityInterface.h"

#pragma mark Config
const char* CALLBACK_METHOD = "CallbackOpen";
const char* ERROR_MESSAGE   = "";

#pragma mark Upload
@interface Upload : NSObject<UIImagePickerControllerDelegate, UINavigationControllerDelegate>

@property(nonatomic) UIImagePickerController* pickerController;
@property(nonatomic) NSString *gameObjectName;
@property(nonatomic) NSString *savePath;

+ (instancetype)sharedInstance;

- (void)open:(NSString *)gameObjectName savePath:(NSString *)savePath;

@end

@implementation Upload
+ (instancetype)sharedInstance
{
    static Upload *instance;
    static dispatch_once_t token;
    dispatch_once(&token, ^{
        instance = [[Upload alloc] init];
    });
    return instance;
}

- (void)open:(NSString *)gameObjectName savePath:(NSString *)savePath
{
    self.gameObjectName = gameObjectName;
    self.savePath = savePath;

    if (self.pickerController != nil)
    {
        UnitySendMessage( [self.gameObjectName UTF8String], CALLBACK_METHOD, ERROR_MESSAGE );
        return;
    }

    switch( [PHPhotoLibrary authorizationStatus] )
    {
        case PHAuthorizationStatusNotDetermined:
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status)
            {
                switch( status )
                {
                    case PHAuthorizationStatusRestricted:
                    case PHAuthorizationStatusDenied:
                        UnitySendMessage( [self.gameObjectName UTF8String], CALLBACK_METHOD, ERROR_MESSAGE );
                        return;
                }
            }];
            break;
    }
    
    self.pickerController = [[UIImagePickerController alloc] init];
    self.pickerController.delegate = self;
    
    self.pickerController.allowsEditing = NO;
    self.pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

    UIViewController *unityController = UnityGetGLViewController();
    [unityController presentViewController:self.pickerController animated:YES completion:^{
    }];
}

- (void)dismissUpload
{
    if (self.pickerController != nil)
    {
        [self.pickerController dismissViewControllerAnimated:YES completion:^{
            self.pickerController = nil;
        }];
    }
}

#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    NSData *imageData = UIImagePNGRepresentation( image );
    if( imageData == nil )
    {
        UnitySendMessage( [self.gameObjectName UTF8String], CALLBACK_METHOD, ERROR_MESSAGE );
        [self dismissUpload];
        return;
    }
    
    NSString *outPath = [NSString stringWithFormat:@"%@/tmpImage.png", self.savePath];
    
    BOOL isSuccess = [imageData writeToFile:outPath atomically:YES];
    if( isSuccess == NO )
    {
        UnitySendMessage( [self.gameObjectName UTF8String], CALLBACK_METHOD, ERROR_MESSAGE );
        [self dismissUpload];
        return;
    }

    UnitySendMessage( [self.gameObjectName UTF8String], CALLBACK_METHOD, [outPath UTF8String] );

    [self dismissUpload];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    UnitySendMessage( [self.gameObjectName UTF8String], CALLBACK_METHOD, ERROR_MESSAGE );
    
    [self dismissUpload];
}

@end

#pragma mark Unity Plugin
extern "C"
{
    void _PluginUpload_Open(const char* gameObjectName, const char* savePath)
    {
        Upload *upload = [Upload sharedInstance];
        [upload open:[NSString stringWithUTF8String:gameObjectName] savePath:[NSString stringWithUTF8String:savePath]];
    }
}

PluginUploadObject.csの記述

前回Android実装時に生成したファイルを拡張します

#if UNITY_IOS
    [DllImport("__Internal")]
    private static extern void _PluginUpload_Open( string gameObjectName, string savepath );
#endif

    // 開く
    public void Open( Action<Sprite, string> callback = null )
    {
        Close();

        // 設定
        _callback = callback;

#if UNITY_IOS
        _PluginUpload_Open( gameObject.name, Application.persistentDataPath );
#else
    }

Android側と比較して1点大きな相違点としては、コピーファイルの拡張子が「png」になるところです。(上手い解決方法が見つからず妥協してしまいました)

[NSString stringWithFormat:@"%@/tmpImage.png", self.savePath];

動画対応等の拡張をしやすいように作ったつもりです。
長い戦いがついに終わりました。。。

では、また次回!