Xamarin – Local notification for Android (1)

Create a local notification

How to build local notification for Android?

  • Create a notification channel by NotificationManager
  • Create an Activity intent
    • Add title, message,..
  • Create a PendingIntent for the above Activity intent
  • Create a NotificationCompat.Builder
  • Send notification by NotificationManager
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Create a notification channel by NotificationManager
private void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
NotificationImportance importance = NotificationImportance.High;
NotificationChannel notificationChannel = new NotificationChannel(mChannelId, mChannelName, importance)
{
Description = mChannelDescription
};
notificationChannel.EnableLights(true);
notificationChannel.EnableVibration(true);
notificationChannel.SetShowBadge(true);
notificationChannel.Importance = NotificationImportance.High;
notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
if (mManager != null)
{
mManager.CreateNotificationChannel(notificationChannel);
}
}
}
// Create a notification channel by NotificationManager private void CreateNotificationChannel() { if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { NotificationImportance importance = NotificationImportance.High; NotificationChannel notificationChannel = new NotificationChannel(mChannelId, mChannelName, importance) { Description = mChannelDescription }; notificationChannel.EnableLights(true); notificationChannel.EnableVibration(true); notificationChannel.SetShowBadge(true); notificationChannel.Importance = NotificationImportance.High; notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 }); if (mManager != null) { mManager.CreateNotificationChannel(notificationChannel); } } }
// Create a notification channel by NotificationManager
private void CreateNotificationChannel()
{
    if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
    {
        NotificationImportance importance = NotificationImportance.High;

        NotificationChannel notificationChannel = new NotificationChannel(mChannelId, mChannelName, importance)
        {
            Description = mChannelDescription
        };
        notificationChannel.EnableLights(true);
        notificationChannel.EnableVibration(true);
        notificationChannel.SetShowBadge(true);
        notificationChannel.Importance = NotificationImportance.High;
        notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });

        if (mManager != null)
        {
            mManager.CreateNotificationChannel(notificationChannel);
        }
    }
}
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public void Send(string title, string message)
{
try
{
// Create an Activity intent
Intent intent = new Intent(mContext, typeof(MainActivity));
intent.PutExtra(mTitleKey, title);
intent.PutExtra(mMessageKey, message);
// Create a PendingIntent
PendingIntent pendingIntent = PendingIntent.GetActivity(mContext, mPendingIntentId++, intent, PendingIntentFlags.UpdateCurrent);
// Create a NotificationCompat.Builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, mChannelId)
.SetContentIntent(pendingIntent)
.SetContentTitle(title)
.SetContentText(message)
.SetSmallIcon(Resource.Drawable.abc_btn_check_material)
.SetVisibility((int)NotificationVisibility.Public)
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);
// Send notification
var notification = builder.Build();
mManager.Notify(mMessageId++, notification);
}
catch (Exception ex)
{
//
}
}
public void Send(string title, string message) { try { // Create an Activity intent Intent intent = new Intent(mContext, typeof(MainActivity)); intent.PutExtra(mTitleKey, title); intent.PutExtra(mMessageKey, message); // Create a PendingIntent PendingIntent pendingIntent = PendingIntent.GetActivity(mContext, mPendingIntentId++, intent, PendingIntentFlags.UpdateCurrent); // Create a NotificationCompat.Builder NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, mChannelId) .SetContentIntent(pendingIntent) .SetContentTitle(title) .SetContentText(message) .SetSmallIcon(Resource.Drawable.abc_btn_check_material) .SetVisibility((int)NotificationVisibility.Public) .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate); // Send notification var notification = builder.Build(); mManager.Notify(mMessageId++, notification); } catch (Exception ex) { // } }
public void Send(string title, string message)
{
    try
    {
        // Create an Activity intent
        Intent intent = new Intent(mContext, typeof(MainActivity));
        intent.PutExtra(mTitleKey, title);
        intent.PutExtra(mMessageKey, message);

        // Create a PendingIntent
        PendingIntent pendingIntent = PendingIntent.GetActivity(mContext, mPendingIntentId++, intent, PendingIntentFlags.UpdateCurrent);

        // Create a NotificationCompat.Builder
        NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, mChannelId)
            .SetContentIntent(pendingIntent)
            .SetContentTitle(title)
            .SetContentText(message)
            .SetSmallIcon(Resource.Drawable.abc_btn_check_material)
            .SetVisibility((int)NotificationVisibility.Public)
            .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);

        // Send notification
        var notification = builder.Build();
        mManager.Notify(mMessageId++, notification);
    }
    catch (Exception ex)
    {
        //
    }
}

