DroidKaigi 2019 シームレスに遷移可能な画面を他のアプリに提供する方法

Please download to get full document.

View again

All materials on our website are shared by users. If you have any questions about copyright issues, please report us to resolve them. We are always happy to assist you.
 2
 
  アプリの画面のように起動し、ユーザーの選択でシームレスにChromeに移ることもできるChrome Custom Tabsや、ランチャーアプリから横スワイプするだけで表示されるGoogle Nowのように、UXを損なうことなくアプリ間を遷移するためには、場合によって通常のIntentによるActivityの遷移とは異なる方法を取る必要があります。 本セッションでは、上で挙げた2つのアプリを始めとした、シームレスな連携をしているアプリの実装がどのようになっているのかを紐解き、その上で他のアプリに画面を提供する方法について考察します。 https://droidkaigi.jp/2019/timetable/70954 アニメーション付きのスライドはこちらからご覧になれます。 https://docs.google.com/presentation/d/e/2PACX-1vShGVlmPnMc2k8pqpTn0rTQiUG8Tj2nAOCcXkQqnf04I7ybs-VnW9rDf4m5-b4XGXklo0mxKTibtyV7/pub?start=false&loop=false&delayms=3000
Share
Transcript
  • 1. #DroidKaigi #room2 /66 シームレスに遷移可能な画面を 他のアプリに提供する方法 2019/2/7 DroidKaigi 2019 エムスリー株式会社 星川 貴樹 1
  • 2. #DroidKaigi #room2 /66 プロフィール - 星川貴樹 (@oboenikui) - エムスリー株式会社所属 (2017〜) - Android & セキュリティエンジニア - 初めてのAndroidはIS01 2
  • 3. #DroidKaigi #room2 /66 エムスリー株式会社 - 医師向けプラットフォームサービスなど医療系Webサービスの会社 - ブースも出しているので遊びに来てね! - We Are Hiring!! 3
  • 4. #DroidKaigi #room2 /66 本セッションについて ゴール - Chrome Custom Tabsや Google Now Launcherをヒン トに、シームレスな遷移の実装 を理解する - 関連技術としてプロセス間通信 (IPC) の方法を理解する 話さないこと - Fragment間をスムーズに遷移 する方法など - アニメーションの付け方 - ConstraintLayout, MotionLayout ... 4
  • 5. #DroidKaigi #room2 /66 注意事項 - 実用的な話よりニッチな話多めです - 本セッションで紹介された内容をプロダクトに活かす場合、危険性を 含めて十分議論の上ご活用ください 5
  • 6. #DroidKaigi #room2 /66 本当に実用的な話だけを聞きたい方へ 6
  • 7. #DroidKaigi #room2 /66 アプリを跨いだ Activity遷移でも Shared Elementが使えます https://developer.android.com/training/transitions/start-activity#start-with-element 7
  • 8. #DroidKaigi #room2 /66 ご清聴ありがとうございました 8
  • 9. #DroidKaigi #room2 /66 ここから先はニッチな話です 9
  • 10. #DroidKaigi #room2 /66 本セッションのきっかけ 数年前、自分には動作原理がよくわからない Androidアプリが3つあった 10
  • 11. #DroidKaigi #room2 /66 1つめ:マルチアカウントアプリ - 他のapkをアプリ内で起動するアプリ - リフレクションでシステムのapkロードの仕組 みを使う - 自分のActivityThreadを他のものであるか のように改竄して対象アプリを騙す ※ DroidKaigi 2018で発表済みなので詳しくはスライド参照 https://www.slideshare.net/TakakiHoshikawa/how-multiaccount-app-works 11
  • 12. #DroidKaigi #room2 /66 2つめ:Chrome Custom Tabs - アプリが提供するWebViewのようにChromeを 開く機能 - Chromeで開いたり、WebViewを使うより高速 に切り替わる - Custom TabからChromeを開く際、Activity が切り替わっているのにウェブページの状態が 引き継がれている 12
  • 13. #DroidKaigi #room2 /66 3つめ:Google Now Launcher - 2013年のNexus 5向けランチャーが初出 - ランチャーの左からGoogle Nowが出てくる - ランチャーアプリ内にはGoogle Nowのコード が入っていない! (Googleアプリの画面が表示されている) 13
  • 14. #DroidKaigi #room2 /66 Agenda - アプリ間の遷移をスムーズにする技術 - Chrome Custom Tabsで使われているプロセス間通信の仕組みを知る - (Custom Tabから通常のChromeへの遷移の仕方を知る) - 動的なコンポーネントを提供する技術 - GoogleアプリはどのようにしてGoogle Nowを表示しているか 14
  • 15. #DroidKaigi #room2 /66 アプリ間の遷移をスムーズにする技術 15
  • 16. #DroidKaigi #room2 /66 Chrome Custom Tabs - Chrome Custom Tabsは、Chromeのタブをア プリのWebViewのように表示する機能 - アプリ内WebViewやIntentによるブラウザ起 動より高速 - Custom TabからChromeの画面にシームレスに 遷移する アプリ間の遷移をスムーズにする技術 16
  • 17. #DroidKaigi #room2 /66 参考リポジトリの話 - Google Chromeはオープンソースではないので、代わりに Chromiumのソースを参考に話をします https://github.com/chromium/chromium https://github.com/kuoruan/Chromium-Android (NDKビルド済み) アプリ間の遷移をスムーズにする技術 17
  • 18. #DroidKaigi #room2 /66 Chrome Custom Tabsの動作を知る CustomTabActivity ChromeTabbedActivity任意のアプリ アプリ間の遷移をスムーズにする技術 18
  • 19. #DroidKaigi #room2 /66 Chrome Custom Tabsの動作を知る CustomTabActivity ChromeTabbedActivity任意のアプリ 遷移前に事前処理を行う アプリ間の遷移をスムーズにする技術 19
  • 20. #DroidKaigi #room2 /66 遷移前後の処理 任意のアプリ アプリ間の遷移をスムーズにする技術 20
  • 21. #DroidKaigi #room2 /66 遷移前後の処理 任意のアプリ CustomTabsService IPCで開くURLを事前に通知 アプリ間の遷移をスムーズにする技術 21
  • 22. #DroidKaigi #room2 /66 遷移前後の処理 任意のアプリ 渡されたURLを基にコネクショ ンを張るなど事前処理を行う アプリ間の遷移をスムーズにする技術 CustomTabsService 22
  • 23. #DroidKaigi #room2 /66 遷移前後の処理 CustomTabActivity任意のアプリ ユーザーアクションにより Custom Tabを起動 アプリ間の遷移をスムーズにする技術 CustomTabsService 23
  • 24. #DroidKaigi #room2 /66 遷移前後の処理 CustomTabActivity任意のアプリ CustomTabsService 事前に張ったコネクションを 利用して高速にページを表示 アプリ間の遷移をスムーズにする技術 24
  • 25. #DroidKaigi #room2 /66 ポイント - サードパーティアプリからChromeのServiceにバインドする - プロセス間通信 (IPC) を行う必要がある - 実装はAIDLを用いている アプリ間の遷移をスムーズにする技術 25
  • 26. #DroidKaigi #room2 /66 AndroidのIPC - Binderと呼ばれる仕組みでデータのやりとりを行う - Parcelという仕組みでデータの読み書きを行う - Parcelに読み書きできるのはプリミティブ型、Parcelable、 Serializable、Listのような一部のデータ構造型 アプリ間の遷移をスムーズにする技術 26
  • 27. #DroidKaigi #room2 /66 Serviceにバインドする - ActivityとServiceがやりとりするにはバインドする必要がある - バインドする方法は以下の3通り バインド方法 プロセスの制約 スレッドの制約 Binderクラスを拡張する 同一プロセス内のみ - メッセンジャーを使用する - すべてのリクエストが1つの スレッドにキューイングされる AIDLを使用する - - アプリ間の遷移をスムーズにする技術 27
  • 28. #DroidKaigi #room2 /66 AIDLの紹介 - Android インターフェース定義言語 (AIDL) - 文法はJavaのinterfaceの記法に近い - プロセス間通信 (IPC) を行うために用いる手法の1つ - そのままではスレッドセーフではないのでAndroidのドキュメント でも基本的には使わないことを推奨 - とはいえ別プロセス & マルチスレッドでメッセージングを行うため には用いられる https://developer.android.com/guide/components/bound-services アプリ間の遷移をスムーズにする技術 28
  • 29. #DroidKaigi #room2 /66 AIDLの仕組み アプリ間の遷移をスムーズにする技術 .aidlファイル Stubクラス (abstract) Proxyクラス interface クライアント側用 リモート側用 クラス自動生成 実装 継承 実装クラス 実装 29
  • 30. #DroidKaigi #room2 /66 AIDLの仕組み アプリ間の遷移をスムーズにする技術 .aidlファイル Stubクラス (abstract) Proxyクラス interface クライアント側用 リモート側用 クラス自動生成 実装 継承 実装クラス 実装 インターフェースを定義 mayLaunchUrl() 30
  • 31. #DroidKaigi #room2 /66 AIDLの仕組み アプリ間の遷移をスムーズにする技術 .aidlファイル Stubクラス (abstract) Proxyクラス interface クライアント側用 リモート側用 クラス自動生成 実装 継承 実装クラス 実装 mayLaunchUrl()メソッドの 実処理を開発者が実装 31
  • 32. #DroidKaigi #room2 /66 AIDLの仕組み アプリ間の遷移をスムーズにする技術 .aidlファイル Stubクラス (abstract) Proxyクラス interface クライアント側用 リモート側用 クラス自動生成 実装 継承 実装クラス 継承・実装 mayLaunchUrl()メソッドには プロセス間通信用の処理が実装 32
  • 33. #DroidKaigi #room2 /66 AIDLの仕組み メソッド呼び出し Parcelに 格納 クライアント側 (例:Activity) リモート側 (例:Service) Proxyクラス binder binder Parcelから 取り出し Stubクラス 実装メソッド呼び出し プロセス間通信 参考:スキルアップのための分散オブジェクト入門 第2回 http://www.atmarkit.co.jp/fjava/rensai2/objetry02/objetry02.html アプリ間の遷移をスムーズにする技術 33
  • 34. #DroidKaigi #room2 /66 AIDLの仕組み メソッド呼び出し Parcelに 格納 クライアント側 (例:Activity) リモート側 (例:Service) Proxyクラス binder binder Parcelから 取り出し Stubクラス 実装メソッド呼び出し プロセス間通信 アプリ間の遷移をスムーズにする技術 34
  • 35. #DroidKaigi #room2 /66 AIDLの仕組み メソッド呼び出し Parcelに 格納 クライアント側 (例:Activity) リモート側 (例:Service) Proxyクラス binder binder Parcelから 取り出し Stubクラス 実装メソッド呼び出し プロセス間通信 アプリ間の遷移をスムーズにする技術 mayLaunchUrl() 呼び出し 35
  • 36. #DroidKaigi #room2 /66 AIDLの仕組み メソッド呼び出し Parcelに 格納 クライアント側 (例:Activity) リモート側 (例:Service) Proxyクラス binder binder Parcelから 取り出し Stubクラス 実装メソッド呼び出し プロセス間通信 アプリ間の遷移をスムーズにする技術 mayLaunchUrl() の実処理を実行 36
  • 37. #DroidKaigi #room2 /66 余談:シームレスなActivity間の遷移 CustomTabActivity ChromeTabbedActivity任意のアプリ Activityが切り替わっているが JavaScriptの状態などは維持 アプリ間の遷移をスムーズにする技術 37
  • 38. #DroidKaigi #room2 /66 余談:シームレスなActivity間の遷移 - Custom Tabから通常のChromeの画面への遷移 があまりに自然すぎる - SharedElementは単に新たなViewをアニメー ションさせるだけだが、この遷移ではViewの状 態が完全に引き継がれている アプリ間の遷移をスムーズにする技術 38
  • 39. #DroidKaigi #room2 /66 状態が保存される遷移の実装 - Viewを含むWebページの状態を保持するオブジェクトをActivity間 で共有 - 生成時のContextは、Application Contextを ContextThemeWrapperに包んだものを使用 - Viewにはほとんど実装を載せず、他のクラスに委譲している アプリ間の遷移をスムーズにする技術 Activity間共有用処理をしている箇所 https://github.com/chromium/chromium/blob/master/chrome/android/java/src /org/chromium/chrome/browser/tab/Tab.java#L1267 39
  • 40. #DroidKaigi #room2 /66 動的なコンポーネントを提供する技術 40
  • 41. #DroidKaigi #room2 /66 使い道 - Google Nowのような汎用の情報画面を表示する (端末メーカー向き) - アプリAの一部機能をアプリBでも使いたいが、アプリB側には実装を 持たせたくない場合 動的なコンポーネントを提供する技術 41
  • 42. #DroidKaigi #room2 /66 Google Nowランチャーの動作を知る - 右の動きは全てランチャーアプリ上での挙動 - 連携のためのコードを除き、ランチャー側に Google Nowの実装は存在しない - ランチャーのコンテンツが右に追い出される動 きはランチャーの実装 動的なコンポーネントを提供する技術 42
  • 43. #DroidKaigi #room2 /66 Google Nowランチャーの動作を知る - 動作原理さえ知っていればランチャーである必 要もない - ただしGoogle Nowの場合、システムアプリで しか利用できないように制限されている 動的なコンポーネントを提供する技術 43
  • 44. #DroidKaigi #room2 /66 参考リポジトリの話 - GoogleアプリはOSSではなく、規約上リバースエンジニアリングで 得た情報を発表するわけにはいかないので、同じ動きをするOSSを参 考に話します https://github.com/FabianTerhorst/DrawerOverlayService 動的なコンポーネントを提供する技術 44
  • 45. #DroidKaigi #room2 /66 Google Nowランチャーの4つのポイント 1. ServiceによってWindowManager#addViewで追加されたViewである 2. 表示するActivityのWindowManager.LayoutParamsを使ってアプリケー ションレイヤに表示させる 3. キーイベントなどに対応するためにWindowクラスのインスタンスを頑張っ て生成している 4. IPCによりランチャー側から指示された位置にViewを表示 動的なコンポーネントを提供する技術 45
  • 46. #DroidKaigi #room2 /66 WindowManagerについて 右:Facebook Messengerの例 - 一般アプリがWindowManagerを直接使う機会 は多くない - 最も利用するケースは他のアプリの上に常に表 示するとき - 実際にはActivityで表示されるViewなども 全てWindowManagerに追加されることで表示 される 動的なコンポーネントを提供する技術 46
  • 47. #DroidKaigi #room2 /66 WindowManagerについて - 一般アプリがWindowManagerを直接使う機会 は多くない - 最も利用するケースは他のアプリの上に常に表 示するとき - 実際にはActivityで表示されるViewなども 全てWindowManagerに追加されることで表示 される WindowManager Activity Window setContentView addView 動的なコンポーネントを提供する技術 Windowクラス 最上位のウィンドウの外観と動作ポリシーを定めたクラスで、背景、タイト ル領域、デフォルトのキー処理などの標準的な UIポリシーを提供する 47
  • 48. #DroidKaigi #room2 /66 WindowManagerについて WindowManager Service - 一般アプリがWindowManagerを直接使う機会 は多くない - 最も利用するケースは他のアプリの上に常に表 示するとき - 実際にはActivityで表示されるViewなども 全てWindowManagerに追加されることで表示 される addView 動的なコンポーネントを提供する技術 48
  • 49. #DroidKaigi #room2 /6649 Androidの表示レイヤー WALLPAPER 表示内容に合わせて現在33層 のレイヤーに分けられている アプリケーションレイヤ PHONE SYSTEM_ALERT バッテリー不足などの システムアラート APPLICATION_OVERLAY Messengerなどは このレイヤー 電話アプリは通常の アプリより手前に描画 通常のアプリ 壁紙 動的なコンポーネントを提供する技術
  • 50. #DroidKaigi #room2 /6650 オーバーレイコンテンツの場合 WALLPAPER 他の重要でないアラートなど よりも上に表示される Activityに紐付かない画面の 提供が可能なので、常に画面 上に表示しておくことが可能 アプリケーションレイヤ PHONE SYSTEM_ALERT バッテリー不足などの システムアラート 電話アプリは通常の アプリより手前に描画 通常のアプリ 壁紙 APPLICATION_OVERLAY Messengerなどは このレイヤー ※ このような通知が出てくる 動的なコンポーネントを提供する技術
  • 51. #DroidKaigi #room2 /6651 Google Nowの場合 WALLPAPER アプリケーションレイヤに表 示する 表示がActivityと紐づくた め、他のアプリの上に表示さ れることはない PHONE SYSTEM_ALERT バッテリー不足などの システムアラート 電話アプリは通常の アプリより手前に描画 壁紙 APPLICATION_OVERLAY Messengerなどは このレイヤー 通常のアプリ アプリケーションレイヤ 動的なコンポーネントを提供する技術
  • 52. #DroidKaigi #room2 /66 アプリケーションレイヤの制限 - セキュリティ上、任意のServiceが勝手にアプリケーションレイヤ にViewを追加できるべきではない - 対策として、WindowManagerが各ウィンドウごとにtokenを管理し ている - tokenはParcelに書き込める形式になっているので、アプリケー ション側からServiceに渡して制限を回避する 動的なコンポーネントを提供する技術 52
  • 53. #DroidKaigi #room2 /66 画面の状態変更やボタン操作に対応する Activityではレイアウトに係る処理をWindowクラスで行っているが、 ServiceにはWindowクラスを使う基本的な手段が存在しない WindowManager Activity Window setContentView addView Service addView 動的なコンポーネントを提供する技術 53
  • 54. #DroidKaigi #room2 /66 System Process Process BProcess A Activity 画面の状態変更やボタン操作に対応する またこれらはそれぞれ別プロセスで動くため、Windowインスタンスを Serviceに渡すなどは不可能 Window Service WindowManager 動的なコンポーネントを提供する技術 54
  • 55. #DroidKaigi #room2 /66 ServiceでWindowクラスのインスタンス生成 - Windowはabstractクラスで、実装はPhoneWindowクラス - PhoneWindowクラスはinternalクラスなので、直接生成するのは 困難だが頑張って生成する 動的なコンポーネントを提供する技術 55
  • 56. #DroidKaigi #room2 /66 PhoneWindowのインスタンスを生成できる箇所 動的なコンポーネントを提供する技術 https://search.siprop.org/android-9.0.0_r1.0/search?q=%22new+PhoneWindow%22&def s=&refs=&path=frameworks%2Fbase%2Fcore%2Fjava&hist=&sort=lastmodtime 56
  • 57. #DroidKaigi #room2 /66 PhoneWindowのインスタンスを生成できる箇所 https://search.siprop.org/android-9.0.0_r1.0/search?q=%22new+PhoneWindow%22&def s=&refs=&path=frameworks%2Fbase%2Fcore%2Fjava&hist=&sort=lastmodtime コンストラクタで生成しており、 getWindow()メソッドで取り出すことも可能 動的なコンポーネントを提供する技術 57
  • 58. #DroidKaigi #room2 /66 ServiceでWindowクラスのインスタンス生成 - Windowはabstractクラスで、実装はPhoneWindowクラス - PhoneWindowクラスはinternalクラスなので、直接生成するのは 困難だが頑張って生成する Dialogを使って簡単に生成できる val window: Window? = Dialog( context, R.style.Theme_Overlay ).window 動的なコンポーネントを提供する技術 58
  • 59. #DroidKaigi #room2 /66 ここまでのポイント 1. ServiceによってWindowManager#addViewで追加されたViewである 2. 表示するActivityのレイアウトパラメータを使ってアプリケーションレイ ヤに表示させる 3. 画面回転などリッチな表示に対応するためにWindowインスタンスを頑張っ て生成している 4. IPCによりランチャー側から指示された位置にViewを表示 動的なコンポーネントを提供する技術 59
  • 60. #DroidKaigi #room2 /6660 ここまでのポイント 1. ServiceによってWindowManager#addViewで追加されたViewである 2. 表示するActivityのレイアウトパラメータを使ってアプリケーションレイ ヤに表示させる 3. 画面回転などリッチな表示に対応するためにWindowインスタンスを頑張っ て生成している 4. IPCによりランチャー側から指示された位置にViewを表示 https://github.com/oboenikui/AppLayerOverlaySample 動的なコンポーネントを提供する技術
  • 61. #DroidKaigi #room2 /66 ここまでのポイント 1. ServiceによってWindowManager#addViewで追加されたViewである 2. 表示するActivityのレイアウトパラメータを使ってアプリケーションレイ ヤに表示させる 3. 画面回転などリッチな表示に対応するためにWindowインスタンスを頑張っ て生成している 4. IPCによりランチャー側から指示された位置にViewを表示 動的なコンポーネントを提供する技術 61
  • 62. #DroidKaigi #room2 /66 IPCでランチャーアプリと通信 動的なコンポーネントを提供する技術 ランチャーアプリ 移動すべき座標を通知 62 Google Nowの サービス
  • 63. #DroidKaigi #room2 /6663 IPCでランチャーアプリと通信 動的なコンポーネントを提供する技術 ランチャーアプリ Google Nowの サービス 移動することを通 知
  • 64. #DroidKaigi #room2 /66 最終的な実装結果 動的なコンポーネントを提供する技術 簡易的にViewPagerのページめくりと同期させた場 合、右のようになる (参考リポジトリの実行結果) 64
  • 65. #DroidKaigi #room2 /66 まとめと考察 - Chrome Custom TabsではAIDLによるプロセス間通信を行う - 同様にAIDLで定めたプロトコルをサードパーティに提供し、Activity 起動前の準備を行うことができる - Google Now LauncherもActivityとプロセス間通信を行うこと でアプリケーションレイヤーに描画する - DialogからWindowを生成する手法はAPPLICATION_OVERLAYレイ ヤーでも使えるかも - 「横スワイプで表示」以外も頑張ればできる 65
  • 66. #DroidKaigi #room2 /66 ご清聴ありがとうございました 66
  • Related Search
    We Need Your Support
    Thank you for visiting our website and your interest in our free products and services. We are nonprofit website to share and download documents. To the running of this website, we need your help to support us.

    Thanks to everyone for your continued support.

    No, Thanks
    SAVE OUR EARTH

    We need your sign to support Project to invent "SMART AND CONTROLLABLE REFLECTIVE BALLOONS" to cover the Sun and Save Our Earth.

    More details...

    Sign Now!

    We are very appreciated for your Prompt Action!

    x