CategoryC#

Android Activities, it’s all about overriding event methods

In my previous post, I talked about class Attributes on Activities.
This post is about overriding event methods to influence the behavior of the Activity.

Activity LifeCycle

When a new Activity is created, the template overrides one event method; OnCreate.

[Activity]
public class MyActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
       .....
    }
}

The OnCreate is part of the Activity LifeCycle.
It is important to understand the Activity LifeCycle, it is one of the fundamentals of an android application.
The OnCreate method works like the Page_Load method of a WebForms page.
This is ideal for setting up the Activity.

For instance:

  • loading layout files
  • updating controls
  • binding event handlers

All event methods of the Activity LifeCycle:

  • OnCreate
  • OnStart
  • OnResume
  • OnPause
  • OnStop
  • OnDestroy
  • OnRestart

When an activity changes state, the corresponding event method is called.
All these methods can be overridden and implemented.

The Activity exposes a lot more overridable event methods.
These are methods I use a lot:

Options menu

The following event methods are used for controlling the options menu:

public override bool OnPrepareOptionsMenu(IMenu menu)
{
       // add your options items to the menu here
      return base.OnPrepareOptionsMenu(menu);
}

public override bool OnOptionsItemSelected(IMenuItem item)
{
    // detect selected menu item and handle action
    return base.OnOptionsItemSelected(item);
}

The OnPrepareOptionsMenu is called when the options menu is created. Custom options can be added to the menu argument.
When an option item is clicked, the OnOptionsItemSelected is called with the selected option item as argument. I usually use a switch on item.Id to detect which item is selected.

The back button

The following event method is called when the back button is pressed:

public override void OnBackPressed()
{
    // handle back button
    base.OnBackPressed();
}

the base.OnBackPressed() provides the default back button behavior. Remove this line when you want to disable the default back button behavior, but I do not recommend it. People expect this behavior from the back button.

Creating Dialogs

This following event method is called when ShowDialog() is called in the current Activity.

public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
    // Create and return dialog here.
}

This method is used to create a dialog.

This should help you get on your way with creating your Activities.

Android Activities, it’s all about the attributes

As promised in my previous post (way too long ago, I know! I’m Sorry!!!), I would talk more about the Activities for Android applications in .Net (By Xamarin).
I want to start with one of the most important parts of the application, the Activities.

[Activity]
public class MyActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
       .....
    }
}

This is the very basic of an Activity. It inherits from Activity and has an attribute Activity. The Activity base class provides many overridable methods, like onCreate, which is called when the Activity is created (think of the Page_Load in WebForm pages).

The Activity attribute has many interesting properties, some of them are listed below:

  • Label, this provides the label for the application, shown in the Android app screen
  • MainLauncher, this is an indication whether the Activity is the main activity and will be started on application startup.
  • Icon, Sets the icon for the application
  • Theme, sets the theme for the application, this can be a custom theme or a predefined theme.
  • ConfigurationChanges, sets which changes are handled by the application itself.
[Activity(Label = "My application",
          MainLauncher = true,
          Icon = "@drawable/icon",
          ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize,
          Theme = "@android:style/Theme.NoTitleBar")]
public class MyActivity : Activity
{
       .....
}

This is an example of the Activity with attributes. No custom code is needed to make this work.

The ConfigurationChanges is set to “Orientation” and “ScreenSize”, this means that orientation changes are handled by the Activity. I use this a lot with WebViews, this stops the application from reloading the page when the orientation changes.

The Theme “NoTitleBar” removes the titlebar from the application. This makes it possible to create your own title bar.
A list of all available predefined themes can be found here

Intercepting and filtering a result of a DataService Request

I’m a big fan of services. It really helps a loosely coupled design.
A WCF DataService isa RESTful service. This means that data can be get, modified or deleted based on the HTTP method used.

  • A GET request will return data
  • A POST request will insert data
  • A PUT request will update data
  • A DELETE request will delete data

It supports many data types (like SOAP, JSON, XML) without any extra programming. This makes it very flexible.

I was experimenting with a DataService and was trying to figure out how I can intercept a request and filter the results before returning the dataset.
In the example below, I am filtering a request for Participants. I only want to show participants with a specific Status.

public class ParticipantService : DataService
{
   // This method is called only once to initialize service-wide policies.
   public static void InitializeService(DataServiceConfiguration config)
   {
       config.SetEntitySetAccessRule("Participants", EntitySetRights.AllRead);
   }

   [QueryInterceptor("Participants")]
   public Expression<Func<Participant, bool>> FilterOnActiveStatus()
   {
       return participant => participant.Status == 2;
   }
}

The QueryInterceptor Attribute intercepts the request for “Participants” and it allows us to return an expression which filters the resultset.

Reading properties by property name via reflection in C#

Reflection can come in handy in some situations.

