ICS for Ampache.NET

12. May 2012 15:19

I recently got an Asus Transformer TF 300 and finally got a chance to start playing around with Ice Cream Sandwich.  An excellent upgrade from the Kindle fire and my gingerbread phone.  Shortly after that I got an email from an Ampache.NET user saying that they couldn't use the search functionality.  So I fired it up on my new tablet and guess what, there is no search soft key like on the Kindle Fire.  That functionality is no more and the menu key has migrated into the Action Bar across the top of your app.  The action bar is great because it gives the developer the power to decide what soft keys should be visible, i.e. if your app doesn't have a search you have to have one.  This is a step up from gingerbread because you always had the 4 hardware keys (or soft keys on tablets) reguardless of if your app actually used them.  So enter a new menu.xml to support the Action Bar

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/search"
android:title="Search"
android:showAsAction="ifRoom"
android:icon="@drawable/ic_menu_search" />
<item android:id="@+id/playlists"
android:title="Playlists" />
<item android:id="@+id/artists"
android:title="Artists" />
<item android:id="@+id/albums"
android:title="Albums" />
<item android:id="@+id/clearPlaylist"
android:title="Clear Playlist" />
<item android:id="@+id/help"
android:title="Help" />
<item android:id="@+id/configure"
android:title="Configure" />
</menu>

Please note the Search action, it appears first, so that it will appear as the farthest from the right side of the screen.  The show as action will down grade it to a menu item if there is no room in the action bar and finally you specify an icon to use.  Now the real work begins, replacing the menu completely with icon action items...

As of now, Ampache.NET 2.4 is available.  This version, and future versions, will be built against Android 4.0 with backwards compatability down to 2.2.  Froyo was the first release that supported mp3 streaming in the Android SDK, kind of a critical function for this app.

 

CSharpSqlite

7. February 2012 15:57

Sense its inception, the .NET frame work has gone to great lengths to make it easy to communicate and query sql based data stores for long term persisted and relational data.  AOD.NET, Linq to SQL and now Entity frame work have made this process less painful to down right enjoyable.  However, .NET has always suffered from a lack a managed database tool to use in programs.  Microsoft has provided common classes to use to query different data base systems, but sometimes your program only needs an in memory database or a simple embedded database.  Microsoft provides SQL Compact edition and there .NET bindings to Sqlite; however, both of these items suffer from the fact that they are native code and if you take the dll or exe produced on your machine there is no guarantee that it will run at all on a different machine.  Recent an intern of mine was working on a project that utilized Sqlite for a simple database.  She got the program working and we moved it to a server for testing.  The program didn't even start.  Sqlite bindings come with the native code and the program was developed on a 64 bit machine but would run on a 32 server.  And we all through .NET was there to prevent this type of problem.  I am very happy to write today that that issue does not have to happen any more.  C#Sqlite is a C# port of Sqlite.  A full port to full managed code.  No native code!  C#Sqlite  This project compiles into one completely managed (hardware independent) library that you can use just like any other AOD.NET provider.  Furthermore, I have created a clone of this project to introduce some fixes to make the project compile and run under mono.  Now you can write you code on windows with and embedded database and run it on a linux server or a provide it to a mac client.  No recompiling, no build mode changes. One set of dlls to run on all hardware and operating systems.

Android Generic Activity

24. December 2011 05:34

Generally, when you create an Activity the activity is designed for one single purpose, to display data to a user on the screen.  UI code is normally very unforgiving and very specific to the task at hand.  That usualy means that your code is not resuable via generics or inheritance; however, that is not always the case.  Take for example a simple activity who's job is to display a list of strings.  If the objects to are trying to display from all implement a common interface that exposes a Name property then it becomes easy and efficent to create a single activity to display all of your entity's names

[Activity (Label = "@string/lookupLabel",Theme="@android:style/Theme.Dialog")] 
public class LookupActivity<TEntity> : ListActivity where TEntity : IEntity
{} 

Problem is that when you invoke the activity with your type at run time monodroid crashes and burns with IL exceptions...  Turns out that the issue is not in the fact that you have an Activity with a generic parameter, but in the fact that the tool cannot map your activity to the android manifest with the generic parameter.  I am not sure if android will even support an activity with a generic parameter because it will need to be listed in the manifest.  I asked around and one of the guys from Xamarin suggested that I use child classes from LookupActivity for my activity class, forum.

[Activity (Label = "@string/lookupLabel",Theme="@android:style/Theme.Dialog")]		
public class PlaylistLookupActivity : LookupActivity<AmpachePlaylist> {}

[Activity (Label = "@string/lookupLabel",Theme="@android:style/Theme.Dialog")]
public class AlbumLookupActivity : LookupActivity<AmpacheAlbum> {}

[Activity (Label = "@string/lookupLabel",Theme="@android:style/Theme.Dialog")]
public class ArtistLookupActivity : LookupActivity<AmpacheArtist> {}

