Posts Tagged Android
Refactoring of logging rules
Posted by Morten in Uncategorized on November 8, 2010
I’ve been working on a logging system for RemoteX Applications, the system is going Live any day now. (In fact since this post will be scheduled it might already have).
So I started out doing the code as straight forward as possible, but it quickly started to nest if-statements as the different logging conditions grew. I got something similar to this:
public void HandleNotification(NotificationEventArgs notificationEventArgs) { if(notificationEventArgs.Type == typeof(Case) ) { var c = getCase(notificationEventArgs.Reference) AddForLogging("Case status changed to "+c.Status); } if(notificationEventArgs.Type == typeof(Resource)) { AddForLogging("Resource changed"); } if(notificationEventArgs.Type == typeof(Cost)) { var p = getProduct(notificationEventArgs.Reference); AddForLogging("Cost updated for product" + p ); } }
Now I wanted the if statements to execute after one anther since they would eventually build up to a single entry in the Log. However as the information that should be logged increased. This method became increasingly hard to maintain.
Also this point is a natural extension point for adding new rules for what should be logged and when. Thus I wanted it to be easy and simple to add things for logging.
By extracting an interface using a variation of the Specification pattern, I get the ILoggingRule.
Each if-statements body is moved to and implementation of the Execute method, and the Boolean expression is expressed in the AppliesFor methods execution. With this and a simple foreach-loop. The above code becomes the following:
public void HandleNotification(NotificationEventArgs notificationEventArgs) { foreach( var loggingRule in _rules.Where( loggingRule => loggingRule.AppliesTo( notificationEventArgs ) ) ) { loggingRule.Execute( notificationEventArgs, AddForLogging); } }
Now this is simple enough to extend using Castle, and it moves the complexity away from the generic log handling. Thus it allows for more complex logging-rules as well.
Here is an example of a logging rule:
public class CaseStatusLoggingRule : ILoggingRule { const string CaseStatusChangeTemplate = "$L{{Log.Case}} $L{{Log.StatusChange}} $L{{Log.Case.Status.{0}}} $L{{Log.To}} $L{{Log.Case.Status.{1}}}."; /// <summary> /// returns true if this rule applies to the notification /// </summary><param name="notificationEventArgs"></param><returns></returns> public virtual bool AppliesTo( NotificationEventArgs notificationEventArgs ) { return notificationEventArgs.EntityType == typeof( Case ) && notificationEventArgs.NotificationType == NotificationType.PropertyChanged; } /// <summary> /// Executes the logging rule /// </summary><param name="notificationEventArgs"></param><param name="logCallback">A callback that will execute the actual logging, first parameter is href, second is message</param> public virtual void Execute( NotificationEventArgs notificationEventArgs, Action<string, string> logCallback ) { var caseHref = "cases/" + notificationEventArgs.EntityRestId; string message = String.Format( CultureInfo.InvariantCulture, CaseStatusChangeTemplate, notificationEventArgs.Changes[0].OldValue, notificationEventArgs.Changes[0].NewValue); logCallback(caseHref, message); } }
As you can see the if this would have been placed in the first code the if-statements and their bodies would wreak havoc on the readability of the code. Now instead its moved to it’s own class, and the logging can naturally be extended without adding complexity other than what’s required for the specific logging criteria.
What’s more funny is that about a month ago I did something similar to how Shuffle handles its serialization of Track entities. It uses the XmlPullParser since I’ve read that it’s the highest performing parser on the Android Platform (please let me know if I’m wrong).
Now parsing a single entity from the Tracks-service follows this procedure:
public ParseResult<E> parseSingle(XmlPullParser parser) { EntityBuilder<E> builder = createBuilder(); E entity = null; boolean success = true; try { int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT && entity == null) { String name = parser.getName(); switch (eventType) { case XmlPullParser.START_DOCUMENT: break; case XmlPullParser.START_TAG: Applier applier = appliers.get(name); if(applier != null) { success &= applier.apply(parser.nextText()); } break; case XmlPullParser.END_TAG: if (name.equalsIgnoreCase(mEntityName)) { entity = builder.build(); } break; } eventType = parser.next(); } } catch (IOException e) { Log.d("Exception", "IO EXception", e); return new ParseResult<E>(); } catch (XmlPullParserException e) { Log.d("Exception", "pullparser exception", e); return new ParseResult<E>(); } return new ParseResult<E>(entity, success); }
As you can see there is nothing entity specific about this code, it’s a template method. The parsing is instead controlled through the dictionary containing something I badly called Appliers. An Applier takes a xml tag and applies it to the Shuffle entity builder.
All parsing is done using this method and the implementing template method classes instead create a list of appliers that can react to an expected xml tag.
An applier looks something like this:
appliers.put("name", new Applier(){ @Override public boolean apply(String value) { specificBuilder.setName(value); return true; } });
I’m using Java’s direct implementation of an interface to allow create the different appliers. Thus the parser just specifies which tag-names it can handle and how to handle them. The parsing is naturally extensible and quite easy to test as well.
I’d appreciate feedback, I’m quite certain there’s a pattern lurking here and I don’t know if the Specification pattern is the correct one.
What’s happening with Shuffle?
Posted by Morten in Uncategorized on July 21, 2010
It’s summer! Which leaves some time for some development on Shuffle.
This is what’s coming:
- Support for small screens, such as the HTC Tattoo
- You can change Synchronization settings without having connection.
- Previously settings were verified by connecting to Tracks before saving. Now there is a test button to test the settings. Allowing you to change them when offline.
There’s also some work in progress that hopefully will be in the same release. We’re working on a model change that will help the synchronization process. No longer should the synchronization process cause un-recoverable deletes, and support for ignoring hidden and completed contexts and projects is underway with it as well.
- There’s a lot of work to do still, but I wanted to give a heads up that something is happening.
Programming for Android
Posted by Morten in Uncategorized on January 15, 2010
So I’ve done my first programming for Android phones and thought I’d write a blog post about the experience.
Programming for Android is a bit different from working with the Compact Framework. The abstraction level for the Dalvik applications is somehow high than the Compact Framework application. One difference for example is that there is no main() method to start your application from.
Central for an Android application is its Android Manifest file. This file describes all services and activities available in the application. This is an XML file that helps describe your application to Android, what it’s capabilities are. Each Activity can then be used as an Entry point, but the manifest also describes Services, Content Providers and Broadcast receivers.
What this gives you is a set of loosely coupled components that interact with each other using Intents, that are passed on a system wide message bus. This allows applications interact not only with central parts of the phone, but also with other applications. Which is quite interesting.
Developing in this manner gives you a set of conventions to follow. I feel that they have managed to find a set of conventions that gives direction in the design of the application, but doesn’t confine you.
The SDK also gives you a set of base classes (template method pattern style base classes) that helps you develop common tasks in a standardized way. An example of these are the Task classes that provide threading and scheduling support. I quickly fell in love the the AsyncTask for example.
Android protects the foreground UI thread quite extensively, making these constructs for doing background work important. For example your not allowed to construct or access any UI elements on background threads. This can be handled by using a special Looper construct that effectively divides your Thread code into different parts. One setup part that’s allowed to access, or setup UI components. And one Loop part that does the actual work.
I worked mainly in the Emulator. The emulator feels fast at first, it takes a while to boot up but is quite responsive once booted. That is until you start typing using the computers keyboard. When you do this the emulator feels slow. Apart from a few issues with the emulator loosing “internet connectivity” when my computer Hibernated.
Now it’s time to mention a tool that’s quite helpful when working with Android applications. It’s the adb.exe logcat tool available in the Android SDK. This tool allows you to watch the result of log statements in runtime, and shows stack traces for those errors the occur but you’ve partially managed to take care of (ignored).
This being said there are some things I’m missing when comparing to working with the Compact Framework. For example, working with XML is much easier in the Compact Framework. I hate having to write my own parsing and serialization code, and there are more tools to help me generate code for doing this in the .Net framework.
Also using the HttpClient in the Android SDK is unnecessarily hard. Https works only with some special glue code. And as far as I can tell everyone seems to simply accept any certificate instead of providing support for showing a UI where the user can accept an unknown (self-signed) certificate.
This is all I can think of right now (this is the second time of writing since I had a crash when I tried to post it…). If there are any questions, please ask them. Hopefully they’ll help generate more knowledge about Android development.
Shuffle 1.4.0 available on Android Market
Posted by Morten in Uncategorized on January 12, 2010
Regarding the previous post, Shuffle 1.4.0 with Tracks synchronization is now available on the Android Market.
Shuffle and Tracks
Posted by Morten in Uncategorized on January 11, 2010
As I mentioned in a previous post I’ve been working on getting the Android application, Shuffle to synchronize with Tracks.
Now that the work has continued this post describes how this feature of Shuffle works. This feature is released with version 1.4.0 of Shuffle and will be available on the Android Market. Special thanks to Andy whom put up with my loads patches.
This feature affects no other features in Shuffle, it simply allows the synchronization between the two systems. If you never configure the synchronization feature it will never affect you.
Configuration
To configure Shuffle to synchronize with tracks start the Shuffle application.
Press menu, and select settings. Select the option called “Change synchronization”
This will open the settings file. Here you can enter the URL to your Tracks installation, username and password. You can also specify the settings for the background synchronization. Simply change the combo box between the different settings.
There is some validation in the settings screen. If you enter a invalid URL the text will change to red to display this.
When you save your settings they are validated by trying to download the contexts from Tracks. If Shuffle cannot get any content from Track with the specified settings it will not save them, but instead display an error message saying that something is wrong with them. You can always cancel.
The Synchronization
Once Shuffle is configured to synchronize with Tracks. You will have an extra button available in the menus across Shuffle. Pressing this will start the synchronization process. To notify that a synchronization is in progress Shuffle will also add a notification message during the synchronization. This is to notify the user that Shuffle synchronizes when doing background synchronization. If you click the notification Shuffle will display the synchronization view.
The synchronization synchronizes the entities in Shuffle in the following order: Contexts, Projects, and Tasks. During a synchronization Shuffle will look at the modification date and select the version of the entity that was latest modified, and merge this entity with the local entity or remote entity, which ever is updated.
Tracks only accept Tasks that have a context set, currently these tasks are excluded from the synchronization process. If you have such task a message is displayed at the end of the synchronization process.
Synchronizing Tracks and Shuffle
Posted by Morten in Uncategorized on January 4, 2010
I did some open-source work last week. I created a synchronization option in the Android program called Shuffle. Allowing it to synchronize with the web tool called Tracks.
Here is a description of how to use the synchronization in Shuffle.
Configuration
Open the settings menu, select the Change Synchronization option.
Specify your Tracks installation URL, username and password.
Make sure that the URL is correctly formatted and that there is no ending slash in the url:
this is wrong: http://my.gtdify.com/
this is correct: http://my.gtdify.com
Usage
On the menu available in most screens there is a button called synchronize. Click it and the synchronization starts. It will first synchronize the contexts, then project and last the Tasks.
Details of the synchronization
The synchronization will try to reduce duplicates that might occur between Tracks and Shuffle. This is done by looking that the description of tasks and the names of contexts and projects.
The synchronization works with a server wins, modification date oriented approach. Should there be a conflict the latest version will win, and in it will try to take as much detail it can from Tracks.
Also, using the “Delete completed” option removes the tasks from Shuffle. This means that the synchronizer wont find them and can’t mark them as finished in Tracks. If you use this synchronization I recommend letting the synchronizer take care of the “cleaning up”. This will be done the second synchronization that a task is complete on.
That is, if you complete a task and synchronize, both tasks will be in both systems as completed. Synchronize again the the task will be removed from Shuffle, but maintained as completed in Tracks.
Happy new year!
Posted by Morten in Uncategorized on December 31, 2009
Happy new year everyone!
To celebrate I’m posting this screenshot.
I’ve been using Shuffle on my HTC Hero for a while now, and been lacking the ability to synchronize it with a online desktop-enables solution.
Well, the above screenshot is the result of what I’ve been doing these last two days. It’s Shuffle that’s synchronized its contexts with a Tracks installation. Still a lot to do, probably a day or three at least. But it’s looking promising.
Happy new year!
Reading the Android developer guide
Posted by Morten in Uncategorized on November 18, 2009
I’ve only glanced at the Android developer guide, never thoroughly read it. Which I’m doing now. I’ve just started so don’t get your hopes up. Never the less, just after reading a few pages I’m already impressed. The guide is easy to overview, and it thus far remains the best API documentation I’ve seen so far.
One of them is the following passage:
By default, each application is assigned a unique Linux user ID. Permissions are set so that the application’s files are visible only that user, only to the application itself — although there are ways to export them to other applications as well.Just look at it, it’s. So elegant, simple, yet it solves a lot of problem by using simple convention and the tools available in the operating system.
Researching Android Calendar
Posted by Morten in Uncategorized on August 12, 2009
I’m itching to buy a HTC Hero. However I want to test it out before committing myself to buying one. One feature in particular I want to test is the Calendar application. A good Calendar application is a must for me.
I got the idea that I could run android on an Emulator to testout the calendar application, to get a look and feel.
I downloaded the SDK for Android, installed it to my dev folder and within minutes I had an emulator running on my desktop. One thing I can mention straight away is that the emulator feels fast, much faster than the Windows Mobile emulator which I’m used to.
However with the basic setup there is no calendar application running in the Android phone. The suggestion on forums is to download the Android source, compile it and then you get the Calendar.apk files which you can install on the phone. However, you cannot compile the source on Windows Machines. Which means I have to figure out some other way of getting my hands on the calendar application.
While researching this I had the chance to look at the development guide for Android, and I must say that I am impressed. The best practice section is great, and I really like the details given in the UI guidelines.