Continuing on my journey into MonoDroid, this post will take a quick look at activities. You may remember from last time that the project template gives us an Activity1.cs file with a click counter. We could launch this from the main launcher / apps list.

But what if my app has a lot of possible screens in it, and I don’t want them all cluttering the apps list? What if I want to launch one from another instead? Are there events or callbacks that let me know when I’m being spun up or spun down?

What Is An Activity

This is perhaps the most succinct definition I've found.
An activity is a single, focused thing that the user can do. - Android Developer's Reference
This one is a bit more complete.
An Activity is an application component that provides a screen with which users can interact in order to do something, such as dial the phone, take a photo, send an email, or view a map. Each activity is given a window in which to draw its user interface. - Android Developer's Guide
The important thing to be aware of here is that your application may be comprised of many activities, but you won't necessarily want to display all (or any!?) of them in the main launcher / app screen.

The [Activity] Attribute

Mono for Android makes it dead simple to include your Activity elements in the AndroidManifest.xml. You might notice that this file isn't even in your project by default. mandroid.exe will generate it based on custom attributes (or merge it if Properties\AndroidManifest.xml does exist).

ActivityAttribute is such a custom attribute.


[Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")]

There are a lot of properties available here, but the ones I’ve used most so far have been

  • MainLauncher - specifies whether the user can launch this Activity from their Apps screen
  • Label - sets the text; this appears in the main launcher
  • Icon - which drawable resource should graphically represent the Activity
  • NoHistory - causes the Activity to be excluded from the history and finished if the user leaves it (i.e., there's no going back)
I imagine that I'll be using LaunchMode and ScreenOrientation in the near future, but haven't needed them quite yet.

The Activity Lifecycle

An Activity has several lifecycle events. That link has a great flowchart as well as a table with descriptions, possible next states, and recommendations on what to do when. No sense in copying it here - go check it out and come back.

For those who learn better by seeing it in action and experimenting, you might write debug statements in each of the methods and experiment in the emulator. Or maybe I can do that for you =p

Launching the activity from the main launcher results in OnCreate followed by OnStart and finally OnResume. Simply clicking the Back button to terminate the Activity results in OnPause, OnStop, and OnDestroy.

I think that should all be pretty self-explanatory. What about Restart? Can we pause and resume without stopping and destroying ourselves?

If you’re in the Activity and press the Home button to navigate away, you’ll get OnPause and OnStop. Going back to the main launcher and starting again, we get OnRestart, OnStart, and OnResume.

In contrast, if you use the emulator’s End Call button to lock the screen, you’ll only get OnPause. You never navigated away in favor of another activity, you just put the to sleep. As you might expect, pressing Begin Call to wake up the device, you only get OnResume.

Launching Activities

The first and most obvious way for an Activity to be launched is from the main launcher / apps screen. We've already seen how this can be achieved simply by setting MainLauncher to true.

An Activity can also launch another. From within an Activity, simply call StartActivity(typeof(YourSuperActivity)). It will become the current activity on the activity stack; the back button will return the user to the calling activity as long as NoHistory was false.

There will be more complex scenarios to follow, but for now, we’re still just covering the basics.

Making A Splash

It should seem pretty clear now how we could make a splash screen.
  • Remove the initial application Activity from the main launcher
  • Create another activity that
    • is started from the main launcher
    • is not part of the Activity history stack
    • has the full screen splash image
    • launches the initial application Activity
My new Splash activity had a couple of new properties on the Activity attribute.

[Activity(MainLauncher=true, NoHistory=true, Theme="@style/Theme.Splash", Label="Foo", Icon="@drawable/icon")]

Note that I’m specifying a theme here. I added it to Resources/Values/Styles.xml.


<resources>
<style name="Theme.Splash" parent="android:Theme">
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>

Also note that the style references a splash image, so be sure to create or add one in Resources/Drawable. Eventually you’ll want to support multiple sizes and densities, but again, we’re still just covering basics.

The guts of our OnCreate method can look something like this


base.OnCreate(bundle);

// For demonstration purposes
Thread.Sleep(2000);

// Move along to the real Activity.
// Since we are NoHistory, this one will be finished
StartActivity(typeof(Activity1));

Optionally, you could add these overrides in your Splash Activity for additional proof that it does get finished and destroyed.


public override void Finish()
{
    System.Diagnostics.Debug.WriteLine("Splash.Finish");
    base.Finish();
}

protected override void OnDestroy()
{
    System.Diagnostics.Debug.WriteLine("Splash.OnDestroy");
    base.OnDestroy();
}

Summary

Activities are a pretty substantial backbone of Android apps. Mono for Android makes it easy to get right down to business and avoid the ceremony of crafting the AndroidManifest.xml. Lifecycle callbacks allow you to perform setup, cleanup, and state preservation logic at critical points, and launching a new Activity can be as simple as calling StartActivity(type).

I’m not sure yet what we’ll look at next time. A couple of the things I’ve been looking at and using in my CodeStock app/hack are the sqlite-net library, and this ActionBar widget, so those are good candidates.

This post originally appeared on The DevStop.