Webサイトの特定のURLにアクセスするとアプリが開く、
Deep Linkに対応したいなと思い、
いろいろ調べてみたときの備忘録(*´ω`*)
Flutterの公式ドキュメントはこのあたり
- Deep linking | Flutter
- Set up app links for Android | Flutter
- Android アプリリンクを検証する | Android Developers
routing packageに、go_routerを利用しているので、
そのあたりも含めて(*´ω`*)
AndroidManifest.xmlの変更
.MainActivity
の<activity>
配下に、以下を追加する。
android:host="example.com"
の部分は自分のドメインで。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application ...> <activity android:name=".MainActivity" ...> <!-- 略 --> + <meta-data android:name="flutter_deeplinking_enabled" android:value="true" /> + <intent-filter android:autoVerify="true"> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + <data android:scheme="http" android:host="example.com" /> + <data android:scheme="https" /> + </intent-filter> </activity> <application> </manifest>
assetlinks.jsonの配置
以下のファイルを作成して、Webサイトに配置する。
package_name
とsha256_cert_fingerprints
は、
自分の環境にあわせて設定する。
<自分のdomain>/.well-known/assetlinks.json
[{ "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "com.example.deeplink_cookbook", "sha256_cert_fingerprints": ["FF:2A:CF:7B:DD:CC:F1:03:3E:E8:B2:27:7C:A2:E3:3C:DE:13:DB:AC:8E:EB:3A:B9:72:A1:0E:26:8A:F5:EC:AF"] } }]
sha256_cert_fingerprints
は以下から取得できる。
- GooglePlayの場合は、
- 「対象のアプリ>設定>アプリの署名」から
- ローカルの場合は、
keytool -list -v -keystore <path-to-keystore>
かcd android && ./gradlew app:signingReport
go_routerの設定
基本的はGoRouteで設定したパスと一致していればOK
ただ、アプリが起動中と起動前では渡されてくるURIが異なるので注意
- 起動中 ... パスのみ(
https://my-site/aaa/bbb
の/aaa/bbb
) - 起動前 ... ホストなども含む(
https://my-site/aaa/bbb
のまま)
そのため、uri.host
やuri.scheme
を確認して、
uri.path
へのリダイレクトが必要。
import 'package:go_router/go_router.dart'; const router = GoRouter( // ...略 redirect: (context, state) { if (state.uri.host.isEmpty || state.uri.scheme.isEmpty) { return state.uri.path; } return null; }, );
Tips
特定のパスのみアプリを開く
sheme
、host
以外に、pathPattern
も指定できる。
<data android:scheme="https" android:host="maguro-sagashi.com" android:pathPattern="(/..)?/stages/.*" />
他にも、path
、pathPrefix
、pathSuffix
などもある。
複数のドメインで対応する
各サイトでassetlinks.json
を配置し、
AndroidManifest.xmlに複数行かけばOK
<data android:scheme="https" android:host="maguro-sagashi.com" android:pathPattern="/stages/.*" /> <data android:scheme="https" android:host="maguro-sagashi.com" android:pathPattern="/../stages/.*" /> <data android:scheme="https" android:host="www.maguro-sagashi.com" android:pathPattern="stages/.*" /> <data android:scheme="https" android:host="www.maguro-sagashi.com" android:pathPattern="/../stages/.*" />
Webサイトとgo_routeのパスが異なる場合
go_routerのredirectで対応すればOK
マグロ探しの場合、英語と日本語でパスが変わるので、
そういった場合も含めて、redirectする必要がある。
// JP: https://maguro-sagashi.com/stages/inori // EN: https://maguro-sagashi.com/en/stages/inori import 'package:go_router/go_router.dart'; const router = GoRouter( // ...略 redirect: (context, state) { final stageIdMatch = RegExp(r'/stages/([^/]+)$').firstMatch(state.uri.path); if (stageIdMatch != null) { return "/creative/stage/${stageIdMatch.group(1)}"; } if (state.uri.host.isEmpty || state.uri.scheme.isEmpty) { return state.uri.path; } return null; }, );
複数のアプリが立ち上がらないようにする
AndroidManifest.xmlのlaunchMode
をsingleInstance
にすればOK
- <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" ...> + <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleInstance" ...>
以上!! これでいい感じに遊べる気がする(*´ω`*)