public abstract class LookupActivity<TEntity> : ListActivity where TEntity : IEntity 
{}

The suggestion works.  Notice the placement of the ActivityAttribute, this is the key as it determines what activities are added to the manifest, and those activities should not have class level generic parameters.

IRJogging

1. October 2011 15:45

I would like to announce that IRJogging, my first android application, is now available in the Android Market.  This application is a route tracker and mapper for jogging, but there is no reason why you can't use it with walking, running, biking, etc.  The application is written in C# using Mono for Android.  I have been working on the app for the last few months in my free time.  Right now it is very basic and only times you and calculates your average speed and distance traveled.  Using GPS it also draws the route for you.  Try it out and let me know what can be done to make it better.

Download IRJogging for Android

MonoDroid GPS Listening

30. July 2011 09:44

It is very easy to get GPS information in Mono for Android.  You need to provide an implementation of ILocationListener and then register that object to recieve location changes.  The only quirk is that your listener should inherit from Java.Lang.Object and not System.Object.  This has to due with the fact that your listener will need to live in the dalvik java world as well as the .net world

public class LocationListener : Java.Lang.Object, ILocationListen

Once you have a listener is it easy to request location updates:

var listener = new LocationListener();
var lm = (LocationManager)GetSystemService(Context.LocationService);
lm.RequestLocationUpdates(LocationManager.GpsProvider, 1000L, 0L, listener);

There are two things to note in the request, the first long parameter is minTime and the second is minDistance.  In this example we will recieve location updates every 1 second.  By setting the distance parameter you will recieve location changes when the device moves x number of meters.

LocationListener.cs (723.00 bytes)

Basic PDF editing in .NET

24. May 2011 18:24

At work we have a program that allows us to batch print many documents at once.  This program is many moons old and has seen better days and well with my company upgrading to windows 7 the program has simply stop working all together in some cases.  Right now this program is really only used for batch printing PDF files, so I suggested that we use an open source pdf library to combine the pdfs and serve up one large pdf file for our users to print.  My boss agreed and so this evening I have found an open source library and did just that.  I am using PDFsharp to do this.  It literally too me ten mintues and six lines of code to do this.  I was plesently shocked about how easy it was todo this.  It was literally as easy as opening two docments, creating a new one and adding the page(s) from the seperate documents to the new one.  Simple.  source is attached and based on the sample from PDFsharp http://www.pdfsharp.net/wiki/ConcatenateDocuments-sample.ashx, it builds and run on mono 2.6 on Ubuntu and should run on any .NET 2.0 or higher, enjoy!

PdfPlay.zip (240.42 kb)

MonoDroid Expandable List

10. May 2011 18:54

About a month ago, Mono for Android 1.0 was released.  I quickly downloaded "trial" version (which is very generous) and started hacking away on my first project.  After working off and on for the last month I think I have enough smarts built up to share some things.  I will start by share my Lazy Expandable List Adapter class for use with, as its name implies, Android Expandable Lists.  The full source code is attached, but I'm going to go over a few of the methods and cool features that a lazy loading parent to child tree viewer can provide.  This posting will assume some basic Android develop skills, i.e. inflating an xml layout and layout integer ids from the Resources.cs/r.java file.  The class is defined as follows:

public class LazyExpandableListViewAdapter<TGroup, TItem> 
: BaseExpandableListAdapter where TGroup : class where TItem : class

From my limited MonoDroid experience I have learned a few things: Android objects live in two places, the CLR and in the Dalvik VM, Android Objects must inherent from java.lang.object, NOT System.Object, and (pure) .NET types DO NOT inherent from java.lang.object.  This can cause some issues with the MonoDroid toolkit because many of the default classes, like for the Expandable Lists, use java.lang.object internally.  This can eliminate pure .NET types from being used.  This class does two things that the default adapters will not easily allow you to do.  1) type safety (TGroup and TItem) and 2) no limitations on what TGroup and TItem are, they do not have to exist the the java world as well.  To accomplish this I had to do two things: 1) custom generic indexers and 2)  custom implementations of GetGroup and GetChild.

public override Java.Lang.Object GetChild (int groupPosition, int childPosition)
{
if (_groups[groupPosition] != default(TGroup) && map.ContainsKey(_groups[groupPosition]))
{
return AVAILABLE_OBJECT;
}
return UNAVAILABLE_OBJECT;
}

To overcome the java object issue I have defined two static readonly java objects, AVAILABLE_OBJECT and UNAVAILABLE_OBJECT.  The are returned if the request item the loaded and not loaded respectively.  With this we can draw a loading view or hydate an inflated view for this item in question based on its availability.  This by itself does not type safety or the ability to read and populate you data.  For that I have created two indexers:

