
Deep Linkを使った画面遷移の導入 REALITY Advent Calendar 2024
この記事はREALITY Advent Calendar 2024の10日目の記事です。
Androidエンジニアのtkcです。
最近ドラクエ3 リメイクを始めました。初期パーティは商人僧侶遊び人です。難易度上げたのでよく死んで楽しいです。
Deep Linkを使った画面遷移を導入しました
今期の改善Weekという取り組みで、サーバー・クライアント合同で
Deep Linkを利用した画面遷移の導入に取り組みました。
どんなことをやった?

ある画面からサーバーレスポンスに応じていろいろな画面へ遷移する場合
これまでは、遷移先画面ごとに定義を作って返していました。
クライアントはこのレスポンスに含まれる遷移先情報に応じてそれぞれ遷移の処理を書きます。

これがdeepLinkのString一個で置き換えられる
この方法では、
レスポンスをAPIごとに定義する必要がある
クライアントは画面ごとにレスポンスに応じた遷移の処理を書く必要がある
上記の2つの課題がありました。
Deep Linkによる遷移を導入することでこれらの課題を解消できました。
Deep Linkによる遷移
前述のように遷移先画面ごとの定義を作ってレスポンスにいれるのをやめ、
URLを返すようにします。
例えば、REALITYの配信画面へ遷移するDeep LinkはこのようなURLです。
"https://reality.app/viewer/{配信ID}"
このように、遷移先画面ごとにURLを決めておき、それに応じて画面遷移の処理を行います。
使い方
Androidxのnavigationライブラリには、Deep Linkを引数にわたすだけで、設定した画面へ遷移する機能がサポートされています。
navigation graphで遷移したい画面に<deeplink>タグでuriを定義します。
<fragment android:id="@+id/a"
android:name="com.example.myapplication.FragmentA"
tools:layout="@layout/a">
<deepLink app:uri="www.example.com"
app:action="android.intent.action.MY_ACTION"
app:mimeType="type/subtype"/>
</fragment>
そして、設定したNavGraphでNavController.navigate(deeplink: String)を実行すれば、マッチした画面への遷移が行われます。
また、placeholderをつかえばnavArgsに値を直接変換して入れてくれます。
例:https://reality.app/viewer/1234?hoge=aaaa&fuga=999のようなURLは下記のようにnav graphで設定しておけば
Fragmentでそれらのargmentを受け取ることができる。
<fragment android:id="@+id/a"
android:name="com.example.myapplication.FragmentA"
tools:layout="@layout/a">
<deepLink app:uri="reality.app/{id}?hoge={hoge}&fuga={fuga}" />
<argument
android:name="id"
app:argType="integer"
/>
<argument
android:name="hoge"
app:argType="string"
/>
<argument
android:name="fuga"
app:argType="integer"
/>
</fragment>
導入したらどうなった?
これまでレスポンスをみてそれぞれの遷移処理を書いていましたが、
Deep Linkを渡すだけで数行のコードで遷移ができるようになりました。

よかったこと
サーバーレスポンスにおける遷移先の定義が統一できた
これまでのようにAPIごとに遷移先の定義を作って返したりする必要がなくなりました
AndroidではDeep Linkを渡すだけで遷移の処理を簡潔に書けるようになった
先述したようなレスポンスに応じた処理のかき分けが不要になった
<deeplink>タグを設定した遷移先であれば、サーバー側の変更だけでリアルタイムに遷移先を変更できるようになった
これまでは、APIごとに各々定義がされていたので、定義がされてない画面への遷移はクライアントの修正が必要だった
こまったこと
Deep Linkでの遷移を実装するにあたって困った点もいくつかありました。
IntのパラメータはBooleanのsafeArgsに変換できない
クエリパラメータでbooleanをかえすとき、?hoge=trueよりは?hoge=1 (falseならhogeをつけない)としたほうがURLとしてよさそうという話になったのだが、navigationライブラリではIntをsafeArgsのIntに変換できませんでした。
結論としては、その部分のargumentはBooleanではなく0/1でfalse/trueを表現するような設計になりました。
クエリパラメータをみて、Argsを加工することはできない
既存の実装で、下記のコードのようなあるパラメータがtrueのときは、別のargumentをnullにするような実装がありましたが、
Deep LinkによるNavigationは値を直接Argumentに変換するので、
あるパラメータをみて、argumentにわたす値を加工するようなことができませんでした。
このケースでは、新たにargumentを追加して、deeplinkのときはFragment側でその値をみて処理を変更するようにして元の動作と整合性を取ることにしました。
//こういうコードに相当する処理はDeep Linkのnavigationではできなかった
findNavController().navigate(
url = if (response.canShare) response.url else null
)

パラメータ周りでそのままではうまくいかないことがある印象
まとめ
サーバーレスポンスに応じて遷移の処理をしていた箇所が、Deep Linkでの処理を導入したことにより
サーバーレスポンスにおける遷移先の定義の統一
クライアント側で遷移の処理が簡潔に書けるようになった
サーバーでリアルタイムに遷移先の変更が可能になった
が実現できました。
普段クライアントの開発をしている身としては
サーバーレスポンスをその都度考える必要がなくなり、遷移の処理も数行で書けるようになって実装が楽になったのが嬉しいポイントです!
