読者です 読者をやめる 読者になる 読者になる

Nobollel開発者ブログ

Nobollelのエンジニアが、UnityやCocos2d-xの旬な情報・技術を紹介します。

UnityでカスタムURLスキーム (iOS編)

Unity iOS

こんにちは、Nobollelエンジニアの古屋です。今回は、UnityでカスタムURLスキームを実装する方法を紹介します。

カスタムURLスキームとは

カスタムURLスキームは、myapp://hogeのような独自のURLからアプリを起動するための仕組みです。これを使えば、Web上のリンクから自分のアプリを起動したり、起動中のあるアプリから別のアプリを立ち上げたりすることができます。

カスタムURLスキームはUnityに統合された機能ではないため、プラットフォームごとに実装する必要があり、この記事ではiOSの実装についてお話します。まずは、単純に自分のアプリをカスタムURLスキームから開けるようにし、次に、アプリ自身がURLスキームによって開かれたことを検知できるようにします。

1. アプリをカスタムURLから開けるようにする

アプリをカスタムURLスキームで開けるようにするのは簡単で、Info.plistに設定を行うだけです。

Info.plistの編集

UnityをiOS向けにビルドするとXcodeプロジェクトが書き出されますが、そのプロジェクト内にあるInfo.plistの中にCFBundleURLTypesとその値を追加します。

編集例:

<?xml version="1.0" encoding="utf-8"?>
<plist version="1.0">
  <dict>
    <!-- ここから -->
    <key>CFBundleURLTypes</key>
    <array>
      <dict>
        <key>CFBundleURLName</key>
        <string>test_name</string>
        <key>CFBundleURLSchemes</key>
        <array>
          <string>test_scheme</string>
        </array>
      </dict>
    </array>
    <!-- ここまで -->
  </dict>
</plist>

CFBundleURLSchemesの値 (test_scheme) が実際のURLスキームになります。ようするに、test_scheme://のようなURLでアプリを起動することができます。

CFBundleURLNameの値 (test_name) が何に使われるのかはよくわからないのですが、Appleのガイドによれば、「URLスキームの抽象名」となっており、ユニークな値なら何でも良く、com.mycompany.myschemeのような形式が推奨ということです。

自動化

ビルドするたびにInfo.plistを編集するのは面倒だし忘れてしまうこともあるので、PostProcessBuildを使って、ビルドの度に設定が自動で行われるようにすると便利です。自動化を行うには、次のようなクラスをEditorフォルダの下に配置します。

using System.IO;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;

public class MyPostprocessor {
    [PostProcessBuild]
    public static void OnPostprocessBuild(BuildTarget buildTarget, string path) {
        EditInfoPlist(path);
    }

    static void EditInfoPlist(string directory) {
        var path = Path.Combine(directory, "Info.plist");
        var document = new PlistDocument();
        document.ReadFromFile(path);

        // URLスキームを追加
        var urlTypes = document.root.CreateArray("CFBundleURLTypes");
        var dict = urlTypes.AddDict();
        dict.SetString("CFBundleURLName", "test_name");
        var urlSchemes = dict.CreateArray("CFBundleURLSchemes");
        urlSchemes.AddString("test_scheme");

        document.WriteToFile(path);
    }
}

Info.plistのXML構造を把握していれば、さきほどの設定をコード上で行っていることがわかると思います。

2. アプリ側でURLスキームから開かれたことを検知する

アプリがURLスキームを開かれたことを検知するには、iOSプラグインを実装する必要があります。

Objective-C側の実装

次のようなクラスを作り、Plugins/iOSフォルダの下に配置します。

MyAppController.mm

#import "UnityAppController.h"

void UnitySendMessage(const char* obj, const char* method, const char* msg);

@interface MyAppController : UnityAppController
@end

@implementation UrlHandlerAppController
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
    const char *url = [[url absoluteString] cStringUsingEncoding:NSUTF8StringEncoding];
    UnitySendMessage("MyUrlReceiver", "OnOpenUrl", url);
    return YES;
}
@end

IMPL_APP_CONTROLLER_SUBCLASS(UrlHandlerAppController)

やるべきことは、

  1. UnityAppControllerの子クラス (MyAppController) を作成
  2. application:openURL:options:を実装してURLを受け取り、UnitySendMessageでUnity側に返す
  3. IMPL_APP_CONTROLLER_SUBCLASSマクロに作成したクラス名を渡す

の3つです。

IMPL_APP_CONTROLLER_SUBCLASSはUnityが定義しているマクロで、指定したカスタムコントローラをデリゲートに設定しコールバックを受け取れるようにしてくれます。

Unity側の実装

さきほど呼び出したUnitySendMessageを受け取るだけです。

次のようなスクリプトを用意し、シーン上のゲームオブジェクトに追加します。ゲームオブジェクトの名前と、コールバックを受け取るメソッドの名前は、UnitySendMessageで指定した名前 (MyUrlReceiver, OnOpenUrl) と同じである必要があります。

MyUrlReceiver.cs

using UnityEngine;

public class MyUrlReceiver : MonoBehaviour {
    void OnOpenUrl(string url) {
        // TODO
    }
}