Creating a Button Bar in Android

In application development we often talk about the importance of consistency, in particular with respect to interfaces.  In mobile application this is even more important.

In Android we often see a standard button bar as shown below.image

This is a common technique that can provide a very flexible consistent layout.  The core XML for your layout file is shown below.image

This is one of the advantages of the RelativeLayout, the ability the precisely control where elements appear.  In this case, we use a LinearLayout to stack the RelativeLayout beneath another LinearLayout.  The RelativeLayout is then configured to anchor itself to the base of the screen.

I am currently using this technique in an application to provide a consistent look for your application.  It gives you flexibility as well.  You can use the RelativeLayout to add additional buttons to the bar.  You could even apply additional layout controls to the RelativeLayout to add more buttons.

Refactoring the IsolatedStorageORM

During the course of the week I got a chance to attend to some of the glaring issues with the framework for managing Isolated Storage on Windows Phone 7.  I am quite pleased with what I came up with.  It permits a good amount of flexibility where needed while still leveraging enough code  in the core to carry out complex operations

Repository Types
The first thing I started looking at was the idea of a singular repository.  When dealing with phone data, for many things you arent talking about multiple users; phones tend to be single user devices so you arent likely to store a bunch of user profiles governing the settings for your application for a number of users.  This concept eventually came though as RepositorySingle to join RepositoryCollection.

IDataHandler
As with the original, the developer writes the actual repository class and inherits from RepositoryBase which will provide the functionality needed to use it with the framework; an example implementation is shown below:

   1: public class IsolatedStorageRepository : RepositoryBase

   2: {

   3:     public RepositoryCollection StorageItems { get; set; }

   4:     public RepositorySingle Options { get; set; }

   5:  

   6:     public IsolatedStorageRepository()

   7:     {

   8:         StorageItems = RepositoryFactory.

   9:             GetRepositoryCollectionInstance("sampleData");

  10:         Options = RepositoryFactory.

  11:             GetRepositorySingleInstance("settings2");

  12:     }

  13: }

While this code looks similar to the code in the prototype, it is actually quite different under the hood.  The main thing was the introduction of IDataHandler which provides method for reading and writing objects from the underlying persistence mechanism; yes the framework can work with other storage mechanisms now. RepositoryFactory contains two overloads for each of the getters. GetRepositoryCollectionInstance is shown below

   1:  

   2:         public static RepositoryCollection GetRepositoryCollectionInstance

   3:             (IDataHandler service) where T : EntityBase, new()

   4:         {

   5:             return new RepositoryCollection(service);

   6:         }

   7:  

   8:         public static RepositoryCollection GetRepositoryCollectionInstance

   9:             (string filepath) where T : EntityBase, new()

  10:         {

  11:             return GetRepositoryCollectionInstance(

  12:                 new IsolatedStorageDataHandler(filepath));

  13:         }

The IDataHandler was introduced to allow me to run my unit tests against the code without a phone behind it and, as it turns out, you cant have IsolatedStorage just cause Smile.  So the gist here is, you can specify your own if you like or you can simply pass the file path and it is assumed that you want IsolatedStorage.

To create your own, you would simply implement IDataHandler, optionally you can inherit from the abstract class DataHandlerBase which will provide some helpful methods for dealing with files.  This is an area that I am targeting for refactor next.

Converters and Attributes
One of the major limitations with the original version was it only supported string properties on any given object.  With this refactor I introduced the concept of a converter associated with the attributes.  The new DataColumnAttribute is now the base class for all typed data column attributes.  Currently, I have added support for int, short, long, boolean, and DateTime.  The entities now look like such:

   1: [DataColumn(0)]

   2: public string FirstName { get; set; }

   3:  

   4: [DataColumn(1)]

   5: public string LastName { get; set; }

   6:  

   7: [DateTimeDataColumn(2)]

   8: public DateTime DateOfBirth { get; set; }

   9:  

  10: [BooleanDataColumn(3)]

  11: public bool IsAlive { get; set; }

 

