Monday, June 17, 2013

Svc handling in IIS

I bump into this issue every-time I am running on a new machine.
When trying to access WCF services, they do not work. That's because IIS by default does not handle it.

In Windows Features (Control Panel\Turn Windows features on or off), you need to make sure you have WCF Activation installed.


Thursday, June 06, 2013

More dynamic Android Fragments with MVVM and MVVMCross

 

Scenario: I need to create and load fragments dynamically (by code).

Example: I have a hierarchical data with categories and items, a category can contain items and other categories, like in Windows Explorer:

image

When user clicks on a folder icon, if it’s a folder, it will show the same view with folder’s child folders and items. If it’s an icon, we want to show just a label with the name of the item (in real-life, this can be rendering a document).

In Android, we will need

  1. an activity class and layout (or even a parent fragment) as host for the views. it will create and show the fragments dynamically by code,
  2. a fragment class and layout for the folder view (with a GridView)
  3. a fragment class and layout for the item view (with a TextView)

With MVVMCross, we will also have:

  1. a view-model class for the activity/parent fragment host
  2. a view-model class for the folder view
  3. a view-model class for the item view

With MVVM, when user clicks on a folder icon, the view-model is responsible to handle the event (by a Command) and trigger navigation to another fragment view, depending on the icon. But remember that the view-model must NOT directly instantiate and show the views, this is platform specific UI code.

In MVVMCross, we call MvxViewModel.ShowViewModel method to‘show’ the view-model. By default, what happens is, the MVVMCross finds the associated activity class (based on a name convention) and shows it. But In our case, this won’t work, because the view-models refer to fragments.

The solution is to use MVVMCross features to control the view creation mechanism.

MVVMCross has a built-in MvxAndroidViewPresenter class used to create and show an activity based on the view-model:

	public class MvxAndroidViewPresenter : IMvxAndroidViewPresenter, IMvxViewPresenter
{
public virtual void Show (MvxViewModelRequest request)
{
IMvxAndroidViewModelRequestTranslator mvxAndroidViewModelRequestTranslator = Mvx.Resolve<IMvxAndroidViewModelRequestTranslator> ();
Intent intentFor = mvxAndroidViewModelRequestTranslator.GetIntentFor (request);
this.Activity.StartActivity (intentFor);
}
}

We can tell MVVMCross to use instead our own view presenter implementation which creates and shows fragments inside our activity or parent fragment.

	public class CustomPresenter : MvxAndroidViewPresenter, ICustomPresenter
{
// map between view-model and fragment host which creates and shows the view based on the view-model type
private Dictionary<Type, IFragmentHost> dictionary = new Dictionary<Type, IFragmentHost>();

public override void Show(MvxViewModelRequest request)
{
IFragmentHost host;
if (this.dictionary.TryGetValue(request.ViewModelType, out host))
{
if (host.Show(request))
{
return;
}
}
base.Show(request);
}

public void Register(Type viewModelType, IFragmentHost host)
{
this.dictionary[viewModelType] = host;
}
}

The class is responsible for keeping a mapping between view-model types and the hosts which will instantiate and show the fragments.


We can now can register it for MVVMCross to use it, this being done in the Setup class in the Android app:

public class Setup : MvxAndroidSetup
{
protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
var customPresenter = new CustomPresenter();
Mvx.RegisterSingleton<ICustomPresenter>(customPresenter);
return customPresenter;
}
}

Note that the custom presenter once registered in MVVMCross, will be called for ANY view-model, whenever we call MvvmViewModel : ShowViewModel<T>();


ICustomPresenter and IFragmentHost are some simple interfaces we define in our code in order to nicely decouple the MVVMCross custom view presenter from the fragment host:

public interface ICustomPresenter
{
void Register(Type viewModelType, IFragmentHost host);
}

public interface IFragmentHost
{
bool Show(MvxViewModelRequest request);
}

It makes sense for the activity class to implement the IFragmentHost interface:

