web-dev-qa-db-fra.com

Firebase Dynamic Link n'est pas intercepté par getInitialLink si l'application est fermée et ouverte par ce lien

Les liens dynamiques générés par programme ne sont pas correctement capturés par

FirebaseDynamicLinks.instance.getInitialLink().

si l'application est fermée. Cependant, si l'application est ouverte, elle est correctement détectée par l'auditeur pour les nouveaux liens dynamiques entrants. Il n'est pas clair pour moi s'il s'agit d'un problème de configuration, comment je génère le lien dynamique.

à reproduire

Commencez par configurer Firebase pour le projet Flutter comme indiqué. Puis pour mettre en place un lien dynamique:

/// 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();
}

Ce lien dynamique peut ensuite être partagé avec d'autres nouveaux utilisateurs.

J'écoute les liens initiaux au démarrage de l'application, puis les nouveaux liens entrants.

1) Le lien ouvre correctement l'application si l'application n'est pas en cours d'exécution mais que getInitialLink ne l'obtient pas.

2) Si l'application est ouverte, le lien est correctement capté par l'auditeur et tout fonctionne.

Voici le très simple main.Dart que j'ai utilisé pour vérifier 1) que le lien initial n'est pas trouvé avec FirebaseDynamicLinks.instance.getInitialLink ().

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')
              ),
            ),
          );
        }
    );
  }
}

Comportement attend

Le lien doit ouvrir l'application et déclencher FirebaseDynamicLinks.instance.getInitialLink()..

Contexte supplémentaire

J'espère un projet Firebase correctement configuré avec la console Firebase. Pour vérifier cela, j'ai créé un lien dynamique à utiliser avec Firebase Auth 'inscription par lien par e-mail' et ces liens dynamiques fonctionnent comme prévu, également lorsque l'application n'est pas ouverte.

Le point ici est que le lien dynamique de référence que je génère par programme ouvre l'application lorsqu'elle est fermée mais n'est ensuite pas intercepté par FirebaseDynamicLinks.instance.getInitialLink(), et pour rendre les choses plus confuses, fonctionne comme prévu si l'application est ouverte . Dans ce cas, il est intercepté par l'auditeur FirebaseDynamicLinks.instance.onLink.

J'ai également configuré le WidgetsBindingObserver dans Flutter pour gérer ce rappel selon les besoins, lorsque l'application retrouve son focus.

Toute aide est grandement appréciée. Le débogage est très délicat, car vous devez le faire sur un appareil réel et non dans le simulateur. Pour aggraver les choses, je n'ai pas compris comment attacher un débogueur pendant que le lien dynamique ouvre l'application. Cela signifie que je suis également coincé dans une enquête plus approfondie sur cette question.

5
Daniel
  • Dans le FirebaseDynamicLinks Deux méthodes 1) getInitialLink ()2) onLink ().

  • Si lorsque votre application est ouverte et que vous cliquez sur le lien dynamique, vous appellerez FirebaseDynamicLinks.instance.onLink (), si votre application est supprimée ou ouverte à partir de PlayStore, vous obtenez de FirebaseDynamicLinks.instance.getInitialLink ();.

  • Vous devez d'abord initialiser l'instance de 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

J'ai essayé la réponse de Rohit et parce que plusieurs personnes sont confrontées au même problème, j'ajoute ici quelques détails supplémentaires. J'ai créé un widget avec état que je place à peu près en haut de l'arborescence des widgets juste sous l'application matérielle:

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);
  }
}

J'utilise le package getit pour injecter des services. Le service de liaison dynamique est à peu près comme ceci:

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);
  }
}

Vous voyez que mon application doit traiter deux types de lien dynamique, l'un est pour l'inscription au lien par e-mail, l'autre lien est notre lien de parrainage qui est utilisé pour relier les utilisateurs entre eux et nous permettre de comprendre qui nous a présenté un nouvel utilisateur. Cette configuration fonctionne maintenant pour nous. J'espère que cela aide aussi les autres.

0
Daniel