So now when you use the vanilla DataColumn attribute, the value stored at this column is assumed to be a string.  As you can see we create derivatives to support the various types, the following is the source for BooleanDataColumnAttribute:

   1: public sealed class BooleanDataColumnAttribute

   2:     : DataColumnAttribute

   3: {

   4:     public BooleanDataColumnAttribute(int index)

   5:         : base(index)

   6:     {

   7:         Converter = new BooleanConverter();

   8:     }

   9: }

As you can see, the Converter is simply assigned in the constructor.  The only requirement is it MUST inherit from IConvertFromString which is publically exposed to allow the creation of custom Converters, for example, in a project I am doing I have the DisplayPaneDataColumnAttribute class:

   1: public class DisplayPaneDataColumnAttribute

   2:     : DataColumnAttribute

   3: {

   4:     public DisplayPaneDataColumnAttribute(int index)

   5:         : base(index)

   6:     {

   7:         Converter = new DisplayPaneConverter();

   8:     }

   9: }

And the source for DisplayPaneConverter:

   1: public class DisplayPaneConverter : IConvertFromString

   2: {

   3:     #region Implementation of IConvertFromString

   4:  

   5:     public object FromString(string s)

   6:     {

   7:         if (Enum.IsDefined(typeof(DisplayPane), s))

   8:             return s.AsEnum();

   9:  

  10:         throw new ArgumentException("...");

  11:     }

  12:  

  13:     #endregion

  14: }

Granted I do not like to require the developer extending the attribute to have to make the assignment, I feel that is the job of the framework, might be a possible refactor.

Usage
So with these new changes what does a use case look like?  Well it gets to be very simple and much of the code is removed and stored away.  Below is an example using RepositorySingle where application settings are stored and read:

   1: public partial class Settings : PhoneApplicationPage

   2: {

   3:     private MyRepository repository =

   4:         new MyRepository();

   5:  

   6:     public Settings()

   7:     {

   8:         InitializeComponent();

   9:         Loaded += Settings_Loaded;

  10:     }

  11:  

  12:     private void Settings_Loaded(object sender, RoutedEventArgs e)

  13:     {

  14:         loopingDefaultPane.DataSource.SelectedItem =

  15:             repository.ApplicationSettings.Single.DefaultDisplayPane;

  16:         loopingRefresh.DataSource.SelectedItem =

  17:             repository.ApplicationSettings.Single.RefreshInterval;

  18:     }

  19:  

  20:     private void btnSave_Click(object sender, RoutedEventArgs e)

  21:     {

  22:         repository.ApplicationSettings.Single.DefaultDisplayPane =

  23:             (DisplayPane) loopingDefaultPane.DataSource.SelectedItem;

  24:  

  25:         repository.ApplicationSettings.Single.RefreshInterval =

  26:             loopingRefresh.DataSource.SelectedItem.ToString().AsInt();

  27:  

  28:         repository.SaveChanges();

  29:     }

  30: }

The next step with this code is to abstract out the direct usage of repository instantiation.  Preventing this is, as of right now, I am loading all data each time a new instance of the repository is created, I don’t like this and I am seeking a way for the instances to share data so that it doesn’t have to be loaded and unloaded all the time.

Conclusion
As with any framework some iterations are required.  I want to clean up some last bits of inefficient code.  The main goal is writing tests to confirm the operation on the various pieces, however, this is difficult.  Much of the code for this is internalized to the given assembly, thus creating external unit tests is difficult.

I do look for this to be something I can use in the future, especially with mobile applications, to assist with working with data in IsolatedStorage.  I am providing a download of my test project in Visual Studio 2010 format.

http://cid-630ed6f198ebc3a4.office.live.com/embedicon.aspx/Source/RelationalIsolatedStorage.zip

IsolatedStorage ORM Prototype

I have no doubt someone else has already created something similar to this, but I wanted to take my crack at it for the application I am writing.

The idea was I wanted to create something that would manage my entities and save/read them from IsolatedStorage for a Windows Phone 7 app.  I understand that using reflection on a mobile device is something you really do try to avoid; to that end, I have reduced the amount to the bare essential.

