【Flutter】Firebaseを用いてパラメータ付きDeep Linkを実装する

Flutter
Flutterプログラミング

レスバアプリ「ひろゆきへの道」が登場!

論破して高評価をもらい、ポイントを獲得しよう

App StoreGoogle Play Storeで配信中


目的

今回は以下のリンクを渡すことを目的としています。

https://example.com/post?id=ABC123

このリンクをクリックするとアプリが起動するようにします。id=ABC123としていますがこの値を変更して別の値を渡すこともできます。

ドメインはFirebaseで借りたものにします。そのため買う必要はありません。

またこのリンクこれはあくまでも目的であるので、最終的には必要に応じて変更します。

id=ABC123がアプリに渡されれば目的達成です。

おおもとの目的

「リンクを渡す」ことを目的としていますが、もともとは「ユーザーが投稿したページを共有する」ことを目的としています。ツイッターみたいな感じです。

上の画像のようにツイートで拡散するのに向いていると思います。

Deep Linkの選択肢

Flutterでディープリンクを実装する場合いくつかの方法があります。

ネットによくあるのがAndroidManifest.xmlを編集してURLからアプリを開けるようにする方法ですが、このやり方だとアプリがすでに起動しているときリンクを受け取ることができず、スルーされてしまいました。(実装方法が悪かっただけかもしれませんが)

そこでいろいろ調べたところFirebaseにディープリンク用の機能があるらしいので今回はこれを使おうと思います。

その機能というのは「Dynamic Links」というものです。

Dynamic Linksのメリット/デメリット

メリット

  • httpsで起動可能
  • 独自ドメインは不要(example.app.linkなどのドメインをくれる)
  • パラメータを渡しながらアプリを起動できる
  • パラメータを渡しながらすでに起動しているアプリを変更できる
  • アプリが入っていなければストアに移動させられる(実装もかなり簡単)
  • PCなどでクリックした場合指定サイトに移動できる

デメリット

僕がまだ理解できていないだけかもしれませんが、使ってみたところ以下の不満点がありました。

  • クリックでアプリ起動する時、画面に読み込み円が表示される
  • リンクが少々長めになる

僕的にはこのデメリットはあまり気にしません。メリットが大きすぎるので。

実装

手順

手順としては、

  • Firebaseコンソールでドメインを作る
  • リンクを受け取る機能を作る
  • リンクを作る
  • リンクを共有する機能を作る

この流れで進めたいと思います。

Firebase Consoleからドメイン作成

Firebase Consoleを開いて「Dynamic Links」をクリックします。

「URL 接頭辞の追加」をクリックしてドメインを作成します。希望のドメイン名を入力してください。

所有しているドメインも登録可能ですが、すでに使用している物は当然不可です。

僕の場合もとのドメインは

example.com

ですが、ここでは

example.app.link

とします。

独自ドメインを持っていない場合は

example.page.link

で無料で作成することができます。

それ以外は特に変わったことはありませんのでそのまま進めていきます。

これでFirebase Console上での操作は終了です。新しいダイナミックリンクを作成する必要はありません。

受け取りを実装

リンクはまだ作っていませんが、先にFlutter内部を操作していきたいと思います。

pubの追加

firebase_dynamic_linksをインストールするために以下を実行します。

$ flutter pub add firebase_dynamic_links

コード

//アプリの一番最初に呼ばれる
class Main extends StatefulWidget {
  const Main({Key? key}) : super(key: key);

  @override
  _Main createState() => _Main();  //_Main()を呼び出す
}

//ここからメイン
class _Main extends State<Main>{

  @override
  void initState() {
    super.initState();

    //ディープリンクを確認
    initDeepLinks();
  }

