ハウツー

Jetpack XR SDK を使用して Androidify を XR に導入する

所要時間: 9 分
Dereck Bridie
デベロッパー リレーション エンジニア

Android XR を搭載した Samsung Galaxy XR が登場このブログ投稿は、 Android XR スポットライト ウィークの一環として公開されたものです。この期間中、Android XR 向けアプリの学習、構築、準備に役立つリソース(ブログ投稿、動画、サンプルコードなど)が提供されます。

Samsung Galaxy XR のリリースにより、Android XR を搭載した初のデバイスが正式にリリースされました。Google Play ストアで提供されているお気に入りのアプリの多くを、3D というまったく新しい次元で楽しめるようになりました。

3 つ目の次元は広々としており、アプリを配置するスペースも十分にあります。今すぐ、アプリに適したツールを使って開発を始めましょう。たとえば、Jetpack XR SDK を使用して、Kotlin や Compose などの最新の Android 開発ツールで没入感のある XR エクスペリエンスを構築できます。

このブログ投稿では、愛されている Androidify アプリの気まぐれさを XR に取り入れた Google の取り組みについてご紹介します。また、アプリを XR に対応させるために必要な基本的なことについても説明します。

Androidify のツアー

Androidify は、Gemini、CameraX、Navigation 3、Jetpack Compose などの最新テクノロジーを使用して Android ボットを作成できるオープンソース アプリです。Androidify は、当初はアダプティブ レイアウトを作成することで、スマートフォン、折りたたみ式デバイス、タブレットで美しく表示されるように設計されました。

customize.png

Androidify は複数のフォーム ファクタで美しく表示されます

適応型レイアウトの重要な柱は、再利用可能なコンポーザブルです。Jetpack Compose を使用すると、さまざまなレイアウトで直感的なユーザー エクスペリエンスを実現できる、小さな UI コンポーネントを作成できます。ユーザーが使用しているデバイスの種類を問いません。実際、Androidify はアプリをまったく変更せずに Android XR に対応しています。

customize_2.png

Androidify は、コードを変更することなく、大画面対応のレスポンシブ レイアウトを使用して XR に適応します

Android XR 向けに特別な処理を行っていないアプリでも、適切なサイズのウィンドウでマルチタスクを実行でき、大画面で実行する場合とほぼ同じように動作します。そのため、Androidify は Android XR で追加の作業なしで完全に機能します。しかし、それだけでは十分ではないと考え、XR ユーザーに快適なエクスペリエンスを提供するために、XR 差別化アプリを作成することにしました。

XR での方向感覚

Android XR の基本的なコンセプトについて説明します。まず、アプリが動作する 2 つのモード(ホームスペースとフルスペース)から始めましょう。

homespace.png
ホーム スペースのアプリ
homespace2.png
フルスペースのアプリ

ホームスペースでは、複数のアプリを並べて実行できるので、異なるウィンドウ間でマルチタスクが可能です。その意味では、大画面の Android デバイスのデスクトップ ウィンドウとよく似ていますが、仮想空間での操作になります。

フルスペースでは、アプリにスペースの境界がなく、空間 UI や仮想環境の制御など、Android XR の空間機能をすべて使用できます。

アプリをフルスペースでのみ実行するようにしたくなるかもしれませんが、ユーザーはアプリでマルチタスクを行いたい場合もあるため、両方をサポートすることでユーザー エクスペリエンスを向上させることができます。

Androidify の新しい次元に対応したデザイン

優れたアプリは、優れたデザインから始まります。Android DevRel のシニア デザイン アドボケイトである Ivy Knight は、Androidify の既存のデザインを基に、XR の新しいデザインを考案するタスクに取り組みました。Ivy さん、お願いします。

XR 向けのデザインには独自の取り組みが必要でしたが、モバイル デザインと共通する点も多くありました。まず、包含について考えました。境界線を明確に示したり、暗黙的に示したりして、サブスペース内の UI 要素を整理し、グループ化する方法です。また、ユーザーの操作に応じて調整や移動を行う空間 UI 要素のさまざまなサイズに対応することも学びました。Androidify と同様に、アダプティブ レイアウトでビルドして、空間 UI のレイアウトをパーツに分割できます。

