Skip to content

Conversation

@devadiab
Copy link

Hi There,
This is the final complete solution used on my enterprise projects contains the following:

1- FCM iOS binding it was only contains the ID registration code.
2- Upgrade the library so it will work 100% correct with Android 8+.

The key for changes on Android 👍
1- Upgrade com.google.firebase:firebase-messaging to version 17.
2- Change the Action on Intent receiver because Android 8+ run the notification as the launcher (android.intent.action.MAIN).
3- Fix Intent and Pending Intent flags so all notifications are clickable and each one contains it's data.

Regards,

@devadiab
Copy link
Author

devadiab commented Jul 12, 2018

@LuisRodriguezLD or @jesusmartinoza could you review this PR ?

Copy link
Contributor

@kusma kusma left a comment

Choose a reason for hiding this comment

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

I really don't get the iOS-specific code in Fuse.Firebase.Android here, but I see that there was already some precedence for it... Seems strange to me.

"google.ttl",
"collapse_key"}));


Copy link
Contributor

Choose a reason for hiding this comment

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

This seems needless

public void DoIt(RemoteMessage remoteMessage)
{
Map<String,String> map = remoteMessage.getData();

Copy link
Contributor

Choose a reason for hiding this comment

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

This also

}

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
mBuilder = new NotificationCompat.Builder(context)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please keep the old name here, as it'll keep the delta smaller...

