ついに日本に上陸したMagicLeapですが、
我々は兼ねてよりxRにおけるUI/UXの検証も踏まえて
MagicLeapのアプリ製作に先行して着手してきました。

これまで開発者のみなさんの手助けとなるよう、
簡単ではありますが開発メモを残しています。

そして、今回はその集大成として
Magic Leap World Conceptsへの申請から公開までの手順を
紹介しようと思います。

みなさんのお役に立てれば幸いです。


Magic Leap World Conceptsとは?

Magic Leap Worldには、アイディアレベルのアプリケーションを公開できる場が提供されています。これをConceptsと呼びます。

Magic Leap社としては、Conceptsに公開されたアプリケーションを他の開発者に体験してもらい、フィードバックを頂き、アプリケーションをより磨き上げる場となるよう考えているようです。(そういった仕組みはありませんが。)

Magic Leap Worldの正式なアプリケーションと比較すると、審査期間が短く、審査基準も緩いのも1つの特徴です。最近は、Magic Leap社が開催している開発者ジャムのアプリケーション公開の場として使用しています。

Magic Leap World Concepts 公開までの道程

完結にまとめるとアプリのβ版をストア申請できる仕組みですね。
正式なアプリと同じストアに並び、
Conceptというタグのようなものが表示されます。


Magic Leap World Conceptsに公開したアプリ

MagicLeapに関しての調査も兼ねて、
短期間で集中的にプロトタイプ作成を行いました。


実際に公開したアプリ→Magical Pencil


Magic Leap World Concepts公開申請手順

さて本題です。申請の手順を紹介していきます。

事前に必要な準備や簡単な実装メモは下記リンク参照です。
【MagicLeap】開発環境構築
【MagicLeap】ハンドトラッキング実装デモ
【MagicLeap】検出した平面をRayで取得してオブジェクトを垂直に配置する
【MagicLeap】レーザーポインターでUI操作
【MagicLeap】オクルージョンの実装方法



提出したいアプリが完成したら、MagicLeapにログインしたのち
公開→パブリッシャー登録の順に進みます。

現状、日本から法人の登録はできないようなので、
個人として参加するを選択します。

あとは規約の確認、住所等を入力して下記画像の画面から
アプリの公開画面に進んでいきます。

続いて、パブリックアプリの選択→コンセプトの選択の順に進みます。

この手順で入力フォームにたどり着いたはずです。


アプリの追加、修正

ここまでの手順でアプリの公開枠を作成した後で、
再度MagicLeapにログインした場合は、
下記画像の状態となり、公開→新しいアプリの公開から
実行ファイル(mpkファイル)を追加することができます。

もし、Magic Leap World ConceptsではなくMagic Leap Worldに
誤って進んでしまった場合などは
作成したアプリのフォームから変更を加えることはできないので
新しいアプリの公開から再登録する必要があります。


アイコン作成

アプリをMagicLeapにインストールした際の
表示アイコンを作成する必要があります。

アイコンビルダー (ログインが必要です)

最低解像度の512×512で作成することをおすすめします。

アイコンファイルのダウンロードを選択するとUnityエディタで設定可能な
アイコンファイルがZip形式でダウンロードされます。

Unityエディタでの設定はPlayer SettingsのIconから行います。
ダウンロードしたIconファイルを下記画像の用に指定します。
プロジェクト配下にアイコンファイルを置いてしまっても大丈夫でした。

この状態でビルドすれば実機にてアイコンを確認できます。


リリース用証明書

開発者用証明書とは異なり、
リリース用の証明書を設定する必要があります。

設定方法自体は、開発者用証明書と相違はありません。
【MagicLeap】開発環境構築 のML Certification参照

しかし、リリース用の証明書付きmpkファイルは
実機にケーブルを使って直接転送することができません。

ですので、デバッグは開発者用証明書を設定した状態で行う必要があります。


詰まった箇所

フォームの入力自体はほとんど詰まることがないのですが、
個人的に一部わかりにくかったハマりポイントをメモします。


プレビュー画像

ガイドには1280×720とありますが、正しくは1280×960です。


manifest.xml

Magic Leap World Conceptsに提出するアプリには
manifestにてml:subtype=”Concept”と追記する必要があります。

manifest.xmlファイル
Assets/Plugins/Luminに格納されています。

