MRが楽しい

MRやVRについて学習したことを書き残す

MetaQuestでアプリ終了時に呼び出し元のアプリを呼び戻す

本日はMetaQuestの小ネタ枠です。
MetaQuestでアプリ終了時に呼び出し元のアプリを呼び戻す方法を調査したので記事に残します。

MetaQuestでアプリ終了時に呼び出し元のアプリを呼び戻す

MetaQuestでアプリ終了時に呼び出し元のアプリを呼び戻す実装方式は大きく分けて2つ考えられます。
1.アプリ間で呼び出し元のアプリを検知して呼び戻す仕組みを作る
2.Intent呼び出しのコールバックを受け取り、呼び出し先のアプリ終了時に再起動する仕組みを作る

今回は比較的実装難度が低い1番の方式で検証してみました。

処理の流れ

試した全体の流れとしては以下の通りになります。
1.アプリ1から呼び出し元のアプリのスキーム名をパラメータに含めてアプリ2をスキームURLで呼び出す
2.アプリ2でスキームURLを受け取りパラメータから呼び出し元のスキーム名を取得する
3.アプリ2の終了タイミングで呼び出し元のスキーム名があればスキームURLで呼び出し元のアプリを呼び戻す

QuestアプリでのスキームURLを使ったアプリ呼び出し

QuestアプリでのスキームURLを使ったアプリ呼び出し方法の詳細は以下の記事を参照ください。
bluebirdofoz.hatenablog.com

QuestアプリでのスキームURLからのパラメータ受け取り

QuestアプリでのスキームURLからのパラメータ受け取り方法の詳細は以下の記事を参照ください。
bluebirdofoz.hatenablog.com

Questアプリでアプリ終了時に任意の処理を実行する

Questアプリでアプリ終了時に任意の処理を実行する方法の詳細は以下の記事を参照ください。
bluebirdofoz.hatenablog.com

サンプルスクリプト

上記記事のサンプルアプリを元に、呼び出し側のアプリ(アプリ1)のスクリプトを以下のように修正しました。
自身のスキーム名をcallappパラメータとして渡してスキームURL呼び出しを行います。
・BrowserTest.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BrowserTest : MonoBehaviour
{
    /// <summary>
    /// 指定のURLをウェブブラウザで開く
    /// </summary>
    /// <returns></returns>
    public void OpenBrowser()
    {
        var uri = new System.Uri("launcherschemereturntwoapp://redirect?callapp=launcherschemereturnoneapp");
        Application.OpenURL(uri.AbsoluteUri);
    }
}

また呼び出し先のアプリ(アプリ2)のスクリプトは以下のように修正しました。
パラメータから呼び出し元のスキーム名を取得し、アプリ終了時にスキームURL呼び出しを行います。
・ProcessDeepLinkChecker.cs

using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class ProcessDeepLinkChecker : MonoBehaviour
{
    [SerializeField]
    private TMP_Text _text;

    private string _returnUrl = string.Empty;

    public static ProcessDeepLinkChecker Instance { get; private set; }

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            Application.deepLinkActivated += onDeepLinkActivated;
            if (!string.IsNullOrEmpty(Application.absoluteURL))
            {
                _text.text = Application.absoluteURL;
                // コールドスタートと Application.absoluteURL は null ではありません。そのため Deep Link を処理します
                onDeepLinkActivated(Application.absoluteURL);
            }
            else
            {
                _text.text = "No Deep Link";
            }
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void onDeepLinkActivated(string url)
    {
        Dictionary<string, string> parameters = new Dictionary<string, string>();

        // URL をデコードして動作を決定します
        // この例では、リンクが以下のようにフォーマットされることを前提としています
        // unitydl://mylink?scene1
        string queryString = url.Split("?"[0])[1];
        string[] dataTexts = queryString.Split("&"[0]);
        foreach (string dataText in dataTexts)
        {
            string[] data = dataText.Split("="[0]);
            parameters.Add(data[0], data[1]);

            // callappのパラメータがあればreturnUrlに保存します
            if (data[0] == "callapp")
            {
                _returnUrl = data[1];
            }
        }

        // URLから取得したパラメーターをテキストメッセージに表示します
        string message = url + "\n";
        foreach (KeyValuePair<string, string> parameter in parameters)
        {
            message += parameter.Key + ": " + parameter.Value + "\n";
        }
        _text.text += message;
    }

    // アプリ終了時に呼び出し元のアプリを呼び出します
    private void OnApplicationPause(bool pause)
    {
        if (!pause) return;

        // アプリが終了する際に呼び出し元のアプリを呼び出す
        // もし _returnUrl が設定されていれば、指定されたURLを開きます
        if (!string.IsNullOrEmpty(_returnUrl))
        {
            var uri = new System.Uri($"{_returnUrl}://redirect?callapp=launcherschemereturntwoapp");
            Application.OpenURL(uri.AbsoluteUri);
        }
    }

    /// <summary>
    /// 指定のURLをウェブブラウザで開く
    /// </summary>
    /// <returns></returns>
    public void OpenBrowser()
    {
        var uri = new System.Uri($"{_returnUrl}://redirect");
        Application.OpenURL(uri.AbsoluteUri);
    }
}

AndroidManifest.xmlで呼び出し元と呼び出し先のアプリのスキーム名をそれぞれ設定しておきます。
詳細は前述の各記事を参照ください。

動作確認

初めに呼び出し元のアプリ(アプリ1)を起動し、スキーマURL起動のボタンを押下します。

即座にアプリ1が終了してアプリ2が起動します。
ログ表示を確認するとアプリ1のスキーマ名がパラメータで取得できていることが分かります。

ホーム画面の[閉じる]ボタンを押してアプリ2を終了します。

すると即座にアプリ1が起動し直しました。

これでアプリ終了時に呼び出し元のアプリを呼び戻すことができました。
ただしこの手法の場合は呼び出し元と呼び出し先にこれらの仕組みを実装しておくことが必須となります。