ウォッチフェイスを最適化する

Wear OS のウォッチフェイスは継続的に動作するため、電力を効率的に使用する必要があります。

また、ウォッチフェイスのパフォーマンスの最適化も重要です。 サービスでは不必要な計算を実行してはなりません。アニメーションを実行するウォッチフェイスは、通知やシステム インジケーターの表示中もスムーズに動作する必要があります。

基本的な最適化

このセクションでは、効率性向上のためのおすすめの方法をご紹介します。

ウォッチフェイスの色と明るさ

暗い色を使用すると、スマートウォッチの電池を節約できます。 以下は、ウォッチフェイスの背景の設定を通じてウォッチフェイスの電池使用量を最適化することができるおすすめの方法です。

  • 色: 可能であれば、黒い背景を使用します。
  • 明るさ: ウォッチフェイスの要件により黒い背景を使用できない場合は、背景色の明るさを HSV(色相、彩度、明度)または HSB スケールで 25% 以下に維持するようにします。たとえば、Color クラスを使用して背景色を設定し、HSV スケールで色を定義する場合、Value の設定(つまり、明度の設定)に 25 以下を使用します。

WatchFaceService.Engine のコールバックを使用する

ウォッチフェイスではアクティブな場合にのみ計算を実行するようにします。つまり、WatchFaceService.Engine のコールバックを使用します。できれば、このクラスの以下のメソッドを使用して、ウォッチフェイスが表示されているかどうかを確認します。

  • onVisibilityChanged(boolean)
  • isVisible()

または、同じクラス(WatchFaceService.Engine)の以下のメソッドを使用します。

  • onCreate()
  • onDestroy()

DataClient インターフェースに登録されているリスナーを使用する

イベントをリッスンするには、DataClient.addListener に登録されているライブリスナーを使用します。 例については、データアイテムの同期についての記事をご覧ください。

WearableListenerService はウォッチフェイスがアクティブかどうかにかかわらず呼び出されるため、イベントのリッスンに使用しないでください。詳しくは、BIND_LISTENER のサポート終了に関するブログをご覧ください。

システム イベント(タイムゾーンの変更や電池に関するイベントなど)を取得するために Android マニフェスト ファイルにブロードキャスト レシーバを登録しないでください。BroadcastReceiver は、ウォッチフェイスがアクティブかどうかにかかわらず呼び出されます。ただし、Context クラスの registerReceiver メソッドを使用してレシーバーを登録することは可能です。

動的な機能を使用してスマートフォンを操作する

ウォッチフェイスにスマートフォン上で動作する処理が必要な場合、そのコードはウォッチフェイスがアクティブなときにのみ実行されるようにします。スマートフォンのアプリで対応するウォッチフェイスがアクティブであることを確認できるようにするには、CapabilityClient API を使用することをおすすめします。

WatchFaceService.EngineonCreate() メソッドで動的に追加される機能を定義します。機能の削除には onDestroy() メソッドを使用します。

たとえば、周期的なデータを取得してウォッチフェイスに表示するアプリでは、ウォッチフェイスによってアドバタイズされる機能のリスナーを登録する必要があります。ウォッチフェイスにアクセス可能な場合は、更新されたデータを取得してウォッチフェイスにプッシュするためのアラームを追加します。ウォッチフェイスの選択が解除された場合や、スマートウォッチにアクセスできなくなった場合、スマートウォッチの電源がオフになった場合、スマートウォッチが最新のデータを受け取ることができない場合は、周期的なアラームを削除します。

消費電力を監視する

デベロッパーやユーザーは Wear OS コンパニオン アプリを通じて、ウェアラブル デバイスの各種プロセスでの電池消費量を確認できます([設定] > [スマートウォッチの電池])。

Android 5.0 で導入された電池寿命の改善機能について詳しくは、Project Volta をご覧ください。

暗号化対応のウォッチフェイスを登録する

Android 7.0 以降はファイルベースの暗号化をサポートしており、ユーザーが起動時に復号パスコードを入力する前に暗号化対応アプリを実行できます。これにより、起動アニメーションからウォッチフェイスへの移行時間を最大 30 秒短縮できます。

起動時間を短縮できるようにするには、android:directBootAware="true" をウォッチフェイスのマニフェストに追加します。

注: この機能は、ウォッチフェイスで認証情報暗号化ストレージを使用しない場合に使用します。

アニメーションに関するおすすめの方法

このセクションのおすすめの方法を使用すると、アニメーションの消費電力を削減できます。

アニメーションのフレームレートを下げる