The following code snippet shows a sample use case:

   1: var repository = new IsolatedStorageRepository();

   2: private void Button_Click(object sender, RoutedEventArgs e)

   3: {

   4:     repository.SaveChanges();

   5: }

   6:  

   7: private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)

   8: {

   9:     StorageItem item = repository.StorageItems.FirstOrDefault();

  10:  

  11:     if (item != null)

  12:     {

  13:         txtTwitter.Text = item.TwitterHandle;

  14:         txtAccessCode.Text = item.AccessCode;

  15:     }

  16: }

Most repository patterns tend to be based off some sort of code generation.  Not in this case, since the aim is to abstract away the IsolatedFileStorage, which is nothing more then file access.  Because of this, we allow the user to define their own repository derivation (IsolatedStorageRepository in this case).  Below is the code that is required for this repository:

   1: public class IsolatedStorageRepository : RepositoryBase

   2: {

   3:     public IRepositoryCollection StorageItems

   4:     {

   5:         get;

   6:         set;

   7:     }

   8:  

   9:     public IsolatedStorageRepository()

  10:     {

  11:         StorageItems = RepositoryCollectionFactory.

  12:             GetRepositoryCollectionInstance("sampleData");

  13:     }

  14: }

The idea is for developers to define what the repository will look like and where the data is for each “collection”.  The RepositoryBase contains a method SaveChanges which uses reflection to find the dirty collections in the repository and call their, internal, SaveChanges method.

All data is stored in a delimited fashion within the isolated storage file.  The delimiter used is “**,**”, which attempts to be unique enough to where conflicts should not arise.  Using this technique gives the lines a column look and feel.  To map these columns we use the custom attribute: DataColumnAttribute.  This attributes chief responsibility is to store the index the property maps to.  An example entity is shown below:

   1: public class StorageItem : EntityBase

   2: {

   3:     [DataColumn(0)]

   4:     public string TwitterHandle { get; set; }

   5:  

   6:     [DataColumn(1)]

   7:     public string AccessCode { get; set; }

   8: }

This essentially says the value in position 0 is the TwitterHandle, at position 1 it is the AccessCode.  The assignment is done through reflection and is one of the areas that I may make a change to remove reflection for performance gains.  However, the idea is that IsolatedStorage will not contain that much data, so speed is not always going to be an issue.

The biggest issue with this code at the moment is how to handle the loading of the existing file.  For the moment, when the collection is instantiated the data file behind it is loaded in if it is determined it hasn’t been loaded already.  This means, this will happen whenever you instantiate a new instance.

This also has the potential to run into threading issues, but this code is still in its very early stages.  Also, one has to remember the user is not really going to query the file like they would a database table, or even an XML file.  The structure set within the IsolatedStorageFile is loose, at best.

Goals moving forward are the continued removal of unnecessary reflective code as well as the establishing consistent idea for data access including how to load the data ahead of time in a timely fashion.

The current code and the accompanying example project are downloadable below.

http://cid-630ed6f198ebc3a4.office.live.com/embedicon.aspx/Source/RelationalIsolatedStorage.zip

CodeMash 2011 in Closing

I really love CodeMash.  It is by far one of the most fun and interesting events that I get the opportunity to attend during the year; and it happens on my birthday, so its doubly fun.

My main focus this year was Mobility as I am really diving head first into the mobile application development.  I got the chance to meet a lot of amazing people and attend some amazing sessions on HTML5 for offline mobile app development and my first real look at MonoDroid.

I am making a promise to myself this year that I will learn about HTML5, it really appears that it will be an essential skills, regardless of what area of programming you are using.  I got a chance to see it in action with JQuery touch, and thus another chance to kick myself for not making enough time to fully explore JQTouch.

MonoDroid shows great promise, though still not mature enough where I would consider it a viable alternative to Java programming.  The biggest problem for them, that I see, at the moment is the necessity to include the Mono framework with the apps. I don’t agree with this approach and I have every confidence that they will change this.  If you look at MonoTouch, Mono is not required for those apps, thus the same should be true for Droid apps.

