blob: c24a8ce9aa59c34dc62295b6d6ccfab9e920b2c1 [file] [log] [blame]
// Copyright 2017 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 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
typedef Future<dynamic> MessageHandler(Map<String, dynamic> message);
/// Implementation of the Firebase Cloud Messaging API for Flutter.
///
/// Your app should call [requestNotificationPermissions] first and then
/// register handlers for incoming messages with [configure].
class FirebaseMessaging {
factory FirebaseMessaging() => _instance;
@visibleForTesting
FirebaseMessaging.private(MethodChannel channel, Platform platform)
: _channel = channel,
_platform = platform;
static final FirebaseMessaging _instance = FirebaseMessaging.private(
const MethodChannel('plugins.flutter.io/firebase_messaging'),
const LocalPlatform());
final MethodChannel _channel;
final Platform _platform;
MessageHandler _onMessage;
MessageHandler _onLaunch;
MessageHandler _onResume;
/// On iOS, prompts the user for notification permissions the first time
/// it is called.
///
/// Does nothing on Android.
void requestNotificationPermissions(
[IosNotificationSettings iosSettings = const IosNotificationSettings()]) {
if (!_platform.isIOS) {
return;
}
_channel.invokeMethod(
'requestNotificationPermissions', iosSettings.toMap());
}
final StreamController<IosNotificationSettings> _iosSettingsStreamController =
StreamController<IosNotificationSettings>.broadcast();
/// Stream that fires when the user changes their notification settings.
///
/// Only fires on iOS.
Stream<IosNotificationSettings> get onIosSettingsRegistered {
return _iosSettingsStreamController.stream;
}
/// Sets up [MessageHandler] for incoming messages.
void configure({
MessageHandler onMessage,
MessageHandler onLaunch,
MessageHandler onResume,
}) {
_onMessage = onMessage;
_onLaunch = onLaunch;
_onResume = onResume;
_channel.setMethodCallHandler(_handleMethod);
_channel.invokeMethod('configure');
}
final StreamController<String> _tokenStreamController =
StreamController<String>.broadcast();
/// Fires when a new FCM token is generated.
Stream<String> get onTokenRefresh {
return _tokenStreamController.stream;
}
/// Returns the FCM token.
Future<String> getToken() async {
return await _channel.invokeMethod('getToken');
}
/// Subscribe to topic in background.
///
/// [topic] must match the following regular expression:
/// "[a-zA-Z0-9-_.~%]{1,900}".
void subscribeToTopic(String topic) {
_channel.invokeMethod('subscribeToTopic', topic);
}
/// Unsubscribe from topic in background.
void unsubscribeFromTopic(String topic) {
_channel.invokeMethod('unsubscribeFromTopic', topic);
}
/// Resets Instance ID and revokes all tokens. In iOS, it also unregisters from remote notifications.
///
/// A new Instance ID is generated asynchronously if Firebase Cloud Messaging auto-init is enabled.
///
/// returns true if the operations executed successfully and false if an error ocurred
Future<bool> deleteInstanceID() async {
return await _channel.invokeMethod('deleteInstanceID');
}
/// Determine whether FCM auto-initialization is enabled or disabled.
Future<bool> autoInitEnabled() async {
return await _channel.invokeMethod('autoInitEnabled');
}
/// Enable or disable auto-initialization of Firebase Cloud Messaging.
Future<void> setAutoInitEnabled(bool enabled) async {
await _channel.invokeMethod('setAutoInitEnabled', enabled);
}
Future<dynamic> _handleMethod(MethodCall call) async {
switch (call.method) {
case "onToken":
final String token = call.arguments;
_tokenStreamController.add(token);
return null;
case "onIosSettingsRegistered":
_iosSettingsStreamController.add(IosNotificationSettings._fromMap(
call.arguments.cast<String, bool>()));
return null;
case "onMessage":
return _onMessage(call.arguments.cast<String, dynamic>());
case "onLaunch":
return _onLaunch(call.arguments.cast<String, dynamic>());
case "onResume":
return _onResume(call.arguments.cast<String, dynamic>());
default:
throw UnsupportedError("Unrecognized JSON message");
}
}
}
class IosNotificationSettings {
const IosNotificationSettings({
this.sound = true,
this.alert = true,
this.badge = true,
});
IosNotificationSettings._fromMap(Map<String, bool> settings)
: sound = settings['sound'],
alert = settings['alert'],
badge = settings['badge'];
final bool sound;
final bool alert;
final bool badge;
@visibleForTesting
Map<String, dynamic> toMap() {
return <String, bool>{'sound': sound, 'alert': alert, 'badge': badge};
}
@override
String toString() => 'PushNotificationSettings ${toMap()}';
}