サービスに関する最新情報

単一機能を超えて: CameraX 1.5 で機能の組み合わせを保証する

所要時間: 6 分
Tahsin Masrur のプロフィールを表示
Tahsin Masrur ソフトウェア エンジニア

最新のカメラアプリは、強力で重複する機能によって定義されます。ユーザーは、鮮やかな HDR で動画を撮影し、60 FPS で滑らかな動きを捉え、プレビューの手ぶれ補正で非常に滑らかな映像を撮影することを期待しています。多くの場合、これらすべてを同時に実現することが求められます。

しかし、開発者であれば、現実はもっと複雑であることをご存じでしょう。特定のデバイスが特定の組み合わせを実際にサポートしていることを保証するにはどうすればよいでしょうか。これまでは、複数の機能を有効にすることは、多くの場合、賭けでした。個々の機能のサポートを確認することはできますが、それらを組み合わせると、未定義の動作が発生したり、最悪の場合、カメラ セッションが失敗したりする可能性があります。この不確実性により、デベロッパーは保守的にならざるを得ず、高性能なデバイスを使用しているユーザーが最高の体験を得ることを妨げています。

たとえば、HDR と 60 FPS の動画を同時に安定してサポートするプレミアム デバイスはごくわずかです。そのため、ほとんどのアプリでは、大半のスマートフォンでユーザー エクスペリエンスが低下するのを防ぐために、両方を同時に有効にしないようにしています。

この問題に対処するため、CameraX の機能グループを導入します。これは、この推測を不要にするために設計された新しい API です。カメラを構成する前に、特定の機能の組み合わせがサポートされているかどうかをクエリできるようになりました。また、CameraX に優先順位を伝えるだけで、サポートされている最適な組み合わせを有効にすることもできます。

CameraX を初めて使用する場合

新しい Feature Group API について詳しく説明する前に、CameraX について簡単に復習しておきましょう。CameraX は、アプリ デベロッパーがカメラアプリの開発を容易にすることを目的とした Jetpack サポート ライブラリです。ほとんどの Android デバイスで機能する一貫性のある使いやすい API サーフェスを提供するとともに、Android 6.0(API レベル 23)への下位互換性も備えています。CameraX を初めて使用する場合は、公式ドキュメントを確認し、Codelab を試すことをおすすめします。

Feature Group API で構築できるもの

機能の組み合わせを試行錯誤する必要がなくなり、対応するハードウェア(Google Pixel 10 Pro など)で HDR と 60 FPS 動画を同時に撮影するなど、可能な限り最高のカメラ エクスペリエンスを自信を持って提供できます。また、その組み合わせをサポートできないデバイスでは、エラーを適切に回避できます。

unnamed.png
HDR と 60 FPS の両方を同時に有効にした Google Pixel 10 Pro
unnamed (1).png
HDR と 60 FPS を同時に実行できない古いデバイスでは、HDR のみが有効になり、60 FPS オプションは無効になります。

Feature Group API を使用すると、次のことが可能になります。

  • よりスマートで動的な UI を構築する: リアルタイムのハードウェア サポートに基づいて、UI の設定をインテリジェントに有効または無効にします。たとえば、ユーザーが HDR を有効にした場合、そのデバイスでこの組み合わせがサポートされていない場合は、60 FPS オプションをすぐにグレー表示にして無効にできます。
hdr.gif
  • 信頼性の高い「高画質」モードを提供する: 優先順位を付けた必要な機能のリストを使用してカメラを構成します。CameraX は、特定のデバイスでサポートされている最適な組み合わせを自動的に見つけて有効にし、デバイス固有の複雑なロジックを使用せずに優れた結果を実現します。
  • カメラ セッションの失敗を防ぐ: 事前にサポートを確認することで、カメラがサポートされていない組み合わせを構成しようとするのを防ぎ、クラッシュの一般的な原因を排除して、スムーズなユーザー エクスペリエンスを提供できます。

仕組み: 主要コンポーネント

新しい API は、SessionConfig と CameraInfo への重要な追加機能を中心に構成されています。

  1. GroupableFeature: この API では、HDR_HLG10、FPS_60、PREVIEW_STABILIZATION、IMAGE_ULTRA_HDR など、事前定義されたグループ化可能な機能のセットが導入されています。計算上の制限により、この API が提供する高い信頼性でグループ化できるのは、特定の機能セットのみです。Google では、このリストを拡大するよう積極的に取り組んでおり、今後のリリースでさらに多くの機能のサポートを導入する予定です。
  2. 新しい SessionConfig パラメータ: カメラ セッションの開始に使用されるこのクラスに、次の 2 つの新しいパラメータが追加されました。
    • requiredFeatureGroup: 構成を成功させるためにサポートする必要がある機能に使用します。これは、ユーザーが明示的に有効にする機能(「HDR」スイッチの切り替えなど)に最適です。確定的で一貫したエクスペリエンスを確保するため、リクエストされた組み合わせがサポートされていない場合、bindToLifecycle 呼び出しは機能リクエストを暗黙的に無視するのではなく、IllegalArgumentException をスローします。この結果を事前にクエリするには、CameraInfo#isFeatureGroupSupported API(詳細は下記を参照)を使用する必要があります。
    • preferredFeatureGroup: 望ましいがオプションである機能に使用します。たとえば、デフォルトの「高画質」モードを実装する場合に使用します。優先順位に従って並べられた必要な機能のリストを指定すると、CameraX は、デバイスがサポートする優先順位が最も高い組み合わせを自動的に有効にします。
  3. CameraInfo#isFeatureGroupSupported(): これは、機能グループがサポートされているかどうかを明示的に確認するためのコア クエリメソッドです。アプリの UI でサポートされている機能オプションのみをユーザーに提供するのに適しています。SessionConfig を渡すと、組み合わせがサポートされているかどうかを示すブール値が返されます。必要な機能を備えた SessionConfig をバインドする場合は、まずこの API を使用して、サポートされていることを確認する必要があります。

