Tuesday, May 29, 2012

Please put some time and love into the WP7 marketplace submission process

I love my Windows Phone

Seriously

I love it

And I love building apps for it too.

But in recent months, I've been finding the Microsoft AppHub slower and slower to use

  • certification which used to take 2-3 days now takes 7+ days
  • post-certification app publishing which used to take an hour, now takes a day
  • beta app publishing which used to take 2-3 hours now takes 2+ days
  • the support on my recent "stuck" app submission has been horrible - the app is currently on day 15 of waiting for testing and the support responses from Microsoft have basically just told me to wait, even though I told them the need for the app was urgent - it was for a conference last weekend :(

The few emails I've received from AppHub support seem to indicate that either Microsoft doesn't care, or that the team simply can't work in an agile way - their automated process has control and when it breaks, then their users don't seem to know how to detect it's broken or how to fix it.

Perhaps also, the Marketplace team are now too busy preparing for Win8 to remember WP7?

From the looks of a straw poll on Twitter today (see some of the comments below), it looks like I'm not alone in noticing the growing and slowing pains.

But I hold out hope that Microsoft care... In fact, I hope and believe that they care a lot...

Dear Microsoft. Please put some time and love into the marketplace. Please stop aiming to match Apple's experience - that's not an experience developers and app publishers love.

Thanks

Stuart


seems the general opinon about marketplace and the certification process is not good. 1 person even said "worse than Apple" :(
 Two weeks ago one of our apps was submitted, but got stuck before being signed, thereby stopping the process.
 Yes, In Firefox, trying to submit an app kicks me into a loop. Forcing me in to *ugh!* Internet explorer.
  I've launched one app and apart from not being able to delete a beta app, the process was find. I also release updates
 yes. update for current app submitted 7 days ago, still waiting for certification
 Haven't tried recently but, in the past, I couldn't submit using any non-IE browsers.
  Yes - beta apps now take 2 days, full app publishing 9 days and my current app is on day 14 "certified" + support no help
 yep, I've even emailed support but no feedback on what's up. My new app taken more than 1.5 weeks to certify, still waiting
 Not recently, but I've certainly seen tweets about it. Maybe I've been lucky and submitted off-peak times.
RT  quick straw poll: have you had issues with the marketplace and/or apphub submission? 
quick straw poll: have you had issues with the  marketplace and/or apphub submission? 

Thursday, May 24, 2012

Showing Console output in Windows Phone 7 Emulator

Sometimes its useful to see some debug output from the internals of your WP7 App without attaching a debugger.

One such time was this morning - where I wanted to trace the memory used in a BackroundAgent in the app I was building:


            string.Format("Peak memory usage {0}"DeviceStatus.ApplicationPeakMemoryUsage);


... and I wanted to trace that in release mode without the debugger attached.

So... to enable console output...

  • in Win32, set the registry key:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\XDE]
    "EnableConsole"=dword:00000001
      
  • in Win64, set the registry key:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\XDE]
    "EnableConsole"=dword:00000001
Then use Console.WriteLine in your app.

Then restart the emulator - a console window will start along with the emulator and then the output will magically appear:


Note: if you use both Console.WriteLine  and Debug.WriteLine in your code, then both will get output when you use the DEBUG build - so you will see every message twice.

For more info, check out: http://nicksnettravels.builttoroam.com/post/2011/01/19/Windows-Phone-7-Console-Window-on-64-bit-machine.aspx and a gem hidden in the middle of http://nicksnettravels.builttoroam.com/post/2010/07/24/Howe28099s-my-Windows-Phone-7-application-being-used-Getting-started-with-the-Microsoft-Silverlight-Analytics-Framework-for-Windows-Phone-development.aspx

Tuesday, May 22, 2012

How do I bind multiple properties in an Android layout element in MvvmCross?

The question....


I'm using MvvmCross to databind my ViewModel to an Android View layout.
From the SimpleBinding example I can see that to bind a value to a property I do this:
  