Some of the situations in which I really like reflection is when you have to read properties when you only have the property name.
For instance when mapping data from xml to strongly typed objects and vice versa.

public T ReadProperty<T>(object model, string propertyName)
{
     Assert.IsNotNull(model, "model");
     Assert.IsNotNull(propertyName, "propertyName");

     var result = default(T);
     PropertyInfo property = model.GetType().GetProperties().FirstOrDefault(p => p.Name == propertyName);
     if (property != null)
     {
         var propertyResult = property.GetValue(model, null);
         if (propertyResult is T)
         {
             result = (T) propertyResult;
         }
         else
         {
             Logging.Info(string.Format("{0}: Property {1} is not of type {2}", typeof(PropertyReader), propertyName, typeof(T)));
         }
     }
     else
     {
         Logging.Info(string.Format("{0}: Property {1} not found in type {2}", typeof(PropertyReader), propertyName, model.GetType()));
     }
     return result;
}

This method reads a property from an object and returns the data in the type provided by the generic type.

This is just one of the few situations in which reflection is very powerful.

Mobile devices, detection and views in .Net MVC

Mobile is hot, and will probably only get hotter. Sites need to be viewable on any kind of devices, so mobile detection is a hot issue.

Headers

But how do we detect mobile devices?

Every http request send to a page or website contains headers. These headers give us information about the sender. A nice tool to intercept a request and check the headers is fiddler. I have been using this tool for some years now, and I gained a lot of knowledge about requests and responses.


GET http://vicreative.nl/ HTTP/1.1
Host: vicreative.nl
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4

This is an example of a request to my website. This request is sent by Chrome.

The header we are looking for is the User-Agent. This header gives us information about the indentity of the browser who send the request. In above example, you can see that the request is send with a Chrome browser. This header will also tell us when the request is send by a mobile browser. I used a mobile device emulator to fake a mobile request:

GET http://www.vicreative.nl/ HTTP/1.1
User-Agent: Opera/9.80 (Android 2.3.7; Linux; Opera Mobi/46154) Presto/2.11.355 Version/12.10
Host: www.vicreative.nl
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, multipart/mixed, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Device-Stock-UA: Opera Mobile Emulator (no stock UA available)

Another header to keep in mind is the following:


X-Requested-With: XMLHttpRequest

This header information tells us that this is an ajax request. This is also used to determine the IsAjaxRequest property in a MVC controller.

So many devices

Now that we know that every device and browser sends its own User-agent header, you will probably think that it’s impossible to know all devices and browsers and operation systems. Well, you’re right.

I think that’s why the mobile device detection of Microsoft does not work so great. They just can’t update it enough to make it work for all devices.

So do not use HttpCapabilitiesBase.IsMobileDevice. It will only work if you override it and set the correct value.

There is a NuGet package which contains many devices and is updated regularly: 51 degrees.mobi

It also comes with a config, which allows you to set actions for mobile devices, like redirects.

Setting Mobile context

Whether a browser is mobile, can be manually overridden:

HttpContext.SetOverriddenBrowser(this.Request.Browser.IsMobileDevice
                                        ? BrowserOverride.Mobile
                                        : BrowserOverride.Desktop);

The 51 degrees framework will automatically do that, so you don’t really have to do this, but it can come in handy when you want to force it for some reason.

The Browser object has a lot more useful properties for determining which view to display, for instance the property Platform.

Creating Display Modes

As described above, the Browser object has a lot of information about the requested device.
At application start, we can create specific display modes for device types. For instance for Andriod devices:

DisplayModes.Modes.Insert(0, new DefaultDisplayMode("android")
{
    ContextCondition = Context => Context.Request.Browser.Platform == "Android"
});

Keep it clean and create a (static) class in the App_start folder called DisplayModes which contains a method RegisterDisplayModes which registers all display Modes:

public class DisplayModes
{
    public static void RegisterDisplayModes(DisplayModeProvider displayModeProvider)
    {
        displayModeProvider.Modes.Insert(0, new DefaultDisplayMode("android")
        {
            ContextCondition = Context => Context.Request.Browser.Platform == "Android"
        });
        .....
    }
}

Now call this method from the App_Start in the Global.asax file:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    DisplayModes.RegisterDisplayModes(DisplayModeProvider.Instance);
    .....
}

Now that we have registered a display mode for android, we can create android specific views.

Know that the first matching DisplayMode will be used. So the order of registration is very important! The mobile display mode is already registered.

Mobile views

Let’s make some mobile views now.

Creating views for devices is really simple, just add the name of the view before the extension of the file and the ViewEngine will automatically pick up the view for the correct device.

mobile-views

This example has a default Index view (index.cshtml) a mobile view for all mobile devices (Index.mobile.cshtml) and a android specific view (Index.android.cshtml).