アニメーションは多くの場合、計算コストが高く、大量の電力を消費します。ほとんどのアニメーションは 30 フレーム/秒でスムーズに見えるため、それより高いフレームレートで実行しないことをおすすめします。draw() メソッドの最後で invalidate() を使用している場合、invalidate() メソッドを呼び出す前に遅延を追加するとフレームレートを抑えることができます。この手順の実装方法については、ウォッチフェイスを描画するをご覧ください。

アニメーションの合間に CPU をスリープさせる

アニメーションの実行や、ウォッチフェイスのコンテンツのわずかな変化でも、CPU のスリープが解除されます。ウォッチフェイスでは、アニメーションの合間に CPU をスリープさせることをおすすめします。たとえばインタラクティブ モードでは、1 秒間隔で短いアニメーションを表示して、その合間に CPU をスリープさせることができます。 CPU をこまめにスリープさせると、個々のスリープ時間は短くても消費電力を大幅に削減できます。

電池寿命を最大限に伸ばすために、アニメーションの使用を控えめにしてください。コロンの点滅でさえ、点滅のたびに CPU のスリープが解除されるため、電池寿命に悪影響を及ぼします。

ビットマップ アセットのサイズを小さくする

ウォッチフェイスの多くは、背景画像と、その上で変形や重ね合わせが行われるその他のグラフィック アセット(時計の針のような徐々に移動するデザイン要素など)で構成されます。これらのグラフィック要素は通常、ウォッチフェイスを描画するで説明されているように、システムがウォッチフェイスを再描画するたびに Engine.onDraw() メソッド内で回転(および、場合によってはサイズ調整)が行われます。

これらのグラフィック アセットはサイズが大きいほど、変形に必要な計算コストが高くなります。 サイズの大きなグラフィック アセットを Engine.onDraw() メソッドで極端に変形させると、システムでアニメーションを実行可能なフレームレートが大幅に下がります。

図 1. 時計の針を切り抜くと、余分なピクセルを削除できる

ウォッチフェイスのパフォーマンスを向上させる方法は次のとおりです。

  • 必要以上にサイズの大きなグラフィック要素を使用しない。
  • 周りの余分な透過ピクセルを削除する。

図 1 の例では、左側にある時計の針のサイズを 97% 縮小できます。

このセクションの説明どおりにビットマップ アセットのサイズを縮小することで、アニメーションのパフォーマンスを向上できるだけでなく、電池を節約することもできます。

ビットマップ アセットを結合する

一緒に描画されることが多いビットマップがある場合は、それらを同じグラフィック アセットに結合することを検討します。多くの場合、インタラクティブ モードの背景画像を目盛りと結合することで、システムがウォッチフェイスを再描画するたびに 2 つの全画面ビットマップを描画する必要がなくなります。

サイズ調整されたビットマップを描画するときにアンチ エイリアスを無効にする

Canvas.drawBitmap() メソッドを使用して、サイズ調整されたビットマップを Canvas オブジェクト上に描画する場合、Paint インスタンスを使用して複数のオプションを設定できます。パフォーマンスを向上させるには、setAntiAlias() メソッドを使用してアンチ エイリアスを無効にします(このオプションはビットマップに対する影響がないため)。

図 2. ビットマップ フィルタリングを無効にした場合(左)と有効にした場合(右)の例

ビットマップ フィルタリングを使用する

ビットマップ アセットを他の要素の上に描画する場合、setFilterBitmap() メソッドを使用して同じ Paint インスタンスに対するビットマップ フィルタリングを有効にします。図 2 は、ビットマップ フィルタリングを有効にした場合と無効にした場合の時計の針を拡大表示したものです。

注: 低ビットの常に画面表示モードでは、システムで画像の色を確実にレンダリングすることができず、ビットマップ フィルタリングが正常に処理されません。常に画面表示モードがアクティブな場合は、ビットマップ フィルタリングを無効にしてください。

コストの高い処理を描画メソッドの外部に移動する

ウォッチフェイスを再描画するたびに Engine.onDraw() メソッドがシステムによって呼び出されるため、このメソッドにはウォッチフェイスの更新に絶対に必要な処理のみを含めると、パフォーマンスを向上させることができます。

可能な場合は、Engine.onDraw() メソッド内で以下の処理を実行しないようにします。

  • 画像やその他のリソースの読み込み
  • 画像のサイズ変更
  • オブジェクトの割り当て
  • フレーム間で結果が変わらない計算の実行

通常、これらの処理は Engine.onCreate() メソッドで実行できます。画像のサイズは、キャンバスのサイズを提供する Engine.onSurfaceChanged() メソッドで事前に変更することができます。

ウォッチフェイスのパフォーマンスを分析するには、CPU プロファイラを使用します。特に、Engine.onDraw() の実行時間が短く、また、各呼び出し間で実行時間が一定であることが重要です。詳しくは、メソッド トレースの記録と検査に関する記事をご覧ください。