Skip to content

feat(fcm): Support proxy field in FCM AndroidNotification #868

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 3 commits into from
Mar 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion firebase_admin/_messaging_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,9 @@ def encode_android_notification(cls, notification):
'visibility': _Validators.check_string(
'AndroidNotification.visibility', notification.visibility, non_empty=True),
'notification_count': _Validators.check_number(
'AndroidNotification.notification_count', notification.notification_count)
'AndroidNotification.notification_count', notification.notification_count),
'proxy': _Validators.check_string(
'AndroidNotification.proxy', notification.proxy, non_empty=True)
}
result = cls.remove_null_values(result)
color = result.get('color')
Expand Down Expand Up @@ -363,6 +365,13 @@ def encode_android_notification(cls, notification):
'AndroidNotification.vibrate_timings_millis', msec)
vibrate_timing_strings.append(formated_string)
result['vibrate_timings'] = vibrate_timing_strings

proxy = result.get('proxy')
if proxy:
if proxy not in ('allow', 'deny', 'if_priority_lowered'):
raise ValueError(
'AndroidNotification.proxy must be "allow", "deny" or "if_priority_lowered".')
result['proxy'] = proxy.upper()
return result

@classmethod
Expand Down
10 changes: 8 additions & 2 deletions firebase_admin/_messaging_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,18 @@ class AndroidNotification:
If ``default_light_settings`` is set to ``True`` and ``light_settings`` is also set, the
user-specified ``light_settings`` is used instead of the default value.
visibility: Sets the visibility of the notification. Must be either ``private``, ``public``,
or ``secret``. If unspecified, default to ``private``.
or ``secret``. If unspecified, it remains undefined in the Admin SDK, and defers to
the FCM backend's default mapping.
notification_count: Sets the number of items this notification represents. May be displayed
as a badge count for Launchers that support badging. See ``NotificationBadge``
https://developer.android.com/training/notify-user/badges. For example, this might be
useful if you're using just one notification to represent multiple new messages but you
want the count here to represent the number of total new messages. If zero or
unspecified, systems that support badging use the default, which is to increment a
number displayed on the long-press menu each time a new notification arrives.
proxy: Sets if the notification may be proxied. Must be one of ``allow``, ``deny``, or
``if_priority_lowered``. If unspecified, it remains undefined in the Admin SDK, and
defers to the FCM backend's default mapping.


"""
Expand All @@ -154,7 +158,8 @@ def __init__(self, title=None, body=None, icon=None, color=None, sound=None, tag
title_loc_args=None, channel_id=None, image=None, ticker=None, sticky=None,
event_timestamp=None, local_only=None, priority=None, vibrate_timings_millis=None,
default_vibrate_timings=None, default_sound=None, light_settings=None,
default_light_settings=None, visibility=None, notification_count=None):
default_light_settings=None, visibility=None, notification_count=None,
proxy=None):
self.title = title
self.body = body
self.icon = icon
Expand All @@ -180,6 +185,7 @@ def __init__(self, title=None, body=None, icon=None, color=None, sound=None, tag
self.default_light_settings = default_light_settings
self.visibility = visibility
self.notification_count = notification_count
self.proxy = proxy


class LightSettings:
Expand Down
3 changes: 2 additions & 1 deletion integration/test_messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ def test_send():
light_off_duration_millis=200,
light_on_duration_millis=300
),
notification_count=1
notification_count=1,
proxy='if_priority_lowered',
)
),
apns=messaging.APNSConfig(payload=messaging.APNSPayload(
Expand Down
16 changes: 16 additions & 0 deletions tests/test_messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,20 @@ def test_invalid_visibility(self, visibility):
expected = 'AndroidNotification.visibility must be a non-empty string.'
assert str(excinfo.value) == expected

@pytest.mark.parametrize('proxy', NON_STRING_ARGS + ['foo'])
def test_invalid_proxy(self, proxy):
notification = messaging.AndroidNotification(proxy=proxy)
excinfo = self._check_notification(notification)
if isinstance(proxy, str):
if not proxy:
expected = 'AndroidNotification.proxy must be a non-empty string.'
else:
expected = ('AndroidNotification.proxy must be "allow", "deny" or'
' "if_priority_lowered".')
else:
expected = 'AndroidNotification.proxy must be a non-empty string.'
assert str(excinfo.value) == expected

@pytest.mark.parametrize('vibrate_timings', ['', 1, True, 'msec', ['500', 500], [0, 'abc']])
def test_invalid_vibrate_timings_millis(self, vibrate_timings):
notification = messaging.AndroidNotification(vibrate_timings_millis=vibrate_timings)
Expand Down Expand Up @@ -580,6 +594,7 @@ def test_android_notification(self):
light_off_duration_millis=300,
),
default_light_settings=False, visibility='public', notification_count=1,
proxy='if_priority_lowered',
)
)
)
Expand Down Expand Up @@ -620,6 +635,7 @@ def test_android_notification(self):
'default_light_settings': False,
'visibility': 'PUBLIC',
'notification_count': 1,
'proxy': 'IF_PRIORITY_LOWERED'
},
},
}
Expand Down