Skip to content

Commit 31ef1cc

Browse files
authored
Add scheduled notifications example. (xamarin#679)
1 parent 82b9083 commit 31ef1cc

File tree

10 files changed

+124
-39
lines changed

10 files changed

+124
-39
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Android.Content;
2+
3+
namespace LocalNotifications.Droid
4+
{
5+
[BroadcastReceiver(Enabled = true, Label = "Local Notifications Broadcast Receiver")]
6+
public class AlarmHandler : BroadcastReceiver
7+
{
8+
public override void OnReceive(Context context, Intent intent)
9+
{
10+
if (intent?.Extras != null)
11+
{
12+
string title = intent.GetStringExtra(AndroidNotificationManager.TitleKey);
13+
string message = intent.GetStringExtra(AndroidNotificationManager.MessageKey);
14+
15+
AndroidNotificationManager.Instance.Show(title, message);
16+
}
17+
}
18+
}
19+
}

LocalNotifications/LocalNotifications/LocalNotifications.Android/AndroidNotificationManager.cs

+46-13
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,33 @@ public class AndroidNotificationManager : INotificationManager
1515
const string channelId = "default";
1616
const string channelName = "Default";
1717
const string channelDescription = "The default channel for notifications.";
18-
const int pendingIntentId = 0;
1918

2019
public const string TitleKey = "title";
2120
public const string MessageKey = "message";
2221

2322
bool channelInitialized = false;
24-
int messageId = -1;
23+
int messageId = 0;
24+
int pendingIntentId = 0;
25+
2526
NotificationManager manager;
2627

2728
public event EventHandler NotificationReceived;
2829

30+
public static AndroidNotificationManager Instance { get; private set; }
31+
2932
public void Initialize()
3033
{
3134
CreateNotificationChannel();
35+
Instance = this;
3236
}
3337

34-
public int ScheduleNotification(string title, string message)
38+
public void Show(string title, string message)
3539
{
36-
if (!channelInitialized)
37-
{
38-
CreateNotificationChannel();
39-
}
40-
41-
messageId++;
42-
4340
Intent intent = new Intent(AndroidApp.Context, typeof(MainActivity));
4441
intent.PutExtra(TitleKey, title);
4542
intent.PutExtra(MessageKey, message);
4643

47-
PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId, intent, PendingIntentFlags.OneShot);
44+
PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId++, intent, PendingIntentFlags.UpdateCurrent);
4845

4946
NotificationCompat.Builder builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
5047
.SetContentIntent(pendingIntent)
@@ -55,9 +52,31 @@ public int ScheduleNotification(string title, string message)
5552
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);
5653

5754
Notification notification = builder.Build();
58-
manager.Notify(messageId, notification);
55+
manager.Notify(messageId++, notification);
56+
}
5957

60-
return messageId;
58+
public void SendNotification(string title, string message, DateTime? notifyTime = null)
59+
{
60+
if (!channelInitialized)
61+
{
62+
CreateNotificationChannel();
63+
}
64+
65+
if (notifyTime != null)
66+
{
67+
Intent intent = new Intent(AndroidApp.Context, typeof(AlarmHandler));
68+
intent.PutExtra(TitleKey, title);
69+
intent.PutExtra(MessageKey, message);
70+
71+
PendingIntent pendingIntent = PendingIntent.GetBroadcast(AndroidApp.Context, pendingIntentId++, intent, PendingIntentFlags.CancelCurrent);
72+
long triggerTime = GetNotifyTime(notifyTime.Value);
73+
AlarmManager alarmManager = GetAlarmManager();
74+
alarmManager.Set(AlarmType.RtcWakeup, triggerTime, pendingIntent);
75+
}
76+
else
77+
{
78+
Show(title, message);
79+
}
6180
}
6281

6382
public void ReceiveNotification(string title, string message)
@@ -86,5 +105,19 @@ void CreateNotificationChannel()
86105

