Building A Reminder Application In Xamarin.Android

Introduction

Let's build a simple reminder application that will remind the particular things (eg: shopping, particular office work/meeting, going to particular place etc.).

This application will take three inputs -  Date, Time, and Content that is needed to be reminded.

On the particular date and time, it will notify you in the notification bar and when you click on the notification, it will show you the reminding content.

This article will cover the following,

  1. Android native application.
  2. DatePicker, TimePicker, Button Events in Xamarin android application.
  3. AlarmManager, Broadcast receiver.
  4. Scheduling of job with the help of AlarmManager.
  5. SQLite database basics operations.
  6. Navigation from one activity to another.
  7. Notification and task stack.

Prerequisites

  1. Basic programming knowledge of C# and knowledge of application creation and its flow.
  2. Knowledge of Xamarin is a plus.
  3. Before/After implementation, please go through the following topics- AlarmManager, BroadcastReceiver, NotificationManager, SQLite Database.

Implementation

I am using Visual Studio Community Edition.

Xamarin

Add a new project Xamarin.Native application with the help of below-given instructions. Click "Next" after selecting the blank Android app.

Xamarin

Give application name, say, “NotificationReminder” and click "Next".

Xamarin

Give the project a name and click "Create".

Xamarin Xamarin

The directory structure of the project will be like below.

Add the following files under Model directory

Add Reminder.cs class file.
  1. using System;  
  2. namespace NotificationReminder.Model  
  3. {  
  4.     public class Reminder  
  5.      {  
  6.           public int Id { get; set; }  
  7.           public string Date { get; set; }  
  8.           public string Time { get; set; }  
  9.           public string Note { get; set; }  
  10.           public Reminder()  
  11.           {  
  12.           }  
  13.     }  
  14. }  
Add DatePickerFragment.cs
  1. using System;  
  2. using Android.App;  
  3. using Android.OS;  
  4. using Android.Util;  
  5. using Android.Widget;  
  6.   
  7. namespace NotificationReminder.Model  
  8. {  
  9.       // Create a class DatePickerFragment    
  10.       public class DatePickerFragment : DialogFragment,  
  11.         DatePickerDialog.IOnDateSetListener  
  12.     {  
  13.         // TAG can be any string of your choice.    
  14.         public static readonly string TAG = "X:" +  typeof(DatePickerFragment).Name.ToUpper();  
  15.         // Initialize this value to prevent NullReferenceExceptions.    
  16.         Action<DateTime> _dateSelectedHandler = delegate { };  
  17.     public static DatePickerFragment NewInstance(Action<DateTime> onDateSelected)  
  18.     {  
  19.         DatePickerFragment frag = new DatePickerFragment();  
  20.         frag._dateSelectedHandler = onDateSelected;  
  21.         return frag;  
  22.     }  
  23.     public override Dialog OnCreateDialog(Bundle savedInstanceState)  
  24.     {  
  25.         DateTime currently = DateTime.Now;  
  26.         DatePickerDialog dialog = new DatePickerDialog(Activity, this,  currently.Year, currently.Month, currently.Day);  
  27.         return dialog;  
  28.     }  
  29.     public void OnDateSet(DatePicker view, int year, int monthOfYear, int   dayOfMonth)  
  30.     {  
  31.         // Note: monthOfYear is a value between 0 and 11, not 1 and 12!    
  32.         DateTime selectedDate = new DateTime(year, monthOfYear + 1,     dayOfMonth);  
  33.         Log.Debug(TAG, selectedDate.ToLongDateString());  
  34.         _dateSelectedHandler(selectedDate);  
  35.     }  
  36.     }  
  37. }  
