この記事は Dave Burke による Android Developers Blog の記事 " 12L and new Android APIs and tools for large screens " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
タブレット、折りたたみ式デバイス、ChromeOS デバイスを合わせると、2 億 5000 万台を超える大画面デバイスが Android を実行しています。ここ 12 か月だけでも、1 億台近くの新しい Android タブレットがアクティベートされました。これは前年比 20% の増加です。現在最も成長が著しいデスクトップ プラットフォームである ChromeOS は、92% の増加率となっていますが、さらに、折りたたみ式デバイスも急増中で、前年比 265% 以上の成長を遂げています。すべて合わせれば、Android が動作しているアクティブな大画面デバイスは 2 億 5000 万台を超えます。その勢いを受けて、このようなデバイスで動作している Android を、ユーザーにとってもデベロッパーにとってもよりよい OS にするために、私たちは努力を続けています。
そこで 2021 年 10 月 27 日 (日本時間:10 月 28 日) の Android Dev Summit (英語、動画は日本語字幕あり) では、大画面に特化した Android 12 のフィーチャー ドロップについてお知らせしました。私たちはこれを 12L と呼んでいます。併せて、大画面向けの開発を容易にするための新 API や新ツール、ガイダンスも準備しています。さらに、Google Play で行っている変更についてもお話ししました。これにより、ユーザーは大画面に最適化されたアプリをこれまで以上に簡単に見つけられるようになります。ここでは、Android の大画面向け新機能について紹介しますので、ぜひお読みください。
先月、12L のデベロッパー プレビュー を提供しました。これは今後公開する予定のフィーチャー ドロップで、Android 12 を大画面でさらに快適に使えるようにするものです。このプレビューを使って、大画面関連の新機能を試したり、自分のアプリを最適化したり、フィードバックの送信が可能です。
12L では、通知、クイック設定、ロック画面、概要、ホーム画面など、大画面向けの UI 全般を改善しました。たとえば、画面領域を有効活用するため、600dp を超える画面では、通知シェードやロック画面、その他のシステム表示を新しい 2 列レイアウトで表示します。システムアプリも最適化されます。
2 列レイアウトによって表示できる内容が増加し、さらに使いやすいものに
また、マルチタスクをこれまで以上に強力で直感的なものにしました。12L では大画面で新しいタスクバーが搭載されるので、ユーザーはすぐにお気に入りのアプリに切り替えることができます。このタスクバーのおかげで、分割画面モードもこれまで以上にわかりやすくなり、タスクバーからドラッグ&ドロップするだけで、アプリを分割画面モードで実行できるようになります。また、Android 12 以降で分割画面モードの操作性を向上させるため、アプリがサイズ変更可能かどうかにかかわらず、すべてのアプリを自動的に分割画面モードに対応させます。
アプリをドラッグ&ドロップして分割画面モードで実行
さらに、互換性モードを改善して見た目と安定性を向上させ、レターボックス表示の快適さを向上させたほか、アプリのデフォルトでの外観も改善しました。レターボックス表示は、デバイス メーカーが簡単にカスタマイズできるようになっているので、カスタムの色や処理を設定したり、はめ込むウィンドウの位置を調整したり、カスタムの角丸を適用したりできるようになっています。
Android 12 のタブレットや折りたたみ式デバイスが次にまとまって登場するタイミングに間に合うように、12L のフィーチャー ドロップは来年の早い時期にリリースする計画です。以上のような機能を大画面デバイスに導入するため、私たちは既に OEM パートナーと協力して作業を進めています。近日中に 12L のデベロッパー プレビューが Lenovo P12 Pro (日本未発表) に搭載される予定なので、ご期待ください。数か月後には、この機能がデバイスに配信されます。今から大画面向けに最適化したアプリの準備を入念にしておきましょう。
デベロッパーの皆さんには、さまざまなサイズのウィンドウの分割画面モードでアプリがどのように動作するかを確かめておくことを強くお勧めします。まだアプリを最適化していない方は、画面の向きを変えたときにどう見えるかを確認し、新しい互換性モードの変更が適用される場合はそれを試してみましょう。12L には、大画面向け機能のほかにも、いくつかのデベロッパー向けの新 API や、新しい API レベルが含まれています。アプリに互換性を破る変更が起こらないように注意しているので、アプリのターゲットを 12L にしなくても Google Play 要件を満たすことができます。
12L を使ってみたい方は、Android Studio の最新プレビュー リリースから、12L Android Emulator のシステム イメージやツールをダウンロードしてください。機能と変更点を確認してアプリをテストする領域を判断し、プレビューの概要でスケジュールやリリースの詳細をご確認ください。問題やリクエストはこちらから報告できます。そしていつものように、フィードバックは大歓迎です。
12L はスマートフォンでも利用できますが、ほとんどの新機能は小さな画面では確認できません。現在、私たちはタブレット、折りたたみ式デバイス、ChromeOS デバイスに重点的に対応しています。今後のプレビューでは、Pixel デバイス向けに Android ベータ版への登録をオープンする予定です。詳しくは、developer.android.com/12L をご覧ください。
どんな画面にも適応する完全にアダプティブなアプリを作り始める時です。そして、それを今まで以上に簡単に実現できるようにしています。OS や Play でアプリの変更に対応できるように、デベロッパー プレビューと併せて API やツール、ガイダンスのアップデートを公開します。
アダプティブ UI をサポートするための第一歩は、小さな画面と大きな画面の両方でうまく動作するアプリを設計することです。私たちは、アプリの UI をあらゆる画面サイズに対応させる際に役立ててもらうため、新しいマテリアル デザインのガイダンス (英語) の作成を進めてきました。このガイダンスは、エコシステムでよく使われている一般的なレイアウト パターンをカバーしているので、さまざまなアイデアが得られるだけでなく、作業を加速することにもつながるはずです。
マテリアル デザインのガイドライン、アダプティブ UI パターン
最高のナビゲーション エクスペリエンスをユーザーに提供するには、ユーザーが使うデバイスのウィンドウ サイズ クラスに合わせたナビゲーション UI を提供する必要があります。私たちが推奨するナビゲーション パターンには、コンパクトな画面(compact)ではナビゲーション バー (英語) を使う、中程度(medium)以上の画面幅(600dp 以上)のデバイスクラスではナビゲーション レール (英語) を使う、などがあります。新たに公開したマテリアル デザインのガイダンス (英語) には、広い画面幅(expanded)のデバイス向けに、いくつかの大画面レイアウトのアイデアが掲載されています。たとえば、SlidingPaneLayout を使って実装できるリスト / 詳細構造などです。ガイダンスを参照して、ビューと Compose でアダプティブ UI 向けのナビゲーションを実装する方法をご確認ください。
フラグメントを使っている既存アプリに大画面に最適なレイアウトを適用する場合、ナビゲーション パターンを更新して SlidingPaneLayout を使うのはすばらしい方法です。しかし、多くの皆さんが複数のアクティビティに基づいたアプリを作っていることは承知しています。そういったアプリでは、Jetpack WindowManager 1.0 ベータ版 03 で新しくリリースしたアクティビティ埋め込み API を使うと、TwoPane ビューなどの新しい UI パラダイムに簡単に対応できます。現在、SlidingPaneLayout をアップデートしてこの API をサポートする作業を進めています。今後数か月間のアップデートに注目してください。
Jetpack Compose を使うと、大画面や多様なレイアウトを対象にした開発が楽になります。Compose の採用を始めているなら、大画面向けの最適化を行う絶好のチャンスです。
Compose は宣言型 UI ツールキットです。すべての UI をコードで記述するので、UI が利用できるサイズにどう適応すべきかを実行時に判断するのは簡単です。Compose がアダプティブ UI の開発に特に向いているのはそのためで、画面サイズやコンポーネントの違いによる UI の変更にとても簡単に対処できます。Compose でアダプティブ レイアウトを構築するためのガイドでは、知っておくべき基本的な事項について説明しています。
Jetpack WindowManager ライブラリを使うと、下位互換性のある形でアプリのウィンドウを操作し、すべてのデバイスを対象としたレスポンシブな UI を開発できます。新機能は以下のとおりです。
アクティビティを埋め込むと、たとえばリスト / 詳細パターンなど、複数のアクティビティを一度に表示することで、大画面で利用できるようになる広い表示領域を有効活用できます。その際、アプリのリファクタリングはほとんど、あるいはまったく必要ありません。並べるか重ねるかなど、アプリにどのようにアクティビティを表示するかは、皆さんが決定します。具体的には、XML 構成ファイルを作成するか、Jetpack WindowManager API を呼び出します。あとはシステムが対応して、作成した構成に基づいて表示方法を決めてくれます。
アクティビティの埋め込みは、折りたたみ式デバイスでもシームレスに動作します。デバイスを折りたたんだり広げたりすると、それに応じてアクティビティが重なったり並んだりします。アプリで複数のアクティビティを使っている方は、アクティビティの埋め込みを使って大画面デバイスでのユーザー エクスペリエンスを向上させることができます。アクティビティ埋め込み API は、Jetpack WindowManager 1.0 ベータ版 03 以降のリリースで試すことができます。詳しくはこちらをご覧ください。
Jetpack WindowManager でアクティビティを埋め込む
ウィンドウ サイズ クラスは、綿密に検討されたビューポートの一連のブレークポイントで、サイズ変更可能なアプリでのレイアウトの設計、開発、テストに利用できます。ウィンドウ サイズ クラスのブレークポイントは、compact(コンパクト)、medium(中程度)、expanded(広い)の 3 つのカテゴリに分かれています。これらは、エコシステムのデバイスの大部分を表しつつ、レイアウトのシンプルさと特異なユースケースにアプリを最適化できる柔軟性との間でバランスをとるように設計されています。WindowSizeClass API は、近日中に Jetpack WindowManager 1.1 で公開される予定です。これにより、レスポンシブ UI の構築がさらに簡単になります。詳しくはこちらをご覧ください。
Jetpack WindowManager のウィンドウ サイズ クラス
WindowManager では、折り目やヒンジなど、さまざまなウィンドウ形状に対応した一般的な API サーフェスも提供されます。折りたたみ対応のアプリでは、折り目やヒンジの部分を避けてウィンドウのコンテンツを表示したり、折り目やヒンジの部分を自然なセパレータとしてうまく活用したりできます。アプリを折りたたみ対応にする方法は、こちらのガイドをご覧ください。
Android アプリは、あらゆるデバイス、そしてあらゆるカテゴリに適応できるように構築すべきです。そこで、Android Studio 全体を対象として、UI やレイアウトの設計、開発、テストを行うたくさんのツールに、リファレンス デバイスを導入します。リファレンス デバイスは 4 つあり、それぞれスマートフォン、大型折りたたみ式デバイスの内側ディスプレイ、タブレット、デスクトップを表します。マーケットのデータを分析して設計したもので、人気のデバイスや急成長中のセグメントを表しています。また、リファレンス デバイスを規定したことで、新しい WindowSizeClass のブレークポイントを使ってアプリがさまざまなよくあるブレークポイントの組み合わせに対応して動作することを確認できるようになります。そのため、アプリができる限り多くのユースケースをカバーすることを保証できます。
リファレンス デバイスの定義
大画面向け UI の対応を始める際に、どこから手を付けてよいかわからない方もいらっしゃるかもしれません。その場合は、まず新しいツールを使って、大画面デバイスで起こりうる問題を確認しましょう。Android Studio Chipmunk では、レイアウト検証によって先回りで UI について警告や提案を行ってくれる新しいビジュアル lint チェックツールを開発しています。どのリファレンス デバイスが影響を受けるかもわかるようになっています。
リファレンス デバイスの各クラスが表示されたレイアウト検証ツール
ランタイムでアプリをテストする場合、Android Studio Chipmunk (英語) に搭載されているサイズ変更可能な新しいエミュレータ構成を使うことができます。サイズ変更可能なエミュレータを使うと、4 つのリファレンス デバイス(スマートフォン、折りたたみ式、タブレット、デスクトップ)をすばやく切り替えることができます。これにより、設計時にレイアウトを検証したり、ランタイムで動作をテストしたりする操作が簡単になります。どちらの作業にも、同じリファレンス デバイスを使うことができます。サイズ変更可能なエミュレータを新規作成するには、Android Studio の Device Manager を使って新しい仮想デバイスを作成し、Resizable デバイス定義と Android 12L(Sv2)システム イメージを選択します。
サイズ変更可能な Android Emulator
タブレット、折りたたみ式、ChromeOS の各デバイスに最適なアプリを簡単に探せるようにするため、ユーザーのデバイスに最も適したアプリを目立たせるように Play を変更します。
現在、それぞれのアプリの品質を大画面アプリ品質ガイドライン (英語) に照らして評価する新たなチェックを追加する作業を行っています。これにより、デバイスに最適なアプリが目立つようになります。Play ストアで大画面のユーザーが大画面に最適化されていないアプリを表示した場合、そのアプリのストア掲載情報ページに通知を表示する予定です。
加えて、既にお知らせしたように、アプリの評価にも大画面専用の評価を導入し、大画面デバイスでアプリがどう動作するかをユーザーが評価できるようにします。以上の変更は来年に実施する予定です。皆さんがアプリの準備を始められるように、あらかじめお知らせいたしました。
また、Google Play で Google のビジネスモデルを進化させてデベロッパーのニーズに応えるための取り組みを紹介した記事も忘れずに確認しておきましょう。
大画面や折りたたみ式デバイス向けの開発を始めるうえで役立てていただけるように、私たちはビューにも Compose にも対応します。新規アプリや既存アプリで異なる画面サイズをサポートする方法、ビューと Compose の両方でナビゲーションを実装する方法、折りたたみ式デバイスのメリットを活用する方法などを紹介したガイダンスの追加や改訂も行っています。ビューのサポートの大画面ガイドのセクション、または Compose ガイドのセクションをご覧ください。
コードほど雄弁なものはありません。以下のサンプルは、レスポンシブ UI に対応するように更新しています。
実践的な演習を行いたい方は、Codelab で、アップデートされた Jetpack WindowManager による折りたたみ式デバイスとデュアル スクリーン デバイスのサポートをご覧ください。
Reviewed by Tamao Imura - Developer Marketing Manager, Google Play
この記事は Jeremy Walker による Android Developers Blog の記事 " Watch out for Wear OS at Android Dev Summit 2021 " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
今年の Android Dev Summit (英語) では、Wear OS プラットフォームのいくつかの主要なアップデートなど、Android デベロッパー期待のお知らせがたくさんありました。Google I/O では、新しい Wear OS のリリースを発表しました。その後、Galaxy Watch4 シリーズに Wear OS Powered by Samsung が搭載されました。Strava、Spotify、Calm などの多くのデベロッパーが、既に最新バージョンの Wear OS 向けに便利なエクスペリエンスを作成しています。今後、デベロッパーの皆さんがスマートウォッチにどんな新しいエクスペリエンスをもたらしてくれるのか、とても楽しみです。詳細な情報を入手してスマートウォッチ向けの優れたアプリを作成したい方は、このままお読みください。API やデザインツール、Google Play ストアのアップデートについて説明します。
Jetpack Compose ライブラリを使うと、短時間で簡単に UI を開発できます。(英語) そして今回 Wear OS に Compose のサポートを追加します。皆さんは、スマートウォッチ向けになったおなじみの UI コンポーネントを使ってアプリをデザインできます。こういったコンポーネントには Material You が含まれているので、少ないコードで美しいアプリを作成できます。
Compose for Wear OS は、現在デベロッパー プレビュー段階です。詳しく知りたい方や試してみたい方は、以下を参考にしてください。
お試しいただき、こちらでフィードバックを共有、もしくは、Jetbrains Slack の #compose-wear チャンネルに参加して感想をお聞かせください。ベータ版で API が確定する前にお願いします!
ウォッチフェイスは、ユーザーがスマートウォッチで自分を表現する方法の中でも、特に特徴的なものものの 1 つです。ウォッチフェイスを作成すると、Wear OS のユーザーに皆さんのブランドをアピールできます。私たちは Samsung と連携し、ウォッチフェイス作成のツールを改善して、Wear OS エコシステムでのウォッチフェイスのデザインを簡単にしました。
Samsung が作成したデザインツール Watch Face Studio (英語) を使うと、コーディングなしで独自のウォッチフェイスを作成、配布できます。直感的なグラフィックス ツールが搭載されているので、簡単にウォッチフェイスをデザインできます。個人で使うためのウォッチフェイスを作ることも、Google Play Console にアップロードして API レベル 28 以上をサポートする Wear OS デバイスのユーザーと共有することもできます。
先日、たくさんの Android Jetpack Wear OS ライブラリ (英語) をリリースしました。これらは、ベスト プラクティスに従い、ボイラープレートを減らし、ユーザーが一目でわかる高パフォーマンスなアプリを作るうえで役立ちます。
現在、タイルはマーケットのほとんどのデバイスで有効で、予測どおりに動作し、一目で情報にアクセスしたりクイック アクションに使用したりできます。API は現在ベータ版です。ぜひお試しください!(英語)
ウォッチフェイスを(Watch Face Studio 以外の方法で)もっと細かく調整したいデベロッパーの皆さんのために、ゼロから Kotlin で開発した新しい Jetpack Watch Face API のベータ版をリリースしました。
新しい API では、たくさんの新機能が提供されます。
今こそ古い Watch Face Support Library から今回の新バージョンに移行を始める絶好のチャンスです。
Google Play ストアで、皆さんの Wear OS アプリを見つけやすくする取り組みも進めています。今年は既にウォッチフェイスを検索できるようにしたほか、ユーザーが Wear カテゴリのアプリを簡単に探せるようにもしました。さらに、スマートフォンの Google Play ストアから直接アプリをスマートウォッチにダウンロードする機能もリリースしました。この変更点の詳細は、こちら (英語) からご確認いただけます。
また、皆さんがユーザーの期待に応えることができるように、Wear OS 品質ガイドラインの更新版 (英語) も公開しました。合わせて、ユーザーがアプリの外見を深く理解できるように、新しいスクリーンショット ガイドライン (英語) も公開しています。2022 年には、フォーム ファクタと国に固有の評価を導入し、アプリがどのようなデバイスや国で利用され、どのように動作しているかを深く理解できるようにする予定です。
Wear OS の開発に関する詳しい情報は、デベロッパー ウェブサイト (英語)をご覧ください。
2021 年 10 月 18 日に開催された、『DroidKaigi 前夜祭』に Google 関係者がパネリストとして登壇しました。
このイベントでは、2021 年に発表した Android/Google Play 関連の製品のお話や、I/O 以降に発表された製品・技術関連の最新情報についての内容を中心に Google 関係者が解説をしました。
この記事では、イベント内で解説した内容をまとめます。
Jetpack Compose は、ネイティブ UI をビルドするための Android の最新ツールキットで、Kotlin API を使用して、少ないコードで Android の UI 開発を簡素化し、加速することができます。Google I/O では、株式会社メルカリ様のケーススタディもリリースされ、UI 開発の生産性が 56 % 向上したという実例もございます。今回のイベントでは、その Jetpack Compose の最新アップデートである、1.1.0 についてお話をさせていただきました。
このセッションでは、Android IDE Android Studio (英語) の Android Gradle Plugin API (AGP) (英語) や Test framework についてについてお話をさせていただきました。公式の強力な Android IDE Android Studio Arctic Fox (2020.3.1) ベータ版 を I/O で発表したあと、7 月に安定版をリリースしました。UI 設計期間の短縮、新しいデバイスへのアプリ拡張、デベロッパーの生産性向上を目的としており、Compose と合わせて使うことで、最新の UI をすばやくデザインすることができます。
このセッションでは、Google Play と Multi Form Factor についてお話をさせていただきました。
Wear OS や大画面対応から、セキュリティ ツールなどのトピックまで幅広くカバーしました。
ご参加いただきました皆さん、ありがとうございました!Android Developer Summit の動画も、ぜひご視聴ください。
この記事は Dave Burke による Android Developers Blog の記事 " Android 12 is live in AOSP! " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
2021 年 10 月 4 日 (日本時間 10 月 5 日) 、ソースを Android オープンソース プロジェクト(AOSP)にプッシュし、Android の最新バージョンを正式にリリースしました。お手元のデバイスに配信される Android 12 にご注目ください。今後数週間で Pixel に、その後今年中に Samsung Galaxy、OnePlus、Oppo、realme、TECNO、Vivo、Xiaomi の各デバイスに配信されます。
いつものことですが、Android 12 ベータ版期間中のフィードバックをありがとうございました。225,000 人以上の方が Pixel やパートナー デバイスで早期リリースをテストし、リリースの品質を改善するために 50,000 件近くの問題を報告してくれました。また、多くの記事やディスカッション、アンケート、そして直接顔を合わせて意見を述べてくださった皆さんや、リリースに間に合うようにアプリの互換性対応を行ってくださった皆さんにも感謝いたします。Android があらゆる人のための偉大なプラットフォームであるのは、皆さんのサポートや貢献があってこそです。
また、10 月 27 日から28 日に開催される今年の Android Dev Summit (英語)では、Android 12 についてさらに詳しくお伝えする予定です。各セッションの動画は、後日日本語字幕もご用意いたしますので、YouTube の「設定」から日本語字幕をオンにしてご覧ください。Android テクニカル セッションの概要など、イベントについての詳細情報も公開されています。この記事でも、後ほど改めてお知らせします。
ここでは、デベロッパーのための Android 12 の新機能をいくつか紹介します。Android 12 デベロッパー サイトでは、すべての新機能について詳しく説明しているので、そちらもご覧ください。
Material You - Android 12 には、Material You (英語) と呼ばれる新しいデザイン言語が導入され、今まで以上にパーソナライズされた美しいアプリを構築できるようになっています。最新のマテリアル デザイン 3 アップデートのすべてをアプリに組み込むには、アルファ版の Material Design Components をお試しください。また、近日中に公開される Jetpack Compose のサポートにも注目です。
通知 UI のアップデート - 通知のデザインも更新し、モダンで使いやすく、便利になりました。Android 12 をターゲットとしたアプリ では、カスタム通知も標準のアフォーダンスで装飾されるようになり、その他すべての通知との一貫性が向上します。詳しくはこちらをご覧ください。
ストレッチ オーバースクロール - アプリのコンテンツをスクロールするときのスムーズさを向上させるため、Android 12 をターゲットとしたアプリでは、すべてのスクロール コンテナに新しい「ストレッチ」オーバースクロール効果が追加されています。この効果は、システムとアプリ全体に共通する自然なスクロール終了インジケーターになります。詳しくはこちらをご覧ください。
アプリ起動時のスプラッシュ画面 - Android 12 をターゲットとしたアプリ では、すべてのアプリにスプラッシュ画面が導入されます。アプリのスプラッシュ画面はさまざまな方法でカスタマイズできるので、アプリ独自のブランディングのニーズを反映できます。詳しくはこちらをご覧ください (英語) 。
システム パフォーマンスの高速化と効率化 - コア システム サービスが利用する CPU 時間を 22%、ビッグコアの利用を 15% 削減しました。また、アプリの起動時間を短縮し、アプリを速く読み込めるように I/O を最適化しました。さらに、データベース クエリでは、大きなウィンドウの CursorWindow を 49 倍近く高速化しました。
フォアグラウンド サービスの最適化 - ユーザー エクスペリエンスを向上させるため、Android 12 ではバックグラウンドのアプリがフォアグラウンド サービスを開始できないようになっています。それに代わる新機能として、アプリは JobScheduler で優先ジョブ (英語) を利用できます。詳しくはこちらをご覧ください。
通知のレスポンシブ性の向上 - Android 12 では、通知トランポリンが制限されるので、通知からアプリを起動する際の時間が短縮されます。たとえば、通知トランポリン削除後の Google フォト アプリは、34% 高速に起動するようになっています。詳しくはこちらをご覧ください。
パフォーマンス クラス - パフォーマンス クラス は一連のデバイス機能で、Android 12 デバイスで要求の厳しいユースケースや高品質なコンテンツをサポートします。アプリは、実行時にデバイスのパフォーマンス クラスを確認することで、デバイスのパフォーマンスを最大限に活用できます。詳しくはこちらをご覧ください。
機械学習の高速化 - Android 12 では、Neural Networks API を通して ML アクセラレータを限界まで活用し、常に最大限のパフォーマンスを発揮できるようになっています。また、ML アクセラレータ ドライバは、プラットフォーム リリースとは独立して Google Play 開発者サービスでアップデートできるようになるので、互換性のあるすべてのデバイスで最新ドライバのメリットを活用できます。
おおよその位置情報 - ユーザーは位置情報データをさらに細かくコントロールできるようになり、アプリが厳密な位置情報をリクエストした場合でも、おおよその位置情報のみを許可できるようになります。詳しくはこちらをご覧ください。
マイクとカメラのインジケーター - アプリがデバイスのカメラやマイクを使っているタイミングを、ステータスバーのインジケーターでユーザーに知らせます。詳しくはこちらをご覧ください。
マイクとカメラの切り替え - サポート対象のデバイスで、クイック設定の新しい切り替え機能から、アプリからのマイクやカメラに対するアクセスをすぐに簡単に無効化できるようにします。詳しくはこちらをご覧ください。
周辺デバイス権限 - アプリで新しい権限を使うと、位置情報の権限がなくても、周辺デバイスのスキャンやペア設定を行えます。詳しくはこちらをご覧ください。
リッチ コンテンツの挿入 - 新しい統合 API を使うと、UI で任意のソース(クリップボード、キーボード、ドラッグ アンド ドロップ)からリッチ コンテンツを受信できます。下位互換性を確保するため、この統合 API は AndroidX にも追加しています。詳しくはこちらをご覧ください。
角の丸い画面のサポート - 多くの最新デバイスで、角の丸い画面が使われています。こういったデバイスで優れた UX を提供するため、新しい API を使って角に関する詳細な情報を問い合わせ、必要に応じて UI 要素を管理できます。詳しくはこちらをご覧ください。
互換メディア コード変換 - HEVC 形式の動画は画質と圧縮率が大幅に向上しており、すべてのアプリでこの形式のサポートが推奨されています。それができないアプリでは、互換メディア コード変換機能を使って AVC ファイルをリクエストすると、システムがコード変換を行ってくれます。詳しくはこちらをご覧ください。
ぼかしや色フィルタなど、エフェクトの使い勝手の向上 - 新しい API では、ビューやレンダリング階層でよく使われるグラフィック エフェクトを適用しやすくなっています。RenderEffect (英語) を使うと、RenderNode (英語) やビューにぼかしや色フィルタなどを適用できます。新しい Window.setBackgroundBlurRadius() (英語) API を使うと、ウィンドウの背景にすりガラス エフェクトをかけることもできます。また、blurBehindRadius (英語) を使うと、ウィンドウの後ろにあるすべてのコンテンツをぼかすことができます。
触覚フィードバックの拡張 - Android 12 では、UI イベントに対する効果的な触覚フィードバック、ゲーム向けの迫力ある楽しい効果、生産性を高めるために注意を促す触覚フィードバックを作成するツールを拡張しています。詳しくはこちらをご覧ください。
新しいカメラ効果とセンサー機能 - アプリで新しいベンダー拡張機能 (英語) を使うと、ぼけ、HDR、ナイトモードなど、デバイス メーカーが組み込んだカスタムのカメラ効果を活用できます。新しい API では、Quad / Nona Bayer パターンを利用する超高解像度カメラセンサーをフル活用することもできます。詳しくはこちらをご覧ください。
ネイティブ コードでのクラッシュのデバッグの改善 - Android 12 では、今までよりも実用的な診断情報が提供されるので、NDK 関連のクラッシュのデバッグが簡単になります。App Exit Reasons API (英語) を使うと、アプリから Tombstone と呼ばれる詳細なクラッシュ ダンプファイルにアクセスできます。
Android 12 でのゲーム - Game Mode API (英語) を使うと、プレーヤーがゲームのパフォーマンス プロファイル(長時間通勤用にバッテリー寿命を延ばす、パフォーマンス モードで最高のフレームレートを実現するなど)を選択する操作に応答できます。インストール時にバックグラウンドでゲームアセットをフェッチできるようにする Play as you download を使うと、プレーヤーをすばやくゲームプレイに導くことができます。
Android 12 が一般公開リリースされたので、ユーザーがスムーズに Android 12 に移行できるよう、すべての Android デベロッパーの皆さんに互換性テストを終えてできる限り早くアップデートを公開することをお願いします。
アプリの互換性をテストするには、Android 12 が動作するデバイスにインストールし、アプリのフローを確認して機能や UI の問題を探します。Android 12 でのすべてのアプリが対象となる動作の変更点を確認し、影響を受ける可能性がある領域を集中的にテストしてください。特にテストしておくべき変更点は、以下のとおりです。
アプリのライブラリや SDK の互換性テストも忘れずに行ってください。SDK の問題を見つけた場合は、最新バージョンの SDK にアップデートするか、デベロッパーに連絡してサポートを求めます。
現在のアプリの互換性のあるバージョンを公開したら、アプリの targetSdkVersion をアップデートするプロセスを開始できます。Android 12 アプリの動作の変更点を確認し、互換性フレームワークを使って問題をすばやく検知します。
#AndroidDevSummit (英語) が帰ってきます。10 月 27 日から28 日(日本時間 10 月 28 日 - 29 日) に開催される、イベントでは、Android 12 を含む Android 開発の最新情報をご紹介します。今年のテーマは、Excellent apps, across devices(デバイスを超える優れたアプリ体験)です。開発ツールや API、タブレットやウェアラブルを含む数十億台のデバイス間で使用できる優れたアプリの開発や、生産性向上を支援する技術についてお話しする予定です。
30 以上の Android テクニカル セッションの概要など、イベントについての詳細情報も公開されました。セッションの情報はこちら(英語) から確認できます。どのセッションに参加するか、計画を立て始めましょう。今後数週間のうちに、皆さんの質問を #AskAndroid に共有することをお願いする予定です。寄せられた質問には、Android チームがイベントの中でライブで回答します。
イベントは、太平洋時間の 10 月 27 日午前 10 時(日本時間 28 日午前 2 時)に開催される 50 分の技術関連の基調講演「The Android Show」でキックオフします。ここでは、Android デベロッパー向けのあらゆる最新ニュースや最新情報を共有しますこちら (英語) のニュースレターに登録して最新情報を受け取りましょう。
この記事は Peter Visontay, Bessie Jiang による Android Developers Blog の記事 " Making permissions auto-reset available to billions more devices " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。寄稿者: Inara Ramji, Rodrigo Farell, James Kelly, Henry Chin
ほとんどのユーザーは、スマートフォンで多くの時間を過ごしています。仕事をする、ゲームをする、友人とつながるなど、アプリは人々にとってデジタルライフの主要な出入り口です。多くの場合、アプリが動作するためには、何らかの許可が必要になります。しかし、特定のデバイスに何十個ものアプリが存在することを考えれば、ユーザーが以前に何を許可したかを覚えておくのは至難の業です。長期間使うことがなかったアプリであればなおさらです。
Android 11 では、アプリの権限を自動リセットする機能を導入しました。この機能は、アプリが数か月にわたって使われなかった場合にランタイム権限を自動的にリセットするので、ユーザーのプライバシー保護に役立ちます。ランタイム権限とは、アプリが許可をリクエストした際に、プロンプトがユーザーに表示されるものです。2021 年 12 月より、この機能を数十億台のデバイスに展開します。この機能は、Google Play 開発者サービス (英語) を搭載し、かつ Android 6.0(API レベル 23)以降を実行しているデバイスで自動的に有効化されます。
この機能は、デフォルトで Android 11(API レベル 30)以降をターゲットとするアプリで有効になりますが、API レベル 23 から 29 をターゲットとするアプリでは、ユーザーが手動で許可の自動リセットを有効化できます。
では、デベロッパーの皆さまにはどのような影響があるのか説明します。
一部のアプリや権限は、自動的にリセットの対象外となります。たとえば、企業が利用中のデバイス管理者のアプリや、エンタープライズ ポリシーで固定された権限などです。
必要に応じて、デベロッパーはユーザーにリクエストを行い、システムがアプリの権限をリセットしないようにすることができます。これは、主にバックグラウンドで動作し、インタラクションを必要としないアプリで便利です。主なユースケースは、こちらに記載されています。
現在の動作
新しい動作
Android 11(API レベル 30)以降のデバイスで、権限が自動的にリセットされます。
以下のデバイスで、権限が自動的にリセットされます。
Google Play 開発者サービスを搭載し、Android 6.0(API レベル 23)から Android 10(API レベル 29)までのバージョン(両端値を含む)を実行しているデバイス
Android 11(API レベル 30)以降を実行しているすべてのデバイス
Android 11 以降をターゲットとするアプリで、デフォルトで権限がリセットされます。Android 6.0(API レベル 23)以降をターゲットとするアプリでは、ユーザーが手動で自動リセットを有効化できます。
現在の動作からの変更はありません。
アプリは、ユーザーに自動リセットの無効化をリクエストできます。
アクション
Android 11 API
(Android 11 以降のデバイスでのみ動作)
新しいクロスプラットフォーム API
(Android 11 以降のデバイスを含む Android 6.0 以降のデバイスで動作)
デバイスで権限の自動リセットが有効化されているかどうかのチェック
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R を確認
androidx.core.content.PackageManagerCompat.getUnusedAppRestrictionsStatus() を呼び出す
アプリで自動リセットが無効化されているかどうかのチェック
PackageManager.
isAutoRevokeWhitelisted() を呼び出す
androidx.core.content.
PackageManagerCompat.
getUnusedAppRestrictionsStatus() を呼び出す
アプリで自動リセットの無効化をユーザーにリクエスト
次のアクションのインテントを送信:
Intent.ACTION_AUTO_REVOKE_PERMISSIONS
次で作成したインテントを送信: androidx.core.content.
IntentCompat.
createManageUnusedAppRestrictionsIntent()
val future: ListenableFuture<Int> = PackageManagerCompat.getUnusedAppRestrictionsStatus(context)future.addListener( { onResult(future.get()) }, ContextCompat.getMainExecutor(context)) fun onResult(appRestrictionsStatus: Int) { when (appRestrictionsStatus) { // Status could not be fetched. Check logs for details. ERROR -> { } // Restrictions do not apply to your app on this device. FEATURE_NOT_AVAILABLE -> { } // Restrictions have been disabled by the user for your app. DISABLED -> { } // If the user doesn't start your app for months, its permissions // will be revoked and/or it will be hibernated. // See the API_* constants for details. API_30_BACKPORT, API_30, API_31 -> handleRestrictions(appRestrictionsStatus) }} fun handleRestrictions(appRestrictionsStatus: Int) { // If your app works primarily in the background, you can ask the user // to disable these restrictions. Check if you have already asked the // user to disable these restrictions. If not, you can show a message to // the user explaining why permission auto-reset and Hibernation should be // disabled. Tell them that they will now be redirected to a page where // they can disable these features. Intent intent = IntentCompat.createManageUnusedAppRestrictionsIntent (context, packageName) // Must use startActivityForResult(), not startActivity(), even if // you don't use the result code returned in onActivityResult(). startActivityForResult(intent, REQUEST_CODE)}
getUnusedAppRestrictionsStatus()
この記事は Manuel Vivo による Android Developers - Medium の記事 " Introduction to Hilt in the MAD Skills series " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
MAD Skills 記事シリーズの Hilt についての記事です。この記事では、依存関係インジェクション(DI)が皆さんのアプリや Hilt にとって重要である理由について説明します。Hilt は、Android で DI を行うための Jetpack の推奨ソリューションです。
動画で視聴したい方は、こちらをご覧ください。
Android アプリで依存関係インジェクションの原理に従うことで、優れたアプリ アーキテクチャの土台を築くことができます。その結果、コードの再利用性が高まり、リファクタリングやテストが簡単になります。DI のメリットの詳細は、こちらをご覧ください。
プロジェクトでクラスのインスタンスを作成する場合、そのクラスが必要とする依存関係や推移的依存関係を満たしていくことで、依存関係グラフを手動で実現できます。
しかし、毎回これを手動で行うと、ボイラープレート コードが必要になり、エラーも起こりやすくなる可能性があります。たとえば、オープンソースの Google I/O アプリ iosched で利用している ViewModel をご覧ください。依存関係と推移的依存関係を含めると、FeedViewModel を作成するために必要なコードがどのくらいの量になるか想像できますか?
FeedViewModel
class FeedViewModel( private val loadCurrentMomentUseCase: LoadCurrentMomentUseCase, loadAnnouncementsUseCase: LoadAnnouncementsUseCase, private val loadStarredAndReservedSessionsUseCase: LoadStarredAndReservedSessionsUseCase, getTimeZoneUseCase: GetTimeZoneUseCase, getConferenceStateUseCase: GetConferenceStateUseCase, private val timeProvider: TimeProvider, private val analyticsHelper: AnalyticsHelper, private val signInViewModelDelegate: SignInViewModelDelegate, themedActivityDelegate: ThemedActivityDelegate, private val snackbarMessageManager: SnackbarMessageManager) : ViewModel(), FeedEventListener, ThemedActivityDelegate by themedActivityDelegate, SignInViewModelDelegate by signInViewModelDelegate { /* ... */}
class FeedViewModel(
private val loadCurrentMomentUseCase: LoadCurrentMomentUseCase,
loadAnnouncementsUseCase: LoadAnnouncementsUseCase,
private val loadStarredAndReservedSessionsUseCase: LoadStarredAndReservedSessionsUseCase,
getTimeZoneUseCase: GetTimeZoneUseCase,
getConferenceStateUseCase: GetConferenceStateUseCase,
private val timeProvider: TimeProvider,
private val analyticsHelper: AnalyticsHelper,
private val signInViewModelDelegate: SignInViewModelDelegate,
themedActivityDelegate: ThemedActivityDelegate,
private val snackbarMessageManager: SnackbarMessageManager
) : ViewModel(),
FeedEventListener,
ThemedActivityDelegate by themedActivityDelegate,
SignInViewModelDelegate by signInViewModelDelegate {
/* ... */
}
これは難解で繰り返しが多いので、容易に間違った依存関係を取得してしまうこともあると思います。依存関係インジェクション ライブラリを使えば、依存関係を手動で提供することなく、DI のメリットを活用できます。必要なコードはライブラリがすべて生成してくれます。その際に活躍するのが Hilt です。
Hilt は Google が開発した依存関係インジェクション ライブラリです。Hilt を使えば手動で書かなければならないボイラープレートをすべて生成してくれるので、アプリで DI のベスト プラクティスを最大限に活用できます。
Hilt はアノテーションを使ってコンパイル時にコードを生成するので、実行はとても高速です。その際に利用するのが、JVM の DI ライブラリである Dagger です。Hilt は、Dagger をベースに作られています。
Hilt は Android アプリの Jetpack 推奨 DI ソリューションであり、ツールや他の Jetpack ライブラリのサポートも含まれています。
Hilt を使うアプリには、@HiltAndroidApp アノテーションを付けた Application クラスを含める必要があります。このアノテーションにより、コンパイル時に Hilt のコード生成が実行されます。また、Hilt がアクティビティに依存関係を注入するには、そのアクティビティに @AndroidEntryPoint アノテーションを付けておく必要があります。
@HiltAndroidApp
@AndroidEntryPoint
@HiltAndroidAppclass MusicApp : Application() @AndroidEntryPointclass PlayActivity : AppCompatActivity() { /* ... */ }
class MusicApp : Application()
class PlayActivity : AppCompatActivity() { /* ... */ }
依存関係を注入するには、Hilt から注入したい変数に @Inject アノテーションを付けます。Hilt が注入したすべての変数は、super.onCreate が呼び出されたときに利用できるようになります。
@Inject
super.onCreate
@AndroidEntryPointclass PlayActivity : AppCompatActivity() { @Inject lateinit var player: MusicPlayer override fun onCreate(savedInstanceState: Bundle) { super.onCreate(bundle) player.play("YHLQMDLG") }}
class PlayActivity : AppCompatActivity() {
@Inject lateinit var player: MusicPlayer
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(bundle)
player.play("YHLQMDLG")
この例では、PlayActivity に MusicPlayer を注入しています。しかし、Hilt は MusicPlayer 型のインスタンスを提供する方法をどのようにして認識しているのでしょうか。実は、この段階ではまだ認識していません。 Hilt にその方法を伝えるためにアノテーションを使います。
PlayActivity
MusicPlayer
クラスのコンストラクタに @Inject アノテーションを付けることで、Hilt にそのクラスのインスタンスの作成方法を伝えることができます。
class MusicPlayer @Inject constructor() { fun play(id: String) { ... }}
class MusicPlayer @Inject constructor() {
fun play(id: String) { ... }
アクティビティへの依存関係の注入に必要なのは、これだけです。とても簡単でしたね。最初の例は簡単で、MusicPlayer は他の型に依存していません。しかし、他の依存関係がパラメータとして渡されると、Hilt はそれを管理し、MusicPlayer のインスタンスを提供する際にその依存関係を満たさなければなりません。
実は、ここで示した例はとても簡単で、単純すぎるものです。しかし、これを手動で行う場合、どうするかを考えてみてください。
手動で DI を行う場合、必要な型を提供し、提供するインスタンスのライフサイクルを管理する 依存関係コンテナ クラスを作ることが考えられます。つまり、まさに Hilt が内部で行っていることです。
アクティビティに @AndroidEntryPoint アノテーションを付けると、PlayActivity と関連付けられた依存関係コンテナが自動的に作成され、管理されます。手動で行うこの実装を PlayActivityContainer と呼ぶことにしましょう。MusicPlayer に @Inject アノテーションを付けることで、MusicPlayer 型のインスタンスの提供方法をコンテナに伝えます。
PlayActivityContainer
// PlayActivity annotated with @AndroidEntryPointclass PlayActivityContainer { // MusicPlayer annotated with @Inject fun provideMusicPlayer() = MusicPlayer() }
// PlayActivity annotated with @AndroidEntryPoint
class PlayActivityContainer {
// MusicPlayer annotated with @Inject
fun provideMusicPlayer() = MusicPlayer()
そしてアクティビティでは、コンテナのインスタンスを作成し、それを使ってアクティビティの依存関係を設定します。これも Hilt ではアクティビティに @AndroidEntryPoint アノテーションを付けることで処理してくれます。
class PlayActivity : AppCompatActivity() { private lateinit var player: MusicPlayer // Created by Hilt when annotating the activity with @AndroidEntryPoint private lateinit var container: PlayActivityContainer override fun onCreate(savedInstanceState: Bundle) { // @AndroidEntryPoint also creates and populates fields for you container = PlayActivityContainer() player = container.provideMusicPlayer() super.onCreate(bundle) player.play("YHLQMDLG") }}
private lateinit var player: MusicPlayer
// Created by Hilt when annotating the activity with @AndroidEntryPoint
private lateinit var container: PlayActivityContainer
// @AndroidEntryPoint also creates and populates fields for you
container = PlayActivityContainer()
player = container.provideMusicPlayer()
ここまで説明してきたのは、クラスのコンストラクタに @Inject アノテーションを付けると、そのクラスのインスタンスの提供方法を Hilt に伝えられることです。また、@AndroidEntryPoint が付いたクラスの変数にこのアノテーションを付けると、Hilt はその型のインスタンスをそのクラスに注入します。
@AndroidEntryPoint は、アクティビティだけでなく、ほとんどの Android フレームワーク クラスに追加できます。このアノテーションは、そのクラスの依存関係コンテナのインスタンスを作成し、@Inject アノテーションが付いたすべての変数を設定します。
Application クラスに付けられた @HiltAndroidApp アノテーションは、Hilt のコード生成をトリガーにするだけでなく、Application クラスに関連付けられた依存関係コンテナも作成します。
Application
Hilt の基本について理解できたので、もう少し複雑な例を見てみましょう。次の例では、MusicPlayer のコンストラクタが依存関係 MusicDatabase を受け取ります。
MusicDatabase
class MusicPlayer @Inject constructor( private val db: MusicDatabase) { fun play(id: String) { ... }}
private val db: MusicDatabase
) {
ここでは、MusicDatabase のインスタンスを提供する方法を Hilt に伝えなければなりません。型がインターフェースである場合や、例えばライブラリから提供されているために自分がクラスを所有していない場合は、コンストラクタに @Inject アノテーションを付けることはできません。
アプリで、永続化ライブラリとして Room を使っているとしましょう。再度、PlayActivityContainer を手動で実装する場合について考えてみます。MusicDatabase を提供するとき、Room を使うと MusicDatabase は抽象クラスになります。そのため、依存関係を提供するコードを実行します。次に、MusicPlayer のインスタンスを提供するときに、MusicDatabase の依存関係を提供する(または満たす)メソッドを呼び出す必要があります。
class PlayActivityContainer(val context: Context) { fun provideMusicDatabase(): MusicDatabase { return Room.databaseBuilder( context, MusicDatabase::class.java, "music.db" ).build() } fun provideMusicPlayer() = MusicPlayer( provideMusicDatabase() )}
class PlayActivityContainer(val context: Context) {
fun provideMusicDatabase(): MusicDatabase {
return Room.databaseBuilder(
context, MusicDatabase::class.java, "music.db"
).build()
fun provideMusicPlayer() = MusicPlayer(
provideMusicDatabase()
)
Hilt では、推移的依存関係について心配する必要はありません。Hlit はすべての推移的依存関係を自動的に取得しますが、MusicDatabase 型のインスタンスの提供方法を伝えておかなければなりません。これを行うために、Hilt のモジュールを使います。
Hilt のモジュールとは、@Module アノテーションが付いたクラスです。このクラスでは、ある型のインスタンスの提供方法を Hilt に伝える関数を作成できます。Hilt が認識するこの情報は、Hilt の専門用語で バインディング とも呼ばれます。
@Module
@Module@InstallIn(SingletonComponent::class)object DataModule { @Provides fun provideMusicDB(@ApplicationContext context: Context): MusicDatabase { return Room.databaseBuilder( context, MusicDatabase::class.java, "music.db" ).build() }}
@InstallIn(SingletonComponent::class)
object DataModule {
@Provides
fun provideMusicDB(@ApplicationContext context: Context): MusicDatabase {
@Provides アノテーションが付いた関数で、MusicDatabase 型のインスタンスの提供方法を Hilt に伝えています。関数本体には、Hilt が実行するコードのブロックが含まれており、先ほどの手動実装のコードとまったく同じものです。
戻り値の型が MusicDatabase となっているので、Hilt はこの関数が提供する型を認識できます。また、関数のパラメータから、対応する型の依存関係も認識できます。この例では、既に Hilt が利用できる ApplicationContext がパラメータになっています。このコードから、Hilt は MusicDatabase 型のインスタンスの提供方法を認識します。別の表現を使うなら、MusicDatabase の バインディング を取得したことになります。
ApplicationContext
Hilt のモジュールには、@InstallIn アノテーションも付いています。これは、この情報がどの依存関係コンテナやコンポーネントで利用できるかを示します。では、コンポーネントとは何でしょうか。この点について詳しく説明しましょう。
@InstallIn
Hilt が生成する コンポーネント クラスは、先ほど手動でプログラミングしたコンテナのように、型のインスタンスを提供する役割を担います。Hilt はコンパイル時にアプリケーションの依存関係グラフをたどり、すべての推移的依存関係の型を提供するコードを生成します。
Hilt が生成する コンポーネント クラスは、型のインスタンスを提供する役割を担う
Hilt は、ほとんどの Android フレームワーク クラスに対して、コンポーネント、つまり依存関係コンテナを生成します。各コンポーネントの情報(バインディング)は、コンポーネント階層を伝播します。
Hilt のコンポーネント階層
MusicDatabase バインディングが Application クラスに対応する SingletonComponent で利用できる場合、その他のコンポーネントでも利用できます。
SingletonComponent
これらのコンポーネントは、コンパイル時に Hilt によって自動生成されます。コンポーネントが作成、管理され、対応する Android フレームワーク クラスに関連付けられるのは、これらのクラスに @AndroidEntryPoint アノテーションを付けたときです。
モジュールの @InstallIn アノテーションは、そういったバインディングが利用できる場所や、利用できる他のバインディングを管理するうえで便利です。
再び、手動で作成した PlayActivityContainer コードについて考えてみます。気づいた方もいらっしゃるかもしれませんが、MusicDatabase の依存関係が必要になるたびに、別のインスタンスが作成されています。
アプリ全体で MusicDatabase の同じインスタンスを再利用したい場合もあるので、この動作は理想的ではありません。そこで、関数を使うのではなく、変数に格納すれば同じインスタンスを共有できます。
class PlayActivityContainer { val musicDatabase: MusicDatabase = Room.databaseBuilder( context, MusicDatabase::class.java, "music.db" ).build() fun provideMusicPlayer() = MusicPlayer(musicDatabase)}
val musicDatabase: MusicDatabase =
Room.databaseBuilder(
fun provideMusicPlayer() = MusicPlayer(musicDatabase)
つまり、MusicDatabase 型のスコープがこのコンテナに適用されるようにすることで、依存関係として常に同じインスタンスが提供されるようにしています。これを Hilt で行うには、どうすればよいでしょうか。もうおわかりと思いますが、ここでも別のアノテーションを使います。
@Provides メソッドに @Singleton アノテーションを付けると、そのコンポーネントでは常にこの型の同じインスタンスを共有するように Hilt に伝えることができます。
@Singleton
@Module@InstallIn(SingletonComponent::class)object DataModule { @Singleton @Provides fun provideMusicDB(@ApplicationContext context: Context): MusicDatabase { return Room.databaseBuilder( context, MusicDatabase::class.java, "music.db" ).build() }}
@Singleton はスコープ アノテーションです。それぞれの Hilt コンポーネントには、1 つのスコープ アノテーションが対応付けられています。
それぞれの Hilt コンポーネントのスコープ アノテーション
ある型のスコープを ActivityComponent にしたい場合、ActivityScoped アノテーションを使います。スコープ アノテーションはモジュールで利用できますが、コンストラクタに @Inject アノテーションが付いているクラスでも利用できます。
ActivityComponent
ActivityScoped
バインディングには次の 2 つのタイプがあります。
Hilt は、ViewModel、Navigation、Compose、WorkManager といった人気のある Jetpack ライブラリと統合されています。
ViewModel 以外と統合する場合は、別のライブラリをプロジェクトに追加する必要があります。詳細は、ドキュメントをご覧ください。このブログ投稿の冒頭で紹介した iosched の FeedViewModel コードを覚えているでしょうか。Hilt を使うと、どのようになるか見てみましょう。
@HiltViewModelclass FeedViewModel @Inject constructor( private val loadCurrentMomentUseCase: LoadCurrentMomentUseCase, loadAnnouncementsUseCase: LoadAnnouncementsUseCase, private val loadStarredAndReservedSessionsUseCase: LoadStarredAndReservedSessionsUseCase, getTimeZoneUseCase: GetTimeZoneUseCase, getConferenceStateUseCase: GetConferenceStateUseCase, private val timeProvider: TimeProvider, private val analyticsHelper: AnalyticsHelper, private val signInViewModelDelegate: SignInViewModelDelegate, themedActivityDelegate: ThemedActivityDelegate, private val snackbarMessageManager: SnackbarMessageManager) : ViewModel(), FeedEventListener, ThemedActivityDelegate by themedActivityDelegate, SignInViewModelDelegate by signInViewModelDelegate { /* ... */}
@HiltViewModel
class FeedViewModel @Inject constructor(
この ViewModel のインスタンスを提供する方法を Hilt に伝えるために、コンストラクタに @Inject アノテーションが付いています。その点を除けば、クラスに @HiltViewModel アノテーションを付けるだけです。
これでだけです!ViewModel のプロバイダを手動で作成する必要はありません。Hilt がそれを行ってくれます。
Hilt は、よく使われている別の依存関係インジェクション ライブラリ Dagger がベースになっています。今後のエピソードには、Dagger が頻繁に登場する予定です。現在 Dagger をご利用の場合、Dagger と Hilt は連携して動作できます。移行 API の詳細は、ガイド(英語)をご覧ください。
Hilt についてさらに詳しく知りたい方は、特によく使われるアノテーションやその効果、使用方法を説明したクイック リファレンス(英語)をご覧ください。Hilt のドキュメントのほかに、ハンズオン形式で学習できる Codelab も公開しています。
今回のエピソードは以上ですが、この話はこれで終わりではありません。MAD Skills シリーズはさらに続くので、Android Developers の Medium 記事 (英語) をフォローして、投稿されたときに確認できるようにしておきましょう。
この記事は Jonathan Koren による Android Developers - Medium の記事 " Trackr comes to the Big Screen " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
Trackr は、タスク管理のサンプルアプリです。Trackr の主な用途は、ユーザー補助をサポートする観点で一般的な UI パターンを確認できるようにすることですが、最先端の Android 開発におけるベスト プラクティスの実例にもなっています。先日、このアプリを大画面対応にしました。その際にマテリアル デザインやレスポンシブ パターンを適用することで、大画面デバイスで洗練された直感的なユーザー エクスペリエンスをどのように実現したのかをご紹介します。
変更前 : タスク一覧画面の下部にあるアプリバーのメニューから、アーカイブと設定にアクセスできました。大画面では、タッチのターゲットとなるメニュー コントロールが小さく、不便な場所にありました。また、下のアプリバーが伸びすぎていました。
左: スマートフォンのナビゲーション。右: タブレットのナビゲーション
変更後 : 画面が広い場合は、ナビゲーション レール (英語) を表示します。さらに、ナビゲーション レールにフローティング アクション ボタン(新規タスク画面を開きます)を表示し、下のアプリバーは完全になくしました。
大画面のナビゲーション レール
この変更は大画面デバイスを念頭に行いましたが、スマートフォンの横表示でも有効で、タスク一覧を表示する縦のスペースを広く使えるようになります。
横向きのスマートフォンのナビゲーション レール
変更前 : タスク一覧画面とアーカイブ画面が横幅いっぱいに広がり、項目をタップすると、一覧が項目の詳細に置き換わっていました。大画面では、UI 要素が引き伸ばされるか、片側に寄ってしまい、画面のバランスが悪く感じられました。
スマートフォンでは自然に見えるが、大画面では最適な形でスペースを利用できていない
変更後 : タスク一覧画面とアーカイブ画面の両方で、SlidingPaneLayout (英語) を使って一覧/詳細 UI を表示します。これを行う方法は、Google I/O アプリに対して行った変更に関する以前の記事 (英語) で解説していますので、技術的な詳しい説明に興味がある方は、ぜひご覧ください。
タスク詳細画面にもフローティング アクション ボタン(タスク編集画面を開きます)がありますが、ナビゲーション レールがある場合に 2 つのフローティング アクション ボタンが表示されることになるので、理想的ではありません。そこで、2 つ目のフローティング アクション ボタンは非表示にし、右上のツールバーに編集ボタンを追加します。
2 ペイン化で画面スペースを活用
変更前 : タスクを編集すると、タスク編集 UI がタスク詳細の代わりに表示され、画面全体を覆っていました。タスク詳細と同じく、画面のバランスが悪く感じられます。新規タスク UI でも同じ問題が発生していました(実は、新規タスクとタスク編集は、ナビゲーション グラフで同じ遷移先になっています)。
左: スマートフォンのタスク編集。右: タブレットのタスク編集
変更後 : 大画面では、DialogFragment を使って他のコンテンツの上にタスク編集 UI を表示します。
ユーザーが現在の目的に集中できるようにするフローティング UI
最初は、タスク詳細の代わりにこの UI を詳細ペインに表示することを考えました。その方が単純でしたが、次の理由により、このアプローチでは納得できないとすぐに感じました。
新規タスク UI は、タスク編集と同じパターンを利用
ここでの学びは、何も考えずにシンプルにデザインしてしまうと、実装してみると機能的におかしい可能性があるということです。そうなったときは、一歩下がってユーザー エクスペリエンスに注目し、ユーザー エクスペリエンスを向上させるデザイン パターンを探しましょう。
タブレットや折りたたみ式デバイスの人気は上昇しています。そのため、レスポンシブな UI を作ることの重要性がこれまでになく高まっています。ナビゲーション レールを追加したり、SlidingPaneLayout を使ったりすると、Trackr アプリの見栄えがよくなるだけでなく、ユーザビリティが劇的に向上し、スマートフォンにはないエクスペリエンスを実現できることをお見せしました。さらに、単に画面のスペースだけではなく、ユーザビリティに注目し、ユーザーのニーズを最大限に満たすことができるようなデザインの再考が必要になる場合があることもお伝えしました。
新たに改善された Trackr が気に入ってもらえることを期待しています。コードは github.com/android/trackr から確認できます。