This works for all views, including layouts, partial views, shared views, strongly typed views etc.

Because we registered the android DisplayMode at position 0 (first), all android devices will be provided with this view.  When the device is not an android device, but is a mobile device, the mobile view will be presented. For all other devices, the normal index view will be displayed.

Testing

It’s kinda difficult to test this from your developer laptop/pc, but there are many tools who simulate mobile devices. I like the mobile emulator from Opera. It has a lot of presets for mobile devices.

But there are many other emulators, even microsoft has its own.

Caching issues MVC 4

Now that you have created and published your mobile friendly application, you deploy it to your server and quickly check it on your mobile to see if it really works. And it works! Hooray!

Soon people start complaining about seeing strange views. It looks like a mixture of mobile and default views.

This is because of a bug in MVC4. The MVC team has released a patch for it, available here on NuGet.

Reading Excel files in .Net using C#

Customers and project managers seem to have one thing in common, they both like working with Excel. Though Excel isn’t really my favorite application, there is one thing very nice about it. It is very easy to read an Excel file in .Net.

In this post, I will try to describe how you can read and parse an Excel file.

This post is based on a computer which has Office 2010 installed. If you try to read excel files on a computer or server without office installed, you first need to install this.

Interfaces

Nobody seems to care about interfaces anymore, that’s why I’m telling you that I do think it is important. It makes your application loosely coupled and unit testable! It also makes you think about generic solutions for problems.

Program to an interface, not an implementation!!

The interface I created for my reader file:


public interface IFileReader<T>
{
     T Read(string filename);
}

I created the following class which implements the IFileReader interface


public class ExcelReader : IFileReader<DataTable>
{
     public DataTable Read(string filename)
     {
      ....
     }
}

The connection string

The Excel file can be read as a database, using an OleDb  (Object Linking and Embedding, Database) connection. This is a connection designed by Microsoft for accessing a variety of sources.

I use two different connection strings for reading Excel files, one for the good old xls files and one for the xlsx files.

I check on file extension for detecting the right connection string (I know this is dirty!!!)


 string connectionString;
 var filename = filePath.Trim().ToLower();
 if (filename.EndsWith(".xlsx"))
 {
    connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\";", filePath);
 }
 else if (filename.EndsWith(".xls"))
 {
    connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\";", filePath);
 }

Please put these connection strings in the connectionstrings section of your app.config or web.config!!

Reading sheets

Now that we have a connection string, we can create a connection.


OleDbConnection connection = new OleDbConnection(connectionString);
connection.Open();

Make sure you use try/catches for the connection.
Now that the connection is open, the next step is reading the tables. The tables in Excel are the available sheets.


DataTable tableSheets = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

Every row in the tableSheets is a sheet


string dataTableName = tableSheets.Rows[0]["TABLE_NAME"].ToString(); 

The above code will give you the name of the first sheet. The sheet name can be used to retrieve the data of this sheet. You can also use a foreach or for loop to retrieve all sheet names if you need to collect data of all sheets.

Reading data


OleDbCommand command = new OleDbCommand(string.Format("SELECT * FROM [{0}]", dataTableName), connection);
command.CommandType = CommandType.Text;

This Command reads the data of the first sheet.
I like to use a DataTable to store the retrieved data. A DataTable is a representation of one table and contains both Columns and Rows.
The first row in a excel sheet are read as columns. The data in the Rows can be retrieved by using the name of the column as index key (like a dictionary).

So we need to fill the DataTable with the result of the Command:


var dataTable = new DataTable();
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(command);
dataAdapter.Fill(dataTable);

The OleDbDataAdapter executes the command and fills the DataTable with the resultset.

The datatable is filled and ready to use. Make sure you handle exceptions properly!

Clean up!

The only thing left to do is clean up! Close the connection and dispose all disposable objects! Why? Because you don’t want memory leaks or other strange behavior in your application! Always dispose disposable objects!  

if (connection.State == ConnectionState.Open)
connection.Close();
connection.Dispose();
command.Dispose();
dataAdapter.Dispose();

I recommend using usings instead of calling dispose!

Setting readonly variables

A lot of people don’t seem to realize that setting readonly variables is indeed possible, it can only be done from inside the constructor:

public class SomeClass
{
   private readonly ISomeService _someService;
   private readonly ISomeOtherService _someOtherService;

   public SomeClass(ISomeService someService, ISomeOtherService someOtherService)
   {
      _someService = someService;
      _someOtherService = someOtherService;
   }
}

This is perfectly fine working code and I strongly recommend it. I use this a lot with dependency injection (DI). This makes sure that the injected instances cannot be overridden, because they can only be set in the constructor.
That’s why I really don’t like the requirement of a parameterless constructor in UserControls in WebForms. There is no possibility for injection, only resolving is possible.