Add TimePickerFragment.cs
  1. using System;  
  2. using Android.App;  
  3. using Android.OS;  
  4. using Android.Text.Format;  
  5. using Android.Util;  
  6. using Android.Widget;  
  7.   
  8. namespace NotificationReminder.Model  
  9. {  
  10.     public class TimePickerFragment : DialogFragment, TimePickerDialog.IOnTimeSetListener  
  11.     {  
  12.         public static readonly string TAG = "MyTimePickerFragment";  
  13.         Action<DateTime> timeSelectedHandler = delegate { };  
  14.   
  15.         public static TimePickerFragment NewInstance(Action<DateTime> onTimeSelected)  
  16.         {  
  17.         TimePickerFragment frag = new TimePickerFragment();  
  18.         frag.timeSelectedHandler = onTimeSelected;  
  19.         return frag;  
  20.         }  
  21.   
  22.         public override Dialog OnCreateDialog(Bundle savedInstanceState)  
  23.         {  
  24.             DateTime currentTime = DateTime.Now;  
  25.             bool is24HourFormat = DateFormat.Is24HourFormat(Activity);  
  26.             TimePickerDialog dialog = new TimePickerDialog  
  27.             (Activity, this, currentTime.Hour, currentTime.Minute, is24HourFormat);  
  28.         return dialog;  
  29.         }  
  30.   
  31.         public void OnTimeSet(TimePicker view, int hourOfDay, int minute)  
  32.         {  
  33.              DateTime currentTime = DateTime.Now;  
  34.              DateTime selectedTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, hourOfDay, minute, 0);  
  35.             Log.Debug(TAG, selectedTime.ToLongTimeString());  
  36.             timeSelectedHandler(selectedTime);  
  37.         }  
  38.     }  
  39. }  

Add the following files under Repository directory.

Add the file DataStore.cs
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using Android.App;  
  6. using Android.Content;  
  7. using Android.OS;  
  8. using Android.Runtime;  
  9. using Android.Views;  
  10. using Android.Widget;  
  11. using Android.Database.Sqlite;  
  12.   
  13. namespace NotificationReminder.Repository  
  14. {  
  15.        public class DataStore : SQLiteOpenHelper  
  16.        {  
  17.        private static string _DatabaseName = "reminderDB.db";  
  18.        public DataStore(Context context) : base(context, _DatabaseName, null, 1) {  
  19.   
  20.        }  
  21.   
  22.        public override void OnCreate(SQLiteDatabase db)  
  23.        {  
  24.            db.ExecSQL(ReminderHelper.CreateQuery);  
  25.        }  
  26.   
  27.        public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)  
  28.        {  
  29.            db.ExecSQL(ReminderHelper.DeleteQuery);  
  30.            OnCreate(db);  
  31.        }  
  32.      }  
  33. }  
Add the file ReminderHelper.cs