How to build a schedule notification for Android?

  • Create a BroadcastReceiver sending a local notification
  • Create a BroadcastReceiver intent
    • Add title, message,..
  • Create a PendingIntent for the above BroadcastReceiver intent
  • Setup an AlarmManager to trigger this pending intent at a setting time
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Create a BroadcastReceiver sending a local notification
[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("title");
string message = intent.GetStringExtra("message");
AndroidNotificationManager.mInstance.Show(title, message);
}
}
}
...
public class AndroidNotificationManager {
public void SendScheduleNotification(string title, string message, DateTime? notifyTime = null)
{
// Create a BroadcastReceiver intent
Intent intent = new Intent(mContext, typeof(AlarmHandler));
intent.PutExtra(mTitleKey, title);
intent.PutExtra(mMessageKey, message);
// Create a PendingIntent
PendingIntent pendingIntent = PendingIntent.GetBroadcast(mContext, mPendingIntentId++, intent, PendingIntentFlags.CancelCurrent);
// Setup an AlarmManager to trigger this pending intent
long triggerTime = GetNotifyTime(notifyTime.Value);
AlarmManager alarmManager = mContext.GetSystemService(Context.AlarmService) as AlarmManager;
alarmManager.Set(AlarmType.RtcWakeup, triggerTime, pendingIntent);
}
}
...
// Create a BroadcastReceiver sending a local notification [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("title"); string message = intent.GetStringExtra("message"); AndroidNotificationManager.mInstance.Show(title, message); } } } ... public class AndroidNotificationManager { public void SendScheduleNotification(string title, string message, DateTime? notifyTime = null) { // Create a BroadcastReceiver intent Intent intent = new Intent(mContext, typeof(AlarmHandler)); intent.PutExtra(mTitleKey, title); intent.PutExtra(mMessageKey, message); // Create a PendingIntent PendingIntent pendingIntent = PendingIntent.GetBroadcast(mContext, mPendingIntentId++, intent, PendingIntentFlags.CancelCurrent); // Setup an AlarmManager to trigger this pending intent long triggerTime = GetNotifyTime(notifyTime.Value); AlarmManager alarmManager = mContext.GetSystemService(Context.AlarmService) as AlarmManager; alarmManager.Set(AlarmType.RtcWakeup, triggerTime, pendingIntent); } } ...
// Create a BroadcastReceiver sending a local notification
[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("title");
            string message = intent.GetStringExtra("message");
            AndroidNotificationManager.mInstance.Show(title, message);
        }
    }
}

...

public class AndroidNotificationManager {
    public void SendScheduleNotification(string title, string message, DateTime? notifyTime = null)
    {
        // Create a BroadcastReceiver intent
        Intent intent = new Intent(mContext, typeof(AlarmHandler));
        intent.PutExtra(mTitleKey, title);
        intent.PutExtra(mMessageKey, message);

        // Create a PendingIntent
        PendingIntent pendingIntent = PendingIntent.GetBroadcast(mContext, mPendingIntentId++, intent, PendingIntentFlags.CancelCurrent);

        // Setup an AlarmManager to trigger this pending intent
        long triggerTime = GetNotifyTime(notifyTime.Value);
        AlarmManager alarmManager = mContext.GetSystemService(Context.AlarmService) as AlarmManager;
        alarmManager.Set(AlarmType.RtcWakeup, triggerTime, pendingIntent);
    }
}