ホーム スペースからデザインを開始する

幸いなことに、Android XR では、ホームスペース向けに現在のアプリをそのまま使用できるため、ウィンドウ ツールバーとフルスペースへの切り替えボタンを追加するだけで、拡張された XR デザインに移行できました。

また、ハードウェアの機能の可能性と、ユーザーがそれらをどのように操作するかについても検討しました。Androidify のモバイル レイアウトは、さまざまなポーズ、クラスサイズ、カメラの数に合わせて調整され、より多くの写真オプションを提供します。このモデルに沿って、ヘッドセット デバイスのカメラ レイアウトも適応させる必要がありました。また、UI とユーザーの距離を考慮して、テキストが機能するように調整する必要もありました。

フルスペースへの移行を考慮した設計

フルスペースは最大の変更でしたが、デザインを適応させるためのクリエイティブな余地が最も大きくなりました。

tablet_to_xr.webp
タブレットから XR へ

Androidify では、視覚的な包含(ペイン)を使用して、背景とアウトラインのある機能([写真を撮るか選択] ペインなど)をグループ化します。また、トップ アプリバーなどのコンポーネントを使用して、他のペインをフレームで囲み、自然な包含関係を作成しました。最後に、特定の要素が他の要素の近くにあることで、内在的な包含が示唆されます。たとえば、[ボットの色を選択] ペインの近くにある [変換を開始] 下部ボタンなどです。

簡単に分離できる空間パネル。空間パネル用にモバイル デザインを調整する方法を決定するには、一番奥のサーフェスから順に削除して、手前に移動してみてください。削除できる背景の数と、残る背景を確認します。Androidify でこの演習を行った結果、大きな緑色の Android の曲線が残りました。この波線は、ブランディングの瞬間と背景として機能するだけでなく、3D 空間内のコンテンツのアンカーとしても機能しました。

このアンカーを設定することで、要素がどのように移動するか、近接性をどのように利用して残りのユーザー エクスペリエンスをブレイクアウトして変換するかを想像しやすくなりました。

アプリを空間対応にするためのその他のデザインのヒント

  • コンポーネントを分離する: コンポーネントを分離し、実際の(空間的な)スペースを与えます。UI 要素に余白を設ける必要があります。
  • サーフェスを削除: 背景を非表示にして、デザインにどのような影響があるかを確認します。
  • モーションでモチベーションを高める: アプリでトランジションをどのように使用していますか?そのキャラクターを使って、アプリが VR に飛び出す様子を想像してみてください。
  • アンカーを選択する: スペース内でユーザーを見失わないようにします。UI の収集またはグラウンディングに役立つ要素がある。

XR UI デザイン パターンの詳細については、Android Developers の Android XR 向けデザインをご覧ください。

空間 UI の基本

Ivy が XR 向け Androidify を設計する際にマインドセットを適応させた経験について説明しました。次は、空間 UI の開発について説明します。最新の Android ツールやライブラリの操作に慣れている方であれば、Jetpack XR SDK を使用した空間 UI の開発は、馴染みのあるものに感じられるはずです。Compose でのレイアウトの作成など、すでによく知っているコンセプトも含まれています。実際、空間レイアウトは行、列、スペーサーを使用する 2D レイアウトとよく似ています。

spatialrows.png

これらの要素は SpatialRowsSpatialColumns に配置されます。

ここに示されている空間要素は SpatialPanel コンポーザブルです。これを使用すると、テキスト、ボタン、動画などの 2D コンテンツを表示できます。

Subspace {
    SpatialPanel(
        SubspaceModifier
            .height(824.dp)
            .width(1400.dp)
    ) {
        Text("I'm a panel!")
    }
}

