-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Implement message-type Android push notifications #4270
Conversation
@roryabraham, could you do an early review of this? Also, I think we should wait until we finish #3844 to include the room/group support in this code. |
Interesting that this has to be written in java. I'm going to defer to @roryabraham's opinion on this review, given that he's got experience in java. |
android/app/src/main/java/com/expensify/chat/CustomAirshipExtender.java
Outdated
Show resolved
Hide resolved
import androidx.annotation.NonNull; | ||
|
||
import com.urbanairship.push.NotificationActionButtonInfo; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
android/app/src/main/java/com/expensify/chat/CustomNotificationListener.java
Outdated
Show resolved
Hide resolved
// Max wait time to resolve an icon. We have ~10 seconds to a little less | ||
// to ensure the notification builds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to ensure the notification builds
What does this mean? Is there a hard limit of 10 seconds?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's related to this: https://developer.android.com/about/versions/12/behavior-changes-all#foreground-service-notification-delay
To provide a streamlined experience for short-running foreground services on Android 12, the system can delay the display of foreground service notifications by 10 seconds for certain foreground services. This change gives short-lived tasks a chance to complete before their notifications appear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Android 12 change only applies to foreground services. Regular notifications have no such limit and should always display -- unless the UA implementation is doing something very weird.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Android is happy for us to do stuff when the app is backgrounded, provided we display a long-running notification (like FB and WhatsApp 'Checking for messages...' notification). But that is very different from what we're trying to do here, which is just display a notification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this then; we should ask the UA team. Still, delaying notifications +10 seconds because we're fetching an avatar doesn't seem like a good idea even in bad network conditions.
android/app/src/main/java/com/expensify/chat/CustomNotificationProvider.java
Outdated
Show resolved
Hide resolved
|
||
@NonNull | ||
private IconCompat fetchIcon(@NonNull String urlString, @DrawableRes int fallbackId) { | ||
// TODO: Add disk LRU cache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't leave TODO's. Does this still need to be done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure, and this was one of the things that I didn't touch at all. It would be interesting to store avatar data in the disk to avoid fetching from the network every time we receive a new notification that belongs to a different person.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you remove the TODO in that case, as it sounds like it is not a priority of ours
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
android/app/src/main/java/com/expensify/chat/CustomNotificationProvider.java
Show resolved
Hide resolved
android/app/src/main/java/com/expensify/chat/CustomNotificationProvider.java
Show resolved
Hide resolved
android/app/src/main/java/com/expensify/chat/CustomNotificationProvider.java
Outdated
Show resolved
Hide resolved
android/app/src/main/java/com/expensify/chat/CustomNotificationProvider.java
Outdated
Show resolved
Hide resolved
android/app/src/main/java/com/expensify/chat/CustomNotificationProvider.java
Outdated
Show resolved
Hide resolved
android/app/src/main/java/com/expensify/chat/CustomNotificationProvider.java
Show resolved
Hide resolved
|
||
if (parsedUrl != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe return early instead, if parsedURl is null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
Log.e(TAG,"Failed to fetch icon", e); | ||
Thread.currentThread().interrupt(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No idea. I copied this function from a Gist that Urban Airship provided us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking better, but these comments remain unsolved:
- This thread
- This thread has a few
issues
My main worry is that we seem to be using a long-running service in order to style notifications based on your comments, which seems very wrong IMO. Notifications should fire once, there is no need to depend on a long-running background service to display notifications as this will definitely get killed by the OS and stop working.
To test this, I built the branch as a release build (compiled JS instead of depending on Chrome) using these steps (letting us background/kill the app as works in production) and I was unable to get one notification to show up. I wonder if you see the same thing when following these steps?
android.background.notification.styling.mov
Regarding the long-running service, no, sorry if I didn't explain myself. The service only gets to run when a new notification arrives. That's why I mentioned the need for persistence. So, in this case, we don't need to worry about having a long running service. I've run into the same issue while testing; sometimes, I've needed to replace this line in Web-Expensify https://github.com/Expensify/Web-Expensify/blob/4e4da7aa858b7cb2eecb0a2bbd8409beaa815203/partners/UrbanAirship/push.php#L29 with: $isInChannel = false; I'm not sure if it is a bug in the app, but I assumed it only happened in dev as I haven't run into the same issue in prod. |
Okay, thanks for clarifying (and sorry for the slow response). I'm still wary of the service though as other Urban Airship RN implementations used an out-of-date method of handling services which is directly responsible for our current problem where notifications are not immediately received. If they simply extend from Each service leads to background processing which will decrease the frequency of future notifications and consume users' battery, so we need be sure that this the only way to achieve styled notifications in a React Native app and that any unnecessary processing on the user's device is avoided. We already consume way more battery in comparison to similar native apps, so we really need to be careful here IMO. I tried looking for the UA docs for this styled notification feature but wasn't able to find it, would you mind sharing the link? Maybe that will help me to understand why they solved the problem in this way. |
I found the UA RN docs and looked into the ReactNative codebase -- but it doesn't look like we have a choice, after all 😞 It seems that React native is limited to using the old Services, which the OS will happily throttle. Given that almost all of my comments have been resolved I'll run the tests again on Monday to see if I can get the notifications to show 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The notifications are looking good, here are a few small things I noticed:
- I saw one notification icon for each unique chat, rather than one grouped notification with a single icon (NAB, we can fix this later)
- Notification deep links are not working as expected. I think this is because we're a bit behind
main
now. Would you mind merging master so I can test this again, please? - I'm seeing some native exceptions related to the image library, but as the Expensify logo is generated it doesn't seem too critical 🤷♂️
Rejecting re-init on previously-failed class java.lang.Class<com.urbanairship.util.ImageUtils$2$1>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/graphics/ImageDecoder$OnHeaderDecodedListener;
I/zygote64: at android.graphics.Bitmap com.urbanairship.util.ImageUtils.fetchScaledBitmap(android.content.Context, java.net.URL, int, int) (ImageUtils.java:112)
I/zygote64: at android.graphics.Bitmap com.expensify.chat.CustomNotificationProvider.lambda$fetchIcon$0$CustomNotificationProvider(java.net.URL, int, int) (CustomNotificationProvider.java:207)
I/zygote64: at java.lang.Object com.expensify.chat.-$$Lambda$CustomNotificationProvider$QwNE5Q7oUthdUtGtsD4dsFZ4bkc.call() (lambda:-1)
I/zygote64: at void java.util.concurrent.FutureTask.run() (FutureTask.java:266)
I/zygote64: at void java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) (ThreadPoolExecutor.java:1162)
I/zygote64: at void java.util.concurrent.ThreadPoolExecutor$Worker.run() (ThreadPoolExecutor.java:636)
I/zygote64: at void java.lang.Thread.run() (Thread.java:764)
|
Thanks for merging main. No problem, we can make that grouped notification change later. I have only ever seen the small Expensify logo when while testing the feature, was I supposed to see user avatars? it might be that whatever image solution UA are using just isn't supported on Android 8 though. Unfortunately, I see a regression since the |
I haven't been able to reproduce that. Did you change this in Web-Expensify? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay here!
Looking good now when building a release build and enabling the manual $isInChannel
override. I still don't see the fully styled notifications, but this isn't worth blocking the PR. I'll create another issue to investigate whether this is expected for Android 8.1.
Holding for n6 |
Merging as the hold is over |
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to staging by @Julesssss in version: 1.1.8-10 🚀
|
🚀 Deployed to production by @roryabraham in version: 1.1.10-2 🚀
|
To note: This PR I think introduced a bug that we didn't notice for 1.5 years, that the roomName in the notifications had a double hashtag because it was being added on both the backend and the frontend. In the future we should I guess make sure that we're not replicating behavior (unless it's on purpose) on both ends. If I'm wrong about where that bug came from, reviewers let me know! |
Details
Fixed Issues
$ #4007
Tests/QA Steps
Tested On
Screenshots
Android 10
Note that this video is recorded in Android 10. If you try to test this in a different Android version, the appearance of the notifications may vary.
Screencast_00002.mp4