This file contains the various database operations like insert, select, delete.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using Android.Content;  
  4. using Android.Database.Sqlite;  
  5. using NotificationReminder.Repository;  
  6. using NotificationReminder.Model;  
  7. using Android.Database;  
  8. namespace NotificationReminder.Repository  
  9. {  
  10.      public class ReminderHelper  
  11.     {  
  12.     private const string TableName = "reminderTable";  
  13.     private const string ColumnID = "Id";  
  14.     private const string ColumnDate = "Date";  
  15.     private const string ColumnTime = "Time";  
  16.        private const string ColumnNote = "Note";  
  17.     public const string CreateQuery = "CREATE TABLE " + TableName + " ( "  
  18.         + ColumnID + " INTEGER PRIMARY KEY,"  
  19.            + ColumnDate + " TEXT,"  
  20.            + ColumnTime + " TEXT,"  
  21.            + ColumnNote + " TEXT)";  
  22.   
  23.   
  24.     public const string DeleteQuery = "DROP TABLE IF EXISTS " + TableName;  
  25.   
  26.     public ReminderHelper()  
  27.     {  
  28.     }  
  29.   
  30.        public static void InsertReminderData(Context context, Reminder reminder)  
  31.     {  
  32.         SQLiteDatabase db = new DataStore(context).WritableDatabase;  
  33.         ContentValues contentValues = new ContentValues();  
  34.            contentValues.Put(ColumnDate, reminder.Date);  
  35.            contentValues.Put(ColumnTime, reminder.Time);  
  36.            contentValues.Put(ColumnNote, reminder.Note);  
  37.   
  38.         db.Insert(TableName, null, contentValues);  
  39.         db.Close();  
  40.     }  
  41.   
  42.        public static List<Reminder> GetReminderList(Context context)  
  43.     {  
  44.         List<Reminder> reminder = new List<Reminder>();  
  45.         SQLiteDatabase db = new DataStore(context).ReadableDatabase;  
  46.            string[] columns = new string[] { ColumnID, ColumnDate, ColumnTime, ColumnNote };  
  47.   
  48.         using (ICursor cursor = db.Query(TableName, columns, nullnullnullnullnull))  
  49.         {  
  50.             while (cursor.MoveToNext())  
  51.             {  
  52.                 reminder.Add(new Reminder  
  53.                 {  
  54.                     Id = cursor.GetInt(cursor.GetColumnIndexOrThrow(ColumnID)),  
  55.                        Date = cursor.GetString(cursor.GetColumnIndexOrThrow(ColumnDate)),  
  56.                        Time = cursor.GetString(cursor.GetColumnIndexOrThrow(ColumnTime)),  
  57.                        Note = cursor.GetString(cursor.GetColumnIndexOrThrow(ColumnNote))  
  58.                     });  
  59.             }  
  60.         }  
  61.         db.Close();  
  62.         return reminder;  
  63.     }  
  64.   
  65.        public static void DeleteReminder(Context context, Reminder reminder )  
  66.     {  
  67.         SQLiteDatabase db = new DataStore(context).WritableDatabase;  
  68.            db.Delete(TableName, ColumnDate + "=? AND "+ ColumnTime +"=? OR " + ColumnID + "=" + reminder.Id, new string[] { reminder.Date, reminder.Time });  
  69.         db.Close();  
  70.     }  
  71.   
  72.        public static Reminder SelectReminder(Context context)  
  73.        {  
  74.            Reminder reminder;  
  75.            SQLiteDatabase db = new DataStore(context).WritableDatabase;  
  76.            string[] columns = new string[] { ColumnID, ColumnDate, ColumnTime, ColumnNote };  
  77.            string datetime = DateTime.Now.ToString();  
  78.            string[] dt = datetime.Split(' ');  
  79.            var date = dt[0];  
  80.            var tt = dt[1].Split(':');  
  81.            var time = tt[0] + ":" + tt[1] + " " + dt[2];  
  82.   
  83.   
  84.            using (ICursor cursor = db.Query(TableName, columns, ColumnDate +"=? AND "+ ColumnTime +"=?"new string[]{date, time},null,null,null))  
  85.            {  
  86.                if (cursor.MoveToNext())  
  87.                {  
  88.                    reminder = new Reminder  
  89.                    {  
  90.                        Id = cursor.GetInt(cursor.GetColumnIndexOrThrow(ColumnID)),  
  91.                        Date = cursor.GetString(cursor.GetColumnIndexOrThrow(ColumnDate)),  
  92.                        Time = cursor.GetString(cursor.GetColumnIndexOrThrow(ColumnTime)),  
  93.                        Note = cursor.GetString(cursor.GetColumnIndexOrThrow(ColumnNote))  
  94.                    };  
  95.                }  
  96.                else  
  97.                {  
  98.                    reminder = null;  
  99.                }  
  100.            }  
  101.            return reminder;  
  102.           }  
  103. }  
  104. }  

Add the following files in BroadcastNotification directory.

Add the file ReminderNotification.cs

We are inheriting the BroadcastReceiver, an abstract class, and implementing the OnReceive method that will execute when it is broadcasted from AlarmManager with its pending intent, that is, ReminderNotification. 

  1. using System;  
  2. using Android.App;  
  3. using Android.Content;  
  4. using Android.OS;  
  5. using Android.Support.V4.App;  
  6. using Newtonsoft.Json;  
  7. using NotificationReminder.Model;  
  8. using NotificationReminder.Repository;  
  9.   
  10. namespace NotificationReminder.BroadcastNotification  
  11. {  
  12.        [BroadcastReceiver(Enabled = true)]  
  13.       public class ReminderNotification : BroadcastReceiver  
  14.       {  
  15.           Reminder reminder;  
  16.          public ReminderNotification()  
  17.          {  
  18.          }  
  19.   
  20.           public override void OnReceive(Context context, Intent intent)  
  21.           {  
  22.            reminder = ReminderHelper.SelectReminder(context);  
  23.            if(reminder != null)  
  24.            {  
  25.                Intent newIntent = new Intent(context, typeof(ReminderContent));  
  26.                newIntent.PutExtra("reminder", JsonConvert.SerializeObject(reminder));  
  27.   
  28.                //Add the next task to the stack  
  29.                Android.Support.V4.App.TaskStackBuilder stackBuilder = Android.Support.V4.App.TaskStackBuilder.Create(context);  
  30.                stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(ReminderContent)));  
  31.                stackBuilder.AddNextIntent(newIntent);  
  32.   
  33.                // set the intent which will open when one click on notification  
  34.                PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, (int)PendingIntentFlags.UpdateCurrent);  
  35.   
  36.                NotificationCompat.Builder builder = new NotificationCompat.Builder(context).SetAutoCancel(true)  
  37.                    .SetDefaults((int)NotificationDefaults.All)  
  38.                    .SetContentIntent(resultPendingIntent).SetContentTitle("Reminder!!")  
  39.                    .SetSmallIcon(Resource.Drawable.Icon).SetContentText("Click for details..")  
  40.                    .SetContentInfo("Start");  
  41.                NotificationManager notificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService);  
  42.                notificationManager.Notify(2, builder.Build());  
  43.             }  
  44.         }  
  45.     }  
  46. }  

