courier_flutter 1.0.61 copy "courier_flutter: ^1.0.61" to clipboard
courier_flutter: ^1.0.61 copied to clipboard

outdated

The best way to add push notifications to your Flutter app!

example/lib/main.dart

import 'package:courier_flutter/courier_provider.dart';
import 'package:courier_flutter/ios_foreground_notification_presentation_options.dart';
import 'package:courier_flutter_sample/env.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'dart:async';

import 'package:courier_flutter/courier_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Listen to push notification events
  // You likely want these callbacks to be handled
  // at a similar "global" level
  Courier.shared.onPushNotificationDelivered = (push) {
    print(push);
    pushDelivered.add(push);
  };

  // This is a good point to check your users authentication
  // or do any other logic needed before your users take action
  // on the notification
  Courier.shared.onPushNotificationClicked = (push) {
    print(push);
    pushClicked.add(push);
  };

  // This is needed to handle FCM tokens
  await Firebase.initializeApp();

  runApp(
    const MaterialApp(
      home: MyApp(),
    ),
  );
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

// These streams are used to simply pass the data to the current UI
// Your implementation will likely be different
StreamController<dynamic> pushDelivered = StreamController<dynamic>();
StreamController<dynamic> pushClicked = StreamController<dynamic>();

class _MyAppState extends State<MyApp> {
  bool _isLoading = true;
  String? _currentUserId;
  final List<CourierProvider> _providers = [CourierProvider.apns, CourierProvider.fcm];

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

    if (!mounted) {
      return;
    }