mBuilder = new NotificationCompat.Builder(this,channel_id);
}
else{
mBuilder = new NotificationCompat.Builder(this);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why go through this dance to allocate mBuilder, only to overwrite it a few lines further down?

.setColor((int)0x@(Project.Android.NotificationIcon.Color))
#endif
.setContentIntent(pendingIntent);
#endif .setContentIntent(pendingIntent);
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like a mistake. Don't mix preprocessor directives with code. Please put these on separate lines... wasn't the old way right anyway?


static void OnRegistrationSucceedediOS(string message) {
//_onRegistrationSucceedediOS.RaiseAsync(message);
debug_log "OnRegistrationSucceedediOS :"+message;
Copy link
Contributor

Choose a reason for hiding this comment

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

please drop random debug-code


- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
NSLog(@"FCM registration token: %@", fcmToken);
// NSLog(@"FCM registration token: %@", fcmToken);
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather delete than comment out, please

@{Firebase.Notifications.NotificationModule.OnRegistrationSucceedediOS(string):Call(fcmToken)};
- (void)messaging:(nonnull FIRMessaging *)messaging
didReceiveMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage{
// NSLog(@"Received data message: %@", remoteMessage.appData);
Copy link
Contributor

Choose a reason for hiding this comment

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

Please don't add commented out code

// NSLog(@"Received data message: %@", remoteMessage.appData);
}
/*
TODO: Not fired but it should be fired !
Copy link
Contributor

Choose a reason for hiding this comment

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

What implication does this TODO have? Does the code work?

FireNotificationCallbacks* fireCB = [[FireNotificationCallbacks alloc] init];
@{_iosDelegate:Set(fireCB)};
[FIRMessaging messaging].delegate = (id<FIRMessagingDelegate>)fireCB;
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

please don't add commented out code

@devadiab
Copy link
Author

devadiab commented Aug 2, 2018

Lol, I'm just busy a bit, i have fixed most of those review points. I need some extra time ;)

@LuisRodriguezLD
Copy link
Member

I closed it by mistake, sorry. I am actually testing this right now 👍

@devadiab
Copy link
Author

devadiab commented Aug 2, 2018

It have some issues, i have to send a commit soon so you can test !

@LuisRodriguezLD
Copy link
Member

Yeah, notifications are complicated. I'll try to make it work

@devadiab devadiab force-pushed the upgrade-FCM-iOS branch 7 times, most recently from bfccaac to 54e8c85 Compare August 8, 2018 05:13
kusma
kusma previously requested changes Aug 8, 2018
Copy link
Contributor

@kusma kusma left a comment

Choose a reason for hiding this comment

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

Only minor complaints, looking pretty good!

I wouldn't mind a litte blit more explanation in the commit message, and maybe factor out some stuff like code-moving to a separate commit, so it's easier to follow?

{
android.net.Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
notificationBuilder.setSound(defaultSoundUri);
notificationBuilder .setSound(defaultSoundUri);
Copy link
Contributor

Choose a reason for hiding this comment

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

Please don't add spaces link this. There's more of this below...

x(null, message);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

While I'm not a fan of these braces in the first place, could pure code-style changes like this be done as a separate PR?

Copy link
Author

Choose a reason for hiding this comment

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

I don't understand this !

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm trying to say that removing the braces, even if it's a nice cleanup, is out of scope for this PR. It makes it harder to read what the change is about, and if we need to revert the intended change for some reason, we'd lose the cleanup,

Copy link
Contributor

Choose a reason for hiding this comment

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

Same as below, I don't feel strongly about this, and I'd be fine with landing this as-is also, to get things working on Android 8.

if( jsonStr != "{}")
{
@{OnRecieve(string,bool):Call(jsonStr, false)};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like a change that could be factored out into it's own commit with an explanation in the commit message. It looks very reasonable IMO, but I'd love to hear why :)

Copy link
Author

Choose a reason for hiding this comment

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

I really didn't what you need to know really, but this code snippet handle the following case :
To distignuesh between Normal app open and Open from notification tray, because of we are listening android.intent.action.MAIN due to Android 8+ app start new policy.
The android.intent.action.MAIN filter catch each app start, while the getIntent() on java provides me the data that attached with app launch. Normal open holds nothing while the open from Notification tray holds the notification data ;)
Hope this goes clear

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for explaining. If I understand correctly, you're saying that this prevents us from calling OnReceive (with empty data) when the app was started normally? If so, I think it would be nice to factor that out into a separate commit that explains that (in the commit message), so future generations will understand what's going on.

I'm not feeling very strongly about this, though. If it's a huge hassle, we can just leave it. Perhaps add a comment? Dunno...

notificationManager.createNotificationChannel(mChannel);
}
// Android > 8 support for Channels because it not supported on previous versions
notificationBuilder = new NotificationCompat.Builder(this,channel_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

space between comma and channel_id.

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
{
NotificationChannel mChannel = notificationManager.getNotificationChannel(channel_id);
if (mChannel == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I know this project isn't completely consistent when it comes to brace-style, but it'd be nice if these two if-blocks were consistent, at least. I'm no Java expert, but whatever is idiomatic there is probably the right choice...

@LuisRodriguezLD
Copy link
Member

Now that we are getting iOS notifications ready I think is a good time to uncomment this line and this line

@kusma kusma dismissed their stale review August 9, 2018 11:04

The important stuff was dealt with

@kusma
Copy link
Contributor

kusma commented Aug 9, 2018

But, this PR now seems to conflict. Could you rebase it, so it could be merged once CI pass?

@devadiab
Copy link
Author

devadiab commented Aug 9, 2018

@kusma, those files are deleted now, can you resolve those conflicts ?

@kusma
Copy link
Contributor

kusma commented Aug 9, 2018

@devadiab: I don't know what the right resolution for these files are...

@devadiab
Copy link
Author

devadiab commented Aug 9, 2018

I have no access to resolve those conflict !

@kusma
Copy link
Contributor

kusma commented Aug 9, 2018

@devadiab: Yes, you do. You rebase your branch on master...

@devadiab
Copy link
Author

devadiab commented Aug 9, 2018

To my master or to upstream/master ?

@kusma
Copy link
Contributor

kusma commented Aug 9, 2018

@devadiab: You need to rebase onto the upstream master, yes.

@devadiab devadiab reopened this Aug 9, 2018
*/
=======

>>>>>>> iOS FCM binding & Android 8+ FCM fix issues:src/Firebase.Notifications/iOS/iOSFirebaseNotificationCallbacks.mm
Copy link
Contributor

Choose a reason for hiding this comment

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

Something went wrong here...

@cbaggers
Copy link
Collaborator

Context on Firebase.Notifications.Android: Originally I wasnt looking to support firebase notifications on ios as they seemed useless due to not being able to deliver if the app was closed or in the background. The thought was that the firebase notification support would be used in tandem with the Fuse.APNS package. I think the naming was a poor choice in hindsight so I'm glad to see this PR cleaning fixing this.

Once this is in we could probably mark *.Android as deprecated and remove it a few months later.

@cbaggers
Copy link
Collaborator

@devadiab has the APNS stuff definitely been working for you? I noticed a few things that confused me compared to the documentation.

  • the 'push notification' capability is not enabled
  • the 'Register for remote notifications' section of https://firebase.google.com/docs/cloud-messaging/ios/first-message looks rather different from our code (seems we only support the iOS 8-9 notifications. (This one might be fine, just was interesting)
  • JS.uno has this but iOSImpl has no instance state or methods. We seem to rely on Common.unos static methods to do the initialization but that will only happen the first time the class is touched (which could be quite late). The reason this matters is that below the 'Register for remote notifications' in the guide it states that:

for devices running iOS 10 and above, you must assign your delegate object to the UNUserNotificationCenter object to receive display notifications, and the FIRMessaging object to receive data messages, before your app finishes launching. For example, in an iOS app, you must assign it in the applicationWillFinishLaunching: or applicationDidFinishLaunching: method.

@cbaggers
Copy link
Collaborator

Also the callback method here is empty. IIRC this is used for data messages (which are the kind we care most about). Are the APNS messages using the AppDelegate callback instead?

@devadiab
Copy link
Author

@cbaggers, thanks for this rich feedback it covers all of my contribution ;)
About the namesapce *.Android The previous contributor added some iOS intergration on it (just supporting register iOS on Firebase and getting the token) which stimulates me to have more adaptation. The second stimuli was Android 8+ have very much problems with GCM and it should be replaced with FCM soon. Third point, Firebase can play as a broker for APNS by linking them tegother by
1- Go to Cloud messaging of you project.
2- Scroll down to iOS app configuration to be like this:

image.
3- You will be finally received notification on all app states.

About the AppDelegate callback, its already used as it coded on Fuse.PushNotification we are enabling it on UXL this.

I'd like also to improve this project as it still not official so we can use it mainly as i do ;)

@LuisRodriguezLD
Copy link
Member

Can't wait for this to be on master. What's missing? How can I help?

@kusma
Copy link
Contributor

kusma commented Aug 18, 2018

@LuisRodriguezLD: well, from a short peek, it looks like something went wrong in a rebase here. This PR used to delete rename the package from Fuse.Notifications.Android to Fuse.Notifiations, but now it seems to just add a modified copy of the code.

Unless there's an explicit "yeah, we want to keep the old code as-is for [good reasons]"-explanation (I can't see one), I'm skeptical to duplicating code.