テンプレートプロジェクトからアプリを作成した場合、
manifest.xmlは下記コードのようになります。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:ml="magicleap" ml:package="com.upft.template" ml:version_code="1" ml:version_name="1.0.0">
  <application ml:sdk_version="1.0" ml:visible_name="Magic Leap Unity Template LWRP" ml:min_api_level="6">
    <component ml:binary_name="bin/Player.elf" ml:name=".fullscreen" ml:type="Fullscreen" ml:visible_name="Magic Leap Unity Template LWRP" ml:subtype="Concept"> //←追記
      <icon ml:model_folder="Icon/Model" ml:portal_folder="Icon/Portal" />
    </component>
    <uses-privilege ml:name="LowLatencyLightwear" />
    <uses-privilege ml:name="BackgroundDownload" />
    <uses-privilege ml:name="BackgroundUpload" />
    <uses-privilege ml:name="BatteryInfo" />
    <uses-privilege ml:name="ConnectBackgroundMusicService" />
    <uses-privilege ml:name="ControllerPose" />
    <uses-privilege ml:name="DrmCertificates" />
    <uses-privilege ml:name="GesturesConfig" />
    <uses-privilege ml:name="GesturesSubscribe" />
    <uses-privilege ml:name="HandMesh" />
    <uses-privilege ml:name="IdentityRead" />
    <uses-privilege ml:name="InAppPurchase" />
    <uses-privilege ml:name="Internet" />
    <uses-privilege ml:name="MusicService" />
    <uses-privilege ml:name="NormalNotificationsUsage" />
    <uses-privilege ml:name="PcfRead" />
    <uses-privilege ml:name="PowerInfo" />
    <uses-privilege ml:name="RegisterBackgroundMusicService" />
    <uses-privilege ml:name="ScreensProvider" />
    <uses-privilege ml:name="SecureBrowserWindow" />
    <uses-privilege ml:name="WifiStatusRead" />
    <uses-privilege ml:name="WorldReconstruction" />
    <uses-privilege ml:name="AddressBookRead" />
    <uses-privilege ml:name="AddressBookWrite" />
    <uses-privilege ml:name="LocalAreaNetwork" />
    <uses-privilege ml:name="AudioCaptureMic" />
    <uses-privilege ml:name="AudioRecognizer" />
    <uses-privilege ml:name="CameraCapture" />
    <uses-privilege ml:name="CoarseLocation" />
    <uses-privilege ml:name="ComputerVision" />
    <uses-privilege ml:name="VoiceInput" />
  </application>
</manifest>

しかし、このままの状態で提出した場合、
リジェクトされます。(後述のリジェクトからの再申請で解説)


レーティングの設定

申請時のレーティングは入力後すぐ反映されるので
きちんとチェックしていれば見逃すことはないのですが、
ついうっかり見逃して成人向けコンテンツとして申請が通ってしまいました。

というのも、Graphic Imageryという項目があるのですが、
MagicLeapが提供する翻訳後のサイトには
グラフィックイメージと表示されます。

私はこれを勘違いして、”穏やか”という項目にチェックを入れて
申請してしまいました。

しかし、このGraphic Imagery“血の描写が含まれるか”
という項目のようで、レーティングに影響を及ぼしていました。

申請前に下記リンクでそれぞれどのような意味を持つのか
しっかりと確認しておくことをお勧めします。
Content Rating Guide


提出レビュー

アプリの申請の最終フローとして下記画像の情報を入力する必要があります。


この入力欄は、iOSやAndroidアプリにも似た欄がありますが、
Webサービスと連携が密なアプリの場合や、
ログインするまでの手順や使用するテストアカウントについて
記述しておく項目となります。
つまり、レビュアーがレビューする手助けをするための情報を書くところです。

特筆すべき確認事項等が無い場合であれば、
英語で「初めての申請です。チェックお願いします。」
等を記述しておけばOKです。


リジェクトからの再申請

申請時点(2020年5月頃)では日本でアプリをリリースされている個人開発の方が一名いらっしゃるだけで(あくまで私の観測範囲の話です)、
日本語の情報が非常に少なく大変な作業でした。

ですので、申請が通るだろうかと心配していました。
案の定、リジェクトされたので、なぜされたのかを説明します。


アプリ内の機能に説明が無い

アプリ内に表示したメニューアイコンのそれぞれに
機能を説明する表示が無かったことを理由に修正を求められました。

Menu Readability

Please provide some text next to your icons, as it is not clear what the icons do based on images alone.

実際のリジェクト内容引用

おっしゃる通り、どのアイコンが何の機能を持っているか
使ってみるまでさっぱりわかりません。

そこで、下記動画のように修正しました。


アプリの終了機能が無い

MagicLeapにはOSの機能として、
ホームタップボタン長押しでホーム画面に戻ることができます。

そのため、アプリの終了はホームボタンの長押しでホーム画面に戻り、
そこから直接終了させれば良い
と思っていましたがそれではダメで、
アプリの終了を可能とする何かしらの機能が必要なようです。

Exit Functionality
please add a button to exit the application.

実際のリジェクト内容引用

ですので、アプリの終了ボタンの実装を追加しました。
ボタンを押下したときのコールバックに下記メソッドを登録しています。

    /// <summary>
    /// アプリの終了
    /// </summary>
    private void quit()
    {
#if UNITY_EDITOR
        UnityEditor.EditorApplication.isPlaying = false;
#elif PLATFORM_LUMIN
        UnityEngine.Application.Quit();
#endif
    }

Manifest Settings

申請時に手を加えたmanifest.xmlですが、
もうひと手間必要だったようです。