That said, it amazes me how much cleaner .NET code looks compared to most other languages.  Looking at an Android app being developed with Mono compared to Java is like comparing a Picasso to an amateur painting.  It just feels so much nicer with the bevy of language features provided by .NET.

Outside of the sessions, I got meet a lot of consulting companies and other vendors whose products I use; really nice to put a face with those products and see what’s in store for the future, ReSharper 6 looks amazing.

However, the conference would not have been complete without the standard competition for prizes where developers choose to make fools of themselves for prizes.  This year Quick Solutions brought a Kinect to the conference and challenged developers to go for high scores and win cash prizes.  In the end, despite having the highest qualifying score, I came in second when we played the hardest Reflex Ridge level from Kinect Adventures.  But honestly, I was fine with it, really loved the guys I met and the other competitors were just awesome.

SmashDroid also did very well, though not as well as I had hoped.  Some small problems with the app, but overall it was stable and did its job.  But the clock timer didn’t always work.  In the end, it really validated that I need to take a new approach to notifying users with more a service based loop approach.

But CodeMash is CodeMash and it just gets better every year.  Great sessions, great people, great times.  Awesome.  Thanks to everyone for attending and I will see you all next year.

Introducing SmashDroid for Android

One of the aspects of CodeMash that I have come to really enjoy is their dedication to providing REST feeds to allow developers to write applications to work with the data for Sessions and Speakers.

Last year was the first year of this and many people entered, including myself.  Being new to Android development at the time and with not much time to work with my commitment to the client in New York, my application was not where I wanted it to be.  This year, I resolved to start earlier and dedicate more time.  Now with the conference two weeks away, I present: SmashDroid.

image

SmashDroid is an Android app that is able to run on devices supporting Android 1.6 (Donut) and above. It features numerous features, the coolest, I think, of which is the ability to have the device notify the owner when a particular session starts, as well as allowing them to view a schedule.

SmashDroid allows the same drill down functionality commonly found in other CodeMash apps.  It loads the Session and Speaker data each time it starts so as to have the most absolute data possible; this is important because CodeMash does often change its information.

Once you reach the level of a Session, you can choose to have your phone notify you when it starts.  Only one session can be set for notification at a given timeslot, the app will warn you before you overwrite an existing notification.

For the purposes of demonstration: http://www.screencast.com/t/lDKs4k79uErK

Please let me know of any comments. And to answer the question, its not a Windows Phone 7 app cause I don’t own a Windows Phone 7 Smile

Customizing Tabs in Android

In my previous post I demonstrated using the “out of the box” tabs in an Android application.  While this is useful for a basic layout, you quickly come to the conclusion that, frankly, the tabs are hideous and that you need to exert some level of customization over them.

The short answer is that Android does support a deep level of control over the look and feel of the tabs, however, as part of the long answer, this ability has only existed since API Level 4 (Android 1.6).  While this means that your application cannot target Android 1.5 and below.  This is an acceptable compromise, recent studies have shown that the dominant Android OS version is 2.x.

Our base code will the be the same as the end result from the previous post, I will demonstrate how to take this code and use XML to define what the tab looks like.  Here is our end code, for reference.

   1: public class TabTestActivity extends TabActivity {

   2:     /** Called when the activity is first created. */

   3:     @Override

   4:     public void onCreate(Bundle savedInstanceState) {

   5:         super.onCreate(savedInstanceState);

   6:         setContentView(R.layout.main);

   7:         

   8:         TabHost.TabSpec tab1 = getTabHost().newTabSpec("Hockey")

   9:             .setIndicator("Hockey Scores")

  10:             .setContent(new Intent().setClass(this,

  11:                 HockeyScoresActivity.class));

  12:         

  13:         TabHost.TabSpec tab2 = getTabHost().newTabSpec("Football")

  14:             .setIndicator("Football Scores")

  15:             .setContent(new Intent().setClass(this,

  16:                 FootballScoresActivity.class));

  17:         

  18:         TabHost.TabSpec tab3 = getTabHost().newTabSpec("Golf")

  19:             .setIndicator("Golf Scores")

  20:             .setContent(new Intent().setClass(this,

  21:                 GolfScoresActivity.class));

  22:         

  23:         getTabHost().addTab(tab1);

  24:         getTabHost().addTab(tab2);

  25:         getTabHost().addTab(tab3);

  26:     }

  27: }