Add the following files under Layout directory in Resource.

Main.axml [Already added. Just modify the content]

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent">  
  6.     <EditText  
  7.         android:id="@+id/date_display"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:hint="Date"  
  11.         android:focusable="false" />  
  12.     <EditText  
  13.         android:id="@+id/time_display"  
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="wrap_content"  
  16.         android:hint="Time"  
  17.         android:focusable="false" />  
  18.     <EditText  
  19.         android:id="@+id/txtNote"  
  20.         android:layout_width="match_parent"  
  21.         android:layout_height="wrap_content"  
  22.         android:hint="Enter your reminder content!" />  
  23.     <Button  
  24.         android:id="@+id/save"  
  25.         android:layout_width="match_parent"  
  26.         android:layout_height="wrap_content"  
  27.         android:text="@string/btn_save" />  
  28.     <Button  
  29.         android:id="@+id/btnList"  
  30.         android:layout_width="match_parent"  
  31.         android:layout_height="wrap_content"  
  32.         android:text="@string/btn_list" />  
  33. </LinearLayout>  
ReminderAdded.axml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent">  
  6.     <TextView  
  7.         android:id="@+id/reminder_label"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content" />  
  10.     <TextView  
  11.         android:id="@+id/date_display"  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="wrap_content" />  
  14.     <TextView  
  15.         android:id="@+id/time_display"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="wrap_content" />  
  18.     <TextView  
  19.         android:id="@+id/txt_note"  
  20.         android:layout_width="match_parent"  
  21.         android:layout_height="wrap_content" />  
  22.     <Button  
  23.         android:id="@+id/btn_back"  
  24.         android:layout_width="match_parent"  
  25.         android:layout_height="wrap_content"  
  26.         android:text="@string/btn_list" />  
  27. </LinearLayout>  
AXML

The listReminder will have the ListView that will take the single item in form of table layout with the table row.

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent">  
  5.     <TableRow>  
  6.         <TextView  
  7.             android:id="@+id/txtId"  
  8.             android:layout_width="wrap_content"  
  9.             android:layout_height="wrap_content" />  
  10.         <TextView  
  11.             android:id="@+id/txtDate"  
  12.             android:layout_width="wrap_content"  
  13.             android:layout_height="wrap_content" />  
  14.         <TextView  
  15.             android:id="@+id/txtTime"  
  16.             android:layout_width="wrap_content"  
  17.             android:layout_height="wrap_content" />  
  18.         <TextView  
  19.             android:id="@+id/txtNote"  
  20.             android:layout_width="wrap_content"  
  21.             android:layout_height="wrap_content" />  
  22.     </TableRow>  
  23. </TableLayout>  
ListReminder.axml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent">  
  6.     <ListView  
  7.         android:id="@+id/listReminder"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:background="#00FF00"  
  11.         android:layout_weight="1"  
  12.         android:drawSelectorOnTop="false"  
  13.         android:backgroundTint="#ff1b1111" />  
  14.     <TextView  
  15.         android:id="@+id/txt_label"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="wrap_content" />  
  18.     <Button  
  19.         android:id="@+id/addNew"  
  20.         android:layout_width="match_parent"  
  21.         android:layout_height="wrap_content"  
  22.         android:text="Add New" />  
  23. </LinearLayout>  
DeleteReminder.axml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent">  
  6.     <TextView  
  7.         android:id="@+id/txt_label"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content" />  
  10.     <Button  
  11.         android:id="@+id/btn_back"  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="wrap_content"  
  14.         android:text="@string/btn_list" />  
  15. </LinearLayout>  
