2024.12.10
“放置系”なのにサイバー攻撃を監視・検知、「統合ログ管理ツール」とは 最先端のログ管理体制を実現する方法
Deep Dive into Slice(全1記事)
リンクをコピー
記事をブックマーク
もり氏(以下、もり):こんばんは。Slicesの内部実装を見ながら自分でこういうの作るにはどうやって作るだろう的な、ちょっと益体のない話をしようと思っています。
自己紹介させてください。森と言います。ヤフーから来ました。
ヤフーには黒帯というこういう場でお話ししたりする役割があるんですが、私はAndroid分野で黒帯をしております。そのほかヤフオクもやっております。
いきなり宣伝になってしまいますが、最近本を出しました。
ところで今我々はこちらヒカリエにいるんですけれども、なんとここに啓文堂書店があります。啓文堂書店、よろしくお願いします。
(会場笑)
では始めていきたいと思います。Slicesについてです。
まずSlicesの仕組みなんですけれども。Slicesを返すSliceProvider、我々はこれを作ります。
このSliceProviderはContentProviderを継承していて、ContentProviderなのでSlicesを表示する側はURIをもとにデータ、ここではSlicesを要求するという感じで動いています。
Slices自体がこんな感じで構造化されたフォーマットのデータになっています。
ほかのSlicesとか表示フォーマットだとかアイコンなんかが含まれています。
SliceProviderを実装するにはAndroid Studio 3.2を入れて右クリックして、NewからOther、SliceProviderを押せば終わりなんすけれども。
それだとあんまりなので少し説明を入れると、SliceProviderを継承したクラスを作ってonBindSliceメソッドの中でSlicesを作って返すという感じで作ります。
これは結局ContentProviderなのでマニフェストファイルにAuthorityとともに追加するという感じで使います。
こうして我々サードパーティーはSliceProviderを作るわけなんですが、作ったとしてどこで使ってもらえるのか? 最初はGoogle検索アプリで使用されます。
Google検索アプリでユーザーがクエリを入力するときのサジェストの中に、自分のアプリのSlicesを表示してもらえる可能性があります。
そのための方法が2通りあって、まずユーザーがアプリ名を入力したときに表示する方法。この方法は簡単で、マニフェストファイルのメインアクティビティにメタデータを追加します。
このメタデータにSlicesに対応するURIを設定して、アクティビティの中でGoogle Play ServicesとGoogle検索のパーミッションを入れれば終わりです。
でもGoogle検索アプリでアプリ名で検索するユーザーって……そんなユースケースあるかな? って感じなので,一般的な単語での検索に反応したいなっていうところです。
これのやり方なんですけれども、FirebaseAppIndexingにIndex登録するときにメタデータとしてSlicesのURIを追加する。こうするとAppIndexingが使用されるタイミングでSlicesが使われる可能性があるという感じになります。
そのあとマニフェストファイルのSliceProviderのエレメントにIndexしたURLを受け取るintent-filterを追加します。SlicesのURIではなくてIndexしたURLを設定します。
最後にSlicesプロバイダーのonMapIntentToUriというところで、AppIndexingが渡してくるディープリンクのURLをSlicesのURIに変換して返すという感じです。
以上がGoogle検索アプリで表示してもらう場合の方法です。
ところでサードパーティーは表示できないのか? というところです。Google検索アプリで表示してもらえるだけでもけっこう嬉しいんですが、サードパーティーのアプリ間で連携できればもうちょっと便利そうな感じがします。
特にヤフーにはたくさんのサービスがあって、いろんなアプリを世に出しています。これらで連携できるようになると、なんか便利そうだなって思うわけですね。ヤフオクのケースだと、例えば決済アプリでネイティブ化するということもできそうです。
こういう連携をどうすれば実現できるかなんですけども。ステップ1、待つ。
(会場笑)
というのもGoogle I/Oから帰ってきたときにGoogleの人と話してきたんですが、Slicesの表示をサードパーティーに解放するかどうかはまだ決まっていない。
今、Slice Viewerというものが公開されていて、SliceViewというSlicesを表示する用のViewもJetpackの中に入ってるんですけども。このAPIも今後どうなるかわからないということを言っていました。
じゃあ、Slicesの表示が解放されなかったらどうやってサードパーティ間連携をしていったらいいのでしょうか? 作りましょう、それっぽいのを。
というわけでSlicesが具体的にどう動いてるのかを追いかけてみたいと思います。今回はSliceViewerのソースコードをもとにSliceを要求するところからSlicesを作って返すところまで追いかけていきたいと思います。
まずSlicesを要求するところから。
SliceViewerではSliceViewのbindメソッドを呼ぶことでSlicesのリクエストが開始されます。
これは拡張関数でして、中ではSliceLiveDataというクラスを生成して値を監視しています。
SliceLiveDataではSliceManagerのインスタンスを取得して、bindSliceメソッドを呼びます。
このSliceManagerのgetInstanceメソッドはAndroid P以降かどうかで返すインスタンスが変わってきます。
Android P以降の場合SliceManagerのラッパーを返すんですが、これは新たに爆誕したSliceManagerというシステムサービスをラップしたものになります。
P未満の場合はSliceManagerCompatというクラスのインスタンスを返します。自分でシステムマネージャー作っても虚しいだけなので、今回はこっちのSliceManagerCompatを追いかけていきます。
このbindSlicesが呼ばれてたいたわけなんですが、このクラスはSliceProviderCompatのメソッドを呼ぶだけのクラスです。今、Slicesを要求している側なんですけども、実はSlicesを返す側もSliceProviderCompatを使います。
実は間にはSliceProviderCompatが入ってお互いのSliceProviderCompat同士で通信します。SliceProviderCompatではURIをチェックしたりしてbindSlicesを呼びます。
ここが終着点なんですが、ContentResolverからContentProviderClientを取得してcallメソッドを呼んで、その戻り値のバンドルからSlicesを生成して返します。
ContentProviderを使ったことがある人っていますか?
(会場挙手)
いっぱいいますよね。ContentProviderClientを使ったことがある人っていますか?
いないですね。ContentProviderClientはAPIレベル5からある古株のクラスです。ContentResolverを経由しないで直接ContentProviderとやり取りするためのものです。
ContentProviderデータを要求するときに毎回ContentResolverを使っていると、毎回URIから対応するプロバイダはどれかなって探す処理が走ります。この探す処理がなくなるのでかなり高速化します。
そのcallメソッドなんですが、リレーショナルな感じでリクエストしないときに使うようなメソッドです。引数としてメソッド名を渡します。
実際には任意のメソッドを呼ぶわけじゃなくて、対応するプロバイダーのcallメソッドが呼ばれます。呼び出されたプロバイダ側で引数として渡されるメソッド名や引数を判定して、なにかを実行して結果をBundleで返します。
ここまでがSlicesを要求するフェーズです。結局のところSliceProviderCompatのcallメソッドを呼んでいました。これに対してSlicesを返す側のアプリは何をしているのかを追いかけてみたいと思います。
callメソッドはこうなっています。handleBindSliceというメソッド内でSlicesを作って、Bundleに変換して、さらにBundleに積んで返しています。
Slicesを作っているhandleBindSliceを見てみると、こんな感じです。
なんやかんやでonBindSliceStrictを呼びます。そのonBindSliceStrictがSlicesを生成するときの終着点になります。
2秒でANRが発生するように設定して、ディスクI/Oなど重たい処理をしたらクラッシュするようにしたうえで、SliceProviderのonBindSliceを呼びます。
SliceProviderのonBindSliceは最初に説明したとおり、自分でオーバーライドして実装するものです。
なので大切なのはSlicesが要求されたときに自分で返す場合には、同期的なディスクI/Oだとかネットワークをしないで、2秒以内に返さないといけません。
すぐに返せないのであれば一旦「読み込み中」とでも返しておいて非同期的にデータを取得してnotifyChangeを呼ぶようにしましょう。
こんな感じでSlicesを返しました。そのSlicesはどのように表示されているかですが、もともとライブデータ内で要求されていたので、まずはpostValueでライブデータを更新します。
それを受け取って、SliceView内のプロパティを更新します。
プロパティアクセスっぽく見えるんですが、実際にはSliceViewのsetSliceが呼ばれていて。メソッド内のreinflateというメソッドを呼びます。
この中でSlicesの値、プロパティを読み取りながらViewを生成していくんですが、そこは単純なのでこれ以降は省略します。
長々とSlicesの内部実装を見てきたわけですが、こうしたSlicesめいたものを自分で作るんだったらどうするのか、ということでまとめます。
まずBundleと相互変換できるクラスを作ります。次にContentProviderClientを使ってBundleをやり取りします。最後にBundleから元のクラスに戻して、その値を参照しながらViewを生成するロジックを書く。ここだけ見ると簡単そうに見えまが、ひたすらめんどくさい感じになります。
全体のまとめとしては、Slicesは古典的なAPIをうまく使って作られています。まずはGoogle検索アプリで使われます。サードパーティー間の連携に使用できるかはまだ不透明なようです。
でも似たようなことは作れるようになりましたね。ということで、ご静聴ありがとうございました。
(会場拍手)
関連タグ:
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.09
10点満点中7点の部下に言うべきこと 部下を育成できない上司の特徴トップ5
2024.12.09
国内の有名ホテルでは、マグロ丼がなんと1杯「24,000円」 「良いものをより安く」を追いすぎた日本にとって値上げが重要な理由
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.29
「明日までにお願いできますか?」ちょっとカチンとくる一言 頭がいい人に見える上品な言い方に変えるコツ
2024.12.06
嫌いな相手の行動が気になって仕方ない… 臨床心理士が教える、人間関係のストレスを軽くする知恵
2024.12.10
職場であえて「不機嫌」を出したほうがいいタイプ NOと言えない人のための人間関係をラクにするヒント
PR | 2024.12.04
攻撃者はVPNを狙っている ゼロトラストならランサムウェア攻撃を防げる理由と仕組み
PR | 2024.11.22
「闇雲なAI導入」から脱却せよ Zoom・パーソル・THE GUILD幹部が語る、従業員と顧客体験を高めるAI戦略の要諦
PR | 2024.11.26
なぜ電話営業はなくならない?その要因は「属人化」 通話内容をデータ化するZoomのクラウドサービス活用術