87106
channelInitialized = true;
88107
}
108+
109+
AlarmManager GetAlarmManager()
110+
{
111+
AlarmManager alarmManager = Android.App.Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
112+
return alarmManager;
113+
}
114+
115+
long GetNotifyTime(DateTime notifyTime)
116+
{
117+
DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(notifyTime);
118+
double epochDiff = (new DateTime(1970, 1, 1) - DateTime.MinValue).TotalSeconds;
119+
long utcAlarmTime = utcTime.AddSeconds(-epochDiff).Ticks / 10000;
120+
return utcAlarmTime; // milliseconds
121+
}
89122
}
90123
}

LocalNotifications/LocalNotifications/LocalNotifications.Android/LocalNotifications.Android.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
1616
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
1717
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
18-
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
1918
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
2019
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
2120
<AndroidUseAapt2>true</AndroidUseAapt2>
@@ -60,6 +59,7 @@
6059
<Compile Include="MainActivity.cs" />
6160
<Compile Include="Resources\Resource.designer.cs" />
6261
<Compile Include="Properties\AssemblyInfo.cs" />
62+
<Compile Include="AlarmHandler.cs" />
6363
</ItemGroup>
6464
<ItemGroup>
6565
<None Include="Resources\AboutResources.txt" />
@@ -87,7 +87,7 @@
8787
<ItemGroup />
8888
<ItemGroup>
8989
<ProjectReference Include="..\LocalNotifications\LocalNotifications.csproj">
90-
<Project>{48AB845E-F987-41F0-B81A-1C178087A374}</Project>
90+
<Project>{A7BE66D7-177D-4188-87A1-E6948B3D1C7C}</Project>
9191
<Name>LocalNotifications</Name>
9292
</ProjectReference>
9393
</ItemGroup>

LocalNotifications/LocalNotifications/LocalNotifications.Android/MainActivity.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ void CreateNotificationFromIntent(Intent intent)
3636
{
3737
if (intent?.Extras != null)
3838
{
39-
string title = intent.Extras.GetString(AndroidNotificationManager.TitleKey);
40-
string message = intent.Extras.GetString(AndroidNotificationManager.MessageKey);
39+
string title = intent.GetStringExtra(AndroidNotificationManager.TitleKey);
40+
string message = intent.GetStringExtra(AndroidNotificationManager.MessageKey);
4141

4242
DependencyService.Get<INotificationManager>().ReceiveNotification(title, message);
4343
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.localnotifications">
3-
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
4-
<application android:label="LocalNotifications.Android"></application>
5-
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
3+
<uses-sdk android:minSdkVersion="21" />
4+
<application android:label="LocalNotifications.Android"></application>
5+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
66
</manifest>

LocalNotifications/LocalNotifications/LocalNotifications.iOS/iOSNotificationManager.cs

+30-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using Foundation;
23
using UserNotifications;
34
using Xamarin.Forms;
45

@@ -7,7 +8,7 @@ namespace LocalNotifications.iOS
78
{
89
public class iOSNotificationManager : INotificationManager
910
{
10-
int messageId = -1;
11+
int messageId = 0;
1112

1213
bool hasNotificationsPermission;
1314

@@ -22,12 +23,12 @@ public void Initialize()
2223
});
2324
}
2425

25-
public int ScheduleNotification(string title, string message)
26+
public void SendNotification(string title, string message, DateTime? notifyTime = null)
2627
{
2728
// EARLY OUT: app doesn't have permissions
28-
if(!hasNotificationsPermission)
29+
if (!hasNotificationsPermission)
2930
{
30-
return -1;
31+
return;
3132
}
3233

3334
messageId++;
@@ -38,11 +39,19 @@ public int ScheduleNotification(string title, string message)
3839
Subtitle = "",
3940
Body = message,
4041
Badge = 1
41-
};
42+
};
4243

43-
// Local notifications can be time or location based
44-
// Create a time-based trigger, interval is in seconds and must be greater than 0
45-
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.25, false);
44+
UNNotificationTrigger trigger;
45+
if (notifyTime != null)
46+
{
47+
// Create a calendar-based trigger.
48+
trigger = UNCalendarNotificationTrigger.CreateTrigger(GetNSDateComponents(notifyTime.Value), false);
49+
}
50+
else
51+
{
52+
// Create a time-based trigger, interval is in seconds and must be greater than 0.
53+
trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.25, false);
54+
}
4655