ReminderContent.axml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent">  
  6.     <TextView  
  7.         android:id="@+id/txt_note"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="wrap_content" />  
  10.     <Button  
  11.         android:id="@+id/btn_back"  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="wrap_content"  
  14.         android:text="@string/btn_back" />  
  15. </LinearLayout>  

Add the following activity files

Modify/Add MainActivity.cs file.

This is the MainLauncher activity and this is responsible for opening the main screen where we give the details regarding reminder.

  1. using System;  
  2. using Android.App;  
  3. using Android.Content;  
  4. using Android.OS;  
  5. using Android.Widget;  
  6. using NotificationReminder.Model;  
  7. using Newtonsoft.Json;  
  8. using NotificationReminder.Repository;  
  9. using NotificationReminder.BroadcastNotification;  
  10.   
  11. namespace NotificationReminder  
  12. {  
  13.     [Activity(Label = "NotificationReminder", MainLauncher = true)]  
  14.     public class MainActivity : Activity  
  15.     {  
  16.         public Reminder reminder;  
  17.         EditText _dateDisplay;  
  18.         EditText _timeDisplay;  
  19.         EditText _txtNote;  
  20.         Button _saveButton;  
  21.         Button _btnList;  
  22.  
  23.         #region DateOperation  
  24.         void DateSelect_OnClick(object sender, EventArgs eventArgs)  
  25.         {  
  26.             DatePickerFragment frag = DatePickerFragment.NewInstance(delegate (DateTime time)  
  27.             {  
  28.                 _dateDisplay.Text = time.ToString().Split(' ')[0];  
  29.                 reminder.Date = _dateDisplay.Text;  
  30.             });  
  31.             frag.Show(FragmentManager, DatePickerFragment.TAG);  
  32.         }  
  33.         #endregion  
  34.  
  35.         #region TimeOperation  
  36.         void TimeSelectOnClick(object sender, EventArgs eventArgs)  
  37.         {  
  38.             TimePickerFragment frag = TimePickerFragment.NewInstance(  
  39.                 delegate (DateTime time)  
  40.                 {  
  41.                     _timeDisplay.Text = time.ToShortTimeString();  
  42.                     reminder.Time = _timeDisplay.Text;  
  43.                 });  
  44.   
  45.             frag.Show(FragmentManager, TimePickerFragment.TAG);  
  46.         }  
  47.         #endregion  
  48.  
  49.         #region SaveDetails  
  50.         void SaveRecords(Object sender, EventArgs eventArgs)  
  51.         {  
  52.             reminder.Note = _txtNote.Text;  
  53.             if(Vaidate())  
  54.             {  
  55.                 DateTime currentDT = DateTime.Now;  
  56.                 DateTime selectedDT = Convert.ToDateTime(reminder.Date + " " + reminder.Time);  
  57.   
  58.                 // Reminder should not be applied on past date time  
  59.                 if (selectedDT > currentDT)  
  60.                 {  
  61.                     ReminderHelper.InsertReminderData(this, reminder);  
  62.                     ScheduleReminder(reminder);  
  63.                     var reminderAdded = new Intent(thistypeof(ReminderAdded));  
  64.                     reminderAdded.PutExtra("reminder", JsonConvert.SerializeObject(reminder));  
  65.                     StartActivity(reminderAdded);  
  66.                 }  
  67.                 else  
  68.                 {  
  69.                     Toast.MakeText(this"This is invalid selelction of Date, Time!", ToastLength.Short).Show();  
  70.                 }  
  71.             }  
  72.   
  73.         }  
  74.   
  75.         bool Vaidate()  
  76.         {  
  77.             if(reminder.Date == string.Empty || reminder.Time == string.Empty || reminder.Note == string.Empty)  
  78.             {  
  79.                 Toast.MakeText(this"Enter the details of all fields!", ToastLength.Short).Show();  
  80.                 return false;  
  81.             }  
  82.             return true;  
  83.         }  
  84.         #endregion  
  85.   
  86.         protected override void OnCreate(Bundle savedInstanceState)  
  87.         {  
  88.             base.OnCreate(savedInstanceState);  
  89.             SetContentView(Resource.Layout.Main);  
  90.             // Create your application here  
  91.             reminder = new Reminder();  
  92.             _dateDisplay = FindViewById<EditText>(Resource.Id.date_display);  
  93.             _timeDisplay = FindViewById<EditText>(Resource.Id.time_display);  
  94.             _txtNote = FindViewById<EditText>(Resource.Id.txtNote);  
  95.   
  96.             _saveButton = FindViewById<Button>(Resource.Id.save);  
  97.             _btnList = FindViewById<Button>(Resource.Id.btnList);  
  98.   
  99.             _dateDisplay.Click += DateSelect_OnClick;  
  100.             _timeDisplay.Click += TimeSelectOnClick;  
  101.             _saveButton.Click += SaveRecords;  
  102.             _btnList.Click += (sender, e) => {   
  103.                 StartActivity(new Intent(thistypeof(ListReminder)));  
  104.             };  
  105.         }  
  106.  
  107.         #region ReminderNotification  
  108.         public void ScheduleReminder(Reminder reminder)  
  109.         {  
  110.             AlarmManager manager = (AlarmManager)GetSystemService(Context.AlarmService);  
  111.             Intent myIntent;  
  112.             PendingIntent pendingIntent;  
  113.             myIntent = new Intent(thistypeof(ReminderNotification));  
  114.            
  115.             //Date and time should be in the format 11/1/1970 and 12:00 AM  
  116.             // get the time parameters hrr,min, am/pm  
  117.             var t = reminder.Time.Split(':');  
  118.             var ampm = t[1].Split(' ')[1];  
  119.             var hrr = Convert.ToDouble(t[0]);  
  120.             var min = Convert.ToDouble(t[1].Split(' ')[0]);  
  121.   
  122.             string dateString = Convert.ToString(reminder.Date + " " + hrr + ":" + min + ":00 " + ampm);  
  123.   
  124.             DateTimeOffset dateOffsetValue = DateTimeOffset.Parse(dateString);  
  125.             var millisec = dateOffsetValue.ToUnixTimeMilliseconds();  
  126.   
  127.             pendingIntent = PendingIntent.GetBroadcast(this, 0, myIntent, 0);  
  128.             manager.Set(AlarmType.RtcWakeup, millisec, pendingIntent);  
  129.         }  
  130.         #endregion  
  131.     }  
  132. }  
