アプリから別アプリを起動するケースがあまり多くないのかまとまった情報はそれほど多くありません。
作業の覚書としてここに書き記しておきます。
目次
アプリからアプリを起動する
Deeplink(Custom URL Scheme)を使ってアプリAからアプリBを起動するには、
- アプリB(起動される側)にカスタムURLスキームを定義する
- アプリA(呼び出し側)に呼び出し処理を実装する
- アプリA(呼び出し側)で、定義したカスタムURLスキームを呼び出す宣言をする (iOS9以降)
が必要となります。
起動される側(アプリB)
まずURLスキームを定義します。
Xcodeで開いている場合はプロジェクト直下にある info.plist を開いて、Information Property List に以下の項目を定義します。
URL types └Item 0 ├URL Identifier : myHost └URL Schemes └Item 0 : myScheme
これで、myScheme://myHost
で起動する準備ができました。1 2
また、Unity上では URL Scheme のみ設定できるようになっています。
File > Build Settings > Player Settings > Inspector を開いて、iOSのタブに「Supported URL schemes」の設定があるのでURLスキームを追加します。
呼び出し側(アプリA)
iOSで実装するには、ネイティブでプラグインを実装してUnity側からプラグインの関数を呼ぶのが簡単です。
プラグインの実装
iOSのプラグインは、 Plugins\iOS に h ファイルと mm ファイルを追加するだけ。あとはビルド時に良しなにやってくれます。 実装ファイルだけで完結する場合は ヘッダーファイルは不要です。
mm は、Objective-CにC++のコードが混在したXcodeで使われるファイルです。Objective-C++なんて呼ばれたりもしますが、言語としては存在しないらしい。
extern "C" { } に記述した関数がUnity側から呼び出すインタフェースになります。
プレース内はCのコードで、名前マングリングをしてくれるらしい。(なんのこっちゃ)
おまじないとして覚えておきましょう。詳しく知りたい人は「名前マングリング」や「リンケージ指定」とかで検索すると良いかも。
サンプルは、URLスキームとiTunesAppIdを引数に渡すと、端末にURLスキームで起動できるアプリがある場合はアプリを、なければApp Storeを指定したアプリIDで開きます。
iOS 10 以降はcanOpenURL と openURL の仕様が変わっており引数が増えています。バージョン判定を行った上で処理を別けています。
@interface Launcher : NSObject +(void)launch:(NSString*) urlStr itunesAppId : (NSString*) itunesAppId; @end @implementation Launcher +(void)launch:(NSString*) urlStr itunesAppId : (NSString*) itunesAppId{ NSURL *url = [NSURL URLWithString:urlStr]; NSURL *storeurl = [NSURL URLWithString:[NSString stringWithFormat:@"itms-apps://itunes.apple.com/app/%@", itunesAppId]]; if(floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max){ // iOS10 以降 if([[UIApplication sharedApplication] canOpenURL:url]){ [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; }else{ [[UIApplication sharedApplication] openURL:storeurl options:@{} completionHandler:nil]; } }else{ // iOS9 以前 if([[UIApplication sharedApplication] canOpenURL:url]){ [[UIApplication sharedApplication] openURL:url]; }else{ [[UIApplication sharedApplication] openURL:storeurl]; } } } @end extern "C"{ void launch(const char *url, const char *itunesAppId){ NSString *urlString = [NSString stringWithCString:url encoding:NSUTF8StringEncoding]; NSString *itunesAppIdString = [NSString stringWithCString:itunesAppId encoding:NSUTF8StringEncoding]; [Launcher launch:urlString itunesAppId:itunesAppIdString]; } }
Unityからプラグインを呼び出す
続いてUnityから呼び出す処理を実装します。
配置したプラグインの extern で定義した関数をDLL関数として呼び出してあげましょう。
public class NewBehaviourScript : MonoBehaviour { public void OnClick1() { new MyPlugin().Launch("myScheme://myHost", "id0123456789"); } } public class MyPlugin { [DllImport("__Internal")] private static extern void launch (string url, string itunesAppId); public void Launch(string url, string itunesAppId) { launch (url, itunesAppId); } }
URLスキームを呼び出す宣言 (iOS9以降)
iOS9以降では、info.plist にそのアプリが起動できるURLスキームを予め宣言しておく必要があります。
この宣言がないと、URLスキームが一致していてもアプリを起動することができません。
info.plist を開いて、Information Property List に LSApplicationQueriesSchemes の項目を定義します。
LSApplicationQueriesSchemes ├Item 0 : myScheme └Item 1 : 必要な分だけ
パラメータを渡す場合
Deeplinkで起動する際にパラメータを渡したい場合は、更に対応が必要になります。
今回はURLにパラメータを付けて渡す方法なので、呼び出し側(アプリA)はURLにパラメータを付けて呼び出すだけです。特に実装の必要はありません。起動される側(アプリB)に以下の実装を加えます。
プラグインの実装と呼び出し
プラグイン作成のポイントは、
- UnityAppController を継承したControllerを定義し、openURLを実装する
- staticな領域に値を退避する
- IMPL_APP_CONTROLLER_SUBCLASS を使って定義したControllerをサブクラスとして登録
- Unityから値を取り出せる関数を用意する
です。
前項の通り、作成したヘッダーファイルと実装ファイルは、Plugins/iOSの配下に置きます。
#import <Foundation/Foundation.h> #import "UnityAppController.h" // static な変数保持用 @interface IntentParameter : NSObject + (NSString*)getUrlString; + (void)setUrlString:(NSString*)str; @end @implementation IntentParameter static id urlString = @""; +(NSString*)getUrlString{ return urlString; } +(void)setUrlString:(NSString*)str{ urlString = [str copy]; } @end // openURLをフックする処理 @interface UrlHandlerAppController : UnityAppController @end @implementation UrlHandlerAppController - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options { [IntentParameter setUrlString:[url absoluteString]]; return YES; } @end IMPL_APP_CONTROLLER_SUBCLASS(UrlHandlerAppController); // APIの定義 extern "C"{ const char* getUrlString(); } const char* getUrlString(){ NSString *string = [IntentParameter getUrlString]; const char *str = [string UTF8String]; char* retStr = (char *)malloc(strlen(str) + 1); strcpy(retStr, str); return retStr; }
Unity側から、extern で定義した関数をDLL関数として呼び出せば値が取り出せます。
public class NativeIntentParameterApi { [DllImport("__Internal")] private static extern string getUrlString(); public static string GetUrlString() { return getUrlString(); } }
プラグインでフックしたopenURLは、起動される側が起動していない場合はもちろん、既に起動していても、カスタムURLスキームを使ってアプリに遷移する時に呼び出されます。アプリ単体で起動した場合は値が取れません。