so Text is bound to the SubTotal property of the ViewModel. But how do I bind to more than one property? In my case I want to bind a ViewModel property called HigherLower to the TextColor attribute of the layout element. I can't add another MvxBind and I can't set MvxBind to an array.

The answer....



The format of the JSON used in the binding expression is a Dictionary of namedMvxJsonBindingDescriptions
public class MvxJsonBindingDescription
{
    public string Path { get; set; }
    public string Converter { get; set; }
    public string ConverterParameter { get; set; }
    public string FallbackValue { get; set; }
    public MvxBindingMode Mode { get; set; }
}
This is used with:
  • the dictionary Key name being the target (View) property for the binding.
  • the binding Path property being the source (DataContext) property for the binding - if Path is not specified then the whole DataContext itself is the binding source.
For Activity/View level axml the DataContext is the ViewModel - but for sub-View axml then the DataContext will normally be a child object of the ViewModel - e.g. inside a ListView the DataContext might be an item inside a List or ObservableCollection owned by the ViewModel.

To specify multiple bindings you can use JSON like:
 {
      'TargetProperty1':{'Path':'SourceProperty1'},
      'TargetProperty2':{'Path':'SourceProperty2'}
 }
For your particular example this might be:
local:MvxBind="
       {
          'Text':{'Path':'SubTotal','Converter':'Float'}, 
          'TextColor':{'Path':'HigherLower','Converter':'MyColorConverter'}
       }"
where your ViewModel is something like:
public class MyViewModel : IMvxViewModel
{
     public float SubTotal { get; set; }

     public bool HigherLower { get; set; }

     // more code here
}
and your converter is something like:
public class MyColorConverter : MvxBaseColorConverter
{
    protected override MvxColor Convert(object value, object parameter, CultureInfo culture)
    {
        return ((bool)value) ? new MvxColor(255,0,0) : new MvxColor(0,255,0);
    }
}
and where that converter is initialized during Setup - e.g. see how the properties of the Converters class are used in TwitterSearch

One sample that shows Multiple Bindings at work is BestSellers - see Click and Text bound in the list itemhttps://github.com/slodge/MvvmCross/blob/master/Sample%20-%20BestSellers/BestSellers/BestSellers.Droid/Resources/Layout/ListItem_Category.axml

How do I do bind custom properties in MvvmCross?

The question


I am using MvxBindableListView to bind a List<> of data objects to a ListView. The layout I am using for the rows has several TextViews. I am successfully binding the Text property for each of these to a property in my data object, but I have found that I cannot bind to TextColor as that property does not exist in Mono For Android TextViews; instead you have use the SetTextColor() method. So how can I bind a data object property to a method?! Below is the code I tried to use:
    

Friday, May 18, 2012

A question about Application LifeCycle in MvvmCross (especially Mono for Android and MonoTouch)


I got asked on StackOverflow about:

I've a ViewModel which contains a Team which has a Players property which is a list of Player objects. Within TeamView the Team is deep loaded, so player data is already in the memory.
What is the best way to pass a given selected Player class instance to a PlayerView?


Here was my answer:

In general navigation, MvvmCross only allows strings to be passed between ViewModels.
The reason for this is that the navigation needs to be done at a platform level via mechanisms such as Xaml Uris or Android Intents.
For the situation you suggest, the general pattern I would typcially use is:
  • that the TeamViewModel gets the team data from the network using an injected ITeamService
  • that the TeamViewModel also uses an injected singleton ITeamCache to cache the Team
  • that the navigation happens via a call like:
this.RequestNavigate(new { teamId, playerId })
  • the PlayerViewModel then receives the TeamId and PlayerId in its constructor, and uses the ITeamCache to collect the right player
This code might look like:
 public class TeamViewModel 
     : MvxViewModel
     , IMvxServiceConsumer
 {
     public TeamViewModel(string teamId, string playerId)
     {
         var teamCache = this.GetService();
         Player = teamCache.GetPlayer(teamId, playerId);
         if (Player == null)
         {
             // todo - handle this error somehow!
         }
     }

     public Player Player { get; set; }
 }
