Skip to content

Commit 08a62c7

Browse files
committed
- Avoid showing notifications in Android when in foreground and priority is high or notification channel importance is set to high
- Android ShowWhen & SetWhen support - Other minor improvements
1 parent 2b2c662 commit 08a62c7

4 files changed

Lines changed: 153 additions & 33 deletions

File tree

docs/AndroidCustomization.md

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,10 @@ There are also some keys you can set on the payload:
7777
* **priority** : Sets the notification priority
7878
* **sound** : Sets the notification sound
7979
* **icon** : Sets the notification icon
80-
* **click_action** : Sets name for notification action
80+
* **large_icon** : Sets the notification large icon
81+
* **click_action** : Sets name for the notification action
8182
* **channel_id** : Sets id for the notification channel that will be used when notification is delivered
83+
* **show_when** : Indicates if the notification timestamp will be shown.
8284

8385
If **sound** or **icon** keys present have priority over the **FirebasePushNotificationManager.SoundUri** and **FirebasePushNotificationManager.IconResource** static customization properties mentioned above.
8486

@@ -215,6 +217,39 @@ Payload sample with icon and sound
215217

216218
If icon not set will set the **FirebasePushNotificationManager.IconResource** value if not set either will use the default application icon.
217219

220+
##### Notification Large Icon
221+
222+
* You can send the large_icon to be displayed on the notification by using **large_icon** key, an icon with the value set should be in your *Resources/drawable* folder.
223+
224+
Payload sample with large icon
225+
226+
```json
227+
{
228+
"data" : {
229+
"title": "hello",
230+
"body": "world",
231+
"priority":"high",
232+
"large_icon":"test"
233+
}
234+
}
235+
```
236+
237+
Payload sample with large icon and sound
238+
239+
```json
240+
{
241+
"data" : {
242+
"title": "hello",
243+
"body": "world",
244+
"priority":"high",
245+
"large_icon":"test",
246+
"sound":"test"
247+
}
248+
}
249+
```
250+
251+
If large icon not set will set the **FirebasePushNotificationManager.LargeIconResource** value.
252+
218253
##### Notification Actions
219254