public class MainView: MvxFragmentActivity, IFragmentHost
{
public bool Show(Cirrious.MvvmCross.ViewModelsMvxViewModelRequest request)
{
// create view model
var loaderService = Mvx.Resolve<IMvxViewModelLoader> ();
var viewModel = loaderService.LoadViewModel (request, null /* saved state */);

// decide which fragment to create based on the view-model type
var fragmentView = ...

// load fragment into view
var ft = fragmentManager.BeginTransaction ();
ft.Replace (Resource.Id.fragmentHost, fragmentView);
ft.AddToBackStack (null);
ft.Commit ();
}
}

Further more, we can have the activity have its own dictionary to keep a mapping between view-models and fragments, such that we can instantiate fragments based on the view-model class:

		// map between view-model and fragment which creates and shows the fragment based on the view-model type
private Dictionary<Type, Type> vmTypeFragmentTypeDictionary = new Dictionary<Type, Type>();

public bool ShowFragment(FragmentManager fragmentManager, MvxViewModelRequest request, bool addToBackstack)
{
Type fragmentType;
if (vmTypeFragmentTypeDictionary.TryGetValue (request.ViewModelType, out fragmentType)) {

// create view model
var loaderService = Mvx.Resolve<IMvxViewModelLoader> ();
var viewModel = loaderService.LoadViewModel (request, null /* saved state */);

// create fragment view and bind it to the view model
var fragmentView = Activator.CreateInstance (fragmentType) as MvxFragment;
fragmentView.ViewModel = viewModel;

// load fragment into view
var ft = fragmentManager.BeginTransaction ();
ft.Replace (Resource.Id.fragmentHost, fragmentView);
if (addToBackstack) {
ft.AddToBackStack (null);
}
ft.Commit ();
return true;
}
else {
return false;
}
}

public void Register(Type viewModelType, Type fragmentType)
{
vmTypeFragmentTypeDictionary[viewModelType] = fragmentType;
}


To make it reusable, we can even create a base class with this code, called for example MvxActivityFragmentHost and have the activity derive from it:

public class MvxActivityFragmentHost : MvxFragment, IFragmentHost
{
...
}

public class MainView : MvxActivityFragmentHost
{
....
}

Monday, June 03, 2013

make Android device available in Windows and copy the .apk to the device


First, I wasn't able to see the Android device available in Xamarin nor in Windows's USB-connected devices tray icon.

The solution to this is to go to Device Manager \ Other Devices, right click on the Android device item and select 'Update driver' and select to browse for the driver on your disk. Select the location of the Goodle USB driver, which is in the location of where Android SDK is installed (extras\google\usb_driver folder). It's a location similar to this one:

C:\Users\[User]\AppData\Local\Android\android-sdk\extras\google\usb_driver

After this, the Android device item should be not disappear from the Device Manager \Others and also appear in the USB menu in tray icon.


When connectig the USB to the device, a ‘USB Mass Storage’ screen appears with this option.
In order to copy .apk to device, you need to turn on the USB storage.  
You can then copy the released and signed .apk file on the sd_card folder.
Then using the AppInstaller app (search on marketplace) you can select and install the app.

Alternatively, the app can be downloaded and installed from a web location.


You can also install an application using the adb (Android Debug Bridge)

adb install -r [path_to_apk]

the adb is in the Android tools directory: %LocalAppData%\Android\android-sdk\platform-tools (shift + right click in explorer on folder to show 'open command prompt from here')

More info on ADB:
http://developer.android.com/tools/help/adb.html
http://stackoverflow.com/questions/4449540/failure-install-failed-already-exists-when-i-tried-to-update-my-application
http://www.vogella.com/articles/AndroidCommandLine/article.html

Issues when deploying a release version of a Xamarin app made with MVVMCross on a device (Android)

First, you can send to someone the .apk file representing the app and he can install it on the device.
There are few deployment options:
  • Via a Website – A Xamarin.Android application can be made available for download on a website, from which users may then install the application by clicking on a link.
  • By e-mail – It is possible for users to install a Xamarin.Android application from their e-mail. The application will be installed when the attachment is opened with an Android-powered device.
  • Through a Market – There are several application marketplaces that exist for distribution, such as Google Play or Amazon App Store for Android.
