Skip to content

[firebase_messaging] Use UNUserNotificationCenter for ios 10+ #121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 20, 2019

Conversation

bparrishMines
Copy link
Contributor

@bparrishMines bparrishMines commented Sep 9, 2019

Description

Switch to use UNUserNotificationCenter once flutter/engine#9864 lands in flutter master. Landed

Follows instructions from: https://firebase.google.com/docs/cloud-messaging/ios/client#register_for_remote_notifications

This includes a test that can run locally on Android and iOS. We can't run it on our CI because it requires a valid Firebase project and a server token.

Related Issues

Should fix flutter/flutter#22099

Possibly Related Issues
flutter/flutter#35375
flutter/flutter#36201

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • If the pull request affects only one plugin, the PR title starts with the name of the plugin in brackets (e.g. [cloud_firestore])
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (please indicate a breaking change in CHANGELOG.md and increment major revision).
  • No, this is not a breaking change.

@bparrishMines bparrishMines added the type: bug Something isn't working label Sep 9, 2019
@bparrishMines bparrishMines changed the title [firebase_messaging] Use UNUserNotificationCenter for ios 10+ [WIP] [firebase_messaging] Use UNUserNotificationCenter for ios 10+ Sep 10, 2019
@collinjackson collinjackson removed the type: bug Something isn't working label Sep 10, 2019
@bparrishMines bparrishMines changed the title [WIP] [firebase_messaging] Use UNUserNotificationCenter for ios 10+ [firebase_messaging] Use UNUserNotificationCenter for ios 10+ Sep 12, 2019
@bparrishMines bparrishMines added the impact: critical Usually a production crash with high user impact. (P1) label Sep 12, 2019
@bparrishMines
Copy link
Contributor Author

bparrishMines commented Sep 12, 2019

@collinjackson @kroikie This PR should hopefully help deal with the recent problems with the plugin. Although, I'm not sure how to test it since my provisioning profile doesn't support Push Notifications or include aps-environment entitlement?

error: Provisioning profile "iOS Team Provisioning Profile: *" doesn't support the Push Notifications capability. (in target 'Runner')
    error: Provisioning profile "iOS Team Provisioning Profile: *" doesn't include the aps-environment entitlement. (in target 'Runner')

Are the test driver tests on Cirrus sufficient?

@collinjackson
Copy link
Contributor

The messaging v1 API might be a good option for integration testing: https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages

@genert
Copy link

genert commented Sep 25, 2019

I think the README should also contain code snippet for those who use Swift when it comes to delegating UNUserNotificationCenter.

Therefore, Swift users must add following line within override func application method in AppDelegate.swift file:

if #available(iOS 10.0, *) {
    UNUserNotificationCenter.current().delegate = self
}

@tvolkert
Copy link
Contributor

It looks like flutter/engine#9864 landed a while back - is this PR ready to resume?

@bparrishMines
Copy link
Contributor Author

@tvolkert I'm still working on adding tests for this.

@minh98
Copy link

minh98 commented Oct 19, 2019

any update ? :D

@@ -143,6 +143,15 @@ To integrate your plugin into the iOS part of your app, follow these steps:

1. Follow the steps in the "[Upload your APNs certificate](https://firebase.google.com/docs/cloud-messaging/ios/client#upload_your_apns_certificate)" section of the Firebase docs.

1. Add the following lines to the `(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`
method In the `AppDelegate.m` of your iOS project.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/In/in

Comment on lines 28 to 73
// We skip this test because it requires a valid server token specified at
// the top of this file uncommenting `setUpAll`, and requires agreeing to
// receive messages by hand on ios.
test('onMessage', () async {
await http.post(
'https://fcm.googleapis.com/fcm/send',
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=$serverToken',
},
body: jsonEncode(
<String, dynamic>{
'notification': <String, dynamic>{
'body': 'this is a body',
'title': 'this is a title'
},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done'
},
'to': await firebaseMessaging.getToken(),
},
),
);

final Completer<Map<String, dynamic>> completer =
Completer<Map<String, dynamic>>();

firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
completer.complete(message);
},
);

final Map<String, dynamic> message = await completer.future;
expect(
message,
containsPair('notification', containsPair('title', 'this is a title')),
);
expect(
message,
containsPair('notification', containsPair('body', 'this is a body')),
);
}, timeout: const Timeout(Duration(seconds: 5)), skip: true);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is skipped for the reasons you identified, could we remove it till we have a good way to run it. Maybe even include it in the README as an option test for developers?

Copy link
Contributor

@collinjackson collinjackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to file an issue and assign to me to get this test running on CI -- I think that the XCUITest stuff I'm doing should make it possible.

@kroikie kroikie mentioned this pull request Oct 30, 2019
13 tasks
@reecepm
Copy link

reecepm commented Nov 1, 2019

As mentioned before, also needs support for swift. I believe it's something like this:

    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }

but not 100% on that

EDIT: I implemented your change and used this line above in my AppDelegate.swift and it worked for me.

[UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
}
```

Copy link

@reecepm reecepm Nov 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, if you are using Swift over Objective C, add the following lines to the

application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool

method in the AppDelegate.swift of your iOS project.

    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out! I added a swift example.

@njovy
Copy link

njovy commented Nov 6, 2019

How long would it take till it’s merged to master?

@kroikie kroikie merged commit 891ea57 into firebase:master Nov 20, 2019
thatfiredev pushed a commit to thatfiredev/flutterfire that referenced this pull request Nov 26, 2019
* bump core version to 0.4.1+4 (firebase#1395)

* Remove deprecated firebase-core dependency (firebase#1417)

* Remove deprecated firebase-core dependency

* [firebase_auth] getIdToken use actual refresh value instead of checking if object exists (firebase#1334)

* getIdToken use actual refresh value instead of checking if object exists

* getIdToken refresh integration test

* update xcode to v11 (firebase#1420)

* Update FirebaseApp creation in tests (firebase#1406)

* [firebase_database] Support v2 android embedder. (firebase#287)

* [firebase_remote_config] Support v2 android embedder. (firebase#282)

* [CI] Add version to example apps (firebase#1426)

* Add hardcode version to example apps

* [firebase_core] Add platform interface (firebase#1324)

* Move firebase_core to firebase_core/firebase_core
* Add firebase_core_platform_interface package
* Update cirrus scripts and documentation

* [firebase_dynamic_links] Add support of expanding from short links (firebase#1381)

* Fixes strict compilation errors. (firebase#1331)

* Upgrade crashlytics to v2 plugin API (firebase#1370)

* Upgraded Crashlytics to v2 of Flutter Plugins.

* Format documentation lists (See also & Errors) correctly (firebase#298)

Fix documentation list format.

* [firebase_auth] Fix NoSuchMethodError exception in `reauthenticateWithCredential` (firebase#237)

* [firebase_auth] Fix NoSuchMethodError exception

Fix NoSuchMethodError exception when calling FirebaseUser.reauthenticateWithCredential

* add integration test

* Fix analyzer warnings

Co-Authored-By: Collin Jackson <[email protected]>

* [cloud_firestore] [firebase_performance] fix analyzer warnings (firebase#1453)

* fix analyzer warnings

* [CI] Skip flaky firebase_performance driver tests (firebase#1452)

* Skip flaky firebase_performance driver tests

* [firebase_auth] Added missing Exception to the reauthenticateWithCredential docs (firebase#1448) (firebase#1449)

* Added missing Exception to the reauthenticateWithCredential docs (firebase#1448)

* [firebase_remote_config] Bumps Android Firebase dependency to 19.0.3 (firebase#1443)

* Bump AGP, Gradle & Google Services Plugin

* Bumps dependency to Firebase Config 19.0.3

* Replaces a deprecated method usage with the updated version

* [firebase_messaging] Use UNUserNotificationCenter for ios 10+ (firebase#121)

* Use UNUserNotificationCenter for ios 10+

* Add swift documentation

* Move http test to README

* Update CONTRIBUTING.md (firebase#1473)

Removes obsolete recommendations about removing mockito (which is now used in testing federated plugins).

* [firebase_core] Migrate to platform_interface (firebase#1472)

* [firebase_messaging] Add an ArgumentError when passing invalid background message (firebase#252)

* [firebase_dynamic_links] support v2 embedding (firebase#1372)

* [cloud_firestore] Fix test that used FirebaseApp.channel (firebase#1476)

* [cloud_firestore] Fix test that used FirebaseApp.channel

* dartfmt

* bump version

* Fixed dynamic issue

* Fixed dynamic issue

* FIxed Object to list of object mapping

* Fixed text result expectation

* Reverted some changes

* Satisfying formatter

* Added android x to pass the test

* Fixed changed log auto formatting
@njovy
Copy link

njovy commented Jan 2, 2020

@kroikie @bparrishMines There are many same or similar issues posted that the latest fcm for flutter doesn't work properly on iOS. Please take a look.

@rscsam
Copy link

rscsam commented Jan 2, 2020

I am still experiencing issues where my onResume and onMessage callbacks are not firing properly. I made no code changes that I can think to be relevant.

@njovy
Copy link

njovy commented Jan 3, 2020

@rscsam The latest library doesn't work on iOS. This isn't about wrong configuration. The library itself just doesn't work at the moment. I guess this repo isn't maintained by any Google developers because I have never had this kind of issue with Google products before. #1644 This is the one I opened up 3 weeks ago and it hasn't been fixed.

@rscsam
Copy link

rscsam commented Jan 4, 2020

@njovy This isn't a "solution" per se, but removing
if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate }
from my AppDelegate.swift fixed this problem for me.

@njovy
Copy link

njovy commented Jan 4, 2020

@rscsam Getting rid of that line is a solution!!

@kekedaine
Copy link

@njovy This isn't a "solution" per se, but removing
if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate }
from my AppDelegate.swift fixed this problem for me.

work fine for me.
Flutter (Channel stable, v1.12.13+hotfix.5, on Mac OS X 10.15.1 19B88

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes impact: critical Usually a production crash with high user impact. (P1)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reduce friction with multiple plugins are being registered as a UNUserNotificationCenterDelegate