4756
var request = UNNotificationRequest.FromIdentifier(messageId.ToString(), content, trigger);
4857
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
@@ -52,8 +61,6 @@ public int ScheduleNotification(string title, string message)
5261
throw new Exception($"Failed to schedule notification: {err}");
5362
}
5463
});
55-
56-
return messageId;
5764
}
5865

5966
public void ReceiveNotification(string title, string message)
@@ -65,5 +72,18 @@ public void ReceiveNotification(string title, string message)
6572
};
6673
NotificationReceived?.Invoke(null, args);
6774
}
75+
76+
NSDateComponents GetNSDateComponents(DateTime dateTime)
77+
{
78+
return new NSDateComponents
79+
{
80+
Month = dateTime.Month,
81+
Day = dateTime.Day,
82+
Year = dateTime.Year,
83+
Hour = dateTime.Hour,
84+
Minute = dateTime.Minute,
85+
Second = dateTime.Second
86+
};
87+
}
6888
}
6989
}

LocalNotifications/LocalNotifications/LocalNotifications/App.xaml.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public App()
88
{
99
InitializeComponent();
1010

11-
// use the dependency service to get a platform-specific implementation and initialize it
11+
// Use the dependency service to get a platform-specific implementation and initialize it.
1212
DependencyService.Get<INotificationManager>().Initialize();
1313

1414
MainPage = new MainPage();

LocalNotifications/LocalNotifications/LocalNotifications/INotificationManager.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ namespace LocalNotifications
55
public interface INotificationManager
66
{
77
event EventHandler NotificationReceived;
8-
98
void Initialize();
10-
11-
int ScheduleNotification(string title, string message);
12-
9+
void SendNotification(string title, string message, DateTime? notifyTime = null);
1310
void ReceiveNotification(string title, string message);
1411
}
1512
}

LocalNotifications/LocalNotifications/LocalNotifications/MainPage.xaml

+10-2
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,21 @@
99
Padding="10">
1010
<StackLayout Margin="0,35,0,0"
1111
x:Name="stackLayout">
12-
<Label Text="Click the button to create a local notification."
12+
<Label Text="Click the button below to create a local notification."
1313
TextColor="Red"
1414
HorizontalOptions="Center"
1515
VerticalOptions="Start" />
1616
<Button Text="Create Notification"
1717
HorizontalOptions="Center"
1818
VerticalOptions="Start"
19-
Clicked="OnScheduleClick"/>
19+
Clicked="OnSendClick" />
20+
<Label Text="Click the button below to schedule a local notification for in 10 seconds time."
21+
TextColor="Red"
22+
HorizontalOptions="Center"
23+
VerticalOptions="Start" />
24+
<Button Text="Create Notification"
25+
HorizontalOptions="Center"
26+
VerticalOptions="Start"
27+
Clicked="OnScheduleClick" />
2028
</StackLayout>
2129
</ContentPage>

LocalNotifications/LocalNotifications/LocalNotifications/MainPage.xaml.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,20 @@ public MainPage()
2020
};
2121
}
2222

23+
void OnSendClick(object sender, EventArgs e)
24+
{
25+
notificationNumber++;
26+
string title = $"Local Notification #{notificationNumber}";
27+
string message = $"You have now received {notificationNumber} notifications!";
28+
notificationManager.SendNotification(title, message);
29+
}
30+
2331
void OnScheduleClick(object sender, EventArgs e)
2432
{
2533
notificationNumber++;
2634
string title = $"Local Notification #{notificationNumber}";
2735
string message = $"You have now received {notificationNumber} notifications!";
28-
notificationManager.ScheduleNotification(title, message);
36+
notificationManager.SendNotification(title, message, DateTime.Now.AddSeconds(10));
2937
}
3038

3139
void ShowNotification(string title, string message)

0 commit comments

Comments
 (0)