Notice that the code above tests for whether Player is null. This is because there is a problem with your assumption "Within TeamView the Team is deep loaded, so player data is already in the memory."
The problem is that in platforms like Android and WP7, the operating system is free to remove your application from memory and to then restart it later. This is referred to as Tombstoning on WP7, but just seems to be called Killed on Android.
In these cases, then the operating system may restart your application later when the user navigates back. This restart will go direct to the activity where the user last was, and it will remember the back stack - it will then be up to your application to properly rehydrate any required objects back into memory.
Here are some very small pictures explaining this...
Android lifecycle from Xamarin docs enter image description here
For more detail, see Xamarin and MSDN

For your Team/Player case, you might be able to cope with rehydration by:
  • Implementing the ITeamCache as a file-backed object - e.g. it could use a JSON file or a SQLite database as a persistent store for the in-memory data
  • Implementing some logic in your code that refetches data from the network when needed
  • Implementing some emergency-navigate-back-home strategy in these cases - as these cases don't happen that often in many applications on modern resource rich phones.
  • Just crashing - although this isn't advisable...
It's no surprise, that many applications don't handle tombstoning very well...

Note - for small objects, your option 3 (serialization) can works well - however, this wouldn't help you with the situation where app rehydration occurs and a user then navigates back from a PlayerViewModel to a TeamViewModel.

For more on some of the recent changes on Android lifecyle within MvvmCross, seehttp://slodge.blogspot.co.uk/2012/05/android-application-initialization-and.html


Wednesday, May 16, 2012

Monodroid application initialization and lifecycle in MvvmCross

The startup/setup lifecycle pattern for Android (Monodroid) within MvvmCross was one of the features that I loved and borrowed from within MonoCross.

Basically, the idea was to use a Intent.ActionMain startup Activity as a SplashScreen - and to use the OnCreate and OnResume handlers within that screen to schedule the initialisation of the framework and the "Core" MonoDroid application .

Within MvvmCross this idea is embodied in two classes within every Android UI project:

  • a SplashScreen Activity which inherits from MvxBaseSplashScreenActivity,which kicks off platform initialization in its initial creation and which then calls IMvxStartNavigation when it detects that initialization is complete.
  • Setup class which owns and controls the actual initialization of the application, including registration of all necessary models, services, plugins, viewmodels and views.

This structure has worked well for lots of simple Android apps...

The bad news..

However, I've always known that something wasn't quite right... and yesterday on StackOverflow there was a question about how an Android BroadcastReceiver might live within an MvvmCross application - "How do i initialize the mvvmcross framework without a splash activity?"

The problem here is one of understanding the lifecycle of the Process in which an Android application is hosted. The simple model used initially in MvvmCross is not correct. An Android application is not always started by being called with a "ActionMain" Intent.

As well as this "Main" route:

  • applications can be started on a secondary Intent declared for an Activity within the application manifest
  • applications can be started because a Service, BroadcastReceiver or ContentProvider component has been requested by some other application (often this is also done by Intent)
  • applications can be restarted on any Activity because the Android OS has previously purged them out of memory, but the user has now requested them back in (a bit like hydration after tombstoning in WP7)

Because of these challenges, the SplashScreen model of startup in MvvmCross was a little bit broken.

The good news :)

The good news is that this startup code was genuinely "only a little bit" broken - it wasn't a big change that was needed.

Looking at the startup scenarios above I realised that what was needed was a decoupling of framework startup from the SplashScreen Activity - so that any Activity or other component could request initialization without requiring the SplashScreen to show, and without requiring IMvxStartNavigation to run.

To achieve this:

- I've added a singleton manager for setup to every Android application - the MvxAndroidSetupSingleton  https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Platform/MvxAndroidSetupSingleton.cs