Running this code yields the following output:

image

Note: I did change the background color from the previous example

Very unsightly. Lets restructure the the tabs to make them look nicer.  How about this:

image

Looks a lot nicer right? So how did we do this, well I first I added a couple things to our project.  The first was a new XML file to house the layout for each tab, the XML is shown below:

image

As with any layout XML in Android, you can do whatever you like with this, for this example, I am keeping things simple.  We have a simple TextView within a standard LinearLayout view group.

The second thing was an image called “tab_divider.png” (available in the source).  This is used to separate the tabs in the view.

Here is our updated code for the Activity:

   1: public class TabTestActivity extends TabActivity {

   2:     /** Called when the activity is first created. */

   3:     @Override

   4:     public void onCreate(Bundle savedInstanceState) {

   5:         super.onCreate(savedInstanceState);

   6:         setContentView(R.layout.main);

   7:         

   8:         getTabHost().getTabWidget().setDividerDrawable(

   9:             R.drawable.tab_divider);

  10:         

  11:         View content = LayoutInflater.from(this).inflate(

  12:             R.layout.tab_content, null);

  13:         ((TextView)content.findViewById(R.id.lblText))

  14:             .setText("Hockey Scores");

  15:         TabHost.TabSpec tab1 = getTabHost().newTabSpec("Hockey")

  16:             .setIndicator(content)

  17:             .setContent(new Intent().setClass(this,

  18:                 HockeyScoresActivity.class));

  19:         

  20:         content = LayoutInflater.from(this).inflate(

  21:             R.layout.tab_content, null);

  22:         ((TextView)content.findViewById(R.id.lblText)).

  23:             setText("Football Scores");

  24:         TabHost.TabSpec tab2 = getTabHost().newTabSpec("Football")

  25:             .setIndicator(content)

  26:             .setContent(new Intent().setClass(this,

  27:                 FootballScoresActivity.class));

  28:         

  29:         content = LayoutInflater.from(this).inflate(

  30:             R.layout.tab_content, null);

  31:         ((TextView)content.findViewById(R.id.lblText)).

  32:             setText("Golf Scores");

  33:         TabHost.TabSpec tab3 = getTabHost().newTabSpec("Golf")

  34:             .setIndicator(content)

  35:             .setContent(new Intent().setClass(this,

  36:                 GolfScoresActivity.class));

  37:         

  38:         getTabHost().addTab(tab1);

  39:         getTabHost().addTab(tab2);

  40:         getTabHost().addTab(tab3);

  41:     }

  42: }

The first thing I will point is the setting of the divider.  This step is NOT required, however it really adds to the look of the tabs and helps the user separate them, you mileage may very.  This MUST be called at this point, if you do not call it first you will not see your divider.

Ok the important stuff here is the inflated view we are using (R.layout.tab_content) defines the layout of each of the tabs.  You could use “n” views here if you wanted, I simply chose to use the same view for each and update the TextView using findViewById method.  It is required that you re-inflate the view each time you wish to use it. Not doing so will cause you to get errors concerning the parent view.

Once you inflate the view and set the various properties as desired, you call the setIndicator(View view) overload.  This overload is only available in API Level 4 and above (that is Android 1.6).

As you can see, taking this step is very easy and straightforward and allows for an impressive amount of customization.

At this point, you have now completed the process of customizing the look of the tabs.  However, if you run the application you may notice that as you switch between tabs, there is no indicator of which tab is selected.  That will be the subject of the next entry, I will only say at this point that it involves: State-Lists.

http://cid-630ed6f198ebc3a4.office.live.com/embedicon.aspx/Public/TabTest.zip

Tabs in Android

For an application that I am writing, I had to use tabs for part of the interface.  Quite honestly, this proved much more difficult then I anticipated; tabs in Android are…. weird, to say the least.  Thus I decided to post a blog entry describing how to use them.  I will save the customization entry for a later entry.

