iOS open docx file from Application.persistentData

I have written a mobile unity app that needs to open a downloaded docx file. I can do this on my android build by simply calling Application.OpenUrl(myPath); and it works fine.

I found that it is not so simple in iOS. I have written a small plugin to use the native iOS code to launch the files. At first the code would crash the app when i would click the button that calls the plugin. But I “fixed” the issue that was causing the crash but now nothing is happening when I call the plugin to launch the file.

The logic steps didn’t change just the methods and arguments used.

This is the unity class for launching the file:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;

public static class FileLauncher {

#if UNITY_IOS
	[DllImport ("__Internal")]
	private static extern bool _canOpenURL(string _url);

	[DllImport ("__Internal")]
	private static extern void _openURL(string _url);
#endif

	public static void LaunchFile(string _path){
		#if UNITY_IOS
		try{
			if(Application.platform == RuntimePlatform.IPhonePlayer){
				if(CanOpenURL(_path)){
					_openURL(_path);
				}
				else{
					Debug.Log("FILELAUNCHER: canopen false");
				}
			}
		}
		catch(Exception _err){
			Debug.Log("FILELAUNCHER: " + _err.Message);
		}
		#else

		Application.OpenURL(_path);

		#endif
	}

	public static bool CanOpenURL(string _path){
		#if UNITY_IOS
		try{
			if(Application.platform == RuntimePlatform.IPhonePlayer){
				return _canOpenURL(_path);
			}
		}
		catch(Exception _err){
			Debug.Log("FILELAUNCHER: " + _err.Message);
			return false;
		}
		#endif
		return true;
	}

}

And this is the current plugin I have written:

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

@interface SampleClass : NSObject

-(bool)CanOpenURL:(NSString *)_url;
-(void)OpenURL:(NSString *)_url;

@end

@implementation SampleClass

-(bool)CanOpenURL:(NSString *)_url{
	UnitySendMessage("AppController", "iOSLog", "CanOpenURL");
    if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:_url]]){
        return YES;
    }
    return NO;
}

-(void)OpenURL:(NSString *)_url{
	UnitySendMessage("AppController", "iOSLog", "OpenURL");
    NSURL *url = [[NSBundle mainBundle] URLForResource:_url withExtension:@"docx"];
    if(url){
        UIDocumentInteractionController *docController = [UIDocumentInteractionController interactionControllerWithURL:url];
        UIViewController *viewController = [[[[UIApplication sharedApplication]delegate]window]rootViewController];
        [docController presentOpenInMenuFromRect:CGRectZero inView:viewController.view animated:YES];
    }
    else{
        UnitySendMessage("AppController", "iOSLog", "OpenFailed");
    }
}

@end

extern "C"
{
    bool _canOpenURL(NSString* _url){
        SampleClass *test = [[SampleClass alloc] init];
        return [test CanOpenURL:_url];
    }
    
    void _openURL(NSString* _url){
        SampleClass *test = [[SampleClass alloc] init];
        [test OpenURL:_url];
    }
    
    char* cStringCopy(const char* _string){
        if (_string == NULL){
            return NULL;
        }
        char* res = (char*)malloc(strlen(_string) + 1);
        strcpy(res, _string);
        return res;
    }
}

I do not have a background in iOS so I am thinking i am overlooking a step or something simple in the interaction between iOS and unity that someone on here may see immediately.

Thanks for your help!

Hi everyone,

I thought I’d share a working plugin that opens a document within an iOS app, as @wolftamer389 was attempting. The document path is specified from a Unity script. Please bare in mind that this is my first time writing Objective-C code and dealing iOS plugins!

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


@interface DocumentHandler : NSObject <UIDocumentInteractionControllerDelegate>
{
    NSURL * fileURL;
}

- (id)initWithURL:(NSURL*)unityURL;

- (void)UpdateURL:(NSURL*)unityURL;

- (bool)OpenDocument;

- (UIViewController *) documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller;

@end


@implementation DocumentHandler

- (id)initWithURL:(NSURL*)unityURL
{
    self = [super init];
    fileURL = unityURL;
    return self;
}

- (void)UpdateURL:(NSURL*)unityURL {
    fileURL = unityURL;
}

- (bool)OpenDocument {
    
    UIDocumentInteractionController *interactionController =
    [UIDocumentInteractionController interactionControllerWithURL: fileURL];
    
    // Configure Document Interaction Controller
    [interactionController setDelegate:self];
    
    [interactionController presentPreviewAnimated:YES];
    
    return true;
}

- (UIViewController *) documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller {
    return UnityGetGLViewController();
}

@end




static DocumentHandler* docHandler = nil;

// Converts C style string to NSString
NSString* CreateNSString (const char* string)
{
    if (string)
        return [NSString stringWithUTF8String: string];
    else
        return [NSString stringWithUTF8String: ""];
}


extern "C" {
    
    bool OpenDocumentOnIOS (const char* path)
    {
        // Convert path to URL
        NSString * stringPath = CreateNSString(path);
        
        NSURL *unityURL = [NSURL fileURLWithPath:stringPath];
        
        if (docHandler == nil)
            docHandler = [[DocumentHandler alloc] initWithURL:unityURL];
        
        else
            [docHandler UpdateURL:unityURL];
            
        [docHandler OpenDocument];
        
        return true;
    }
}

Simply add this file as a .mm in your Classes folder inside the Xcode project exported by Unity. Finally, to call this function from a Unity script, do the following:

#if UNITY_IOS
[DllImport ("__Internal")]
internal static extern bool OpenDocumentOnIOS (string path);
#endif

And then call your the function normally.

I really hope this helps!

Hello @martejpad,

Sorry, I’m new with IOS. I’d like to know how to open a pdf stored in the steaming assets folder in a pdf reader app using your plugin. How to do so with a unity script? It’s pretty simple on Android, but with IOS it seams more difficult.

Thanks a lot for your help,
Pascal

Hello @martejpad,
i was follow the same steps that you tell us but after put the file into the classes folder, my app is built and and show uploaded in organizer.But, the app is not visiable in test flight.