...

https://github.com/hung-nb/xamarin-localnotification

How to create daily schedule notification?

Set alarm every Wednesday

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// LocalNotification { Title, Message }
// HourMinute { mHour, mMinute }
// dayOfWeek {1: Sunday, 2: Monday, 3: Tuesday, 4: Wednesday, 5: Thursday, 6: Friday, 7: Saturday}
// Example: Send notification at 9:00am every Wednesday: scheduleTime = { mHour: 9, mMinute: 0 }, dayOfWeek = 4
public void SetSchedule(LocalNotification notification, HourMinute scheduleTime, int dayOfWeek)
{
var appContext = Application.Context;
int id = 1234567890;
// Create a BroadcastReceiver intent
Intent intent = new Intent(appContext, typeof(AlarmBroadcastReceiver));
intent.PutExtra("title", notification.Title);
intent.PutExtra("message", notification.Message);
// Create a PendingIntent
PendingIntent pendingIntent = PendingIntent.GetBroadcast(appContext, id, intent, PendingIntentFlags.CancelCurrent);
// Set trigger time
var triggerTime = Calendar.Instance;
while (triggerTime.Get(CalendarField.DayOfWeek) != dayOfWeek)
{
// if today is not dayOfWeek, then find next day until find that day
// dayOfWeek = Calendar.Wednesday
triggerTime.Add(CalendarField.Date, 1);
}
triggerTime.Set(CalendarField.HourOfDay, scheduleTime.mHour);
triggerTime.Set(CalendarField.Minute, scheduleTime.mMinute);
triggerTime.Set(CalendarField.Second, 0);
Console.WriteLine("+++++++++++++" + triggerTime.Time);
// Setup an AlarmManager to trigger this pending intent
// Example: Send notification at 9:00am every Wednesday: scheduleTime = { mHour: 9, mMinute: 0 }, dayOfWeek = 4
AlarmManager alarmManager = appContext.GetSystemService(Context.AlarmService) as AlarmManager;
alarmManager.SetRepeating(AlarmType.RtcWakeup, triggerTime.TimeInMillis, AlarmManager.IntervalDay * 7, pendingIntent);
}
// LocalNotification { Title, Message } // HourMinute { mHour, mMinute } // dayOfWeek {1: Sunday, 2: Monday, 3: Tuesday, 4: Wednesday, 5: Thursday, 6: Friday, 7: Saturday} // Example: Send notification at 9:00am every Wednesday: scheduleTime = { mHour: 9, mMinute: 0 }, dayOfWeek = 4 public void SetSchedule(LocalNotification notification, HourMinute scheduleTime, int dayOfWeek) { var appContext = Application.Context; int id = 1234567890; // Create a BroadcastReceiver intent Intent intent = new Intent(appContext, typeof(AlarmBroadcastReceiver)); intent.PutExtra("title", notification.Title); intent.PutExtra("message", notification.Message); // Create a PendingIntent PendingIntent pendingIntent = PendingIntent.GetBroadcast(appContext, id, intent, PendingIntentFlags.CancelCurrent); // Set trigger time var triggerTime = Calendar.Instance; while (triggerTime.Get(CalendarField.DayOfWeek) != dayOfWeek) { // if today is not dayOfWeek, then find next day until find that day // dayOfWeek = Calendar.Wednesday triggerTime.Add(CalendarField.Date, 1); } triggerTime.Set(CalendarField.HourOfDay, scheduleTime.mHour); triggerTime.Set(CalendarField.Minute, scheduleTime.mMinute); triggerTime.Set(CalendarField.Second, 0); Console.WriteLine("+++++++++++++" + triggerTime.Time); // Setup an AlarmManager to trigger this pending intent // Example: Send notification at 9:00am every Wednesday: scheduleTime = { mHour: 9, mMinute: 0 }, dayOfWeek = 4 AlarmManager alarmManager = appContext.GetSystemService(Context.AlarmService) as AlarmManager; alarmManager.SetRepeating(AlarmType.RtcWakeup, triggerTime.TimeInMillis, AlarmManager.IntervalDay * 7, pendingIntent); }
// LocalNotification { Title, Message }
// HourMinute { mHour, mMinute }
// dayOfWeek {1: Sunday, 2: Monday, 3: Tuesday, 4: Wednesday, 5: Thursday, 6: Friday, 7: Saturday}
// Example: Send notification at 9:00am every Wednesday: scheduleTime = { mHour: 9, mMinute: 0 }, dayOfWeek = 4
public void SetSchedule(LocalNotification notification, HourMinute scheduleTime, int dayOfWeek)
{
    var appContext = Application.Context;
    int id = 1234567890;

    // Create a BroadcastReceiver intent
    Intent intent = new Intent(appContext, typeof(AlarmBroadcastReceiver));
    intent.PutExtra("title", notification.Title);
    intent.PutExtra("message", notification.Message);

    // Create a PendingIntent
    PendingIntent pendingIntent = PendingIntent.GetBroadcast(appContext, id, intent, PendingIntentFlags.CancelCurrent);

    // Set trigger time
    var triggerTime = Calendar.Instance;
    while (triggerTime.Get(CalendarField.DayOfWeek) != dayOfWeek)
    {
        // if today is not dayOfWeek, then find next day until find that day
        // dayOfWeek = Calendar.Wednesday
        triggerTime.Add(CalendarField.Date, 1);
    }
    triggerTime.Set(CalendarField.HourOfDay, scheduleTime.mHour);
    triggerTime.Set(CalendarField.Minute, scheduleTime.mMinute);
    triggerTime.Set(CalendarField.Second, 0);

    Console.WriteLine("+++++++++++++" + triggerTime.Time);

    // Setup an AlarmManager to trigger this pending intent
    // Example: Send notification at 9:00am every Wednesday: scheduleTime = { mHour: 9, mMinute: 0 }, dayOfWeek = 4
    AlarmManager alarmManager = appContext.GetSystemService(Context.AlarmService) as AlarmManager;
    alarmManager.SetRepeating(AlarmType.RtcWakeup, triggerTime.TimeInMillis, AlarmManager.IntervalDay * 7, pendingIntent);
}