Add ReminderAdded.cs

Once you added the reminder from MainActivity, this activity will simply show you that the particular reminder is added and it contains the list button that will take you to the list of reminders you added.

  1. using System;  
  2. using Android.App;  
  3. using Android.Content;  
  4. using Android.OS;  
  5. using Android.Widget;  
  6. using Newtonsoft.Json;  
  7. using NotificationReminder.Model;  
  8.   
  9. namespace NotificationReminder  
  10. {  
  11.     [Activity(Label = "ReminderAdded")]  
  12.     public class ReminderAdded : Activity  
  13.     {  
  14.         TextView _reminderLabel;  
  15.         TextView _dateDisplay;  
  16.         TextView _timeDisplay;  
  17.         TextView _txtNote;  
  18.         Button _backButton;  
  19.         Reminder reminder;  
  20.   
  21.         protected override void OnCreate(Bundle savedInstanceState)  
  22.         {  
  23.             base.OnCreate(savedInstanceState);  
  24.             SetContentView(Resource.Layout.ReminderAdded);  
  25.             // Create your application here  
  26.             reminder = JsonConvert.DeserializeObject<Reminder>(Intent.GetStringExtra("reminder"));  
  27.   
  28.             _reminderLabel = FindViewById<TextView>(Resource.Id.reminder_label);  
  29.             _dateDisplay = FindViewById<TextView>(Resource.Id.date_display);  
  30.             _timeDisplay = FindViewById<TextView>(Resource.Id.time_display);  
  31.             _txtNote = FindViewById<TextView>(Resource.Id.txt_note);  
  32.             _backButton = FindViewById<Button>(Resource.Id.btn_back);  
  33.   
  34.             _reminderLabel.Text = "Reminder added successfully!!";  
  35.             _dateDisplay.Text = "Date : " + reminder.Date;  
  36.             _timeDisplay.Text = "Time : " + reminder.Time;  
  37.             _txtNote.Text = "Content: " + reminder.Note;  
  38.   
  39.             _backButton.Click += (object obj, EventArgs e) => {   
  40.                 StartActivity(new Intent(thistypeof(ListReminder)));  
  41.             };  
  42.         }  
  43.     }  
  44. }  