  Future<void> initDeepLinks() async {
    FirebaseDynamicLinks.instance.onLink(
        onSuccess: (PendingDynamicLinkData? dynamicLink) async {
      final Uri? deepLink = dynamicLink?.link;

      if (deepLink != null) {
        //ここにdeepLink変数を基に処理を書いていく
        OpenPost(context, deepLink.queryParameters["id"].toString()); //id(つまりABC123)を渡す
      }
    }, onError: (OnLinkErrorException e) async {
      print('onLinkError');
      print(e.message);
    });

    final PendingDynamicLinkData? data =
        await FirebaseDynamicLinks.instance.getInitialLink();
    final Uri? deepLink = data?.link;

    if (deepLink != null) {
      //ここにdeepLink変数を基に処理を書いていく
      OpenPost(context, deepLink.queryParameters["id"].toString()); //id(つまりABC123)を渡す
    }
  }

  @override
  Widget build(BuildContext context) {
  ..........
  }
}

//Navigatorでページを表示。目的ページはここで表示する。
void OpenPost(BuildContext context, String path){
  WidgetsBinding.instance?.addPostFrameCallback((_) {
    Navigator.pushNamed(
      context,
      "/post",
      arguments: {'id': postId},
    );
  });
}

説明

コード中にコメントアウト説明を書きましたがわかりづらいので上から説明していきます。

class Main extends StatefulWidget{
  ......
}

ここの説明は省きます。いつものFlutterです。


void initState(){
  .....
}

ここで initDeepLinks() を呼び出します。


Future<void> initDeepLinks() async {
  ..........
}

ディープリンクがあるかどうかを確認します。

気にするべきところは2つある、

if (deepLink != null) { }

の内部です。それ以外はコピペでも構いません。

ここでアプリがディープリンクによって開かれたかどうかを確認しています。

この中にディープリンクを用いた処理を書いていきます。

今回はここで OpenPost()を呼び出しています。


void OpenPost(BuildContext context, String path){
  .......
}

ここで Navigator.pushNamed()を呼び出してページを表示させます。

これの引数についてはこちらの記事で解説されています。

リンクを作る

クリックしたらパラメータを含みながらアプリを開くことができるリンクを作ります。

結論から言うと以下のようになります。

https://example.page.link/?link=https%3A%2F%2Fexample.com%2Fpost?id=ABC123&apn=com.yukiit.example

このリンクをクリックすることでABC123をアプリに持っていけます。

詳しく説明していきます。

  • https://example.page.link/

Firebase Consoleで作成したドメインです。

  • ?link=https%3A%2F%2Fexample.com%2Fpost

PCなどアプリをインストールできない環境でリンクをクリックしたときに飛ばしたいリンクです。

例としてはhttps://example.com/postです。ここは独自ドメインなのですが、所有していない方はFirebaseで作ったドメインを使用してもかまいません。example.app.linkでなければ。

また「%3A%2F%2F」は「://」という意味です。そのまま記号でもイケるっぽいですが怖いので16進数で書きます。

  • ?id=ABC123

ここでid=ABC123を渡しています。

  • &apn=com.yukiit.example

アプリのパッケージ名を指定します。このパッケージ名のアプリが起動します。

リンクを共有できるようにする

投稿したいページにボタンを設置してそれをタップしたら共有画面を表示するようにします。

ここではパッケージ「share」を使用しています。

import 'package:share/share.dart';

String id = "ABC123";

ここで先ほど作ったURLを使用します。id変数は閲覧中のIDが入ります。ここではABC123。

IconButton(
    onPressed: (){
      String url =
        "https://example.page.link/?link=https%3A%2F%2Fexample.com%2Fpost?id=${id}&apn=com.yukiit.example";
      Share.share(url);
    },
    icon: Icon(Icons.share)
  )

ただリンクを引数に、Share.share()してるだけです。

shareパッケージが便利すぎてこれだけで済みました。

おわりに

これでリンクをWebサイトのボタンやSNSなどで貼り付ければ投稿ページを開いた状態でアプリを起動できます。

分かりづらいところが多々あると思いますが、もし間違えている部分があれば教えていただけると幸いです。

コメント

コメント投稿前に必ずプライバシーポリシーを確認してください。

タイトルとURLをコピーしました