Set alarm from Monday to Friday

Set alarm repeating every day and in on Receive check current day. If its sat or sun ignore it

Create a background service using AlarmManager + BroadcastReceivers

(Deprecated) How to make notification work even when app is killed?

Call local notification (AlarmManager) in a foreground service

  • Create a service
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
[Service]
public class AlarmService : Service
{
IBinder binder;
public override IBinder OnBind(Intent intent)
{
binder = new AlarmServiceBinder(this);
return binder;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
// this method would hold the code to be run when the service is started.
// Call local notification here
Send(message, title);
return StartCommandResult.NotSticky;
}
}
public class AlarmServiceBinder : Binder
{
readonly AlarmService service;
public AlarmServiceBinder(AlarmService service)
{
this.service = service;
}
public AlarmService GetAlarmService()
{
return service;
}
}
[Service] public class AlarmService : Service { IBinder binder; public override IBinder OnBind(Intent intent) { binder = new AlarmServiceBinder(this); return binder; } public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) { // this method would hold the code to be run when the service is started. // Call local notification here Send(message, title); return StartCommandResult.NotSticky; } } public class AlarmServiceBinder : Binder { readonly AlarmService service; public AlarmServiceBinder(AlarmService service) { this.service = service; } public AlarmService GetAlarmService() { return service; } }
    [Service]
    public class AlarmService : Service
    {
        IBinder binder;

        public override IBinder OnBind(Intent intent)
        {
            binder = new AlarmServiceBinder(this);
            return binder;
        }

        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            // this method would hold the code to be run when the service is started.
            // Call local notification here
            Send(message, title);

            return StartCommandResult.NotSticky;
        }
    }

    public class AlarmServiceBinder : Binder
    {
        readonly AlarmService service;

        public AlarmServiceBinder(AlarmService service)
        {
            this.service = service;
        }

        public AlarmService GetAlarmService()
        {
            return service;
        }
    }
  • Run service in StartForegroundService
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public void RunForegroundService()
{
var intent = new Intent(MainActivity.AppInstance, typeof(AlarmService));
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
MainActivity.AppInstance.StartForegroundService(intent);
}
else
{
MainActivity.AppInstance.StartService(intent);
}
}
public void RunForegroundService() { var intent = new Intent(MainActivity.AppInstance, typeof(AlarmService)); if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O) { MainActivity.AppInstance.StartForegroundService(intent); } else { MainActivity.AppInstance.StartService(intent); } }
        public void RunForegroundService()
        {
            var intent = new Intent(MainActivity.AppInstance, typeof(AlarmService));


            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
            {
                MainActivity.AppInstance.StartForegroundService(intent);
            }
            else
            {
                MainActivity.AppInstance.StartService(intent);
            }

        }
  • Add this line into AndroidManifest
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<application android:label="XXXXXX" android:usesCleartextTraffic="true">
...
<receiver android:name=".AlarmBroadcastReceiver" android:enabled="true" android:exported="true" />
...
</application>
<application android:label="XXXXXX" android:usesCleartextTraffic="true"> ... <receiver android:name=".AlarmBroadcastReceiver" android:enabled="true" android:exported="true" /> ... </application>
<application android:label="XXXXXX" android:usesCleartextTraffic="true">
    ...
    <receiver android:name=".AlarmBroadcastReceiver" android:enabled="true" android:exported="true" />
    ...