To start you need to understand the basic structure of a page with tabs.  The code below displays the basics of a tab page:
image

First item to note, the root ViewGroup: TabHost.  This does not render any UI, persay, it merely informs the activity that it will be hosting n activities, for each tab.  the TabWidget represents where the tabs themselves will be displayed.  The FrameLayout is where the content goes.  In so far as I have been able to tell, it is easiest to use these default names and have your underlying Activity inherit from TabActivity.

Next, the id values that I am using here are, for what I can tell, required; as is the syntax.  You will see how to access these components in the Activity code.

   1: public class TabTestActivity extends TabActivity {

   2:     /** Called when the activity is first created. */

   3:     @Override

   4:     public void onCreate(Bundle savedInstanceState) {

   5:         super.onCreate(savedInstanceState);

   6:         setContentView(R.layout.main);

   7:         

   8:         TabHost.TabSpec tab1 = getTabHost().newTabSpec("Hockey")

   9:             .setIndicator("Hockey Scores")

  10:             .setContent(new Intent()

  11:                 .setClass(this, HockeyScoresActivity.class));

  12:         

  13:         TabHost.TabSpec tab2 = getTabHost().newTabSpec("Football")

  14:             .setIndicator("Football Scores")

  15:             .setContent(new Intent()

  16:                 .setClass(this, FootballScoresActivity.class));

  17:         

  18:         TabHost.TabSpec tab3 = getTabHost().newTabSpec("Golf")

  19:             .setIndicator("Golf Scores")

  20:             .setContent(new Intent()

  21:                 .setClass(this, GolfScoresActivity.class));

  22:         

  23:         getTabHost().addTab(tab1);

  24:         getTabHost().addTab(tab2);

  25:         getTabHost().addTab(tab3);

  26:     }

  27: }

getTabHost() is a method that is implemented by TabActivity which will return the TabHost, assuming it has the name tabhost.  For each tab, an activity will be loaded into FrameLayout, hence the use of the Intents above; that being the case, do not forget to register your activities with your manifest file.  Running this code will produce the following:
image

Notice that there is some empty space above the “content” that we set.  This is because the default tabs expect an icon to be placed here.  Without it, as you can see, it looks rather odd.  I wont cover customizing tabs to that extent in this entry, but definitely in the next, as understanding it is critical to making tabs look good within a custom application.

The activities can contain pretty much anything you like.  One thing to notice is that we used a LinearLayout to separate the TabWidget and FrameLayout.  The layout you see above is not at all predefined, you can place the TabWidget and FrameLayout anywhere on the page with any number of other views.  For example:
image

Notice I added a TextView above the TabWidget.  When run, this code now looks like this:
image

Come to think of the TabWidget and FrameLayout as “hot zones”, that is places where the specialized effect resides and that can be used in a layout; if that makes any sense Smile

So at this point, I think you can see how tabs can be used within your application.  Obviously, understanding them to this point is not going to do you well except for the most basic of applications.  So to help you forward I will say this: to truly customize your tabs, you will need to targeting Android 2.x, and using the updated setContent call which takes a type View as a parameter.

I am including the source code for this version of the example application, I will be using it again in the next entry when I take this example further with Tab customization.
http://cid-630ed6f198ebc3a4.office.live.com/embedicon.aspx/Public/TabTest.zip

Notifying the User in Android

Wow, what a month November was, epically busy I was with various things both professionally and personally.  First, congratulations are in order to the organizing team for CodeMash; it sold 700 tickets in 3.5 days, absolutely destroying the original record of 31 days for the 2010 CodeMash.  Unfortunately, I was not selected to give my Android talk at the conference, though I do plan to still attend (I was one of the lucky ones who got a ticket during the small window they were available).

I am pleased to say that I was selected to present my Android talk in print via the SmashCode magazine, a magazine whose purpose it is to supplement the attendees of CodeMash.  At the time of this writing, I am preparing to review the second draft of my article, we are very close to completion, so look for it if you are one of those attending the conference in January.

Along the lines of Android, today I would like to talk about a topic of great use: notifications, more specifically, how to raise a notification using the AlarmManager.