Add activity GridReminder.cs

We are inheriting the BaseAdapter an abstract class and implementing its abstract methods. The GetView method will be used to get the View that is single record in table layout. This method will be called and will return View for all items of the list that we pass in its constructor.

  1. using Android.App;  
  2. using Android.Views;  
  3. using Android.Widget;  
  4. using NotificationReminder.Model;  
  5.   
  6. namespace NotificationReminder  
  7. {  
  8.     public class GridReminder : BaseAdapter  
  9.     {  
  10.         private Activity context;  
  11.         private Reminder[] listitem;  
  12.         public override int Count  
  13.         {  
  14.             get  
  15.             {  
  16.                 return listitem.Length;  
  17.             }  
  18.         }  
  19.         public GridReminder(Activity context, Reminder[] listitem )  
  20.         {  
  21.             this.context = context;  
  22.             this.listitem = listitem;  
  23.         }  
  24.         public override Java.Lang.Object GetItem(int position)  
  25.         {  
  26.             return null;  
  27.         }  
  28.         public override long GetItemId(int position)  
  29.         {  
  30.             return listitem.Length;  
  31.         }  
  32.         public override View GetView(int position, View convertView, ViewGroup parent)  
  33.         {  
  34.             var view = context.LayoutInflater.Inflate(Resource.Layout.Reminder_SingleItem, parent, false);  
  35.             TextView txtDate = (TextView)view.FindViewById(Resource.Id.txtDate);  
  36.             TextView txtTime = (TextView)view.FindViewById(Resource.Id.txtTime);  
  37.             TextView txtNote = (TextView)view.FindViewById(Resource.Id.txtNote);  
  38.             txtDate.Text = (listitem[position].Date).ToString();  
  39.             txtTime.Text = (listitem[position].Time).ToString();  
  40.             txtNote.Text = (listitem[position].Note == null?"no content":listitem[position].Note).ToString();  
  41.             return view;  
  42.         }  
  43.     }  
  44. }  
Add Activity ListReminder.cs

This is responsible for generating the list. Simply, we are using the list item as array and creating the adapter object that will use the same list array and apply that to the adapter of the list. Clicking on any item will ask you to delete the particular reminder if you want.

  1. using System;  
  2. using Android.App;  
  3. using Android.Content;  
  4. using Android.OS;  
  5. using Android.Widget;  
  6. using NotificationReminder.Model;  
  7. using NotificationReminder.Repository;  
  8.   
  9. namespace NotificationReminder  
  10. {  
  11.     [Activity(Label = "ReminderList")]  
  12.     public class ListReminder : Activity  
  13.     {  
  14.         TextView _txtLabel;  
  15.         ListView list;  
  16.         Reminder reminder;  
  17.         Reminder[] listitem;  
  18.         Button addNew;  
  19.         GridReminder adapter;  
  20.         protected override void OnCreate(Bundle savedInstanceState)  
  21.         {  
  22.             base.OnCreate(savedInstanceState);  
  23.   
  24.             // Create your application here  
  25.             SetContentView(Resource.Layout.ListReminder);  
  26.             _txtLabel = FindViewById<TextView>(Resource.Id.txt_label);  
  27.             list = (ListView)FindViewById(Resource.Id.listReminder);  
  28.             _txtLabel.Visibility = Android.Views.ViewStates.Invisible;  
  29.             BindData();  
  30.             addNew = FindViewById<Button>(Resource.Id.addNew);  
  31.             addNew.Click += (sender, e) => {   
  32.                 StartActivity(typeof(MainActivity));  
  33.             };  
  34.         }  
  35.         private void List_ItemClick(object sender, AdapterView.ItemClickEventArgs e)  
  36.         {  
  37.             Android.App.AlertDialog.Builder dialog = new AlertDialog.Builder(this);  
  38.             AlertDialog alert = dialog.Create();  
  39.             alert.SetTitle("Delete");  
  40.             alert.SetMessage("Are you sure!");  
  41.             alert.SetIcon(Resource.Drawable.Icon);  
  42.             alert.SetButton("yes", (c, ev) =>  
  43.             {  
  44.                 reminder = listitem[e.Position];  
  45.                 ReminderHelper.DeleteReminder(this,reminder);  
  46.                 StartActivity(new Intent(this,typeof(DeleteReminder)));  
  47.                 GC.Collect();  
  48.             });  
  49.             alert.SetButton2("no", (c, ev) => { });  
  50.             alert.Show();             
  51.         }  
  52.         private void BindData()  
  53.         {  
  54.             listitem = ReminderHelper.GetReminderList(this).ToArray();  
  55.             if(listitem.Length > 0)  
  56.             {  
  57.                 adapter = new GridReminder(this, listitem);  
  58.                 list.Adapter = adapter;  
  59.                 list.ItemClick += List_ItemClick;      
  60.             }  
  61.             else  
  62.             {  
  63.                 list.Visibility = Android.Views.ViewStates.Invisible;  
  64.                 _txtLabel.Visibility = Android.Views.ViewStates.Visible;  
  65.                 _txtLabel.Text = "No upcoming reminders!!";  
  66.             }  
  67.   
  68.   
  69.         }  
  70.     }  
  71. }  