220255
* For notification with actions will look for **click_action** key value as the match. More information here: [Notification Actions](NotificationActions.md)
@@ -236,5 +271,22 @@ If icon not set will set the **FirebasePushNotificationManager.IconResource** va
236271
}
237272
```
238273

274+
##### Notification Show When
275+
276+
* **show_when** key if set to false will not show the notification timestamp, otherwise will show it
277+
278+
Payload sample without timestamp
279+
280+
```json
281+
{
282+
"data" : {
283+
"title": "hello",
284+
"body": "firebase",
285+
"show_when" : "false"
286+
287+
}
288+
}
289+
```
290+
239291
<= Back to [Table of Contents](../README.md)
240292

src/Plugin.FirebasePushNotification/DefaultPushNotificationHandler.android.cs

Lines changed: 89 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Android.Content.PM;
1616
using Android.Content.Res;
1717
using Java.Util;
18+
using static Android.App.ActivityManager;
1819

1920
namespace Plugin.FirebasePushNotification
2021
{
@@ -111,6 +112,11 @@ public class DefaultPushNotificationHandler : IPushNotificationHandler
111112
/// </summary>
112113
public const string IconKey = "icon";
113114

115+
/// <summary>
116+
/// Large Icon
117+
/// </summary>
118+
public const string LargeIconKey = "large_icon";
119+
114120
/// <summary>
115121
/// Sound
116122
/// </summary>
@@ -127,6 +133,11 @@ public class DefaultPushNotificationHandler : IPushNotificationHandler
127133
/// </summary>
128134
public const string ChannelIdKey = "channel_id";
129135

136+
/// <summary>
137+
/// Show Timestamp Key
138+
/// </summary>
139+
public const string ShowWhenKey = "show_when";
140+
130141
public virtual void OnOpened(NotificationResponse response)
131142
{
132143
System.Diagnostics.Debug.WriteLine($"{DomainTag} - OnOpened");
@@ -136,7 +147,7 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
136147
{
137148
System.Diagnostics.Debug.WriteLine($"{DomainTag} - OnReceived");
138149

139-
if ((parameters.TryGetValue(SilentKey, out object silent) && (silent.ToString() == "true" || silent.ToString() == "1")))
150+
if ((parameters.TryGetValue(SilentKey, out object silent) && (silent.ToString() == "true" || silent.ToString() == "1")) || (IsInForeground() && (!(!parameters.ContainsKey(ChannelIdKey) && parameters.TryGetValue(PriorityKey, out var imp) && ($"{imp}" == "high" || $"{imp}" == "max")) || (!parameters.ContainsKey(PriorityKey) && !parameters.ContainsKey(ChannelIdKey) && FirebasePushNotificationManager.DefaultNotificationChannelImportance != NotificationImportance.High && FirebasePushNotificationManager.DefaultNotificationChannelImportance != NotificationImportance.Max))))
140151
return;
141152

142153
Context context = Application.Context;
@@ -145,6 +156,12 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
145156
string title = context.ApplicationInfo.LoadLabel(context.PackageManager);
146157
var message = string.Empty;
147158
var tag = string.Empty;
159+
var showWhenVisible = FirebasePushNotificationManager.ShouldShowWhen;
160+
var soundUri = FirebasePushNotificationManager.SoundUri;
161+
var largeIconResource = FirebasePushNotificationManager.LargeIconResource;
162+
var smallIconResource = FirebasePushNotificationManager.IconResource;
163+
var notificationColor = FirebasePushNotificationManager.Color;
164+
var chanId = FirebasePushNotificationManager.DefaultNotificationChannelId;
148165

149166
if (!string.IsNullOrEmpty(FirebasePushNotificationManager.NotificationContentTextKey) && parameters.TryGetValue(FirebasePushNotificationManager.NotificationContentTextKey, out object notificationContentText))
150167
message = notificationContentText.ToString();
@@ -182,6 +199,11 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
182199
}
183200
}
184201

202+
if (parameters.TryGetValue(ShowWhenKey, out var shouldShowWhen))
203+
{
204+
showWhenVisible = $"{shouldShowWhen}".ToLower() == "true";
205+
}
206+
185207
if (parameters.TryGetValue(TagKey, out object tagContent))
186208
tag = tagContent.ToString();
187209

@@ -198,7 +220,7 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
198220
soundResId = context.Resources.GetIdentifier(soundName, "raw", context.PackageName);
199221
}
200222

201-
FirebasePushNotificationManager.SoundUri = new Android.Net.Uri.Builder()
223+
soundUri = new Android.Net.Uri.Builder()
202224
.Scheme(ContentResolver.SchemeAndroidResource)
203225
.Path($"{context.PackageName}/{soundResId}")
204226
.Build();
@@ -213,43 +235,73 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
213235
System.Diagnostics.Debug.WriteLine(ex.ToString());
214236
}
215237

216-
if (FirebasePushNotificationManager.SoundUri == null)
217-
FirebasePushNotificationManager.SoundUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
238+
if (soundUri == null)
239+
soundUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
218240

219241
try
220242
{
221-
if (parameters.TryGetValue(IconKey, out object icon) && icon != null)
243+
if (parameters.TryGetValue(IconKey, out var icon) && icon != null)
222244
{
223245
try
224246
{
225-
FirebasePushNotificationManager.IconResource = context.Resources.GetIdentifier(icon.ToString(), "drawable", Application.Context.PackageName);
247+
smallIconResource = context.Resources.GetIdentifier(icon.ToString(), "drawable", Application.Context.PackageName);
248+
if (smallIconResource == 0)
249+
{
250+
smallIconResource = context.Resources.GetIdentifier($"{icon}", "mipmap", Application.Context.PackageName);
251+
}
226252
}
227253
catch (Resources.NotFoundException ex)
228254
{
229255
System.Diagnostics.Debug.WriteLine(ex.ToString());
230256
}
231257
}
232258

233-
if (FirebasePushNotificationManager.IconResource == 0)
234-
FirebasePushNotificationManager.IconResource = context.ApplicationInfo.Icon;
259+
if (smallIconResource == 0)
260+
smallIconResource = context.ApplicationInfo.Icon;
235261
else
236262
{
237-
string name = context.Resources.GetResourceName(FirebasePushNotificationManager.IconResource);
263+
var name = context.Resources.GetResourceName(smallIconResource);
238264
if (name == null)
239-
FirebasePushNotificationManager.IconResource = context.ApplicationInfo.Icon;
265+
{
266+
smallIconResource = context.ApplicationInfo.Icon;
267+
}
240268
}
241269
}
242270
catch (Resources.NotFoundException ex)
243271
{
244-
FirebasePushNotificationManager.IconResource = context.ApplicationInfo.Icon;
272+
smallIconResource = context.ApplicationInfo.Icon;
273+
System.Diagnostics.Debug.WriteLine(ex.ToString());
274+
}
275+
276+
try
277+
{
278+
if (parameters.TryGetValue(LargeIconKey, out object largeIcon) && largeIcon != null)
279+
{
280+
largeIconResource = context.Resources.GetIdentifier($"{largeIcon}", "drawable", Application.Context.PackageName);
281+
if (largeIconResource == 0)
282+
{
283+
largeIconResource = context.Resources.GetIdentifier($"{largeIcon}", "mipmap", Application.Context.PackageName);
284+
}
285+
}
286+
287+
if (largeIconResource > 0)
288+
{
289+
string name = context.Resources.GetResourceName(largeIconResource);
290+
if (name == null)
291+
largeIconResource = 0;
292+
}
293+
}
294+
catch (Resources.NotFoundException ex)
295+
{
296+
largeIconResource = 0;
245297
System.Diagnostics.Debug.WriteLine(ex.ToString());
246298
}
247299

248300
if (parameters.TryGetValue(ColorKey, out object color) && color != null)
249301
{
250302
try
251303
{
252-
FirebasePushNotificationManager.Color = Color.ParseColor(color.ToString());
304+
notificationColor = Color.ParseColor(color.ToString());
253305
}
254306
catch (Exception ex)
255307
{
@@ -278,30 +330,29 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
278330

279331
var pendingIntent = PendingIntent.GetActivity(context, requestCode, resultIntent, PendingIntentFlags.UpdateCurrent);
280332

281-
var chanId = FirebasePushNotificationManager.DefaultNotificationChannelId;
282-
if (parameters.TryGetValue(ChannelIdKey, out object channelId) && channelId != null)
333+
if (parameters.TryGetValue(ChannelIdKey, out var channelId) && channelId != null)
283334
{
284335
chanId = $"{channelId}";
285336
}
286337

287338
var notificationBuilder = new NotificationCompat.Builder(context,chanId)
288-
.SetSmallIcon(FirebasePushNotificationManager.IconResource)
339+
.SetSmallIcon(smallIconResource)
289340
.SetContentTitle(title)
290341
.SetContentText(message)
291342
.SetAutoCancel(true)
343+
.SetWhen(Java.Lang.JavaSystem.CurrentTimeMillis())
292344
.SetContentIntent(pendingIntent);
293345

294-
if (FirebasePushNotificationManager.LargeIconResource > 0)
346+
if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr1)
295347
{
296-
try
297-
{
298-
var largeIcon = BitmapFactory.DecodeResource(context.Resources, FirebasePushNotificationManager.LargeIconResource);
299-
notificationBuilder.SetLargeIcon(largeIcon);
300-
}
301-
catch (Exception ex)
302-
{
303-
System.Diagnostics.Debug.WriteLine(ex.ToString());
304-
}
348+
notificationBuilder.SetShowWhen(showWhenVisible);
349+
}
350+
351+
352+
if (largeIconResource > 0)
353+
{
354+
Bitmap largeIconBitmap = BitmapFactory.DecodeResource(context.Resources, largeIconResource);
355+
notificationBuilder.SetLargeIcon(largeIconBitmap);
305356
}
306357

307358
var deleteIntent = new Intent(context,typeof(PushNotificationDeletedReceiver));
@@ -356,7 +407,7 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
356407
try
357408
{
358409

359-
notificationBuilder.SetSound(FirebasePushNotificationManager.SoundUri);
410+
notificationBuilder.SetSound(soundUri);
360411
}
361412
catch (Exception ex)
362413
{
@@ -369,8 +420,8 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
369420
// Try to resolve (and apply) localized parameters
370421
ResolveLocalizedParameters(notificationBuilder, parameters);
371422

372-
if (FirebasePushNotificationManager.Color != null)
373-
notificationBuilder.SetColor(FirebasePushNotificationManager.Color.Value);
423+
if (notificationColor != null)
424+
notificationBuilder.SetColor(notificationColor.Value);
374425

375426
if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBean)
376427
{
@@ -390,7 +441,6 @@ public virtual void OnReceived(IDictionary<string, object> parameters)
390441
var notificationCategories = CrossFirebasePushNotification.Current?.GetUserNotificationCategories();
391442
if (notificationCategories != null && notificationCategories.Length > 0)
392443
{
393-
IntentFilter intentFilter = null;
394444
foreach (var userCat in notificationCategories)
395445
{
396446
if (userCat != null && userCat.Actions != null && userCat.Actions.Count > 0)
@@ -503,5 +553,15 @@ public virtual void OnError(string error)
503553
/// <param name="parameters">Notification parameters.</param>
504554
public virtual void OnBuildNotification(NotificationCompat.Builder notificationBuilder, IDictionary<string, object> parameters) { }
505555

556+
bool IsInForeground()
557+
{
558+
bool isInForeground;
559+
560+
RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
561+
ActivityManager.GetMyMemoryState(myProcess);
562+
isInForeground = myProcess.Importance == Android.App.Importance.Foreground;
563+
564+
return isInForeground;
565+
}
506566
}
507567
}

src/Plugin.FirebasePushNotification/FirebasePushNotificationManager.android.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class FirebasePushNotificationManager : Java.Lang.Object, IFirebasePushNo
3838
public static string NotificationContentDataKey { get; set; }
3939
public static int IconResource { get; set; }
4040
public static int LargeIconResource { get; set; }
41+
public static bool ShouldShowWhen { get; set; } = true;
4142
public static Android.Net.Uri SoundUri { get; set; }
4243
public static Color? Color { get; set; }
4344
public static Type NotificationActivityType { get; set; }

src/Plugin.FirebasePushNotification/Plugin.FirebasePushNotification.csproj

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
<PackageIconUrl>https://github.com/CrossGeeks/FirebasePushNotificationPlugin/blob/master/art/icon.png?raw=true</PackageIconUrl>
2626
<RepositoryUrl>https://github.com/CrossGeeks/FirebasePushNotificationPlugin</RepositoryUrl>
2727
<PackageTags>iOS,Android,firebase,push notifications,cloud messaging,xamarin,plugins</PackageTags>
28-
<PackageReleaseNotes>Android token registration error handling</PackageReleaseNotes>
28+
<PackageReleaseNotes>
29+
- Avoid showing notifications in Android when in foreground and priority is high or notification channel importance is set to high
30+
- Android ShowWhen & SetWhen support
31+
</PackageReleaseNotes>
2932
<Title>Firebase Push Notification Plugin for Xamarin iOS and Android</Title>
3033
<Summary>Receive and handle firebase push notifications across Xamarin.iOS and Xamarin.Android</Summary>
3134
<Description>Receive and handle firebase push notifications across Xamarin.iOS and Xamarin.Android</Description>
@@ -62,14 +65,18 @@
6265
<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.iOS')) ">
6366
<Compile Include="**\*.ios.cs" />
6467
<Compile Include="**\*.ios.*.cs" />
65-
<PackageReference Include="Xamarin.Firebase.iOS.CloudMessaging" Version="4.1.1.1" />
66-
<PackageReference Include="Xamarin.Firebase.iOS.InstanceID" Version="4.2.1" />
68+
<PackageReference Include="Xamarin.Firebase.iOS.CloudMessaging" Version="4.1.1.2" />
69+
<PackageReference Include="Xamarin.Firebase.iOS.Core" Version="6.6.0" />
70+
<PackageReference Include="Xamarin.Firebase.iOS.InstanceID" Version="4.3.0" />
6771
</ItemGroup>
6872

6973
<ItemGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid')) ">
7074
<Compile Include="**\*.android.cs" />
7175
<Compile Include="**\*.android.*.cs" />
76+
<PackageReference Include="Xamarin.Firebase.Common" Version="[71.1610.0, 72)" />
7277
<PackageReference Include="Xamarin.Firebase.Messaging" Version="[71.1740.0, 72)" />
78+
<PackageReference Include="Xamarin.GooglePlayServices.Basement" Version="[71.1620.0, 72)" />
79+
<PackageReference Include="Xamarin.GooglePlayServices.Tasks" Version="[71.1601.0, 72)" />
7380
</ItemGroup>
7481
<Import Project="$(MSBuildSDKExtrasTargets)" Condition="Exists('$(MSBuildSDKExtrasTargets)')" />
7582
</Project>

0 commit comments

Comments
 (0)