First it is important to understand the flow for this process:

  1. Some action is taken in code to create an alarm
  2. The alarm will “go off” at some point in time
  3. The alarm will send an intent that the Android system will hear via a listening receiver
  4. The receiver will create a notification that the user can then respond to
  5. The user responding to the event sends an intent that can achieve just about any end

To begin with, we need to create some code that can create the alarm – below is an excerpt from an application I am writing.

image

The key part of this code is the interaction with the AlarmManager. First look at line 36, the set operation for an alarm.  The first parameter here indicates what type of alarm this is; RTC_WAKEUP states that the alarm should wake the device if it is sleeping, other options are documented here.  The second parameter indicates when the alarm should go off, in milliseconds from the current time.  Here we are using the Calendar class to set the time for 30 seconds from now.  Finally, we send a “pending intent” object, which wraps our original intent (defined on line 28).

Ok, so lets look at this more closely, effectively we have defined an alarm that, at a given point in time, will send an “intent” to android, as we have defined.  Our application will see this intent via this line in our Manifest file:

image

This defines that this receiver should expect to receive and intent of this type.  Receiver as a special type in Android that expect to receive an intent from somewhere.  Ours will inherit from BroadcastReceiver and is responsible for actually creating the notification the user will see on their phone.

image

Ok so there is quite a bit going on here.  First, Android features a class known as the NotificationManager, this class instance will be responsible for “notifying” the user.  Something to point out here is the use of the FLAG_AUTO_CANCEL flag.  This will automatically cause the notification to be cleared when the user selects it.  Leaving this off will cause the notification to sit in the status bar uncleared, unless you clear it manually.  Notice the first parameter to notifiy(), this is the notification code that you would be referencing to clear.

More Intents and PendingIntents, though in this case we are just transferring an object passed with the original intent to the new intent; this new intent will be used to respond to the user acknowledging the notification.  In this case, we are taking the user to one of the activities in our App.

SetLastestInfo will define what our notification will look like; here I am using the basic look.  Finally, we call notify() on the NotificationManager instance which will cause the notification to appear in the status bar and be clickable by the user.  Notice this will happen instantly, hence the reason for using an alarm to initiate it.

So, to conclude, there are times we may want to notify the user of something at a certain time.  The NotificationManager features a notify method to allow us to raise notifications, however, if we want to schedule a notification, then one option is to create an alarm which will use a receiver listening for the intent to create the notification.

Look for this to be used in my upcoming app designed for CodeMash – CodeMashDroid, available near the end of December.

Understanding Intents in Google Android

When creating applications on Android we will inevitably need access to the user’s data on the phone.  Using this data not only creates a much more engaging experience and gives us data that is relevant to our user, but it also makes the application feel more personal; this helps us guarantee the user will keep the application on their device.

There is a caveat to this principle, however.  Data on a users phone is very sensitive and personal to that user, so it is important that we gain clearance from the user to access this data.  On Android, we use Intents, that are granted permission by the AndroidManifest.xml file.  Intents could be used to access contact information, systems resources, or to simply launch a new activity within the application.  All of this needs to be stated before hand so the runtime can be aware of what the application will/could do.

An example of using an Intent is to have the user select a contact from their contact list.

image

In this example, we are using the Intent class to specify we want to perform a “pick” action on a set of data.  The data in this case is the set of data that comprises our contact list.  This code will cause a special activity to start that will display our contact list to the user so they can select a single contact.  If you run this code, as is, you will get a SecurityException as you are attempting to access restricted data without first clearing it with the runtime.  You will need to add the following like to your AndroidManifest.xml file.

image

Note: these tags are defined immediately following the tag block.

With this in place, you will now be ale to have the user pick their contacts, but even if they do, nothing will happen, because there is nothing listening for the return. 

Return to the first block of code and notice our call to startActivityForResult.  This is a special call that indicates the activity being launched will be used to return a result.  To handle this return action, we need to override the method that will receive the callback:

image

Lets walk through this code.  Once we have established that the return is for the action we want (the activity could start multiple activities for results) and that the action completed successfully, we perform some querying functions to extract the picked contact from the data stream indicated by the URI.

