※本記事は、Joyce Toh氏とChris Assigbe氏によるGoogle I/O 2026のセッション「Build a modern note-taking app on Android」の内容を基に作成されています。動画の詳細情報は https://www.youtube.com/watch?v=ZyFb2geQ-GQ でご覧いただけます。本記事では、動画の内容を要約しております。なお、本記事の内容は登壇者の見解を正確に反映するよう努めていますが、要約や解釈による誤りがある可能性もありますので、正確な情報や文脈については、オリジナルの動画をご視聴いただくことをお勧めいたします。
Joyce Toh氏はAndroid Developer Relations Teamに所属し、Chris Assigbe氏はAndroidのDeveloper Relations Engineerを務めています。両氏は、Jetpack Ink APIおよびBrush Designerを用いた低遅延・表現力豊かな描画体験と、Notes role・デスクトップウィンドウイング・マルチインスタンスサポートといったAndroidの各種システム統合機能について、サンプルアプリ「Cahier」を交えて解説しています。
また、以下の関連リソースもあわせてご参照ください。
- Ink API documentation:https://goo.gle/48GyUap
- Sample code GitHub:https://goo.gle/4dffw5Y
- Create a note-taking app:https://goo.gle/3PnDL9W
- How to support connected displays:https://goo.gle/4d2MkyH
- Google I/O 2026のAndroidセッション一覧:https://goo.gle/Android-at-IO2026
- Android Developersチャンネル登録:https://goo.gle/AndroidDevs
1. イントロダクション:ラージスクリーン時代のノートアプリと生産性
1.1 スタイラス対応大画面デバイスが切り拓く新しい活用シーン
Joyce: こんにちは、Android Developer Relations TeamのJoyce Tohです。本日は、Jetpack Ink Libraryを軸にしたインキングの基盤と、それを取り巻く様々なAndroidの機能を通じて、開発者の皆さんがユニークで楽しいノートテイキング体験をどう作り上げられるかを一緒に見ていきたいと思っています。もし今、ご自身が作っているアプリがノートテイキングを主眼にしたものではないとしても、どうかここで離脱しないでください。今日お話しする内容は、決してノートアプリだけに閉じたものではないと考えているからです。
Joyce: 私がまずお伝えしたいのは、Androidというプラットフォームそのものの変化です。かつてはモバイル専用のOSという位置づけでしたが、現在ではさまざまなデバイスが共存するエコシステムへと大きく進化しました。今日ご紹介するインキングやプロダクティビティに関する内容の多くは、創造性を伴う体験を追加したいと考えているあらゆるタイプのアプリにとって、そしてこの現代的なAndroidエコシステムに最適化したいと考えているすべての開発者にとって、依然として関連性の高いテーマだと私は捉えています。
Joyce: 中でも私が特に注目しているのは、スタイラスのような追加の入力手段をサポートするラージスクリーンデバイスです。これらはプロダクティビティ系のワークフロー、とりわけノートテイキングに非常に適したセットアップになっていると感じています。スタイラス入力があれば、こうしたラージスクリーンデバイスを一台のデジタルノートブックに変えてしまうことができます。ユーザーは、自分のノートやToDoリスト、そして手描きのイラストまで、たった一台のデバイスからアクセスできるようになるのです。
1.2 Jetpack Ink APIの提供価値とセッション構成
Joyce: もちろん、プレミアムなノートテイキングアプリの中核にあるのは、自然でシームレスなインキング体験だと私は考えています。Jetpack Ink APIを使えば、美しいインクストロークの描画や操作を簡単に実現できます。そして私たちが実現した、限りなくゼロに近いレイテンシーによって、まるでインクがスタイラスの延長であるかのような感覚を得られるようになっています。さらに、カスタムブラシを組み合わせることで、ユーザーに無限とも言える楽しさと創造性の可能性を提供できると考えています。
Joyce: インキング体験そのものを離れても、Androidのエコシステムに存在するあらゆるデバイスやフォームファクターに向けて作られた、ユニークでモダンなアプリだと感じてもらうための機能はまだあります。たとえば、デスクトップウィンドウイングやマルチインスタンスといったマルチタスキング機能によって、ユーザーの生産性をさらに高めることができます。加えて、Notes roleを通じてOSから新たなエントリーポイントを開放したり、ドラッグアンドドロップによる直感的なデータのやり取りをサポートしたりすることで、アプリの完成度をさらに一段引き上げることができると私は考えています。ぜひこの後の内容もそのまま聞き進めていただければと思います。これから、こうしたコンセプトの一つひとつを掘り下げながら、Chrisが構築に関わった実際のノートテイキングアプリを題材に、具体的な実装例をお見せしていきます。
Chris: ありがとうございます、Joyce。Android のDeveloper Relations Engineerを務めているChris Assigbeです。ここからは私が、実装の観点からお話をしていきます。
2. Jetpack Ink APIのアーキテクチャ
2.1 開発者が抱えていた課題とAPI設計思想、6モジュールの全体像
Chris: 流動的で自然なインキング体験を構築するというのは、これまで非常に難しい仕事でした。ペンで紙に書いているかのような感覚を実現しようとすると、複雑なグラフィックスパイプラインを自前で管理し、ベジェ曲線を扱い、線を一本消すためだけにカスタムのジオメトリツールまで作り込まなければならなかったのです。私たちがJetpack Ink APIを作ったのは、まさにこうした背景があったからです。
Chris: 私たちがこのAPIで目指したゴールはシンプルでした。複雑なグラフィックス処理と入力処理はこちらで引き受けるので、開発者の皆さんにはユニークな機能づくりに集中してもらいたい、という思いです。そのために、私たちはこのAPIを高度にモジュール化された形で設計しました。つまり、一連の機能セット全体を採用することもできますし、自分のユースケースに必要な部分だけを選んで使うこともできるということです。実際、Androidが自社で提供しているCircle to Searchという機能は、Ink APIのAuthoringモジュールとBrushモジュールを活用して、入力を正確に捉えつつ、あの特徴的な光るラインを描画しています。
Chris: Ink APIは大きく6つのモジュールに分かれています。まずStrokesモジュールです。これは入力のバッチ処理やインキングに関わるあらゆるジオメトリを扱う、いわば基盤となる部分です。次にAuthoringです。これはポインター入力――今回で言えばスタイラスの入力を想定していますが――をリアルタイムに捕捉する役割を担っています。しかもこれは限りなくゼロに近いレイテンシーで実現されているのですが、それはInk APIが、私たちが以前リリースした低レイテンシーライブラリとモーション予測APIの上に構築されているからです。
Chris: そしてRenderingモジュールです。これは最適化されたグラフィックスパイプラインを用いて、皆さんのストロークをAndroidキャンバスへと効率的に描画する役割を担っています。Geometryモジュールは、選択ツールやカスタム消しゴムといったものを構築するための数学的なプリミティブを提供します。一方でBrushモジュールは、ストロークの見た目のスタイル、サイズ、色を定義するものです。
Chris: そして最後に、私たちの中でも最も新しいモジュールであるStorageです。これはプロトコルバッファとデルタ圧縮アルゴリズムを使って、ストロークデータを効率的にシリアライズするためのモジュールになっています。
2.2 パートナー事例に見る実運用
Chris: それでは、実際に私たちのパートナーがInk APIをどのように使っているか、いくつか見てみたいと思います。Google Docsでは、新しいスマートマークアップ機能のためにInk APIを利用してもらっています。また、RV AppstudioによるPDF Scannerでは、シームレスかつ低レイテンシーなドキュメントへのマークアップを提供するためにこのAPIが使われています。
Chris: ここで皆さんの中には、こうした話を実際にどう実践に落とし込めばよいのかと疑問に思う方もいらっしゃるかもしれません。そこでご紹介したいのが、私たちのCahierというサンプルアプリです。これは包括的でオフラインファーストなノートテイキングアプリで、現在GitHub上で公開されています。このセッションでは、CahierがInk APIのCompose向けコンポーネントを使って低レイテンシーな描画をどう実現しているか、表現力豊かなカスタムブラシをどう実装しているか、そして深いシステム統合によってどのようにプレミアムな使い心地を実現しているかを、順を追ってお見せしていきます。
3. Cahierによる描画体験の実装
3.1 入力キャプチャから描画・消しゴムまでの一連の処理
Chris: それでは実際の描画キャンバスから見ていきましょう。Cahierの描画画面では、Authoringモジュールが提供するIn Progress StrokesというComposeコンポーネントを使って、リアルタイムのスタイラス入力とタッチ入力の両方をハンドリングしています。このモジュールがポインターイベントを捕捉し、現在描画中のアクティブなストローク、つまり「wet ink」を、可能な限り低いレイテンシーで描画してくれます。
Chris: 実装としては、現在のブラシの状態と、ストロークが完了した際のコールバックをこのコンポーネントに渡すだけで済みます。ユーザーがスタイラスを画面から離すと、そのストロークは完了、つまり「乾いた(dry)」状態になったとみなされます。その瞬間にストローク完了のコールバックが発火し、Strokesモジュールから確定済みで不変なストロークオブジェクトがアプリ側に渡されます。私たちはこれをViewModelで管理しています。
Chris: 既存のストロークと、新たに乾いたストロークの両方を表示するために、CahierではRenderingモジュールが提供するCanvas Stroke Rendererを使っています。これはストロークオブジェクトを標準のComposeキャンバス上に効率的に描画してくれるものです。私たちはこれを二箇所で使っていまして、一つは実際に描画を行うドローイングサーフェス内、もう一つはホーム画面にあるノート詳細ペインのプレビューで、ノートの静止画としてのプレビューを表示する際に使っています。
Chris: では、ユーザーが意図しない描画をしてしまった場合はどうするか。ここで登場するのがGeometryモジュールです。Cahierで消しゴムツールが有効になっているとき、このモジュールは入力ジェスチャーの軌跡に沿って可変の平行四辺形を生成します。そして、この形状と既存ストロークのバウンディングボックスとの交差判定を行うことで、何を消去すべきかを正確に決定しています。これによって、消去の操作が直感的かつ精密なものになっていると感じています。
3.2 ストロークデータの永続化における課題と解決
Chris: 最後に、アプリを再起動したときなどに、描いた内容を後から取り出せるよう保存しておく必要があります。ここで一つ注意が必要なのですが、1本のストロークには数百ものデータポイントが含まれることがあります。これをそのまま素朴に保存することも技術的には可能ですが、そうするとアプリのデータベースはあっという間に肥大化してしまい、場合によってはストロークのサイズの大きさが原因でクラッシュしてしまうことすらあります。
Chris: この問題を解決するために、CahierではStorageモジュールをRoomと組み合わせて使っています。私たちのConverterクラスの内部では、Storageモジュールが提供するencode関数を使って、ストロークの入力バッチ、つまり生のポイントデータをバイト配列へとシリアライズしています。このとき、高度に最適化されたデルタ圧縮アルゴリズムが適用され、データのフットプリントが大幅に小さくなります。
Chris: そのバイト配列は、JSON文字列として保存しています。ノートが読み込まれる際には、decode関数がストロークを再構築してくれます。ここで一点忘れてはいけないのが、ストロークを保存する際にはブラシのプロパティも一緒にシリアライズする必要があり、ストロークを再描画する際にはそれをデシリアライズし直す必要があるということです。低レイテンシーで入力を捕捉できるのは素晴らしいことですが、それと同時に、ユーザーは自分のノートを自分らしい創造性の表現にもしたいと考えているはずです。
4. カスタムブラシによる表現力の拡張
4.1 ブラシの内部構造とビヘイビアグラフという仕組み
Chris: まず標準搭載のブラシについてお話しします。Ink APIには、圧力感知式のペン、マーカー、蛍光ペン、破線といった、よく使われるブラシスタイルがストックブラシとしてあらかじめ用意されています。なぜこれを大切にしているかというと、こうしたブラシがあることで、カスタムのデザイン作業を一切行わなくても、高品質でユーザーにとって馴染みのあるツールをすぐに使い始められるからです。
Chris: これらのストックブラシは、色やサイズ、そしてズームした際のストロークの描画精度を左右するイプシロンといったプロパティを変更することも可能です。ただ、私たちはそこからさらに一歩進めて、芸術的な表現の可能性を解き放ちたいと考えました。それがカスタムブラシです。カスタムブラシを使うことで、単純な線を超えて、まったく独自の質感を作り出すことができます。
Chris: たとえば、カリグラフィーペンや濡れた絵の具、あるいはアニメーションするパーティクルエフェクトのようなものまで思い浮かべてみてください。こうした表現によって、自社アプリがもともと持っている特徴的なツールセットに合わせたり、あるいはまったく新しいものを作ってユーザーを楽しませたりすることができます。実際に、私たちのローンチパートナーであるNoteInは、カスタムブラシを使って自社のコアとなるブラシ群をInkへと移行してくれました。この仕組みを理解するには、Jetpack Inkエンジンの内部構造を見ていただく必要があります。
Chris: ブラシというのは、単なる色とサイズの組み合わせではありません。むしろ、動的な物理モデルだと捉えていただいたほうが正確です。1つのブラシファミリーは1つ以上のブラシコートを持っており、これはつまり、1本のストロークが実際には複数の重なり合ったインクの層を落とし込んでいることを意味します。それぞれのコートは、ティップとペイントという2つの要素で定義されています。ティップというのは、ニブの物理的なジオメトリのことで、スケールや傾き、角の丸みなどを指します。そしてペイントは、色やブレンディング、テクスチャを扱う部分です。
Chris: ただ、本当の面白さはビヘイビアの部分にあると私は思っています。ビヘイビアは、フレームごとにネイティブで評価されるノードベースのロジックグラフです。スタイラスの筆圧や速度といったソースノードを、減衰やランダムノイズのような数式ノードに通して、それをサイズや不透明度といったターゲットノードへとつなぎ込むことができます。これによって、たとえばユーザーがスタイラスを速く動かすほど、減衰カーブを適用してストロークの不透明度を滑らかに0へフェードさせる、といったルールを簡単に組み立てることができるのです。
4.2 Brush Designerを用いたカリグラフィーペン作成の実演から得られる気づき
Chris: ただ、こうした複雑なグラフを手作業で、しかもプロトコルバッファのコードとして組み立てていくのは、正直かなり骨の折れる作業です。そこで本日、私たちはBrush Designerというツールをリリースします。これはビジュアルツールで、デザインチームがノードのグラフを組み立てたり、テクスチャを調整したり、圧力や傾きに対するブラシの反応カーブを調整したりしながら、ネイティブエンジンがそのブラシをどのようにリアルタイムでレンダリングするかをその場で確認できるというものです。
Chris: このツールはCahierの設定画面からアクセスできます。実際にBrush Designerを使ってブラシを設計し、それを使う流れを見ていきましょう。ここでは例として、表現力豊かなカリグラフィーペンを作ってみます。まずは基本のストロークから始めます。これは完全に均一な線で、標準的なペンとしては良いのですが、正直なところ少し味気なく、カリグラフィーペンらしさとは程遠いものです。
Chris: カリグラフィーペンの特徴を決定づけているのは、太いダウンストロークと細いクロスストロークを生み出す、平たいニブ、つまりチゼル形状です。そこでまず向かうのがTip Shapeタブです。Scale Xの値をタップして、およそ100%に設定します。次にScale Yをタップして、およそ30%まで下げます。すると、丸かったドットが瞬時に、横に広がった扁平な楕円形、つまりチゼルニブへと変わります。
Chris: 続いて、角の丸みを0%に設定して、エッジをくっきりさせます。この状態でプレビューキャンバスに描いてみると、すでにあの特徴的な太細の変化――ダウンストロークでは太く、クロスストロークでは細くという変化――が得られていることが分かります。これはまさにジオメトリだけの力によるものです。ただ、これをさらに生き生きとした表現にすることもできます。そこで次にBehaviorsタブに移ります。
Chris: Standard Dynamicsの中にあるPressure Sizeをタップします。これによって、スタイラスの筆圧をストロークの太さにマッピングするビヘイビアが追加されます。これで、強く押し込むほどニブが広がるようになり、まさに実際のペンが圧力によってしなるかのような感覚が得られます。さらにプレミアムで滑らかな感覚を追求するために、Advanced Dynamicsの中にあるSmooth Pressure to Sizeというボタンをタップします。
Chris: これによって、圧力の入力とサイズの出力の間に減衰フィルターが加わります。すると、太さが瞬間的に切り替わるのではなく、ごく短い時間をかけて滑らかに変化するようになります。これはまさに、実際のインクが紙に染み込んでいく感覚を見事に模倣していると感じます。最後にもう一つビヘイビアを加えましょう。Smooth Speed to Opacityをタップします。これは、ストロークの速度を取り込んで、それを不透明度の駆動に使うというものです。
Chris: これで、画面上で素早く払うように描くと、インクが美しく尾を引きながらフェードアウトしていきます。それぞれのビヘイビアは展開して、減衰のギャップやソースの範囲、ターゲットの倍率などを細かく調整することもできます。ほんの数クリックの操作だけで、私たちは単純なデジタルの線から、物理挙動に基づいた表現力豊かなツールへとたどり着くことができました。
4.3 ブラシのエクスポート・アプリ統合・カスタムテクスチャの実装
Chris: 自分にとって理想のブラシを設計し終えたら、それを.brushファイルとしてエクスポートすることができます。このファイルの中身は、実はgzip圧縮されたプロトコルバッファのメッセージです。これをAndroidプロジェクトに取り込むのも簡単です。Cahierでは、この.brushファイルをres/rawディレクトリにそのまま配置しています。ただ、必ずしもエクスポートする必要はありません。Cahierでは、Brush Designerを自分たちのデータベースに直接組み込んでいます。
Chris: Save to Paletteをクリックすると、ViewModelがプロトコルバッファのバイト列をgzip圧縮してローカルに保存します。メインの描画キャンバスはそのデータベースを監視しているので、新しく作ったカスタムブラシが即座にCahierのツールボックスに反映され、すぐに使えるようになります。実行時には、単純に入力ストリームをBrushFamily.decodeに渡すだけです。ネイティブエンジンがペイロードを解凍し、ビヘイビアグラフを解析して、ブラシを初期化してくれます。
Chris: そして、もしそのブラシが楽譜柄やCahierのために作ったざらついた質感のシャドウブラシのような、カスタムテクスチャを使うものであっても、同じくらい簡単です。エンジンがタイリングやスタンピング、スプライトシートのアニメーションを自動的に処理してくれます。開発者としては、ビットマップをTextureBitmapStoreに読み込み、SRC_OVERやMODULATEといったブレンドモードを設定し、そのストアをCanvasStrokeRendererに直接渡すだけで済みます。
Chris: こうして、ユーザーは豊かでプレミアムな、カスタムパレットにアクセスできるようになるわけです。ここまでで、Ink APIによって非常に低いレイテンシーで描画できる、美しい描画キャンバスができあがりました。次は、皆さんのアプリを真に生産性の高いツールにするための話をしていきたいと思います。それでは、Joyceにバトンを渡します。
5. アダプティブUIとマルチタスキング対応
5.1 画面サイズ対応の重要性とNotabilityのAndroid展開
Joyce: ありがとうございます、Chris。プレミアムなインキング体験がノートテイキングアプリの中核にあることは間違いありませんが、アプリを第一級のAndroid体験へとさらに引き上げるためには、他にも気を配るべきことがあると私は考えています。ここからは、アダプティブなアプリ体験の構築、そしてデスクトップウィンドウイングやマルチインスタンスといったマルチタスキング機能について取り上げていきます。あわせて、Androidのノートroleの実装や、自然なデータのインポート・エクスポートを実現するドラッグアンドドロップについてもお話ししていきます。
Joyce: こうした差別化された体験とアダプティブなアプリUIを十分に取り入れているノートテイキングアプリとして、私が挙げたいのがNotabilityです。Notabilityは、何百万人もの学生やクリエイター、プロフェッショナルに長年愛用されてきたアプリで、非常に流動的なインキングと、ノートテイキングやAI活用型の学習のための音声書き起こし機能で高い評価を得ています。そして本日、私たちはとても嬉しいお知らせがあります。Notabilityが正式にAndroidにやってくるのです。
Joyce: NotabilityはAndroidのモダンな開発フレームワークとベストプラクティスに基づいて構築されており、アダプティブUI、ノートrole、マルチインスタンスサポート、ドラッグアンドドロップといったAndroidの強力なAPI群を数多く活用することで、真に生産性が高く、システムと統合されたノートテイキング体験を実現しています。これから各トピックを深掘りしていく中で、Notabilityがこれらの機能をどのように実装しているか、その一端をプレビューとしてお見せしていきたいと思います。もしご自身で試してみたいという方は、現在Notabilityはベータ版としてPlayストアで公開されており、年内の正式リリースを予定しています。それでは、まずアダプティブなアプリ体験の構築から見ていきましょう。
Joyce: モダンなAndroidアプリの基盤にあるのは、デバイスのフォームファクター、画面サイズ、ディスプレイモード、デバイス構成といったあらゆる条件をまたいで、優れた体験を提供できることだと私は考えています。ノートテイキングアプリは非常に個人的な性質を持つものであり、ユーザーはいつでも自分のあらゆるAndroidデバイスからノートにアクセスしたいと考えています。ですので、アプリはアダプティブなUIとレイアウトを実装し、あらゆる画面サイズやデバイス構成において最適化されたユーザー体験を提供すべきだと私は考えています。
Joyce: さらに、Androidに最近登場したConnected Display Supportによって、ユーザーは対応デバイスを外部モニターに接続し、デバイスをデスクトップのような環境へと変えることができるようになりました。ですので、キーボードやマウス、トラックパッドといった追加の入力手段への対応を強化することが、生産性の観点からますます重要になってきていると感じています。デスクトップ環境向けのアダプティブなアプリ構築についてさらに詳しく知りたい方は、「Design and Build Desktop-Class Android Experiences」というI/Oのセッションもぜひご覧いただければと思います。
5.2 デスクトップウィンドウイングとマルチインスタンスの実装
Joyce: ラージスクリーンのタブレットやデスクトップデバイス、そして今回新たに登場したConnected Displaysの体験においては、マルチタスキングがユーザーの生産性を大きく高める重要な利用パターンになっていると私は捉えています。追加された画面の広さは、ユーザーが複数のタスクを同時にこなし、ワークフローを効率的に管理するために活用されるべきものです。Androidは高度なウィンドウイング機能を提供しており、ユーザーが自分のワークスペースを自由にカスタマイズできる柔軟性を実現しています。デスクトップウィンドウイングを使うことで、ユーザーは複数のアプリを同時に動かし、それぞれ独立して動かしたり自由にリサイズしたりできる、デスクトップライクな体験を得ることができます。
Joyce: ご覧の通り、Cahierではすでにデスクトップウィンドウイングが有効になっており、アプリはリサイズ可能なウィンドウとして自由に動かせるようになっているため、ユーザーは自分のワークスペースのニーズに合わせて調整することができます。デスクトップウィンドウイングをサポートするためには、アプリがリサイズ可能であることを保証し、構成の変更を適切にハンドリングする必要があります。まず、マニフェストの中でresizableActivityをtrueに設定し、マルチウィンドウモードを有効にします。これには分割画面とデスクトップウィンドウイングの両方が含まれます。なお、API level 31以上のAndroid 12からは、ラージスクリーンにおいてはアプリ側の設定にかかわらず、デフォルトですでにマルチウィンドウモードがサポートされるようになっている点にも触れておきたいと思います。
Joyce: また、マルチインスタンスという仕組みを活用することもできます。これは、1つのアプリが別々のウィンドウの中で複数の独立したインスタンスを起動できるようにするものです。すべてのアプリにとって意味のある機能というわけではありませんが、ノートテイキングにおいては、ユーザーが複数のノートを同時に扱えるようになることで生産性を高めることができると考えています。実際にCahierではマルチインスタンスを実装しており、ユーザーは2つのノートを並べて参照・比較したり、複数のノートの間をより手軽に切り替えながら作業を進めたりできるようになっています。
Joyce: ユーザーがシステムのランチャーやタスクバーからアプリの別インスタンスを起動できるようにするためには、アプリのマニフェストファイルの中で、ランチャーアクティビティの要素にresizableActivity属性をtrueに設定しておく必要があります。マルチインスタンスをサポートするための前提条件として、マルチウィンドウのサポートが必要になるからです。あわせて、launchMode属性が複数インスタンスの起動を妨げるようなモードに設定されていないことも確認してください。
Joyce: API level 35以上のAndroid 15では、Property Supports Multi Instance System UIというプロパティを使うことで、マルチインスタンスへの対応を宣言し、システムUI側にウィンドウイングのコントロールを表示させて、ユーザーが複数インスタンスを作成できるようにシグナルを送ることもできます。一方で、アプリ内から新しいインスタンスを起動したい場合には、CahierがしているようにインテントにFlag_Activity_New_Taskを追加することで、新しいアクティビティを起動することができます。
Joyce: そして、同じアクティビティに対してすでにタスクが実行中である場合に備えて、Flag_Activity_Multiple_Taskも合わせて追加することで、そのアクティビティと新しいタスクの両方を強制的に新規作成することができます。これにより、システムが既存のタスクを前面に呼び戻してしまう挙動を防ぐことができます。ここまででデスクトップウィンドウイングによるマルチタスキングを実現できたわけですが、これによって、システムや他のアプリとのさらなる連携の可能性が開けてくることになります。
6. システム統合機能:ドラッグ&ドロップとNotes role
6.1 ドラッグ&ドロップによるアプリ内外のデータ転送
Joyce: 真に生産性の高いアプリというのは、OSや他のアプリとシームレスに連携して動作するべきものであり、とりわけデータのやり取りに関してはそれが顕著だと私は考えています。マルチウィンドウをサポートするラージスクリーンデバイスにおいては、タッチ入力とカーソル入力のどちらにとっても、ドラッグアンドドロップは直感的なパターンだと言えます。Androidは、アプリ内、あるいはアプリ間でのデータ転送を可能にするドラッグアンドドロップのフレームワークを提供しています。
Joyce: これには、テキストや画像、そしてURIで表現できるその他のデータのコピーや移動が含まれます。Jetpack Composeは、ドラッグアンドドロップをサポートするために、dragAndDropSourceとdragAndDropTargetという2つのモディファイアを提供しています。まずは、Cahierがアプリの外や、あるいはアプリ内自体でメディアをドラッグできるようにしている仕組みから見ていきましょう。
Joyce: Cahierでは、データ転送の起点を設定するために、dragAndDropSourceモディファイアを使っています。このモディファイアは、ドラッグされる要素にドラッグシャドウを適用してくれます。関数はDragAndDropTransferDataオブジェクトを返しますが、これが転送可能なデータを表現するものです。データはClipDataオブジェクトの中にラップされています。アプリの境界を越えてドラッグできるようにするためには、flags引数にDRAG_FLAG_GLOBALを含めて設定します。これは、データを1つのアプリから別のアプリへとドラッグできることを指定するものです。
Joyce: 次に、Cahierがイベントを受け取るためのドロップゾーンをdragAndDropTargetモディファイアでどのように設定しているかを見てみましょう。このモディファイアは2つのパラメータを受け取ります。1つ目のshouldStartDragAndDropパラメータは、そのコンポーザブルがドラッグアンドドロップのイベントを受け取りたいかどうかを判断する関数です。ここは、MIMEタイプを確認して互換性のあるコンテンツかどうかをチェックするのに適した場所になっています。
Joyce: 2つ目のパラメータは、イベントと転送データを受け取るDragAndDropTargetインターフェースです。ここで、ドラッグイベントの開始・終了、あるいはコンポーネントへの出入りを観測するコールバックを実装することができ、UIやアプリの挙動をきめ細かく制御できるようになっています。onDropコールバックはオーバーライドして実装し、ドラッグされたデータの解析と消費を行う必要があります。
Joyce: 他のアプリからデータを受け取るためには、requestDragAndDropPermissionを呼び出す必要があります。そして、データを受け取った後にはそのパーミッションを解放します。ここで一点注意していただきたいのは、コールバックから渡されるドラッグアンドドロップイベントは、パーミッションリクエストのメソッドが期待しているものとは異なるという点です。そのため、まずtoAndroidDragEvent拡張関数を呼び出して、その裏側にあるDragEventを取得する必要があります。
6.2 Notes roleによるOS統合、ロック画面・フローティングウィンドウ対応
Joyce: 最後に、ユーザーが自分の好みのノートテイキングアプリに、デバイスのランチャーやタスクバーからだけでなく、必要なときにいつでもどこからでも素早くアクセスできるようにしたいと考えています。Androidはこれを、デフォルトのノートテイキングアプリを特定するNotes roleという仕組みを通じて優先的にサポートしており、ロック画面のショートカットや、他のアプリを開いたままフローティングウィンドウを使うことで、さらに素早いアクセスを可能にしています。
Joyce: ここで嬉しいお知らせがあります。LenovoもAndroid 15以降が動作するタブレットにおいて、Notes roleのサポートを有効にしてくれました。ですので、Lenovo Yoga Tab、Yoga Tab Plus、Idea Tab Pro Gen 2、そして今後発売されるすべてのLenovoタブレットのユーザーは、これらの追加のエントリーポイントとプロダクティビティ機能を有効にするために、デフォルトのノートテイキングアプリを設定できるようになります。
Joyce: Notes roleのサポートを宣言するためには、アプリのアクティビティがノートテイキングのインテントをハンドリングする必要があります。Cahierのアプリマニフェストでは、次のような宣言を行っています。showWhenLockedは、デバイスのロック画面からアプリにアクセスできるようにするものです。turnScreenOnは、アプリが実行される際にデバイスの画面をオンにできるようにするものです。そして、CREATE_NOTEというアクションが、アプリが応答するノートテイキングのインテントになります。
Joyce: このアクションは、ロック画面上でアクティビティを起動するために使うことができます。このアプリマニフェストの宣言によって、そのアプリがNotes roleの候補になりうることをシステムに対してシグナルすることになります。Notes roleを持てるアプリは同時に1つだけなので、そのroleの状態を確認する必要があります。roleManagerを使って、ROLE_NOTESに対してisRoleAvailableメソッドを呼び出します。
Joyce: もしそれが利用可能であれば、Settings画面へユーザーを誘導するインテントを作成し、そこでユーザーが自分のアプリにNotes roleを付与できるようにします。デフォルトのノートテイキングアプリとして、アプリはデバイスのロック画面から起動できるフルスクリーンのアクティビティを提供する必要があります。ユーザーのプライバシーとセキュリティを守るために、ロック画面から開かれた場合には、新しいノートの作成のみを行うようにしてください。
Joyce: 例えば、Notabilityがデフォルトのノートテイキングアプリとして設定されている場合、デバイスのロック画面にあるノートテイキングのショートカットをクリックすると、すぐに新しい空白のノートがアプリ内で開かれます。これにより、ユーザーはデバイスのロックを解除することなく、素早くノートを取ることができます。一方で、ユーザーがデバイスのロック解除済みの状態で、過去のノートを表示することに明示的に同意している場合には、過去のノートの履歴を表示するという選択をしても構いません。
Joyce: ロック画面の状態を確認するには、keyguardManagerのisKeyguardLockedメソッドを使用します。また、デバイスがロック解除された状態でノートテイキングアプリが呼び出された場合には、アプリはフローティングウィンドウの中で開かれ、文脈に応じたノートテイキングを可能にします。最適なユーザー体験を実現するためには、アプリがフローティングウィンドウに対応したアクティビティを提供するようにしてください。
Joyce: Notabilityの場合、デバイスがロック解除されている状態でショートカットが押されると、アプリはフローティングウィンドウの中で開かれ、利用可能なすべてのノートを表示することで、マルチタスキングをしながらでも柔軟かつ手軽にノートを取れるようにしています。ここでもう一つ思い出していただきたいのですが、先ほどデスクトップウィンドウイングの機能の一環としてマルチインスタンスモードを有効にしたことを覚えていらっしゃるでしょうか。実は、ノートテイキングアプリがすでにフルスクリーンや分割画面のモードで開かれているというシナリオをカバーするために、このマルチインスタンスによって複数のフローティングウィンドウを有効にできるようになっているのです。
Joyce: ですので、先ほどあの対応をしておいて本当に良かったと思っています。ご覧いただいた通り、マルチインスタンスとドラッグアンドドロップ、そしてNotes roleを組み合わせることで、Androidはノートテイキングアプリに対して、差別化された機能を構築し、システムと緊密に統合するための多くの手段を提供しています。そしてこれらはすべて、Jetpack Ink APIが提供する高パフォーマンスな描画体験や、表現力豊かなカスタムブラシがもたらす楽しさの上に成り立っているものだと考えています。
7. まとめと今後のアクション
Chris: それでは最後に、Joyceからまとめのバトンを受けて、私からクロージングをさせていただきます。今回お話しした内容をぜひ皆さん自身の手で試していただきたいと思っています。私たちは、今回ご紹介したサンプル一式と、Brush Designerの両方をまるごとオープンソースとして公開しました。ですので、これまでお話ししてきた内容が実際にどのように組み合わさって動いているのかを、皆さん自身の目で確認していただくことができます。ぜひGitHubのリポジトリをチェックしてみてください。
Chris: あわせて、developer.android.com上で更新された開発者向けガイドもぜひ読んでいただきたいと思います。そして、ご自身のシグネチャーとなるようなブラシを作り始めるために、Brush Designerもぜひ実際に試してみてください。
Joyce: また、今回のようなAndroidのラージスクリーンに関する他のセッションもぜひチェックしていただければと思います。たとえば、私たちの同僚であるDianaとEmilyによる「Adaptive Development for the Expanding Android Ecosystem」というセッションもおすすめです。
Joyce & Chris: 本日はご参加いただき、本当にありがとうございました。皆さんが何を作り上げてくださるのか、私たちも心から楽しみにしています。