web-dev-qa-db-ja.com

アプリがそのリンクによって閉じられ、開かれた場合、Firebase Dynamic LinkはgetInitialLinkによってキャッチされません

プログラムで生成されたダイナミックリンクが適切にキャッチされない

FirebaseDynamicLinks.instance.getInitialLink().

アプリが閉じている場合。ただし、アプリが開いている場合、リスナーは新しい着信動的リンクを正しく検出します。セットアップの問題かどうか、ダイナミックリンクを生成する方法はわかりません。

再現

最初に、ドキュメントどおりにFirebase for Flutterプロジェクトを設定します。次に、ダイナミックリンクを設定します。

_/// See also
/// https://firebase.google.com/docs/dynamic-links/use-cases/rewarded-referral
/// how to implement referral schemes using Firebase.
Future<ShortDynamicLink> buildDynamicLink(String userId) async {
  final PackageInfo packageInfo = await PackageInfo.fromPlatform();
  final String packageName = packageInfo.packageName;

  var androidParams = AndroidParameters(
    packageName: packageInfo.packageName,
    minimumVersion: Constants.androidVersion, // app version and not the Android OS version
  );

  var iosParams = IosParameters(
    bundleId: packageInfo.packageName,
    minimumVersion: Constants.iosVersion, // app version and not the iOS version
    appStoreId: Constants.iosAppStoreId,
  );

  var socialMetaTagParams = SocialMetaTagParameters(
    title: 'Referral Link',
    description: 'Referred app signup',
  );

  var dynamicLinkParams = DynamicLinkParameters(
    uriPrefix: 'https://xxxxxx.page.link',
    link: Uri.parse('https://www.xxxxxxxxx${Constants.referralLinkPath}?${Constants.referralLinkParam}=$userId'),
    androidParameters: androidParams,
    iosParameters: iosParams,
    socialMetaTagParameters: socialMetaTagParams,
  );

  return dynamicLinkParams.buildShortLink();
}
_

このダイナミックリンクは、他の新しいユーザーと共有できます。

アプリの起動時に初期リンクをリッスンしてから、新しい着信リンクをリッスンします。

1)アプリが実行されていなくてもgetInitialLinkがアプリを取得しない場合、リンクはアプリを適切に開きます。

2)アプリが開いている場合、リンクはリスナーによって適切に捕捉され、すべて機能します。

これは、1)FirebaseDynamicLinks.instance.getInitialLink()で初期リンクが見つからないことを確認するために使用した非常にシンプルなmain.Dartです。

_void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  PendingDynamicLinkData linkData = await FirebaseDynamicLinks.instance.getInitialLink();
  String link = linkData?.link.toString();
  runApp(MyTestApp(link: link));
}

class MyTestApp extends StatelessWidget {
  final String link;

  MyTestApp({this.link});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        builder: (BuildContext context, Widget child) {
          return Scaffold(
            body: Container(
              child: Center(
                  child: Text('Initial dynamic Firebase link: $link')
              ),
            ),
          );
        }
    );
  }
}
_

予想される動作

リンクはアプリを開き、FirebaseDynamicLinks.instance.getInitialLink().をトリガーする必要があります。

追加のコンテキスト

FirebaseコンソールでFirebaseプロジェクトを適切に構成したいと思います。これを確認するために、Firebase Authの「メールでのサインアップリンク」で使用するダイナミックリンクを作成しました。これらのダイナミックリンクは、アプリが開いていない場合でも期待どおりに機能しています。

ここでのポイントは、プログラムで生成した紹介ダイナミックリンクは、閉じたときにアプリを開いていますが、FirebaseDynamicLinks.instance.getInitialLink()によってキャッチされず、混乱を招くように、アプリが開いている場合は期待どおりに機能することです。その場合、リスナー_FirebaseDynamicLinks.instance.onLink_によってキャッチされます。

また、FlutterでWidgetsBindingObserverを設定して、アプリが再びフォーカスを取得したときに、必要に応じてそのコールバックを処理します。