</application>

(New) How to make notification work even when app is killed?

Create a background service

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
using System;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Support.V4.App;
using static Android.OS.PowerManager;
namespace localnotification.Droid.Notification
{
[Service(Enabled = true)]
public class MyRequestService : Service
{
private Handler handler;
private Action runnable;
private bool isStarted;
private WakeLock wakeLock;
private long DELAY_BETWEEN_LOG_MESSAGES = 15000;
private int NOTIFICATION_SERVICE_ID = 999999;
private int NOTIFICATION_SERVICE_ALARM_ID = 9999990;
private string NOTIFICATION_CHANNEL_ID = "888888";
private string NOTIFICATION_CHANNEL_NAME = "channel_name_123";
public override void OnCreate()
{
base.OnCreate();
handler = new Handler();
// Here is what you want to do always, i just want to push a notification every 15 seconds here
runnable = new Action(() =>
{
DispatchNotificationThatAlarmIsGenerated("I'm running");
handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
});
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
if (isStarted)
{
// service is already started
}
else
{
// Popup start service notification
CreateNotificationChannel();
DispatchNotificationThatServiceIsRunning();
// Pop up notification every 15s
handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
isStarted = true;
// Keep app work when device sleeps
PowerManager powerManager = (PowerManager)this.GetSystemService(Context.PowerService);
WakeLock wakeLock = powerManager.NewWakeLock(WakeLockFlags.Full, "Client Lock");
wakeLock.Acquire();
}
return StartCommandResult.Sticky;
}
public override void OnTaskRemoved(Intent rootIntent)
{
//base.OnTaskRemoved(rootIntent);
}
public override IBinder OnBind(Intent intent)
{
// Return null because this is a pure started service. A hybrid service would return a binder that would
// allow access to the GetFormattedStamp() method.
return null;
}
public override void OnDestroy()
{
// Stop the handler.
handler.RemoveCallbacks(runnable);
// Remove the notification from the status bar.
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Cancel(NOTIFICATION_SERVICE_ID);
isStarted = false;
wakeLock.Release();
base.OnDestroy();
}
private void CreateNotificationChannel()
{
//Notification Channel
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationImportance.Max);
notificationChannel.EnableLights(true);
notificationChannel.LightColor = Color.Red;
notificationChannel.EnableVibration(true);
notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
NotificationManager notificationManager = (NotificationManager)this.GetSystemService(Context.NotificationService);
notificationManager.CreateNotificationChannel(notificationChannel);
}
private void DispatchNotificationThatServiceIsRunning()
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.SetDefaults((int)NotificationDefaults.All)
.SetSmallIcon(Resource.Drawable.abc_btn_check_material)
.SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
.SetSound(null)
.SetChannelId(NOTIFICATION_CHANNEL_ID)
.SetPriority(NotificationCompat.PriorityDefault)
.SetAutoCancel(false)
.SetContentTitle("Mobile")
.SetContentText("My service started")
.SetOngoing(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
//notificationManager.Notify(NOTIFICATION_SERVICE_ID, builder.Build());
StartForeground(NOTIFICATION_SERVICE_ID, builder.Build());
}
private void DispatchNotificationThatAlarmIsGenerated(string message)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.abc_btn_check_material)
.SetContentTitle("Alarm")
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(NOTIFICATION_SERVICE_ALARM_ID, notificationBuilder.Build());
}
}
}
using System; using Android.App; using Android.Content; using Android.Graphics; using Android.OS; using Android.Support.V4.App; using static Android.OS.PowerManager; namespace localnotification.Droid.Notification { [Service(Enabled = true)] public class MyRequestService : Service { private Handler handler; private Action runnable; private bool isStarted; private WakeLock wakeLock; private long DELAY_BETWEEN_LOG_MESSAGES = 15000; private int NOTIFICATION_SERVICE_ID = 999999; private int NOTIFICATION_SERVICE_ALARM_ID = 9999990; private string NOTIFICATION_CHANNEL_ID = "888888"; private string NOTIFICATION_CHANNEL_NAME = "channel_name_123"; public override void OnCreate() { base.OnCreate(); handler = new Handler(); // Here is what you want to do always, i just want to push a notification every 15 seconds here runnable = new Action(() => { DispatchNotificationThatAlarmIsGenerated("I'm running"); handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES); }); } public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) { if (isStarted) { // service is already started } else { // Popup start service notification CreateNotificationChannel(); DispatchNotificationThatServiceIsRunning(); // Pop up notification every 15s handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES); isStarted = true; // Keep app work when device sleeps PowerManager powerManager = (PowerManager)this.GetSystemService(Context.PowerService); WakeLock wakeLock = powerManager.NewWakeLock(WakeLockFlags.Full, "Client Lock"); wakeLock.Acquire(); } return StartCommandResult.Sticky; } public override void OnTaskRemoved(Intent rootIntent) { //base.OnTaskRemoved(rootIntent); } public override IBinder OnBind(Intent intent) { // Return null because this is a pure started service. A hybrid service would return a binder that would // allow access to the GetFormattedStamp() method. return null; } public override void OnDestroy() { // Stop the handler. handler.RemoveCallbacks(runnable); // Remove the notification from the status bar. var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.Cancel(NOTIFICATION_SERVICE_ID); isStarted = false; wakeLock.Release(); base.OnDestroy(); } private void CreateNotificationChannel() { //Notification Channel NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationImportance.Max); notificationChannel.EnableLights(true); notificationChannel.LightColor = Color.Red; notificationChannel.EnableVibration(true); notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 }); NotificationManager notificationManager = (NotificationManager)this.GetSystemService(Context.NotificationService); notificationManager.CreateNotificationChannel(notificationChannel); } private void DispatchNotificationThatServiceIsRunning() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) .SetDefaults((int)NotificationDefaults.All) .SetSmallIcon(Resource.Drawable.abc_btn_check_material) .SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 }) .SetSound(null) .SetChannelId(NOTIFICATION_CHANNEL_ID) .SetPriority(NotificationCompat.PriorityDefault) .SetAutoCancel(false) .SetContentTitle("Mobile") .SetContentText("My service started") .SetOngoing(true); NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this); //notificationManager.Notify(NOTIFICATION_SERVICE_ID, builder.Build()); StartForeground(NOTIFICATION_SERVICE_ID, builder.Build()); } private void DispatchNotificationThatAlarmIsGenerated(string message) { var intent = new Intent(this, typeof(MainActivity)); intent.AddFlags(ActivityFlags.ClearTop); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) .SetSmallIcon(Resource.Drawable.abc_btn_check_material) .SetContentTitle("Alarm") .SetContentText(message) .SetAutoCancel(true) .SetContentIntent(pendingIntent); var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.Notify(NOTIFICATION_SERVICE_ALARM_ID, notificationBuilder.Build()); } } }
using System;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Support.V4.App;
using static Android.OS.PowerManager;

namespace localnotification.Droid.Notification
{
    [Service(Enabled = true)]
    public class MyRequestService : Service
    {
        private Handler handler;
        private Action runnable;
        private bool isStarted;
        private WakeLock wakeLock;
        private long DELAY_BETWEEN_LOG_MESSAGES = 15000;
        private int NOTIFICATION_SERVICE_ID = 999999;
        private int NOTIFICATION_SERVICE_ALARM_ID = 9999990;
        private string NOTIFICATION_CHANNEL_ID = "888888";
        private string NOTIFICATION_CHANNEL_NAME = "channel_name_123";

        public override void OnCreate()
        {
            base.OnCreate();

            handler = new Handler();

            // Here is what you want to do always, i just want to push a notification every 15 seconds here
            runnable = new Action(() =>
            {
                DispatchNotificationThatAlarmIsGenerated("I'm running");
                handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
            });
        }

        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            if (isStarted)
            {
                // service is already started
            }
            else
            {
                // Popup start service notification
                CreateNotificationChannel();
                DispatchNotificationThatServiceIsRunning();

                // Pop up notification every 15s
                handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
                isStarted = true;

                // Keep app work when device sleeps
                PowerManager powerManager = (PowerManager)this.GetSystemService(Context.PowerService);
                WakeLock wakeLock = powerManager.NewWakeLock(WakeLockFlags.Full, "Client Lock");
                wakeLock.Acquire();
            }
            return StartCommandResult.Sticky;
        }

        public override void OnTaskRemoved(Intent rootIntent)
        {
            //base.OnTaskRemoved(rootIntent);
        }

        public override IBinder OnBind(Intent intent)
        {
            // Return null because this is a pure started service. A hybrid service would return a binder that would
            // allow access to the GetFormattedStamp() method.
            return null;
        }

        public override void OnDestroy()
        {
            // Stop the handler.
            handler.RemoveCallbacks(runnable);

            // Remove the notification from the status bar.
            var notificationManager = (NotificationManager)GetSystemService(NotificationService);
            notificationManager.Cancel(NOTIFICATION_SERVICE_ID);

            isStarted = false;
            wakeLock.Release();
            base.OnDestroy();
        }

        private void CreateNotificationChannel()
        {
            //Notification Channel
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationImportance.Max);
            notificationChannel.EnableLights(true);
            notificationChannel.LightColor = Color.Red;
            notificationChannel.EnableVibration(true);
            notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });

            NotificationManager notificationManager = (NotificationManager)this.GetSystemService(Context.NotificationService);
            notificationManager.CreateNotificationChannel(notificationChannel);
        }

        private void DispatchNotificationThatServiceIsRunning()
        {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                   .SetDefaults((int)NotificationDefaults.All)
                   .SetSmallIcon(Resource.Drawable.abc_btn_check_material)
                   .SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
                   .SetSound(null)
                   .SetChannelId(NOTIFICATION_CHANNEL_ID)
                   .SetPriority(NotificationCompat.PriorityDefault)
                   .SetAutoCancel(false)
                   .SetContentTitle("Mobile")
                   .SetContentText("My service started")
                   .SetOngoing(true);

            NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);

            //notificationManager.Notify(NOTIFICATION_SERVICE_ID, builder.Build());
            StartForeground(NOTIFICATION_SERVICE_ID, builder.Build());
        }

        private void DispatchNotificationThatAlarmIsGenerated(string message)
        {
            var intent = new Intent(this, typeof(MainActivity));
            intent.AddFlags(ActivityFlags.ClearTop);
            var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);

            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .SetSmallIcon(Resource.Drawable.abc_btn_check_material)
                .SetContentTitle("Alarm")
                .SetContentText(message)
                .SetAutoCancel(true)
                .SetContentIntent(pendingIntent);

            var notificationManager = (NotificationManager)GetSystemService(NotificationService);
            notificationManager.Notify(NOTIFICATION_SERVICE_ALARM_ID, notificationBuilder.Build());
        }
    }
}

Call service in MainActivity.cs

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public void StartMyRequestService()
{
var serviceToStart = new Intent(this, typeof(MyRequestService));
StartService(serviceToStart);
}
public void StopMyRequestService()
{
var serviceToStart = new Intent(this, typeof(MyRequestService));
StopService(serviceToStart);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected override void OnPause()
{
base.OnPause();
StartMyRequestService();
}
protected override void OnDestroy()
{
base.OnDestroy();
StartMyRequestService();
}
protected override void OnResume()
{
base.OnResume();
StopMyRequestService();
}
public void StartMyRequestService() { var serviceToStart = new Intent(this, typeof(MyRequestService)); StartService(serviceToStart); } public void StopMyRequestService() { var serviceToStart = new Intent(this, typeof(MyRequestService)); StopService(serviceToStart); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected override void OnPause() { base.OnPause(); StartMyRequestService(); } protected override void OnDestroy() { base.OnDestroy(); StartMyRequestService(); } protected override void OnResume() { base.OnResume(); StopMyRequestService(); }
        public void StartMyRequestService()
        {
            var serviceToStart = new Intent(this, typeof(MyRequestService));
            StartService(serviceToStart);
        }

        public void StopMyRequestService()
        {
            var serviceToStart = new Intent(this, typeof(MyRequestService));
            StopService(serviceToStart);
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        protected override void OnPause()
        {
            base.OnPause();
            StartMyRequestService();
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();
            StartMyRequestService();
        }

        protected override void OnResume()
        {
            base.OnResume();
            StopMyRequestService();
        }

Add permission into Manifest file

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?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.localnotification">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:label="localnotification.Android" android:theme="@style/MainTheme"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>
<?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.localnotification"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" /> <application android:label="localnotification.Android" android:theme="@style/MainTheme"></application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> </manifest>
<?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.localnotification">
	<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
	<application android:label="localnotification.Android" android:theme="@style/MainTheme"></application>
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>

How to re-schedule notification after reboot?

Hold RECEIVE_BOOT_COMPLETED and have a BroadcastReceiver to receive the boot so that if the phone is rebooted you can re-schedule your alarms.

https://stackoverflow.com/questions/51196658/schedule-notification-at-monday-of-every-week-in-android

Create background service using WorkManager

WorkManager is a library that makes it easy to schedule deferrable, asynchronous tasks even if the app exits or the device restarts.

It was designed to be backwards compatible to API 14 and does so by wrapping JobScheduler, AlarmManager, and BroadcastReceivers all in one.

Using JobScheduler your app will be running on a device that is API 23+. Anything below, you’ll be using a combination of AlarmManager + BroadcastReceivers.

But the minimum interval for PeriodicWork is 15 minutes (same as JobScheduler Periodic Job).
If you need it every 30 seconds — consider using OneTimeWork and schedule it again when the work is done.
But
Approximately your location query every 30 seconds will responsible for about 10% battery drain.

Be the first to comment

Leave a Reply

Your email address will not be published.


*