Note: I know there is a way to have the user pick multiple contacts, but I have yet to determine the means to accomplish this.  Possibly a custom activity that reads the contact data stream.

This is an example of using Intents to access data on the device that allows the user to not only use your application more effectively, but also gives it a more personal feel.

The above was an example or using a predefined activity to acquire data.  Intents can also be used to start other activities in your application.

Ideally, your application will contain a single Activity that acts as a “home page”, allowing launching points off into other parts of the application.  It is very inadvisable to maintain your entire application in one activity, though circumstances and features may be dictate otherwise.

The first thing to understand about other activities is they must be registered within the AndroidManifest.xml file.  The following code sample illustrates how to add new activities to your application:

image

Lets walk through this.  The name refers to the name of the class within the package.  Starting with a “.” will indicate to start at the package root, or where the main activity is located.  In this case, I have a class CameraActivity located at the same level as my root activity.

Intent-Filter describes what actions the activity can respond to.  In this case, we are saying allow an Intent action with the CameraActivity to initiate the activity CameraActivity, you can almost think of this as an alias for the activity.  The “category” describes what type of action is being taken, Default, in this case, means to simply launch the event.

At this point, we have now taken the appropriate steps to allow Android to run our secondary activity, all we have to do know is tell it to do so, using an Intent.

image

Notice this looks very similar to what we stated above with the exception that instead of passing a standard action (courtesy of the Intent class) we are passing the alias that we specified as the action for the activity.  The filter will see this and realize that it can only start the CameraActivity activity.

Because we used the startActivity function above, this new activity is started without the expectation of returning to the previous activity.  If you wanted to use the new activity to somehow acquire a value to be used by the first activity, you would use startActivityForResult.  And your second activity, would need to indicate that the value had been selecting with the following block of code at the end:

image

First, we create an intent that contains the data that we wish to pass back to the previous activity.  Then we pass the OK result code along with this intent through setResult which will ensure that our onActivityResult function is called once the subsequent call to finish is made and the activity exits.

We can then read this result by processing the incoming intents Bundle:

image

A quick note here, this is an example application that I was working with and thus you see the magic number (3) in the code above.  Ideally, you would use a constant to make this meaningful to the user.  In this case, 3 is the request code I passed in when I called startActivityForResult.

Once you have determine what the request code is and thus how you want to handle the result and the application came back ok, you can then grab the extras from incoming Intent, the variable “data” in this case.

So in this posting you learned the basics about Intents.  Intents are, like Launchers and Choosers in Windows Phone 7, vital to creating usable, interesting, and valuable applications for your users.  They allow you to spread your application out and access valuable data that the user could use with a task.

In Android, there is a lot of security surround their use and the access to the data that they can provide.  Always remember to check your LogCat when debugging crashing errors for SecurityExceptions.

Grand Rapids Day of .NET – Introduction to Android v2.0

Today, October 23, 2010 was the Grand Rapids Day of .NET.  Since I joined NuSoft, now RCM, I have always loved this particular event, because it gives the entire .NET community in Grand Rapids to get together and share ideas.  Ever since the first time I went, I have always wanted to speak at the event.  Well this year, courtesy of my connections with Chris Woodruff, I got a chance to not only speak but also got to experience first hand what it was like to plan, setup, and run such an event; and of course it had to be a record breaking year for attendance.

Despite it being a Day of .NET, we elected to open the talks to all technologies in keeping with the theme that Microsoft is embracing of being “open”. To that end, I was allowed to give my “Introduction to Android” presentation.  It went quite well, despite the networking hurdles and lack of equipment on my end, still getting used to presenting with a Mac.  Thanks to some quick action by a student, I was able to use “join.me” and present my code samples which accomplished the goal of giving a sense of what programming for Android is like, including how archaic it feels next to something like Visual Studio and C#.

As promised for those interested, I am attaching my slides and the sample Eclipse projects that I used during the talk.  Download it below

http://cid-630ed6f198ebc3a4.office.live.com/embedicon.aspx/Public/AndroidTalk_grdodn2010.zip