As for the actual code, I think this PR is still way too dense. Several changes are needlessly baked into a single commit. Here's what I think would be a good way of doing this:

  • Start with a commit fixing the empty jsonStr change. Include the explanation given above in the commit message
  • Then do a commit dealing moving the FLAG_ACTIVITY_SINGLE_TOP/FLAG_UPDATE_CURRENT etc change. Explain why in the commit message. I believe the explanation exist here somewhere, but it should be in the commit message.
  • Rename the package.
  • Finally add the iOS implementation as a separate commit.

In addition, there's some thing in the code that doesn't quite look right:

  • There's still some needless white-space changes
  • channel_name, channel_id and channel_description seems to have nonsensical definitions. I think this should probably be configurable from the project file or something like that instead of hard-coded.

I also think @cbaggers's ack here would be great.

Copy link
Contributor

@kusma kusma left a comment

Choose a reason for hiding this comment

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

Here's some more direct code-review, in addition to the stuff above.

extern(Android)
static NotificationService()
{
Firebase.Core.Init();
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems to undo what @LuisRodriguezLD did in c8542d9. You guys need to decide on what the right code to initialize here is. Or make the code able to initialize correctly from multiple locations or something...

Copy link
Member

Choose a reason for hiding this comment

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

This was actually my fault. But I've done exactly that, the core now initializes the core and makes sure it does not happen twice.

_receivedNotification += value;
foreach (var n in _pendingNotifications)
{
debug_log "_pendingNotifications : "+n.Key+" fromNotificationBar:"+n.Value;
Copy link
Contributor

Choose a reason for hiding this comment

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

This probably shouldn't be left in.

public static class NotificationService
{
extern(Android)
static NotificationService()
Copy link
Contributor

Choose a reason for hiding this comment

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

Android and iOS aren't the only two platforms; removing the "Firebase Notifications are not yet available on this platform"-message here doesn't seem right. You should probably update the extern for that platform to be something like extern(!Android && !iOS).

@@ -0,0 +1,3 @@
<Extensions Backend="CPlusPlus" Condition="iOS">
<Define AppDelegate.PushNotificationMethods="1" />
</Extensions> No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

This could use a newline at the end of the file.


String channel_name = "my_package_channel";
String channel_id = "my_package_channel_1";
String channel_description = "my_package_first_channel";
Copy link
Contributor

Choose a reason for hiding this comment

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

channel_description is unused, please remove it.

@cbaggers
Copy link
Collaborator

cbaggers commented Sep 26, 2018

Sorry I've been off for a while. I have Firebase APNS working in my fork (along with topics). It includes the fixes I was talking about previously and has been tested in a soon to ship app which has been through Apple's app store review.

One big caveat is that APNS does not like data notifications, so I recommend using the new topics feature (also in my fork) to send data messages to android & notification messages to iOS. Using this we could deliver to all our devices in 2 http requests. This is a limitation that is outside of our control, apple does like data messages but our android integration requires them to provide a consistent experience.

I think I'd like to clean up my fork and make a new PR for that if it's ok with you. We could port the work over to this PR but we risk introducing bugs.

[EDIT] woops, forgot to link the branch
https://github.com/cbaggers/Fuse.Firebase/commits/feature/push-notify-topics

@cbaggers cbaggers mentioned this pull request Sep 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants