Building a Simple Pomadoro Timer Android App with Xamarin

I’ve been meaning to try my hand at making a mobile app for quite awhile, and I had a free Saturday afternoon and decided to finally give it a go.

Prerequisites

I’m developing on Win 10 with Visual Studio 2015 Community edition.  I have the Xamarin and Android tools installed.  One thing to note is that Hyper-V needs to be enabled in order for the Android phone emulator to work.  This was a minor issue for me as I use VMware Workstation as my vmplatform of choice.  I needed to install Hyper-V and will be unable to run VMware will the feature is enabled.  More of a nuisance that I’ll need to reboot everytime I need to switch gears.

Choosing an Idea

For a first app, I didn’t want to dive in and attempt a huge complicated project or even use too many native features, I wanted to kick the tires on Xamarin and get a little feel for how development works within it. I’ve been using the Pomadoro technique for awhile to ensure my focus on critical tasks.  I haven’t really found an app version that I’m in love with right now so might as well make it the way I’d like it.  For the uninitiated, the Pomadoro technique is basically 25 minutes of uninterrupted work followed by a short 5 minute break with a longer 15-20 minute break as the 4th break.  Ideally you’d like to be able to work uninterrupted during your Pomadoro and be able to handle your distractions during your breaks.

Creating your Project

I created a new App, and Selected the Single-View App template under Android.   This will create the structure and basic resources that we need in order get our project working.

Assuming you have your Android SDK and Hyper-V running, debugging the default solution will open up a simple app that increments as a button is clicked.  Neat.  The solution is comprised of XAML layouts what will comprised our view, XML resources, and Csharp code files.  I’m not going to dive into the MVVM pattern with my initial go, but look for that update in a future post.  I also removed a few of the default files – the GettingStarted.Xamarin, AboutAssets.txt, and AboutResourses.txt files can get binned.

Getting Started With Views

I doubled clicked the Main.axml file to open up the visual designer.  The views are XAML based so if you’ve ever worked with WPF in the past it’s basically the same idea.  I added a TextView and a Button in a Linear Layout.  It’s a simple matter of editing a few properties to get the app looking as you’d like.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="25px"
    android:minHeight="25px"
    android:background="#FF0000"
    android:backgroundTint="#ffff0000">
    <TextView
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textSize="120sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/TimerTextView"
        android:layout_weight="1"
        android:gravity="center"
        android:background="#ff0000"
        android:textColor="#ffffff"
        android:backgroundTint="#ffff0000" />
    <Button
        android:id="@+id/StartButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/TimerButton"
        android:layout_weight="0"
        android:background="#8b0000"
        android:backgroundTint="#ff8b0000"
        android:textSize="40sp" />
</LinearLayout>

Wiring up the Timer

Android comes with a convenient Chronometer control that would handle timers perfectly.  Unfortunately there is one major problem for this use case – the Chronometer only counts up from 0 – there aren’t any built-in controls to handle a countdown timer. No problem as we can make use of the System.Timers.Timer class to help us out.  Notice in the snippet below that the MainActivity class is decorated with Activity – this is necessary to indicate that this is an entry point for the application and encompasses the code that supports the view.  With the OnCreate event, the Timer is getting initialized with an EventHandler added to it, the Main View is attached to the code, and the other UI elements are initialized.

    
[Activity(Label = "Pomadoro App", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { private Timer _timer = new Timer(); protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); _timer.Interval = 1000; _timer.Elapsed += TimerElapsedEvent; SetContentView(Resource.Layout.Main); TextView timerText = FindViewById<TextView>(Resource.Id.TimerTextView); timerText.Text = secondsToCountdown(); Button button = FindViewById<Button>(Resource.Id.StartButton); button.Click += delegate { TimerButtonClicked(); }; }

The next section handles the rest of this simple app.  The code for TimerButtonClicked  determines the current timer state and starts or stops it.  If the timer is stopped, we move to the next timer in the Series by calling GetNextTimer.  Also to note is the RunOnUiThread call to SetTimerButtonText.  UI elements need to be manipulated on the UI thread in order to be reflected on the screen.

The TimerElapsedEvent is the EventHandler we added to the timer in the OnCreate event.  It basically counts down the current timer, updates the UI element, and checks for the timer to be finished.  If the timer is done, it moves on to the next one and starts it up.

GetNextTimer simply checks what timer should run next a break or a Pomadoro timer.  I’m also planning on keeping track of stats in the feature so I’m incrementing some variables that aren’t currently being used in this example.

        private void TimerButtonClicked()
        {
            if (_timerState == TimerState.STOPPED)
            {
                _timer.Start();
                _timerState = TimerState.RUNNING;
            }
            else
            {
                _timer.Stop();
                _timerState = TimerState.STOPPED;
                GetNextTimer();
            }
            RunOnUiThread(SetTimerButtonText);
        }

        private void TimerElapsedEvent(object sender, ElapsedEventArgs e)
        {
            _countseconds--;
            RunOnUiThread(DisplaySeconds);
            if (_countseconds == 0)
            {
                _timer.Stop();
                GetNextTimer();
                _timer.Start();
            }
        }

        private void GetNextTimer()
        {
            switch (_currentTimer)
            {
                case TimerType.POMODORO:
                    _currentPomodoro++;                    
                    if ((_totalBreak % _longBreakInterval) == 0)
                    {
                        _currentTimer = TimerType.LONGBREAK;
                        _countseconds = _longBreak;
                    }
                    else
                    {
                        _currentTimer = TimerType.SHORTBREAK;
                        _countseconds = _shortBreak;
                    }
                    break;
                case TimerType.SHORTBREAK:
                    _totalBreak++;
                    _currentTimer = TimerType.POMODORO;
                    _countseconds = _pomodroTime;                   
                    break;
                case TimerType.LONGBREAK:
                    _totalBreak++;
                    _currentTimer = TimerType.POMODORO;
                    _countseconds = _pomodroTime;
                    break;
            }
            RunOnUiThread(SetTimerBackground);
        }

The Result

Publishing to Your Phone

It’s a bit premature to think about adding this to the Google Play at this juncture, but it works enough to actually make use of during the day.  To generate an .apk file, right click on the project and select archive from the menu.  The Archive Manager will open up and start bundling up your application.  Once it’s completed, click on the Distribute button.

On the Distribute screen, you want to select Ad hoc, and create a key.  Select your key and click save as.  Now you should have a packaged up Android apk that you can email to yourself and install on your device.

View Source on GitHub
By | 2017-08-19T17:57:16+00:00 January 29th, 2017|Categories: Xamarin|Tags: , , |

Share This Story, Choose Your Platform!

About the Author:

Jason is a Magento Certified Solution Specialist and has been working with Magento for a few years - both with Enterprise and Community Editions.