Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Commit

Permalink
Add scheduled notifications example. (#679)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbritch committed Dec 3, 2020
1 parent 82b9083 commit 31ef1cc
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 39 deletions.
@@ -0,0 +1,19 @@
using Android.Content;

namespace LocalNotifications.Droid
{
[BroadcastReceiver(Enabled = true, Label = "Local Notifications Broadcast Receiver")]
public class AlarmHandler : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent?.Extras != null)
{
string title = intent.GetStringExtra(AndroidNotificationManager.TitleKey);
string message = intent.GetStringExtra(AndroidNotificationManager.MessageKey);

AndroidNotificationManager.Instance.Show(title, message);
}
}
}
}
Expand Up @@ -15,36 +15,33 @@ public class AndroidNotificationManager : INotificationManager
const string channelId = "default";
const string channelName = "Default";
const string channelDescription = "The default channel for notifications.";
const int pendingIntentId = 0;

public const string TitleKey = "title";
public const string MessageKey = "message";

bool channelInitialized = false;
int messageId = -1;
int messageId = 0;
int pendingIntentId = 0;

NotificationManager manager;

public event EventHandler NotificationReceived;

public static AndroidNotificationManager Instance { get; private set; }

public void Initialize()
{
CreateNotificationChannel();
Instance = this;
}

public int ScheduleNotification(string title, string message)
public void Show(string title, string message)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}

messageId++;

Intent intent = new Intent(AndroidApp.Context, typeof(MainActivity));
intent.PutExtra(TitleKey, title);
intent.PutExtra(MessageKey, message);

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

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

Notification notification = builder.Build();
manager.Notify(messageId, notification);
manager.Notify(messageId++, notification);
}

return messageId;
public void SendNotification(string title, string message, DateTime? notifyTime = null)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}

if (notifyTime != null)
{
Intent intent = new Intent(AndroidApp.Context, typeof(AlarmHandler));
intent.PutExtra(TitleKey, title);
intent.PutExtra(MessageKey, message);

PendingIntent pendingIntent = PendingIntent.GetBroadcast(AndroidApp.Context, pendingIntentId++, intent, PendingIntentFlags.CancelCurrent);
long triggerTime = GetNotifyTime(notifyTime.Value);
AlarmManager alarmManager = GetAlarmManager();
alarmManager.Set(AlarmType.RtcWakeup, triggerTime, pendingIntent);
}
else
{
Show(title, message);
}
}

public void ReceiveNotification(string title, string message)
Expand Down Expand Up @@ -86,5 +105,19 @@ void CreateNotificationChannel()

channelInitialized = true;
}

AlarmManager GetAlarmManager()
{
AlarmManager alarmManager = Android.App.Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
return alarmManager;
}

long GetNotifyTime(DateTime notifyTime)
{
DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(notifyTime);
double epochDiff = (new DateTime(1970, 1, 1) - DateTime.MinValue).TotalSeconds;
long utcAlarmTime = utcTime.AddSeconds(-epochDiff).Ticks / 10000;
return utcAlarmTime; // milliseconds
}
}
}
Expand Up @@ -15,7 +15,6 @@
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
<AndroidUseAapt2>true</AndroidUseAapt2>
Expand Down Expand Up @@ -60,6 +59,7 @@
<Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="AlarmHandler.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\AboutResources.txt" />
Expand Down Expand Up @@ -87,7 +87,7 @@
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\LocalNotifications\LocalNotifications.csproj">
<Project>{48AB845E-F987-41F0-B81A-1C178087A374}</Project>
<Project>{A7BE66D7-177D-4188-87A1-E6948B3D1C7C}</Project>
<Name>LocalNotifications</Name>
</ProjectReference>
</ItemGroup>
Expand Down
Expand Up @@ -36,8 +36,8 @@ void CreateNotificationFromIntent(Intent intent)
{
if (intent?.Extras != null)
{
string title = intent.Extras.GetString(AndroidNotificationManager.TitleKey);
string message = intent.Extras.GetString(AndroidNotificationManager.MessageKey);
string title = intent.GetStringExtra(AndroidNotificationManager.TitleKey);
string message = intent.GetStringExtra(AndroidNotificationManager.MessageKey);

DependencyService.Get<INotificationManager>().ReceiveNotification(title, message);
}
Expand Down
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.localnotifications">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:label="LocalNotifications.Android"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-sdk android:minSdkVersion="21" />
<application android:label="LocalNotifications.Android"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
@@ -1,4 +1,5 @@
using System;
using Foundation;
using UserNotifications;
using Xamarin.Forms;

Expand All @@ -7,7 +8,7 @@ namespace LocalNotifications.iOS
{
public class iOSNotificationManager : INotificationManager
{
int messageId = -1;
int messageId = 0;

bool hasNotificationsPermission;

Expand All @@ -22,12 +23,12 @@ public void Initialize()
});
}

