diff --git a/.github/workflows/firebase_messaging.yaml b/.github/workflows/firebase_messaging.yaml new file mode 100644 index 000000000000..788cd070fa11 --- /dev/null +++ b/.github/workflows/firebase_messaging.yaml @@ -0,0 +1,53 @@ +name: firebase_messaging + +on: + pull_request: + paths: + - "packages/firebase_messaging/**" + - ".github/workflows/firebase_messaging.yaml" + push: + branches: + - master + +env: + FLUTTERFIRE_PLUGIN_SCOPE: "*firebase_messaging*" + FLUTTERFIRE_PLUGIN_SCOPE_EXAMPLE: "*firebase_messaging_example*" + +jobs: + android: + runs-on: macos-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 0 + - name: "Install Flutter" + run: ./.github/workflows/scripts/install-flutter.sh stable + - name: "Install Tools" + run: ./.github/workflows/scripts/install-tools.sh + - name: "Build Example" + run: ./.github/workflows/scripts/build-example.sh android + - name: "Drive Example" + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 28 + arch: x86_64 + target: google_apis + profile: Nexus 5X + script: ./.github/workflows/scripts/drive-example.sh android + + ios: + runs-on: macos-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 0 + - name: "Install Flutter" + run: ./.github/workflows/scripts/install-flutter.sh stable + - name: "Install Tools" + run: ./.github/workflows/scripts/install-tools.sh + - name: "Build Example" + run: ./.github/workflows/scripts/build-example.sh ios + - name: "Drive Example" + run: ./.github/workflows/scripts/drive-example.sh ios diff --git a/docs/messaging/overview.mdx b/docs/messaging/overview.mdx new file mode 100644 index 000000000000..8af8c2940956 --- /dev/null +++ b/docs/messaging/overview.mdx @@ -0,0 +1,52 @@ +--- +title: Firebase Cloud Messaging +sidebar_label: Overview +--- + +## What does it do? + +Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably send messages at no cost. + +Using FCM, you can notify a client app that new email or other data is available to sync. You can send notification +messages to drive user re-engagement and retention. For use cases such as instant messaging, a message can transfer +a payload of up to 4KB to a client app. + + + +## Installation + +### 1. Add dependency + +```yaml {5} title="pubspec.yaml" +dependencies: + flutter: + sdk: flutter + firebase_core: "^{{ plugins.firebase_core }}" + firebase_messaging: "^{{ plugins.firebase_messaging }}" +``` + +### 2. Download dependency + +``` +$ flutter pub get +``` + +### 3. (Web Only) Add the SDK + +> Web is currently not supported. See the [FlutterFire roadmap](https://github.com/FirebaseExtended/flutterfire/issues/2582). + +### 4. Rebuild your app + +Once complete, rebuild your Flutter application: + +```bash +$ flutter run +``` + +## Next Steps + +Once installed, you're ready to start using Firebase Cloud Messaging in your Flutter Project. + +> Additional documentation will be available once the Firebase Firebase Cloud Messaging plugin update lands as part of the [FlutterFire roadmap](https://github.com/FirebaseExtended/flutterfire/issues/2582). + + diff --git a/docs/sidebars.js b/docs/sidebars.js index 80b86881044c..4de03e62ae15 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -30,7 +30,7 @@ module.exports = { toReferenceAPI("cloud_firestore"), ], "Cloud Functions": ["functions/overview", toReferenceAPI("cloud_functions")], - // "Cloud Messaging": ["messaging/usage", toReferenceAPI("firebase_messaging")], + "Cloud Messaging": ["messaging/overview", toReferenceAPI("firebase_messaging")], "Cloud Storage": ["storage/overview", toReferenceAPI("firebase_storage")], Core: ["core/usage", toReferenceAPI("firebase_core")], // Crashlytics: ["crashlytics/usage", toReferenceAPI("firebase_crashlytics")], diff --git a/packages/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/CHANGELOG.md index a79c42f1ec4f..3de0cddde0f3 100644 --- a/packages/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/CHANGELOG.md @@ -1,3 +1,10 @@ +## 7.0.0-dev.1 + +* Depend on `firebase_core` pre-release versions and migrate plugin to use `firebase_core` native SDK versioning features; + * Firebase iOS SDK versions are now locked to use the same version defined in `firebase_core`. + * Firebase Android SDK versions are now using the Firebase Bill of Materials (BoM) to specify individual SDK versions. BoM version is also sourced from `firebase_core`. +* Allow iOS to be imported as a module. + ## 6.0.16 * Fix push notifications clearing after app launch on iOS. diff --git a/packages/firebase_messaging/android/build.gradle b/packages/firebase_messaging/android/build.gradle index b18269aef9b8..35c606b47cca 100644 --- a/packages/firebase_messaging/android/build.gradle +++ b/packages/firebase_messaging/android/build.gradle @@ -21,6 +21,19 @@ rootProject.allprojects { apply plugin: 'com.android.library' +def firebaseCoreProject = findProject(':firebase_core') +if (firebaseCoreProject == null) { + throw new GradleException('Could not find the firebase_core FlutterFire plugin, have you added it as a dependency in your pubspec?') +} else if (!firebaseCoreProject.properties['FirebaseSDKVersion']) { + throw new GradleException('A newer version of the firebase_core FlutterFire plugin is required, please update your firebase_core pubspec dependency.') +} + +def getRootProjectExtOrCoreProperty(name, firebaseCoreProject) { + if (!rootProject.ext.has('FlutterFire')) return firebaseCoreProject.properties[name] + if (!rootProject.ext.get('FlutterFire')[name]) return firebaseCoreProject.properties[name] + return rootProject.ext.get('FlutterFire').get(name) +} + android { compileSdkVersion 28 @@ -32,35 +45,11 @@ android { disable 'InvalidPackage' } dependencies { - implementation 'com.google.firebase:firebase-messaging:20.0.1' - implementation 'androidx.annotation:annotation:1.1.0' + api firebaseCoreProject + implementation platform("com.google.firebase:firebase-bom:${getRootProjectExtOrCoreProperty("FirebaseSDKVersion", firebaseCoreProject)}") + implementation 'com.google.firebase:firebase-messaging' implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' - } -} - -// TODO(kroikie): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348 -afterEvaluate { - def containsEmbeddingDependencies = false - for (def configuration : configurations.all) { - for (def dependency : configuration.dependencies) { - if (dependency.group == 'io.flutter' && - dependency.name.startsWith('flutter_embedding') && - dependency.isTransitive()) - { - containsEmbeddingDependencies = true - break - } - } - } - if (!containsEmbeddingDependencies) { - android { - dependencies { - def lifecycle_version = "1.1.1" - implementation "android.arch.lifecycle:runtime:$lifecycle_version" - implementation "android.arch.lifecycle:common:$lifecycle_version" - implementation "android.arch.lifecycle:common-java8:$lifecycle_version" - } - } + implementation 'androidx.annotation:annotation:1.1.0' } } diff --git a/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java b/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java index 3d0048d4e8ea..d475b9e0a3b8 100644 --- a/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java +++ b/packages/firebase_messaging/android/src/main/java/io/flutter/plugins/firebasemessaging/FirebaseMessagingPlugin.java @@ -15,7 +15,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; -import com.google.firebase.FirebaseApp; import com.google.firebase.iid.FirebaseInstanceId; import com.google.firebase.iid.InstanceIdResult; import com.google.firebase.messaging.FirebaseMessaging; @@ -54,7 +53,6 @@ public static void registerWith(Registrar registrar) { private void onAttachedToEngine(Context context, BinaryMessenger binaryMessenger) { this.applicationContext = context; - FirebaseApp.initializeApp(applicationContext); channel = new MethodChannel(binaryMessenger, "plugins.flutter.io/firebase_messaging"); final MethodChannel backgroundCallbackChannel = new MethodChannel(binaryMessenger, "plugins.flutter.io/firebase_messaging_background"); diff --git a/packages/firebase_messaging/example/android/app/src/main/java/io/flutter/plugins/firebasemessagingexample/MainActivity.java b/packages/firebase_messaging/example/android/app/src/main/java/io/flutter/plugins/firebasemessagingexample/MainActivity.java index f06e404bfcc1..733f2218974e 100644 --- a/packages/firebase_messaging/example/android/app/src/main/java/io/flutter/plugins/firebasemessagingexample/MainActivity.java +++ b/packages/firebase_messaging/example/android/app/src/main/java/io/flutter/plugins/firebasemessagingexample/MainActivity.java @@ -7,6 +7,7 @@ import dev.flutter.plugins.e2e.E2EPlugin; import io.flutter.embedding.android.FlutterActivity; import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.plugins.firebase.core.FlutterFirebaseCorePlugin; import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin; public class MainActivity extends FlutterActivity { @@ -15,6 +16,7 @@ public class MainActivity extends FlutterActivity { @Override public void configureFlutterEngine(FlutterEngine flutterEngine) { flutterEngine.getPlugins().add(new FirebaseMessagingPlugin()); + flutterEngine.getPlugins().add(new FlutterFirebaseCorePlugin()); flutterEngine.getPlugins().add(new E2EPlugin()); } } diff --git a/packages/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/example/pubspec.yaml index f9ecc8a52929..e72da865bb83 100644 --- a/packages/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/example/pubspec.yaml @@ -7,7 +7,8 @@ dependencies: sdk: flutter firebase_messaging: path: ../ - firebase_core: ^0.4.0 + firebase_core: + path: ../firebase_core/firebase_core dev_dependencies: pedantic: ^1.8.0 diff --git a/packages/firebase_messaging/example/test_driver/firebase_messaging.dart b/packages/firebase_messaging/example/test_driver/firebase_messaging_e2e.dart similarity index 51% rename from packages/firebase_messaging/example/test_driver/firebase_messaging.dart rename to packages/firebase_messaging/example/test_driver/firebase_messaging_e2e.dart index a6d5c888b6dd..bcc40fa5bd7d 100644 --- a/packages/firebase_messaging/example/test_driver/firebase_messaging.dart +++ b/packages/firebase_messaging/example/test_driver/firebase_messaging_e2e.dart @@ -1,18 +1,23 @@ -import 'dart:async'; +// Copyright 2020, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. -import 'package:flutter_driver/driver_extension.dart'; +import 'package:e2e/e2e.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; void main() { - final Completer completer = Completer(); - enableFlutterDriverExtension(handler: (_) => completer.future); - tearDownAll(() => completer.complete(null)); + E2EWidgetsFlutterBinding.ensureInitialized(); group('$FirebaseMessaging', () { - final FirebaseMessaging firebaseMessaging = FirebaseMessaging(); + FirebaseMessaging firebaseMessaging; + setUp(() async { + await Firebase.initializeApp(); + firebaseMessaging = await FirebaseMessaging(); + }); - test('autoInitEnabled', () async { + testWidgets('autoInitEnabled', (WidgetTester tester) async { await firebaseMessaging.setAutoInitEnabled(false); expect(await firebaseMessaging.autoInitEnabled(), false); await firebaseMessaging.setAutoInitEnabled(true); @@ -20,16 +25,16 @@ void main() { }); // TODO(jackson): token retrieval isn't working on test devices yet - test('subscribeToTopic', () async { + testWidgets('subscribeToTopic', (WidgetTester tester) async { await firebaseMessaging.subscribeToTopic('foo'); }, skip: true); // TODO(jackson): token retrieval isn't working on test devices yet - test('unsubscribeFromTopic', () async { + testWidgets('unsubscribeFromTopic', (WidgetTester tester) async { await firebaseMessaging.unsubscribeFromTopic('foo'); }, skip: true); - test('deleteInstanceID', () async { + testWidgets('deleteInstanceID', (WidgetTester tester) async { final bool result = await firebaseMessaging.deleteInstanceID(); expect(result, isTrue); }); diff --git a/packages/firebase_messaging/example/test_driver/firebase_messaging_e2e_test.dart b/packages/firebase_messaging/example/test_driver/firebase_messaging_e2e_test.dart new file mode 100644 index 000000000000..27e264e5475b --- /dev/null +++ b/packages/firebase_messaging/example/test_driver/firebase_messaging_e2e_test.dart @@ -0,0 +1,7 @@ +// Copyright 2020, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:e2e/e2e_driver.dart' as e2e; + +void main() => e2e.main(); diff --git a/packages/firebase_messaging/example/test_driver/firebase_messaging_test.dart b/packages/firebase_messaging/example/test_driver/firebase_messaging_test.dart deleted file mode 100644 index 38fe6c447e05..000000000000 --- a/packages/firebase_messaging/example/test_driver/firebase_messaging_test.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'package:flutter_driver/flutter_driver.dart'; - -Future main() async { - final FlutterDriver driver = await FlutterDriver.connect(); - await driver.requestData(null, timeout: const Duration(minutes: 1)); - driver.close(); -} diff --git a/packages/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m b/packages/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m index 0a1cca151235..ec35948f6364 100644 --- a/packages/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m +++ b/packages/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m @@ -52,11 +52,6 @@ - (instancetype)initWithChannel:(FlutterMethodChannel *)channel { if (self) { _channel = channel; _resumingFromBackground = NO; - if (![FIRApp appNamed:@"__FIRAPP_DEFAULT"]) { - NSLog(@"Configuring the default Firebase app..."); - [FIRApp configure]; - NSLog(@"Configured the default Firebase app %@.", [FIRApp defaultApp].name); - } [FIRMessaging messaging].delegate = self; } return self; diff --git a/packages/firebase_messaging/ios/firebase_messaging.podspec b/packages/firebase_messaging/ios/firebase_messaging.podspec index 6723c59f8391..8dea10a3e89d 100644 --- a/packages/firebase_messaging/ios/firebase_messaging.podspec +++ b/packages/firebase_messaging/ios/firebase_messaging.podspec @@ -1,29 +1,44 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html -# - require 'yaml' + pubspec = YAML.load_file(File.join('..', 'pubspec.yaml')) -libraryVersion = pubspec['version'].gsub('+', '-') +library_version = pubspec['version'].gsub('+', '-') + +firebase_sdk_version = '6.26.0' +if defined?($FirebaseSDKVersion) + Pod::UI.puts "#{pubspec['name']}: Using user specified Firebase SDK version '#{$FirebaseSDKVersion}'" + firebase_sdk_version = $FirebaseSDKVersion +else + firebase_core_script = File.join(File.expand_path('..', File.expand_path('..', File.dirname(__FILE__))), 'firebase_core/ios/firebase_sdk_version.rb') + if File.exist?(firebase_core_script) + require firebase_core_script + firebase_sdk_version = firebase_sdk_version! + Pod::UI.puts "#{pubspec['name']}: Using Firebase SDK version '#{firebase_sdk_version}' defined in 'firebase_core'" + end +end Pod::Spec.new do |s| - s.name = 'firebase_messaging' - s.version = '0.0.1' - s.summary = 'Firebase Cloud Messaging plugin for Flutter.' - s.description = <<-DESC -Firebase Cloud Messaging plugin for Flutter. - DESC - s.homepage = 'https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_messaging' + s.name = pubspec['name'] + s.version = library_version + s.summary = pubspec['description'] + s.description = pubspec['description'] + s.homepage = pubspec['homepage'] s.license = { :file => '../LICENSE' } - s.author = { 'Flutter Team' => 'flutter-dev@googlegroups.com' } + s.authors = 'The Chromium Authors' s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.public_header_files = 'Classes/**/*.h' - s.dependency 'Flutter' - s.dependency 'Firebase/Core' - s.dependency 'Firebase/Messaging' - s.static_framework = true + + s.source_files = 'Classes/**/*.{h,m}' + s.public_header_files = 'Classes/*.h' + s.ios.deployment_target = '8.0' + s.dependency 'Flutter' - s.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{libraryVersion}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-fcm\\\"" } + s.dependency 'firebase_core' + s.dependency 'Firebase/CoreOnly', "~> #{firebase_sdk_version}" + s.dependency 'Firebase/Messaging', "~> #{firebase_sdk_version}" + + s.static_framework = true + s.pod_target_xcconfig = { + 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{library_version}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-fcm\\\"", + 'DEFINES_MODULE' => 'YES' + } end diff --git a/packages/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/pubspec.yaml index 76cae50c701a..4fc5f71be84f 100644 --- a/packages/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_messaging description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_messaging -version: 6.0.16 +version: 7.0.0-dev.1 flutter: plugin: @@ -18,6 +18,7 @@ dependencies: platform: ^2.0.0 flutter: sdk: flutter + firebase_core: ^0.5.0-dev.1 dev_dependencies: pedantic: ^1.8.0 @@ -25,11 +26,9 @@ dev_dependencies: mockito: ^3.0.0 flutter_test: sdk: flutter - firebase_core: ^0.4.0 flutter_driver: sdk: flutter - e2e: ^0.6.1 environment: sdk: ">=2.0.0 <3.0.0" - flutter: ">=1.10.0 <2.0.0" + flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/packages/firebase_messaging/test/firebase_messaging_e2e.dart b/packages/firebase_messaging/test/firebase_messaging_e2e.dart deleted file mode 100644 index 00b98a2ffc87..000000000000 --- a/packages/firebase_messaging/test/firebase_messaging_e2e.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:e2e/e2e.dart'; - -void main() { - E2EWidgetsFlutterBinding.ensureInitialized(); - - testWidgets('Can get auto init enabled', (WidgetTester tester) async { - final FirebaseMessaging messaging = FirebaseMessaging(); - final bool autoInitEnabled = await messaging.autoInitEnabled(); - expect(autoInitEnabled, isTrue); - }); -}