public IEnumerable<TItem> this[TGroup g]
{
get
{
if (map.ContainsKey(g))
{
return map[g];
}
return System.Linq.Enumerable.Empty<TItem>();
}
set
{
if (!_groups.Contains(g))
{
_groups.Add(g);
}
if (map.ContainsKey(g))
{
map.Remove(g);
}
map.Add(g, new List<TItem>(value));
NotifyDataSetChanged();
}
}

public TGroup this[int position]
{
get { return _groups[position]; }
}
public void LoadGroups(IEnumerable<TGroup> groups)
{
_groups = new List<TGroup>(groups);
map.Clear();
NotifyDataSetChanged();
}

This provides you a type safe way to populate and access you data objects and takes care of change notifications to Android when you do so.  The source for this class is attached, anyone reading enjoy.

LazyExpandableListViewAdapter.cs (4.02 kb)

ASP.NET on linux

24. February 2011 18:53

Having recently put up this blog I figured that the next logical step would be to create an actual web site for people to land on, rather that just this blog.  I also have seen a personal site that one of my co-workers has and became a little envious.  I have known that the mono project has supported ASP.NET for some time and sense that is where my skills are and I am using a linux server, I figured that I would take it out for a test drive and see what I could get.  With ASP.NET, the development pattern of the day is Microsoft's MVC frame work.  I fired up Monodevelop and one of the project types is a MVC web appliction.  I have done some SilverLight develoment and am familure with the MVVM pattern.  It is great for unit testing but there are two sticking point, IMO.  First the syntax for the actual binding is tricky to wrap your head around the first time you jump in, second, I find that my ViewModels tend to become very bloated classes because in addition to some logic, the properties on ViewModels must have setter logic to notify of changes.  Using a good template it takes a one line property and turns it into a 10 to 15 line getter and setter.  Add a dozen or so of those and you code files becomes quite large.  I am a big fan of code files under 100 lines, but I can never do that with a ViewModel.  ASP.NET MCV is managed code, so any implementation of the .net framework should run it, and mono is no exception.  What really impressed me is that the Monodevelop guys have put some good work into making the development experience very positive.  They have provided custom dialogs for adding views and controllers.  Monodevelop is an excelent Visual Studio lite.  Then when I hit run, the web site just works, exactly like I would expect it to in Windows.  Nice!  So I take it a step further, adding some AJAX.  In linux land I could not find the java script files for AJAX support.  I had to go out on a windows machine and find them, but once I had them, I just setup and Ajax.ActionLink() and pointed it to a partial view.  Again when I ran the web site everything just work.  Excellent job mono and monodevelop!  Now my site is still quite simple but I have no reason why I wouldn't use ASP.NET, mono, and linux for any serious web site I would ever develop.

WCF Service on Linux

14. February 2011 20:27

As of Mono 2.6 (little old at this point, but it is what's installed on my ubuntu 10.04 machine) is is possible to host and consume basic WCF services.  Good news for .NET developers that like linux like me (linux server hosting is much cheaper than windows servers.)  Creating a service is as simple as following the WCF example service from MSDN.   Not everything is implemented in mono, only Basic Http and net tcp endpoints are implemented and the security model is lacking.  In the attached sample I have a simple service that returns a string.  So you can fire up the service and point your browser to http://localhost:8080/service and you should see a link to the services wsdl.

Now for the harder part, the client.  Like Visual Studio, to consume a service you need to add a web reference to it from Monodevelop.  Also like Visual Studio, Monodevelop run svcutil to generate a client proxy.  That's about where the similarities end.  To add your reference you need to reference the wsdl file directly, i.e. http://localhost:8080/service?wsdl

Not that big of a deal.  Now the first issue I have noticed, the generated client is created inside the Namespace you provide, but that is the only thing generated inside the namespace.  Data Contracts are not included inside your name space.  Again not that big of a deal because you can change the generated file a little bit to correct.  Problem number two is that contracts with a parent/child relationship are not always present.  The Know Type Attribute is not supported in the wsdl generation.  I can work around this, not always ideal but I can deal with it.  Here is the real problem that bugs me.

Currently the generated proxy has the wrong namespace for your service.  This is easy enough to fix, but unlike other issues this will crash your clients if you don't correct it.  Now keep in mind that I'm using an older version of mono, 2.6, and I am using ubuntu and not the official image from Novel.  Inspite of these issues it is still pretty cool what you can do in a complete linux environment.  Attached is a service and client that runs on ubuntu 10.04 with mono 2.6.7.

WCF Mono.zip (15.75 kb)

About the author

John Moore is a C# and .NET developer for Associated Electric Coop (aeci.org) in Springfield Missouri, USA.  I am also a Mono and .NET linux developer in my free time.  I am the author of the banshee-ampache extension.  If you are interested in my work then please look at the extension's source. Please file a bug or contact me with any issues.  Finally a link to my Resume.