- I've modified the way the application Setup is located - it is now located by convention - so your setup class must be called Setup; it must be derived from MvxBaseAndroidSetup; and it must have a public constructor which takes a Context as a parameter.

- This also means that the old code which provides a Setup creation method within SplashScreenActivity must now be removed from existing applications.

- I've added a check to the OnCreate of every MvxActivityView - so that now every view (with the exception of special SplashScreen views) checks that the Setup/platform is initialized before OnCreate completes:


    var setup = MvxAndroidSetupSingleton.GetOrCreateSetup(activity.ApplicationContext);
    setup.EnsureInitialized(androidView.GetType());


- This same code can now also be added to other Components which require the platform to be initialized - e.g. a Service or a BroadcastReceiver

- The Type parameter to EnsureInitialized does provide developers with a mechanism to override application initialization if they want to. For example, they could choose to initialize only small parts of their app for some Activities, and larger parts for others. The details of exactly how they do this is down to them...

- The current SplashScreen is modified just slightly - but it remains in place to allow you to provide a visually pleasant loading screen while your app loads through "Main".

- The opportunity is also there now for additional SplashScreens to be used for "secondary" Activities - for other Activities which may also loaded using external Intents.

Current state...

The new code is checked in to Master and seems to work well across all samples.

It's not yet tested thoroughly on all the scenarios - so there may be problems. I can see these especially happening in any situations where multiple requests to start components within an application might happen simultaneously.

As we get a few more people building multi-Intent applications, BroadcastReceivers, Services and ContentProviders then we may discover other gaps, problems and opportunities.


Key design consideration - your startup time is important

Regardless of these changes, when you design your application setup code, then please pay careful attention to the time it takes for startup to execute. While the Intent.ActionMain route for your app is "protected" by a SplashScreen, the other startup scenarios for your application will not have the same protection.

And, of course, even when you do have a SplashScreen in place, then startup time - or perceived startup time - can still be a key factor for usability, and for how much your users love your apps.

Monday, May 14, 2012

A MonoDroid MvvmCross experiment in autocomplete


I got asked a question about implementing Mono for Android/MonoDroid autocomplete support on Jabbr - http://jabbr.net/#/rooms/mvvmcross
After some hacking at a Google Books API sample, then I created a sample - see the video at:
This example works using a new alpha databinding Autocomplete class and adaptor within the MvvmCross framework. It may be that these classes never actually make the cut to be full time framework members - in which case they can live in some external library instead.
The basic functionality uses databinding on 3 new properties:
  • PartialText - which is a partial text string - sent from the View to the ViewModel
  • ItemsSource - which is the set of current items available for the supplied PartialText - sent from the ViewModel to the View
  • SelectedObject - which is the current selected item - sent from the View to the ViewModel
You can see these setup in the binding xml as:
<Mvx.MvxBindableAutoCompleteTextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  local:MvxItemTemplate="@layout/listitem_book"
  local:MvxBind="{'Text':{'Path':'EnteredText','Mode':'TwoWay'},
  'ItemsSource':{'Path':'AutoCompleteSuggestions'},
  'PartialText':{'Path':'CurrentTextHint'},
  'SelectedObject':{'Path':'CurrentBook'}}"
    />
Note that because of the Android threading model it is essential that every change in PartialText is met by an eventual signalled change in ItemsSource - and this should be a single change in object collection rather than lots of small changes.
Note that this sample uses "simple binding" rather than the full Mvx framework and as a result there is slightly more threading to worry about in the ViewModel.
The binding view and its adapter are not simple code to follow - the binding code is fairly abstract in nature - but they can be found in:
One Two Three
If you are doing anything network-linked then in the long term I believe it may be better to implement a new autocomplete view rather than to use the built into Android today!
And if you are doing an autocomplete sample, then I highly recommend the google books api - it's simple to use and fab for demos :)

Portable Class Libraries in MvvmCross vNext


The first version of MvvmCross provided an excellent way to share ViewModel, Model and Service code between WP7, WindowsRT, MonoTouch and Mono for Android.