Add Activity DeleteReminder.cs

This will simply give you the message that you have deleted the reminder.

  1. using Android.App;  
  2. using Android.Content;  
  3. using Android.OS;  
  4. using Android.Widget;  
  5.   
  6. namespace NotificationReminder  
  7. {  
  8.     [Activity(Label = "DeleteReminder")]  
  9.     public class DeleteReminder : Activity  
  10.     {  
  11.         TextView _txtLabel;  
  12.         Button _btn_back;  
  13.         protected override void OnCreate(Bundle savedInstanceState)  
  14.         {  
  15.             base.OnCreate(savedInstanceState);  
  16.             SetContentView(Resource.Layout.DeleteReminder);  
  17.             // Create your application here  
  18.             _txtLabel = FindViewById<TextView>(Resource.Id.txt_label);  
  19.             _btn_back = FindViewById<Button>(Resource.Id.btn_back);  
  20.             _txtLabel.Text = "Deleted!!";  
  21.             _btn_back.Click += (sender, e) => {   
  22.                 StartActivity(new Intent(this,typeof(ListReminder)));  
  23.             };  
  24.         }  
  25.     }  
  26. }  
Add Activity cs

This is the content View of the reminder. This will activated when the Broadcast Receiver calls its OnReceive method for the particular reminder. This will show you the content you want the application to remind you.

After reminding, it will delete that reminder from the database. 

  1. using Android.App;  
  2. using Android.Content;  
  3. using Android.OS;  
  4. using Android.Widget;  
  5. using Newtonsoft.Json;  
  6. using NotificationReminder.Model;  
  7. using NotificationReminder.Repository;  
  8.   
  9. namespace NotificationReminder  
  10. {  
  11.     [Activity(Label = "ReminderContent")]  
  12.     public class ReminderContent : Activity  
  13.     {  
  14.         Reminder reminder;  
  15.         TextView _txtNote;  
  16.         Button _btnBack;  
  17.         protected override void OnCreate(Bundle savedInstanceState)  
  18.         {  
  19.             base.OnCreate(savedInstanceState);  
  20.             SetContentView(Resource.Layout.ReminderContent);  
  21.   
  22.             // Create your application here  
  23.             reminder = JsonConvert.DeserializeObject<Reminder>(Intent.GetStringExtra("reminder"));  
  24.             ReminderHelper.DeleteReminder(this,reminder);  
  25.             _txtNote = FindViewById<TextView>(Resource.Id.txt_note);  
  26.             _txtNote.Text = reminder.Note;  
  27.             _btnBack = FindViewById<Button>(Resource.Id.btn_back);  
  28.             _btnBack.Click += (sender, e) => {   
  29.                 StartActivity(new Intent(thistypeof(ListReminder)));  
  30.             };  
  31.         }  
  32.     }  
  33. }  

Modify the Strings.xml file in Resources/Values directory.

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <string name="app_name">NotificationReminder</string>  
  4.     <string name="btn_save">Save</string>  
  5.     <string name="btn_back">Back</string>  
  6.     <string name="btn_list">List</string>  
  7.     <string name="save_message">Saving...</string>  
  8. </resources>   

Application screens are as follow -

Xamarin Xamarin
Xamarin Xamarin
Xamarin Xamarin
Xamarin Xamarin

Next Recommended Readings