5

I'm building a flutter application, and am having some trouble actually opening the app using the firebase_dynamic_links package. I basically took the example code found at https://pub.dev/packages/firebase_dynamic_links#-example-tab- in order to get started, but changed the information in their example to match my own firebase project (which has been setup in both android and iOS, but this testing has all been done with iOS).

I will include code and more useful information below, but I was really just hoping to get a simplified example of how this process should work. I have searched online quite a bit, following different tutorials, but none of them have done the trick for me. It could just be that I'm quite new to flutter, and am missing basic things. In my final application, I will be using dynamic links to allow users to invite other users to join the app (as well as groups within the app) via text, just to give context as to why it is needed.

Here is the code for what I have so far, but as I mentioned it is largely based off of the example from the link above.

main.dart

// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:io' show Platform;

import 'package:flutter/material.dart';
import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:shopsync/helloworld.dart';

void main() async {
  //Setup firebase connection
  WidgetsFlutterBinding.ensureInitialized();
  final FirebaseApp app = await FirebaseApp.configure(
    name: 'shop-sync-d97d8',
    options: Platform.isIOS
        ? const FirebaseOptions(
            googleAppID: 'my_googleAppID',
            gcmSenderID: 'my_senderID',
            databaseURL: 'https://shop-sync-d97d8.firebaseio.com',
            apiKey: 'AIzaSyC1TdwTs_KRXMGG2oIAGMX8v48HWqS62dc',
          )
        : const FirebaseOptions(
            googleAppID: 'my_googleAppID',
            apiKey: 'myApiKey',
            databaseURL: 'my_url',
          ),
  );
  runApp(MaterialApp(
    title: 'Dynamic Links Example',
    routes: <String, WidgetBuilder>{
      '/': (BuildContext context) => _MainScreen(),
      '/helloworld': (BuildContext context) => HelloWorldScreen(),
    },
  ));
}

class _MainScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _MainScreenState();
}

class _MainScreenState extends State<_MainScreen> {
  String _linkMessage;
  bool _isCreatingLink = false;
  String _testString =
      "To test: long press link and then copy and click from a non-browser "
      "app. Make sure this isn't being tested on iOS simulator and iOS xcode "
      "is properly setup. Look at firebase_dynamic_links/README.md for more "
      "details.";

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

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

    if (deepLink != null) {
      Navigator.pushNamed(context, deepLink.path);
    }

    FirebaseDynamicLinks.instance.onLink(
        onSuccess: (PendingDynamicLinkData dynamicLink) async {
      final Uri deepLink = dynamicLink?.link;

      if (deepLink != null) {
        Navigator.pushNamed(context, deepLink.path);
      }
    }, onError: (OnLinkErrorException e) async {
      print('onLinkError');
      print(e.message);
    });
  }

  Future<void> _createDynamicLink(bool short) async {
    setState(() {
      _isCreatingLink = true;
    });

    final DynamicLinkParameters parameters = DynamicLinkParameters(
      uriPrefix: "https://shopsync.page.link",
      link: Uri.parse("https://shopsync.page.link/helloworld"),
      androidParameters: AndroidParameters(
        packageName: 'com.chrismcdonnell.shopsync',
        minimumVersion: 0,
      ),
      dynamicLinkParametersOptions: DynamicLinkParametersOptions(
        shortDynamicLinkPathLength: ShortDynamicLinkPathLength.short,
      ),
      iosParameters: IosParameters(
        bundleId: 'com.chrismcdonnell.shopsync',
        minimumVersion: '0',
      ),
    );

    Uri url;
    if (short) {
      final ShortDynamicLink shortLink = await parameters.buildShortLink();
      url = shortLink.shortUrl;
    } else {
      url = await parameters.buildUrl();
    }

    setState(() {
      _linkMessage = url.toString();
      _isCreatingLink = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Dynamic Links Example'),
        ),
        body: Builder(builder: (BuildContext context) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                ButtonBar(
                  alignment: MainAxisAlignment.center,
                  children: <Widget>[
                    RaisedButton(
                      onPressed: !_isCreatingLink
                          ? () => _createDynamicLink(false)
                          : null,
                      child: const Text('Get Long Link'),
                    ),
                    RaisedButton(
                      onPressed: !_isCreatingLink
                          ? () => _createDynamicLink(true)
                          : null,
                      child: const Text('Get Short Link'),
                    ),
                  ],
                ),
                InkWell(
                  child: Text(
                    _linkMessage ?? '',
                    style: const TextStyle(color: Colors.blue),
                  ),
                  onTap: () async {
                    if (_linkMessage != null) {
                      await launch(_linkMessage);
                    }
                  },
                  onLongPress: () {
                    Clipboard.setData(ClipboardData(text: _linkMessage));
                    Scaffold.of(context).showSnackBar(
                      const SnackBar(content: Text('Copied Link!')),
                    );
                  },
                ),
                Text(_linkMessage == null ? '' : _testString)
              ],
            ),
          );
        }),
      ),
    );
  }
}

class _DynamicLinkScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Hello World DeepLink'),
        ),
        body: const Center(
          child: Text('Hello, World!'),
        ),
      ),
    );
  }
}

helloworld.dart

//IMPORT NEEDED PACKAGES
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

//CREATE STATEFUL WIDGET
class HelloWorldScreen extends StatefulWidget {
  @override
  _HelloWorldScreen createState() => _HelloWorldScreen();
}

//CREATE STATE WIDGET
class _HelloWorldScreen extends State<HelloWorldScreen> {
  @override
  Widget build(BuildContext context) {
    //Since this class represents an entire screen, return a scaffold with elements inside it
    return Scaffold(
      backgroundColor: Colors.white,
      //Create AppBar w/ title "My Account"
      appBar: AppBar(
        title: Text('Hello World'),
        automaticallyImplyLeading: false,
      ),
      //Most of the content of the screen will go here
      body: SafeArea(
        child: Text('Testing'),
      ),
    );
  }
}

And lastly, here is the dynamic link I created within the console for testing. Although the final version of the application will create them programatically. Screenshot of link with ios tab in firebase

If anything else is needed please let me know. Any help would be greatly appreciated.

Christopher M
  • 99
  • 2
  • 7
  • What's the issue here? Could you provide more details of the expected and actual behavior that you're getting? – Omatt Apr 20 '21 at 15:41

0 Answers0