See more here http://docs.xamarin.com/guides/android/deployment,_testing,_and_metrics/publishing_an_application
I am trying to deploy the app on a device by sending the .apk file to someone to test it on his device.
First, I need to compile the app in Release mode and sign it. When compiling, Xamarin produces a signed version of the app.
In the \bin\Release folder, there is yourapp.apk and yourapp-Signed.apk files.

Second, I encountered different problems when running the app in Release mode on the device, there were a number of issues with MVVMCross.

The issues are related to the Xamarin linker. If you look to the build properties of the Xamarin app (In Xamarin Studio, that's project Options \ Build \ Android Build \ General tab), there are few linker options:

  1. Don't Link
  2. Link SDK Assemblies
  3. Link All Assemblies

Linking is described in Xamarin docs: http://docs.xamarin.com/guides/android/advanced_topics/linking
'Don't Link' option produces the largest app files, linker not being enabled. The app will definitely work without an issue.
Issues start appearing with the two options, becausue with these two options, the linker is enabled.
The issues appear at runtime, for example I was getting MvvMCross errors written in the application output, mentioning about bindings / events not working right.

When using the 'Don't link' linker option, the app size was 20 MB! When switching to 'Link SDK Assemblies', it was 7 MB!
The idea is to use 'Link SDK Assemblies' linker option and do the necessary to make linker do the right thing.

A solution is to force the linker include code from MVVMCross, using a dummy class.

class LinkerIncludePlease
{
private void IncludeVisibility(View widget)
{
widget.Visibility = widget.Visibility + 1;
}
private void IncludeClick(View widget)
{
widget.Click += (s,e) => {};
}
private void IncludeRelativeLayout(RelativeLayout relativeLayout)
{
relativeLayout.Click += (s, e) => { };
}
public void Include(INotifyCollectionChanged changed)
{
changed.CollectionChanged += (s,e) => { var test = string.Format("{0}{1}{2}{3}{4}", e.Action,e.NewItems, e.NewStartingIndex, e.OldItems, e.OldStartingIndex); } ;
}
}

 More info here:
http://stackoverflow.com/questions/16924178/issues-with-mvvmcross-and-linking-on-android/16924320?noredirect=1#comment24433662_16924320
http://stackoverflow.com/questions/11349864/mvvmcross-monotouch-fail-to-bind-properties-on-a-real-ipad-but-it-works-on-th (including the info and links from comments)
http://spouliot.wordpress.com/2011/08/11/when-to-link-monotouch-applications/

Note there are other options, in the same Build tab: Use shared Mono runtime and Fast assembly deployment. These are not meant to be used on Release (if you have over the options, the explanation is pretty good and you should get a good idea of how they work).



MvvmCross Android app with dynamic fragments

It’s not much different than implementing the app with Java, except using the MvvmCross MvxXXXX classes.
Let’s do a simple exercise: have an activity loading a fragment by code behind.
Here’s the code we need:

1. a MvxFragmentActivity derived class.  It is the corresponding to Android’s FragmentActivity class

[Activity(Label = "View for FirstViewModel")]
public class FirstView : MvxFragmentActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.FirstView);
this.AddChildView ();
}
void AddChildView()
{
var childView = new ChildView () {
ViewModel = new ChildViewModel()
};
var fm = this.SupportFragmentManager;
var ft = fm.BeginTransaction ();
ft.Add (Resource.Id.childViewHost, childView, "childView");
ft.Commit ();
}


2. a corresponding Android layout for it: FirstView.axml
  it needs to have a host widget for the fragment, let’s say a FrameLayout called childViewHost
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/childViewHost" />
</FrameLayout >

 
  3. a MvxFragment derived class. Note the MvvmCross BindingInflate method which makes binding work in the fragment
public class ChildView : MvxFragment
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var ignored = base.OnCreateView(inflater, container, savedInstanceState);
return this.BindingInflate(Resource.Layout.ChildView, null);
}
}
4. a corresponding Android layout  for it: ChildView.axml. Let’s have a textbox bound to the ViewModel’s property
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<TextView
local:MvxBind="Text Hello"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/textView2" />
</LinearLayout>