SpatialPanel はサブスペース コンポーザブルです。Subspace コンポーザブルは Subspace 内に含める必要があり、SubspaceModifier オブジェクトによって変更されます。サブスペースはアプリの UI 階層内の任意の場所に配置でき、サブスペース コンポーザブルのみを含めることができます。SubspaceModifier オブジェクトも Modifier オブジェクトとよく似ています。サイズや位置などのパラメータを制御します。

Orbiter SpatialPanel に接続でき、接続先のコンテンツとともに移動できます。通常は、関連付けられているコンテンツに関するコンテキスト上のコントロールを提供するために使用され、コンテンツが主な焦点となります。コンテンツの 4 辺のいずれかに、設定可能な距離で配置できます。

orbiter.png
オービターが SpatialPanel の下部にアタッチされている

空間 UI 要素は他にもたくさんありますが、Androidify の空間レイアウトの作成に使用したのは、主にこれらの要素です。

XR 開発を始める

まず、プロジェクトのセットアップから始めましょう。Jetpack XR Compose の依存関係を追加しました。これは、Jetpack XR の依存関係ページで確認できます。

ユーザーをフルスペースに移行するボタンのコードを追加しました。まず、その機能があるかどうかを検出します。

@Composable
fun couldRequestFullSpace(): Boolean =
   LocalSpatialConfiguration.current.hasXrSpatialFeature && 
   !LocalSpatialCapabilities.current.isSpatialUiEnabled
}

次に、既存のレイアウトに コンテンツを開くアイコンを使用する新しいボタン コンポーネントを作成し、onClick 動作を割り当てました。

@Composable

fun RequestFullSpaceIconButton() {
   if (!couldRequestFullSpace()) return
   val session = LocalSession.current ?: return

   IconButton(
       onClick = {
           session.scene.requestFullSpaceMode()
       },
   ) {
       Icon(
           imageVector =  
               vectorResource(R.drawable.expand_content_24px),
           contentDescription = 
               stringResource("To Full Space"),
       )
   }
}

このボタンをクリックすると、フルスペースに Medium レイアウトが表示されるだけになります。空間機能を確認し、空間 UI を表示できるかどうかを判断できます。表示できる場合は、新しい空間レイアウトを表示します。

@Composable

fun HomeScreenContents(layoutType: HomeScreenLayoutType) {
   val layoutType = when {
      LocalSpatialCapabilities.current.isSpatialUiEnabled -> 
          HomeScreenLayoutType.Spatial
      isAtLeastMedium() -> HomeScreenLayoutType.Medium
      else -> HomeScreenLayoutType.Compact
   }

   when (layoutType) {
      HomeScreenLayoutType.Compact ->
          HomeScreenCompactPager(...)

      HomeScreenLayoutType.Medium ->
          HomeScreenMediumContents(...)

      HomeScreenLayoutType.Spatial ->
          HomeScreenContentsSpatial(...)
   }
}

ホーム画面のデザインを実装する

フルスペースのホーム画面の空間設計に戻って、その実装方法を見てみましょう。

customize_3.png

ここでは、2 つの SpatialPanel 要素(右側の動画カードがあるパネルと、メイン UI を含むパネル)を特定しました。最後に、上部に Orbiter が取り付けられています。まず、動画プレーヤー パネルから見ていきましょう。

@Composable
fun HomeScreenContentsSpatial(...) {
   Subspace {
      SpatialPanel(SubspaceModifier
                   .fillMaxWidth(0.2f)
                   .fillMaxHeight(0.8f)
                   .aspectRatio(0.77f)
                   .rotate(0f, 0f, 5f),
      ) {
          VideoPlayer(videoLink)
      }
   }
}

通常のレイアウトの 2D VideoPlayer コンポーネントを SpatialPanel に再利用しただけで、追加の変更は必要ありませんでした。スタンドアロンの例を次に示します。

bluetiel.png

メイン コンテンツ パネルも同様で、中程度のパネル コンテンツを SpatialPanel で再利用しました。

