📱

【Unity】Unityの古いバージョンでiOSのApplication.OpenURLが効かない場合の対処法

に公開

最近、Unity 2021.x以下で開発しているアプリにおいて、Application.OpenURLiOS18で動作しないケースに遭遇しました。

この問題、Unityのバージョンを上げられれば解決する可能性が高いのですが、プロジェクトの都合で簡単にバージョンアップできないケースも多いですよね。

そんな人のために、Objective-Cを使った簡単なネイティブプラグインでの回避方法をご紹介します。

原因

現象としてはこちらのやりとりで記載されていることが発生していたようです。

おそらく、Application.OpenURL が内部的に 非推奨のAPI を使っているため、iOS18で動作しなくなったのだと考えられます。
非推奨のAPI(Objective-C)
代わりに使用が推奨されているAPI(Objective-C)

メソッド名はどちらもopenURLで引数が増えているだけに見えるのですが、実際の挙動は異なるようです。

公式「openURLは廃止されます」
ぼく「ふむふむ」
公式「代わりにopenURLを使ってください」
ぼく「?」

みたいになって混乱しました。
メソッド名変えてくれれば良かったのに

対処法:Objective-Cでネイティブプラグインを作成

1. ネイティブコードの作成

というわけで推奨されているAPIを使うネイティブプラグインを作成します。
以下のコードをUnityプロジェクトの Assets/Plugins/iOS フォルダに配置します。

CustomOpenUrl.mm
#import <UIKit/UIKit.h>

extern "C" {
    void CustomOpenUrl(const char* url) {
        if (url == NULL) {
            return;
        }

        NSString *nsUrlString = [NSString stringWithUTF8String:url];
        NSURL *nsUrl = [NSURL URLWithString:nsUrlString];

        if (nsUrl == nil) {
            return; // URL が無効な場合は処理をスキップ
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            if (@available(iOS 10.0, *)) {
                [[UIApplication sharedApplication] openURL:nsUrl options:@{} completionHandler:nil];
            } else {
                // TODO: 古いiOSバージョンへの対応が不要な場合は消してください
                [[UIApplication sharedApplication] openURL:nsUrl];
            }
        });
    }
}

2. Unity側のC#コード

続いて作成したネイティブコードを呼び出す処理をUnityのスクリプトに追加します。

CustomUrlOpener.cs
using UnityEngine;

public static class CustomUrlOpener
{
#if UNITY_IOS && !UNITY_EDITOR
    [DllImport("__Internal")]
    private static extern void CustomOpenUrl(string url);
#endif

    public static void Open(string url)
    {
#if UNITY_IOS && !UNITY_EDITOR
        CustomOpenUrl(url);
#else
        Application.OpenURL(url);
#endif
    }
}

3. 呼び出し例

あとは既存のコードで Application.OpenURL を呼び出している箇所を以下のように修正します。

CustomUrlOpener.Open("https://example.com");

ネイティブプラグイン初心者向けの補足

Objective-Cベースのネイティブプラグインは Assets/Plugins/iOS に配置するだけで、UnityがiOSビルド時に自動でXcodeプロジェクトに含めてくれます
Assets/Plugins/iOS に配置されていれば中がどういうフォルダ構成になっていても大丈夫です。
もしプロジェクト内でルールが設けられているようであればそれに合わせてください。

Unityのスクリプト側では DllImport("__Internal") でC関数として宣言すれば呼び出せます。
スクリプトの配置場所も特に制限はありませんので、プロジェクト内のルールに合わせてください。

まとめ

項目 内容
問題 iOS18 + Unity2021以下で Application.OpenURL が効かない
原因(推測) 内部で非推奨APIを使っているため、iOS側で無視される
解決策 Objective-Cでネイティブ側の処理を用意し、Unityから呼び出す

この方法なら、Unityのバージョンを無理に上げなくてもiOS18に対応可能です。
必要に応じて、この記事のコードをベースに他のネイティブ機能も追加していけます。

Discussion