This was achieved using solutions where every project platform had:
  • a platform specific UI project containing code unique to that platform (e.g. UI widgets and views)
  • a platform specific class library which was exactly the same code across all projects – the only difference between the different platforms was a difference in the project library/build type.
For example, see the TwitterSearch hierarchy:




This type of solution works really well as a cross platform development architecture - it encourages code reuse, its easy to work in and it delivers product :)

However, there are a few things that I feel could be done better:
  1. Maintaining the different projects requires manual cut and paste maintenance which is tedious and error prone. There is a tool that can help with this – the Project Linker Synchronization Tool - http://msdn.microsoft.com/en-us/library/ff921108(v=PandP.20).aspx – but it only helps a bit…
  2. While the tools from Microsoft and Xamarin were first class, and while plugins like VSMonoTouch and VSMono help fill some gaps, there are still issues with refactoring. Fundamentally the above code architecture forces the project hierarchies to be independent, and this means it is impossible to do automated refactoring across all the hierarchies – and I find automated refactoring a very important tool for development.
  3. Because there are separate project hierarchies and separate build projects, it encourages developers to add non-portable code and to add things like ”#define”
  4. I expect this architecture will become less maintainable when I try to add Silverlight, WPF, WP8, MonoMac and PlayStationStudio to the MvvmCross platform. 

These portability ideas and questions are of course not new – they have been highlighted and discussed before by many other developers, including lots of notable “big fish” in the cross platform development community:

My personal hope for vNext for me is that MvvmCross will be able to achieve portability using the next generation of Portable Class Libraries.

What is a Portable Class Library?

The Portable Class Library tools provide:
  • a special class library project type
  • a set of portability profile definitions – each of which defines an “API level” which libraries must conform to in order for them to be portable. 
When a portable library project is built, then it builds against a given profile, but it only when the code is linked that the platform specific implementations of those APIs are actually located.

To understand PCLs more, Jeremy Likeness did a great 3 part blog post – see http://csharperimage.jeremylikness.com/2012/03/understanding-portable-library-by.html

What’s needed in PCLs for MvvmCross?


The profile I’ve been using in MvvmCross for my PCL work is “Profile 104”

This profile includes:

  • mscorlib 
  • system.core.dll 
  • system.net.dll 
  • system.runtime.serialization.dll 
  • system.servicemodel.dll 
  • system.servicemodel.web.dll 
  • a very small part of system.windows.dll 
  • system.xml.dll 
  • system.xml.linq.dll 

Almost all of these are supported directly in the MonoTouch and MonoDroid platforms, although a very small amount of type redirection and substitution is needed for System.net.dll and system.windows.dll

This is achieved through using dedicated “shim” assemblies which simply redirect the Type load calls from (for example) System.Net.IPAddress in System.Net.dll to System.Net.IPAddress in Monodroid’s System.dll
You can see this redirection in action for MonoDroid in:
By using this profile 104, then I have managed to get the solution down to a much smaller size:

 

Moreover, within this solution above:
  • builds for all of WP7, Droid and Touch within VisualStudio 
  • allows automated refactoring 
  • has no manual cut and paste steps required 
  • the build executables run on WP7 and Droid straight from the VS2010 environment. 
  • Behind the scenes there is now a superb new MvvmCross library and plugin architecture which also uses PCLs – and this makes producing and extending MvvmCross much easier. 

So… what’s remaining to do?


There's one major challenge remaining:
  • I can’t yet get this project to build and run within MonoDevelop on the Mac – so I can’t deploy onto an iOS device. 
This is obviously quite a serious problem!

However, the good news is that the latest Beta versions of MonoDevelop do seem to contain some new support for PCL :)

Currently I’m still playing with this support but the initial result looks good – I can at least load the same VS2010 solution inside MonoDevelop - and the PCL projects and their references all look to be present and correct.

I’m currently investigating some problems with incompatibilities between some core System.Core definitions – especially around System.Action and System.Func - and I do still have to find a way to get System.Windows.dll (touch) and System.Net.dll (touch) into the MonoTouch GAC.