SpatialPanel(SubspaceModifier.fillMaxSize(),
             resizePolicy = ResizePolicy(
                 shouldMaintainAspectRatio = true
             ),
             dragPolicy = MovePolicy()
) {
    Box {
        FillBackground(R.drawable.squiggle_full)
        HomeScreenSpatialMainContent(...)
    }
}

このパネルに ResizePolicy を設定しました。これにより、パネルの端にハンドルが表示され、ユーザーがパネルのサイズを変更できるようになります。また、ユーザーがドラッグして移動できる MovePolicy もあります。

customize_4.png

同じサブスペースに配置すると、互いに独立した状態になるため、VideoPlayer パネルをメイン コンテンツ パネルの子にしました。これにより、メイン コンテンツ パネルが親子関係を通じてドラッグされると、VideoPlayer パネルが移動します。

@Composable
fun HomeScreenContentsSpatial(...) {
   Subspace {
       SpatialPanel(SubspaceModifier..., resizePolicy, dragPolicy) {
           Box {
               FillBackground(R.drawable.squiggle_full)
               HomeScreenSpatialMainContent(...)
           }
           Subspace {
              SpatialPanel(SubspaceModifier...) {
                  VideoPlayer(videoLink)
              }
           }
       }
   }
}

これが最初の画面の作成方法です。

他の画面に移動する

他の画面についても簡単に説明し、それぞれの画面で考慮した点について説明します。

fullspace.png
フルスペースの作成画面

ここでは、SpatialRow コンポーザブルと SpatialColumn コンポーザブルを使用して、推奨される視聴スペースに合わせたレイアウトを作成しています。ここでも、Medium レイアウトのコンポーネントを再利用しています。

fullspace_2.png

フルスペースの検索結果画面: 「赤い野球帽、アビエイター サングラス、水色の T シャツ、赤と白のチェック柄のショートパンツ、緑色のビーチサンダルを身につけ、テニスラケットを持っている」というプロンプトで生成されたボット。


結果画面では、フェザリング効果を使用して補完的な引用符が表示され、画面の端付近でフェードアウトします。また、使用された入力を表示する際に、実際の 3D トランジションを使用して、空間内で画像を反転させます。

Google Play ストアへの公開

空間レイアウトで XR に対応したアプリの準備が整ったので、Google Play ストアでリリースしました。アプリの AndroidManifest.xml ファイルに加えた最後の重要な変更は次のとおりです。

<!-- Androidify can use XR features if they're available; they're not required. -->
<uses-feature android:name="android.software.xr.api.spatial" 
              android:required="false" />

これにより、このアプリに XR 差別化機能があることが Google Play ストアに認識され、ユーザーに XR を念頭に置いて作成されたアプリであることを知らせるバッジが表示されます。

androidify2.png
Android XR の Google Play ストアに表示される Androidify


リリースをアップロードする際に、XR 向けにリリースするための特別な手順は必要ありません。モバイル トラックのユーザーにも、XR デバイスのユーザーにも、同じアプリが通常どおりに配信されます。ただし、アプリの XR 固有のスクリーンショットを追加したり、空間動画アセットを使用してアプリの没入型プレビューをアップロードしたりすることもできます。Android XR デバイスでは、Google Play ストアでこのプレビューが没入型の 3D プレビューとして自動的に表示され、ユーザーはアプリをインストールする前にコンテンツの奥行きやスケールを体験できます。

今すぐ独自の体験を構築しましょう

Androidify は、既存の 2D Jetpack Compose アプリを空間化する方法を示す優れた例です。本日、Androidify の空間 UI を設計からコード、公開まで開発する全プロセスをご紹介しました。既存のデザインを空間パラダイムに対応するように変更し、SpatialPanel と Orbiter のコンポーザブルを使用して、ユーザーがフルスペースに入ったときに表示される空間レイアウトを作成しました。最後に、アプリの新しいバージョンを Google Play ストアにリリースしました。

このブログ投稿が、Android XR で独自のアプリを利用する方法を理解するうえで役立つことを願っています。以下に、お役に立つ可能性のあるリンクをいくつかご紹介します。

作成者:

続きを読む