public int ScheduleNotification(string title, string message)
public void SendNotification(string title, string message, DateTime? notifyTime = null)
{
// EARLY OUT: app doesn't have permissions
if(!hasNotificationsPermission)
if (!hasNotificationsPermission)
{
return -1;
return;
}

messageId++;
Expand All @@ -38,11 +39,19 @@ public int ScheduleNotification(string title, string message)
Subtitle = "",
Body = message,
Badge = 1
};
};

// Local notifications can be time or location based
// Create a time-based trigger, interval is in seconds and must be greater than 0
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.25, false);
UNNotificationTrigger trigger;
if (notifyTime != null)
{
// Create a calendar-based trigger.
trigger = UNCalendarNotificationTrigger.CreateTrigger(GetNSDateComponents(notifyTime.Value), false);
}
else
{
// Create a time-based trigger, interval is in seconds and must be greater than 0.
trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.25, false);
}

var request = UNNotificationRequest.FromIdentifier(messageId.ToString(), content, trigger);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
Expand All @@ -52,8 +61,6 @@ public int ScheduleNotification(string title, string message)
throw new Exception($"Failed to schedule notification: {err}");
}
});

return messageId;
}

public void ReceiveNotification(string title, string message)
Expand All @@ -65,5 +72,18 @@ public void ReceiveNotification(string title, string message)
};
NotificationReceived?.Invoke(null, args);
}

NSDateComponents GetNSDateComponents(DateTime dateTime)
{
return new NSDateComponents
{
Month = dateTime.Month,
Day = dateTime.Day,
Year = dateTime.Year,
Hour = dateTime.Hour,
Minute = dateTime.Minute,
Second = dateTime.Second
};
}
}
}
Expand Up @@ -8,7 +8,7 @@ public App()
{
InitializeComponent();

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

MainPage = new MainPage();
Expand Down
Expand Up @@ -5,11 +5,8 @@ namespace LocalNotifications
public interface INotificationManager
{
event EventHandler NotificationReceived;

void Initialize();

int ScheduleNotification(string title, string message);

void SendNotification(string title, string message, DateTime? notifyTime = null);
void ReceiveNotification(string title, string message);
}
}
Expand Up @@ -9,13 +9,21 @@
Padding="10">
<StackLayout Margin="0,35,0,0"
x:Name="stackLayout">
<Label Text="Click the button to create a local notification."
<Label Text="Click the button below to create a local notification."
TextColor="Red"
HorizontalOptions="Center"
VerticalOptions="Start" />
<Button Text="Create Notification"
HorizontalOptions="Center"
VerticalOptions="Start"
Clicked="OnScheduleClick"/>
Clicked="OnSendClick" />
<Label Text="Click the button below to schedule a local notification for in 10 seconds time."
TextColor="Red"
HorizontalOptions="Center"
VerticalOptions="Start" />
<Button Text="Create Notification"
HorizontalOptions="Center"
VerticalOptions="Start"
Clicked="OnScheduleClick" />
</StackLayout>
</ContentPage>
Expand Up @@ -20,12 +20,20 @@ public MainPage()
};
}

void OnSendClick(object sender, EventArgs e)
{
notificationNumber++;
string title = $"Local Notification #{notificationNumber}";
string message = $"You have now received {notificationNumber} notifications!";
notificationManager.SendNotification(title, message);
}

void OnScheduleClick(object sender, EventArgs e)
{
notificationNumber++;
string title = $"Local Notification #{notificationNumber}";
string message = $"You have now received {notificationNumber} notifications!";
notificationManager.ScheduleNotification(title, message);
notificationManager.SendNotification(title, message, DateTime.Now.AddSeconds(10));
}

void ShowNotification(string title, string message)
Expand Down

0 comments on commit 31ef1cc

Please sign in to comment.