どんな助けでも大歓迎です。シミュレータではなく実際のデバイスでデバッグを行う必要があるため、デバッグは非常にトリッキーです。さらに悪いことに、ダイナミックリンクがアプリを開いている間にデバッガーを接続する方法がわかりませんでした。これは、この問題をさらに調査することにも行き詰まっていることを意味します。

5
Daniel
  • FirebaseDynamicLinks2つのメソッド1)getInitialLink()2)onLink()

  • アプリが開いているときにダイナミックリンクをクリックすると、FirebaseDynamicLinks.instance.onLink()が呼び出されます。アプリが強制終了されているか、PlayStoreから開いている場合は、FirebaseDynamicLinks.instanceから取得します。 getInitialLink();

  • FirebaseDynamicLinks.instanceのインスタンスを初期化する必要があります。

      static void initDynamicLinks() async {
        final PendingDynamicLinkData data =
            await FirebaseDynamicLinks.instance.getInitialLink();
        final Uri deepLink = data?.link;
    
        if (deepLink != null && deepLink.queryParameters != null) {
          SharedPrefs.setValue("param", deepLink.queryParameters["param"]);
        }
    
        FirebaseDynamicLinks.instance.onLink(
            onSuccess: (PendingDynamicLinkData dynamicLink) async {
          final Uri deepLink = dynamicLink?.link;
    
          if (deepLink != null && deepLink.queryParameters != null) {
            SharedPrefs.setValue("param", deepLink.queryParameters["param]);
          }
        }, onError: (OnLinkErrorException e) async {
          print(e.message);
        });
      }
    
1
Rohit Soni

私はRohitの答えを試しましたが、何人かの人々が同じ問題に直面しているので、ここにいくつかの詳細を追加します。ステートフルウィジェットを作成しました。これは、マテリアルツリーアプリのすぐ下のウィジェットツリーの一番上に配置します。

class DynamicLinkWidget extends StatefulWidget {
  final Widget child;

  DynamicLinkWidget({this.child});

  @override
  State<StatefulWidget> createState() => DynamicLinkWidgetState();
}

class DynamicLinkWidgetState extends State<DynamicLinkWidget> with WidgetsBindingObserver {

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    locator.get<DynamicLinkService>().initDynamicLinks();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(child: widget.child);
  }
}

Getitパッケージを使用してサービスを注入します。ダイナミックリンクサービスは、おおよそ次のようになります。

class DynamicLinkService {
  final UserDataService userDataService;

  final ValueNotifier<bool> isLoading = ValueNotifier<bool>(false);

  final BehaviorSubject<DynamicLinkError> _errorController = BehaviorSubject<DynamicLinkError>();

  Stream<DynamicLinkError> get errorStream => _errorController.stream;

  DynamicLinkService({@required this.userDataService});

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

    if (deepLink != null) {
      processDynamicLink(deepLink);
    }

    FirebaseDynamicLinks.instance.onLink(
        onSuccess: (PendingDynamicLinkData dynamicLink) async {
          final Uri deepLink = dynamicLink?.link;
          if (deepLink != null) {
            print('=====> incoming deep link: <${deepLink.toString()}>');
            processDynamicLink(deepLink);
          }
        },
        onError: (OnLinkErrorException error) async {
          throw PlatformException(
            code: error.code,
            message: error.message,
            details: error.details,
          );
        }
    );
  }

  Future<void> processDynamicLink(Uri deepLink) async {
    if (deepLink.path == Constants.referralLinkPath && deepLink.queryParameters.containsKey(Constants.referrerLinkParam)) {
      var referrer = referrerFromDynamicLink(deepLink);
      userDataService.processReferrer(referrer);
    } else {
      await FirebaseEmailSignIn.processDynamicLink(
          deepLink: deepLink,
          isLoading: isLoading,
          onError: this.onError
      );
    }
  }

  void onError(DynamicLinkError error) {
    _errorController.add(error);
  }
}

私のアプリは2種類のダイナミックリンクを処理する必要があることがわかります。1つは電子メールリンクのサインアップ用、もう1つはユーザーをリンクして、新しいユーザーを紹介したユーザーを理解するために使用される紹介リンクです。このセットアップは今私たちのために動作します。それが他の人にも役立つことを願っています。

0
Daniel