APIで利用する権限とmanifest.xml内の権限が一致している必要があります。
余計なものを書いていたので「その機能本当に使っているの?」と
怒られたというわけです。

We noticed some issues with your Magic Leap Manifest Settings:

— Please remove the following unsupported privileges, or otherwise let us know if you are using these features:
—- VoiceInput
—- InAppPurchase
—- ScreensProvider
—- RegisterBackgroundMusicService
—- AudioRecognizer
—- WifiStatusRead
—- AddressBookRead
—- PowerInfo
—- BackgroundUpload
—- DrmCertificates
—- ConnectBackgroundMusicService
—- IdentityRead
—- BatteryInfo
—- BackgroundDownload
—- NormalNotificationsUsage
—- SecureBrowserWindow
—- AddressBookWrite
—- MusicService
—- ComputerVision

実際のリジェクト内容引用

今回の私のアプリで言うと使用する権限は下記まで絞る必要がありました。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:ml="magicleap" ml:package="com.upft.template" ml:version_code="1" ml:version_name="1.0.0">
  <application ml:sdk_version="1.0" ml:visible_name="Magic Leap Unity Template LWRP" ml:min_api_level="6">
    <component ml:binary_name="bin/Player.elf" ml:name=".fullscreen" ml:type="Fullscreen" ml:visible_name="Magic Leap Unity Template LWRP" ml:subtype="Concept">
      <icon ml:model_folder="Icon/Model" ml:portal_folder="Icon/Portal" />
    </component>
    <uses-privilege ml:name="LowLatencyLightwear" />
    <uses-privilege ml:name="ControllerPose" />
    <uses-privilege ml:name="GesturesConfig" />
    <uses-privilege ml:name="GesturesSubscribe" />
    <uses-privilege ml:name="HandMesh" />
    <uses-privilege ml:name="Internet" />
    <uses-privilege ml:name="PcfRead" />
    <uses-privilege ml:name="WorldReconstruction" />
    <uses-privilege ml:name="LocalAreaNetwork" />
    <uses-privilege ml:name="AudioCaptureMic" />
    <uses-privilege ml:name="CameraCapture" />
    <uses-privilege ml:name="CoarseLocation" />
  </application>
</manifest>

 Privileges

スマホのアプリで誰もが一度は見たことのある権限確認のポップアップですが、
MagicLeapにおいても同様に、一部機能においては
ユーザーが権限を許可するか選択できるように設定する必要があるようです。

— Please verify the following privileges are in use in your app:
—- GesturesSubscribe
—- GesturesConfig
—- CameraCapture
—- HandMesh
—- AudioCaptureMic

実際のリジェクト内容引用


その設定を容易にするPrivilege Requesterという
便利コンポーネントが用意されているので
シーンに配置して必要な権限確認を追加します。

自動で付与される権限は一覧にはないので特に何もしなくて大丈夫です。



ホームボタンでのメニューの切り替え

今回提出したアプリは手のジェスチャーに応じて
メニューの表示・非表示が切り替わるという機能を実装していました。
※【参考リンク】:【MagicLeap】ハンドトラッキング実装デモ

しかし、ホームボタンによるメニューの表示・非表示の切り替え機能の追加を
求められました。

Please use the HomeTap button to toggle the menu. 

実際のリジェクト内容引用

公式フォーラムやアプリの申請用件チェックリストなど、
それなりに綿密に調べましたが、
“ホームボタンによるメニューの表示・非表示切り替え機能の追加
が必要な理由にたどり着けなかったので

「ジェスチャーによるメニューの表示・非表示の切り替えを
 実装しているのですが、どのような要件に違反しているのでしょうか?」

という問い合わせをメールで送信したのですが、
返答がなく困り果てていました。

いつまでも返答を待っていても状況は変わらないので、
「MagicLeapはOSの機能としてホームボタンを押すと
 前の画面に戻れるようになっている。
 だから、その機能をアプリにも組み込む必要があるのではないか」

という仮説を立てました。

そして、手のジェスチャーによる画面の切り替え機能はそのままに、
ホームボタン(長押しではない)押下によるメニューの表示・非表示の
切り替え機能も追加して再申請したところ、

We have reviewed, approved and published your app to the Magic Leap World store. Congratulations!

問い合わせメールに対する返信

上記の内容で問い合わせたメールに返信がきました。
どうやら申請が通ったようです。

欲を言えば何がダメだったのかについてレビュワーから情報を引き出して
みなさんの役に立つ情報として共有したかったのですが、
返答となるメールにその記載はありませんでした。力及ばず。。。


最後に

前例が少ない中でのアプリ公開はそこそこタフでしたが、
一度知ってしまえば怖くないです。

ここまで、あたかも全て自力でなんとかしたかのように書いていますが、
ほとんどがLEAPERS JAPAN(Magic Leap Community)にて
助言をいただいたことで解決しました。

非常に助かりました。ありがとうございます。
開発者のみなさんにはコミュニティーへの参加をお勧めします。