However, this feels really close now…. The future is close… and it’s already looking awesome :)

Thursday, May 10, 2012

One pattern for error handling in MvvmCross


One pattern for how to handle errors/exceptions during async calls in MvvmCross is available in the BestSellers example: MvvmCross BestSellers Sample
BestSellers uses 2 techniques that I find I've used quite a lot in MvvmCross applications:
  • the use of BaseViewModel classes for shared ViewModel code like error handling
  • the use of an app level "error router" to get errors from the ViewModels to UI notifications like UIAlertViews, Toasts and/or MessageBoxes.

At a more detailed level, what BestSellers does is:
Each ViewModel uses a direct call to a webservice for book information. For example the Category List is constructed as:
    public CategoryListViewModel()
    {
        AsyncLoad();
    }

    private void AsyncLoad()
    {
        GeneralAsyncLoad(URL_CATEGORIES, ProcessResult);
    }
where GeneralAsyncLoad is defined in a shared BaseViewModel:
    protected void GeneralAsyncLoad(string url, Action responseStreamHandler)
    {
        try
        {
            IsLoading = true;
            var request = WebRequest.Create(url);
            request.BeginGetResponse((result) => GeneralProcessResponse(request, result, responseStreamHandler), null);
        }
        catch (ThreadAbortException)
        {
            throw;
        }
        // obviously we could do better than catching all `Exception` here!
        catch (Exception exception)
        {
            IsLoading = false;
            ReportError("Sorry - problem seen " + exception.Message);
        }
    }
The ReportError method within the above exception handler uses an injected object - anIErrorReporter.
This injected object is initialised as a singleton during App construction - seeErrorApplicationObject in App.cs
During their construction and setup, the UI projects all subscribe to events from that same singleton - but using an IErrorSource interface instead or IErrorReporter.
This then allows each platform to display it's own error display - e.g.:

Obviously, if you need error handling as well as error displaying - e.g. if you want to retry the asynchronous operation or if you want to load an offline copy of data instead - then you can add this to your error handling within the ViewModel and the BaseViewModel.

Using Custom ViewModelLocators in MvvmCross


In MvvmCross, the "container" for ViewModelLocators is the MvxApplication object. By default it uses a convention based MvxDefaultViewModelLocator which just tries to construct ViewModel instances by using their declared constructors which have string parameters.
If you would like to use your own ViewModel locator, then the easiest way is simple to inherit from MvxViewModelLocator and to provide either public Properties or public Methods which return your ViewModel instances:
e.g:
public class MyViewModelLocator : MvxViewModelLocator
{
    public MyFirstViewModel CreateFirst()
    {
        return new MyFirstViewModel();
    }

    public MySecondViewModel CreateSecond(string aParameter)
    {
        var someLookup1 = ComplicatedStaticThing1.Lookup(aParameter);
        var viewModel = new MySecondViewModel(someLookup1);

        var someLookup2 = ComplicatedStaticThing2.Lookup(aParameter, someLookup1);
        viewModel.DoSomething(someLookup2);

        return viewModel;
    }

    private readonly MyThirdViewModel _third = new MyThirdViewModel();
    public MyThirdViewModel Third
    {
        get
        {
            return _third;
        }
    }
}
If you want to go even lower than this, then you can also implement IMvxViewModelLocator directly instead.
To add the ViewModelLocator to the application, simply instantiate and add it inside your app - e.g:
public class App 
    : MvxApplication
    , IMvxServiceProducer
{
    public App()
    {
        this.RegisterServiceInstance(new StartApplicationObject());

        base.AddLocator(new MyViewModelLocator());

        // to disable the default ViewModelLocator, use:
        // base.UseDefaultViewModelLocator = false;
    }
}

Note: - apart from for design time data, I now very rarely find the need to implement custom ViewModelLocator - in general everything I want to do can be done within the ViewModel construction.