    _registerAlertStreams();
    _start();
  }

  _registerAlertStreams() {
    // These exist to simply show the message
    // Your implementation will be different
    pushDelivered.stream.listen((push) {
      _showAlert(context, 'Push Delivered', push.toString());
    });

    pushClicked.stream.listen((push) {
      _showAlert(context, 'Push Clicked', push.toString());
    });
  }

  Future _start() async {
    try {
      setState(() {
        _isLoading = true;
      });

      Courier.shared.isDebugging = true;
      print(Courier.shared.isDebugging);

      Courier.shared.iOSForegroundNotificationPresentationOptions = [
        iOSNotificationPresentationOption.banner,
        iOSNotificationPresentationOption.sound,
        iOSNotificationPresentationOption.list,
        iOSNotificationPresentationOption.badge,
      ];
      print(Courier.shared.iOSForegroundNotificationPresentationOptions);

      final userId = await Courier.shared.userId;
      print(userId);

      final fetchStatus = await Courier.shared.getNotificationPermissionStatus();
      print(fetchStatus);

      final requestStatus = await Courier.shared.requestNotificationPermission();
      print(requestStatus);

      // Set the current FCM token
      // Android will automatically handle this, but iOS will not
      final fcmToken = await FirebaseMessaging.instance.getToken();
      if (fcmToken != null) {
        await Courier.shared.setFcmToken(token: fcmToken);
      }

      // Handle FCM token changes
      FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) {
        Courier.shared.setFcmToken(token: fcmToken);
      }).onError((err) {
        throw err;
      });

      setState(() {
        _currentUserId = userId;
      });
    } catch (e) {
      print(e);
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  Future<String> _showUserIdAlert() async {
    final textController = TextEditingController();

    await showDialog(
      barrierDismissible: false,
      context: context,
      builder: (context) => AlertDialog(
        title: const Text("Enter User Id"),
        content: TextField(
          autofocus: true,
          autocorrect: false,
          enableSuggestions: false,
          decoration: const InputDecoration(hintText: "Courier User Id"),
          controller: textController,
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text("Cancel"),
          ),
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text("Sign In"),
          ),
        ],
      ),
    );

    return Future.value(textController.text);
  }

  _signIn() async {
    try {
      setState(() {
        _isLoading = true;
      });

      final courierUserId = await _showUserIdAlert();
      if (courierUserId.isEmpty) return;

      await Courier.shared.signIn(
        accessToken: Env.accessToken,
        userId: courierUserId,
      );

      final userId = await Courier.shared.userId;
      setState(() {
        _currentUserId = userId;
      });
    } catch (e) {
      print(e);
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  _signOut() async {
    try {
      setState(() {
        _isLoading = true;
      });

      await Courier.shared.signOut();
      final userId = await Courier.shared.userId;
      setState(() {
        _currentUserId = userId;
      });
    } catch (e) {
      print(e);
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  _showAlert(BuildContext context, String title, String body) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(title),
        content: Text(body),
        actions: [
          TextButton(
            child: const Text('Ok'),
            onPressed: () => Navigator.pop(context),
          )
        ],
      ),
    );
  }

  _getFcmToken(BuildContext context) async {
    final token = await Courier.shared.fcmToken;
    print(token);
    _showAlert(context, 'FCM Token', token ?? 'No token set');
  }

  _getApnsToken(BuildContext context) async {
    final token = await Courier.shared.apnsToken;
    print(token);
    _showAlert(context, 'APNS Token', token ?? 'No token set');
  }

  _handleProviderSwitch(CourierProvider selectedProvider) {
    if (_providers.contains(selectedProvider)) {
      setState(() {
        _providers.removeWhere((provider) => provider == selectedProvider);
      });
    } else {
      setState(() {
        _providers.add(selectedProvider);
      });
    }
  }

  Future _sendPush() async {
    if (_providers.isEmpty) {
      return;
    }

    try {
      setState(() {
        _isLoading = true;
      });

      final userId = await Courier.shared.userId ?? '';

      final requestId = await Courier.shared.sendPush(
        authKey: Env.authKey,
        userId: userId,
        title: 'Hey $userId',
        body: 'Push sent from: ${_providers.map((e) => e.name).join(' & ')}',
        providers: _providers,
      );

      print(requestId);
    } catch (e) {
      print(e);
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  Widget _buildContent() {
    if (_isLoading) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }

    if (_currentUserId != null) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text('Current user id: ${_currentUserId!}'),
          TextButton(
            child: const Text('Sign Out'),
            onPressed: () => _signOut(),
          ),
          const Divider(),
          SwitchListTile(
            value: _providers.contains(CourierProvider.apns),
            onChanged: (bool value) {
              _handleProviderSwitch(CourierProvider.apns);
            },
            title: Text(
              CourierProvider.apns.name.toUpperCase(),
            ),
          ),
          SwitchListTile(
            value: _providers.contains(CourierProvider.fcm),
            onChanged: (bool value) {
              _handleProviderSwitch(CourierProvider.fcm);
            },
            title: Text(
              CourierProvider.fcm.name.toUpperCase(),
            ),
          ),
          TextButton(
            onPressed: () => _sendPush(),
            child: const Text('Send Push'),
          ),
          const Divider(),
          TextButton(
            child: const Text('See FCM Token'),
            onPressed: () => _getFcmToken(context),
          ),
          TextButton(
            child: const Text('See APNS Token'),
            onPressed: () => _getApnsToken(context),
          ),
        ],
      );
    }

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const Text('No user signed into Courier'),
        TextButton(
          child: const Text('Sign In'),
          onPressed: () => _signIn(),
        ),
        const Divider(),
        TextButton(
          child: const Text('See FCM Token'),
          onPressed: () => _getFcmToken(context),
        ),
        TextButton(
          child: const Text('See APNS Token'),
          onPressed: () => _getApnsToken(context),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Courier example app'),
      ),
      body: _buildContent(),
    );
  }

  @override
  void dispose() {
    super.dispose();
    pushDelivered.close();
    pushClicked.close();
  }
}
4
likes
0
points
1.35k
downloads

Publisher

unverified uploader

Weekly Downloads

The best way to add push notifications to your Flutter app!

Homepage

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on courier_flutter

Packages that implement courier_flutter