実装の実践

これらのコンポーネントを使用して、より優れたカメラ エクスペリエンスを構築する方法を見てみましょう。

シナリオ 1: 「ベスト エフォート」高画質モード

デフォルトで最適な機能を有効にする場合は、優先順位を付けたリストを preferredFeatureGroup に提供します。この例では、CameraX に HDR、60 FPS、プレビューの手ぶれ補正の順に優先するよう指示しています。CameraX は、考えられるすべての組み合わせをチェックし、デバイスがサポートする最適な組み合わせを選択するという複雑な処理を行います。

たとえば、デバイスが HDR と 60 FPS を同時に処理できるものの、プレビューの手ぶれ補正には対応していない場合、CameraX は最初の 2 つを有効にし、3 つ目を破棄します。これにより、デバイス固有の複雑なチェックを記述することなく、最適なエクスペリエンスを実現できます。

cameraProvider.bindToLifecycle(

    lifecycleOwner,

    cameraSelector,

    SessionConfig(

        useCases = listOf(preview, videoCapture),

        // The order of features in this list determines their priority. 

        // CameraX will enable the best-supported combination based on these

        // priorities: HDR_HLG10 > FPS_60 > Preview Stabilization.  

        preferredFeatureGroup =

           listOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION),

    ).apply {

        // (Optional) Get a callback with the enabled features

        // to update your UI. 

        setFeatureSelectionListener { selectedFeatures ->

            updateUiIndicators(selectedFeatures)

        }

    }

)

このコード スニペットでは、CameraX は次の優先順位で機能の組み合わせを有効にしようとし、デバイスが完全にサポートしている最初の組み合わせを選択します。

  1. HDR + 60 FPS + プレビューの手ぶれ補正
  2. HDR + 60 FPS
  3. HDR + プレビューの手ぶれ補正
  4. HDR
  5. 60 FPS + プレビューの手ぶれ補正
  6. 最大 60 FPS
  7. プレビューの手ぶれ補正
  8. 上記の機能はどれも使用していない

シナリオ 2: リアクティブ UI を構築する

ユーザーの選択に応答し、サポートされていない機能の組み合わせをユーザーが選択できないようにする UI を作成するには、サポートを直接クエリします。以下の関数は、ユーザーが現在選択している機能と互換性のない機能をチェックし、対応する UI 要素を無効にできるようにします。

/**

 * Returns a list of features that are NOT supported in combination

 * with the currently selected features.

 */

fun getUnsupportedFeatures(

    currentFeatures: Set<GroupableFeature>

): Set<GroupableFeature> {

    val unsupportedFeatures = mutableSetOf<GroupableFeature>()

    val appFeatureOptions = setOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION)


    // Iterate over every available feature option in your app. 

    appFeatureOptions.forEach { featureOption ->

        // Skip features the user has already selected. 

        if (currentFeatures.contains(featureOption)) return@forEach


        // Check if adding this new feature is supported. 

        val isSupported = cameraInfo.isFeatureGroupSupported(

            SessionConfig(

                useCases = useCases,

                // Check the new feature on top of existing ones.

                requiredFeatureGroup = currentFeatures + featureOption

            )

        )


        if (!isSupported) {

            unsupportedFeatures.add(featureOption)

        }

    }


    return unsupportedFeatures

}

このロジックを ViewModel または UI コントローラに組み込むことで、ユーザー入力に反応し、動作が保証された構成でカメラを再バインドできます。

// Invoked when user turns some feature on/off.

fun onFeatureChange(currentFeatures: Set<GroupableFeature>) {

    // Identify features that are unsupported with the current selection.

    val unsupportedFeatures = getUnsupportedFeatures(currentFeatures)



    // Update app UI so that users can't enable them.

    updateDisabledFeatures(unsupportedFeatures)



    // Since the UI now only allows selecting supported feature combinations, 

    // `currentFeatures` is always valid. This allows setting

    // `requiredFeatureGroup` directly, without needing to re-check for

    // support or set a feature selection listener.  

    cameraProvider.bindToLifecycle(

        lifecycleOwner,

        cameraSelector,

        SessionConfig(

            useCases = listOf(preview, videoCapture),

            requiredFeatureGroup = currentFeatures,

        )

    )

}

これらのコンセプトを実際のアプリケーションで確認するには、Google の内部テストアプリをご覧ください。このアプリには、上述の「ベスト エフォート」シナリオと「リアクティブ UI」シナリオの両方の完全な実装が用意されています。

これはテスト アプリケーションであり、公式にサポートされているサンプルではありません。Feature Group API のリファレンスとしては優れていますが、本番環境での使用向けに調整されていません。

今すぐ始めましょう

Feature Group API を使用すると、高度なカメラ機能を使用する際の曖昧さが解消されます。機能サポートをクエリする決定論的な方法を提供することで、より強力で信頼性の高いカメラアプリを自信を持って構築できます。

この API は CameraX 1.5 で試験運用版として利用可能であり、1.6 リリースで完全に安定する予定です。今後もサポートと改善が予定されています。

詳しくは、公式ドキュメントをご覧ください。皆様の創造性あふれる作品を楽しみにしています。また、皆様からのフィードバックをお待ちしております。ご意見、ご要望、問題の報告は、次の方法でお送りいただけます。

作成者:
続きを読む