XamarinForms – Overriding a ContentPage with a custom PageRenderer on Android

The short version:

If you want to have default behavior on all platforms except for Android. Do the following

  • Create your content page with all of it’s goodies
  • Create a custom PageRenderer
  • In the OnElementChanged function
    • Cast the Context property of the renderer to the Activity type associated
    • Take that value and execute the SetContentView method while passing in your new view!

The awesome story version:

I’m building a Xamarin Forms application which has a default implementation in most platforms and a special snowflake behavior on Android. While working through the Xamarin documentation I realized that custom renderers were the way to go.

The default behavior for all platforms is performed through a WebView, which has some custom logic when pages are navigated. While the functionality still works, it doesn’t feel seamless. However, in Android there is already native functionality that really improves the user experience, so I wanted to make sure that if I was on the Android platform, I would not display that web view and I would go straight to the native view.

While navigating through the sea of googlementation(http://bfy.tw/7ljK), I saw various examples on how to do stuff with custom renderers and I walked through them one by one hoping to hit my use case. Most search results demonstrated how to replace the view when doing a custom renderer on a control element with the SetNativeControl method. However, this was a page renderer. So it was time for experiments!

The behavior that I got was that the default view was still rendering and my custom view was not. If commented out the content on the default ContentPage then it would successfully output the custom view. However that in turn meant no default behavior. There was no winning! It was like arguing with a cat!

Hours later, I was able to debug and discover that I had access to the Android Activity. Using the activity, I was able to replace the main content with the SetContentView method like so.

...
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(FooPage), typeof(FooPageRenderer))]
namespace FooApp.Droid.Renderer
{
    public class FooPageRenderer : PageRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs e)
        {
            base.OnElementChanged(e);
            var activity = this.Context as MainActivity;
            var newView = activity.FindViewById(Resource.Layout.foo);
            activity.SetContentView(newView);
        }

    }
}

I hope this helps other people save a few hours in their quests of building awesome things.

Keep on coding on friends!

** Update ** EntityFramework detecting complex type with database first

Originally, I posted a question on StackOverflow

http://stackoverflow.com/questions/21630431/entityframework-detecting-complex-type-with-database-first

While we’re still not using complex types, we’ve worked out a mechanism to preventing our developers from breaking the autogenerated models when re-generating from the DB.

We’ve altered the T4 template generated by EF.

First we’ve created a method in the CodeStringGenerator class

public string BaseClassAndInterfaces(EntityType entity)
{
    var properties = new List<EdmProperty>(_typeMapper.GetSimpleProperties(entity));
    bool hasAuditFields = false;
    if (properties.Exists(property => _code.Escape(property) == "CreatedBy") &&
        properties.Exists(property => _code.Escape(property) == "CreatedDate") &&
        properties.Exists(property => _code.Escape(property) == "UpdatedBy") &&
        properties.Exists(property => _code.Escape(property) == "UpdatedDate"))
    {
        hasAuditFields = true;
    }
 
    return string.Format(" : {0}", hasAuditFields ? "Auditable" : "NotificationObject");
}

If it detects that a table contains those auditing fields, then it prepares to generate the class with a base class “Auditable”, which has those four properties. You’ll notice that if we don’t see the auditing properties, we then set the base class to NotificaitonObject. That’s because we’re still using our own variant of the deprecated Prism NotificationObject.

Next in the T4 template, in the class declaration, we do the following.

<#=codeStringGenerator.EntityClassOpening(entity)#><#=codeStringGenerator.BaseClassAndInterfaces(entity)#>

This basically outputs the

public class MyAwesomeAuditableModel : Auditable

Next it gets a bit messy. However, the goal of the following lines is to prevent the T4 template from autogenerating the columns that are already defined in the base class.

var simpleProperties = new List<EdmProperty>(typeMapper.GetSimpleProperties(entity));
if (simpleProperties.Any())
{
    bool hasAuditFields = false;
    if (simpleProperties.Exists(property => code.Escape(property) == "CreatedBy") &&
        simpleProperties.Exists(property => code.Escape(property) == "CreatedDate") &&
        simpleProperties.Exists(property => code.Escape(property) == "UpdatedBy") &&
        simpleProperties.Exists(property => code.Escape(property) == "UpdatedDate"))
    {
        hasAuditFields = true;
    }
 
    foreach (var edmProperty in simpleProperties)
    {
        if (!hasAuditFields ||
            (code.Escape(edmProperty) != "CreatedBy" &&
             code.Escape(edmProperty) != "CreatedDate" &&
             code.Escape(edmProperty) != "UpdatedBy" &&
             code.Escape(edmProperty) != "UpdatedDate"))
        {
#>
<#=codeStringGenerator.Property(edmProperty)#>
<#
        }
    }
}

That’s it! Now, we have our dev team, re-generating models all day long, high five-ing and hugging each other all through the days because of how awesomely convenient things are now.

Below is a link to the actual T4 template file that you can play with and see how it’ll impact your generated output classes. If you decide to use it, you will likely have to tweak it, to conform to the conventions in your environment.

http://www.ninjacrab.com/randomcodingdownloads/Example.tt

Keep on coding on!

Gitmongous Distributed Repositories

So it’s been a little while as I’ve been busy assisting my beautiful wife on some projects she’s had, I’ve been at the tail end of a working marathon and finally I was on vacation last week. However, I’ve got a bit of free time now and I wanted to share an interesting downside of distributed version control systems.

Sometimes, you’ll have team members who will carelessly deposit massive multi-megabyte files, they’ll alter it to store more multi-megabyte files. These files then duplicate everywhere and make merging insanely painful from the sheer size.

There are solutions to this problem, but it’s a multi-step process that involves a priest, a rabbi, a shaman, 6 shots of vodka and a jump rope.

With that said, this isn’t entirely the same problem in a remote version controlled repository like Subversion. If some unrelated branch has all of the megafiles, you’re not sitting there staring at the progress indicator, scrolling in a pattern that seems like an infinite loop when you have to clone the repository.

So while, it won’t change our decision on what we’re using, it’s good to know and handy to monitor carefully as it will impact all of your team’s productivity.

100 YouTube Subscribers!

Yay!

So I’ve reach a small milestone of 100 YouTube subscribers! Besides the one or two friends that I have, most of them have discovered me either via the TopCoding video 1 or the RandomCoding Visual Studio snippets video.

After creating another 4 TopCoding videos, neither seemed to have the reigning success of the first video.

The Random Coding video 2 had a decent number of views because it was a difficult solution to find and I posted it on StackOverflow. However, all others are relatively unpopular.

I’d like to increase the reach of my videos, but I don’t want to radically change the intent. I want my videos to all be related to programming, yet have some entertaining spin.

I’ll start thinking of some ideas for May, but want to spend most of my energy on Conflicademia.

If any of you do have suggestions, I’m all ears!

Facebook Unity – Keystore missing

So I just recently noticed that the Facebook team wrote a unity plugin to make your games easily integrate with Facebook! I’m super excited to get Conflicademia connected so off I went.

Apparently, a while ago, I attempted this before and found an old Facebook assembly that I couldn’t get working. It also conflicted with the new library and so step one was to remove that booger. This is not likely something anyone else will have to do.

The next thing was to correct an issue with the imported module. In the Assets/Facebook/Editor/android/FacebookAndroidUtil.cs class, there is a method to return the debug key store path. When imported it looked like the following

private static string DebugKeyStorePath
{
    get
    {
         return (Application.platform == RuntimePlatform.WindowsEditor) ?
            System.Environment.GetEnvironmentVariable("HOMEPATH") + @"\.android\debug.keystore" : 
            System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) + @"/.android/debug.keystore";
    }
}

Problem is that the HOMEPATH variable doesn’t include the root drive on my machine. I assume it must include the root drive on the devs @ Facebook who worked on it. So I modified it to the following

private static string DebugKeyStorePath
{
    get
    {
        return (Application.platform == RuntimePlatform.WindowsEditor) ?
            System.Environment.GetEnvironmentVariable("HOMEDRIVE") + 
            System.Environment.GetEnvironmentVariable("HOMEPATH") + @"\.android\debug.keystore" : 
            System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) + @"/.android/debug.keystore";
    }
}

Once that went though, I also went through the steps of creating a keystore and key in Unity through the Player/Platform settings. Facebook wasn’t working, most likely because I actually created this keystore. So I thought it was most likely due to the Key hash that Facebook requests. I used the popular keytool command that I’ve regularly seen on stackoverflow to get the keyhash but that didn’t work. I then enabled development mode and monitored the Android logging output. When I filtered to “Unity” I discovered the following line in the verbose settings

02-16 13:05:24.388: V/FBUnitySDK(22110): sending to Unity OnInitComplete({"key_hash":"[SuperDuperSecretHashKey]\n"})

I want to note that it actually put a line feed at the end of the key, so when I copied and pasted the key into facebook I had to make sure it didn’t include the has key. With that, I did a little bit more experiments and I am connected!

Conflicademia with facebook!
Conflicademia with facebook!

I’d like to get back to my next Topcoding video and this time it’s seriously a challenge! I’m not even at the coding part of it yet either! :p

It’s soooooo obvious!

While using the Newtonsoft Json.Net library I received the error

"Explicitly define an Id for the type using a JsonObject/JsonArray attribute or automatically generate a type Id using the UndefinedSchemaIdHandling property."

When attempting to generate a schema for some types that were created that have circular references. My types were created in EntityFramework database first strategy, so I didn’t want to figure out how to hack the T4 generator to add the Json attribute, and I didn’t quite understand what it mean by using the “UndefinedSchemaIdHandling property”. I suppose it might seem obvious to the author as when I searched the interwebs for an example, this was one of the first results

http://json.codeplex.com/workitem/22569

His response was pretty much recursive error output.

if (user.hasError)
{
  print(error);
  while (user.doesNotUnderstandsError) 
  {
    print(error);
  }
}

Now, unfortunately, I was in that loop for a little bit, looking at the method overloads, thinking about maybe a partial class to add the attribute, staring at the message expecting some epiphany and looked online with no success. It clearly must have been obvious to everyone else besides me, because I couldn’t find any articles on it. So I downloaded the source code for the library, read through the logic until I got to the method that leveraged a public property on the generator class itself, in which you can how you want to handle the undefined schema Id.

So in case any other developers out there, not quite as dumb as I am, still are not able to figure out that error from the exception message alone. Here is a easy code snippet to move past this problem.

JsonSchemaGenerator schemaGenerator = new JsonSchemaGenerator();
schemaGenerator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName;

var result = schemaGenerator.Generate(typeof(MyComplicatedRecursiveTypeWithNoIds));

Happy coding!

Javascript is Evil – Curly brace indentation

So I’m building a little DurandalJS SPA (single page app) test site tonight and while building the view model I do what I’ve typically done in the past when I run into Java curly brace convention, which is to plop that sucker down to the next line a la default VS C# convention.

Little did I realize that it was going to bite me in the booty and give me a crazy run around.

My view Model originally

return
{
    displayName: 'Cats',
    cats: ko.observableArray([])
};

The version that works in js

return {
    displayName: 'Cats',
    cats: ko.observableArray([])
};

¿c wut I did there?

Who in hell would be as so evil to seriously make that a difference and why has JS become the dominant language of the web? Unfortunately the question is rhetorical and it’s reason for success is numerous, but seriously the language is nasty. Once I get my sample running, I’m going to go investigate Typescript and Coffeescript. I’m such a web newb.

Wix Windows Service – Start on install

So I was building a wix setup project for a windows service and kept running into a wall while getting the service to start after a successful install. It kept giving me an error “Verify that you have sufficient privileges to start system services”. I searched through nearly 50 articles that led me on a wild goose chase of the issue being related to actual permissions, dual service control tags, the wait attribute and hacks inside the service installer code behind. To actual solution was ridiculously simple, the error was just too obscure to identify the root cause.

My wxs file had the following contents

<ServiceInstall
  Id="ServiceInstaller"
  Type="ownProcess"
  Vital="yes"
  Name="Ninjacrab Awesome Service"
  DisplayName="Ninjacrab Awesome Service"
  Description="The super awesome service"
  Start="auto"
  Account="LocalSystem"
  ErrorControl="ignore"
  Interactive="no"
  />
<ServiceControl
  Id="StartService"
  Name="NinjacrabAwesomeService"
  Start="install"
  Stop="both"
  Remove="uninstall"
  Wait="yes"
  />

Not sure how it caught my eye, but I noticed the name was different

<ServiceInstall
  Id="ServiceInstaller"
  Type="ownProcess"
  Vital="yes"
  Name="Ninjacrab Awesome Service"
  DisplayName="Ninjacrab Awesome Service"
  Description="The super awesome service"
  Start="auto"
  Account="LocalSystem"
  ErrorControl="ignore"
  Interactive="no"
  />
<ServiceControl
  Id="StartService"
  Name="Ninjacrab Awesome Service"
  Start="install"
  Stop="both"
  Remove="uninstall"
  Wait="yes"
  />

Sure enough this fixed the problem and I went on my merry way.

Random Coding 3 didn’t happen… yet!

Well, I was diligently playing with Nuget packaging and hoping to make a video where I create a Nuget package that hosts the VSIX that I created in random coding two. However, it seems as though Nuget doesn’t support installing a VSIX, item templates or project templates.

I then sat back and thought “Unpossibleh!!!”

I’m certain I’ve downloaded packages that alter Visual Studio’s menus and options and then it hit me.

I built a Visual Studio Extension.

Nuget is a package manager for libraries.

I didn’t need to place the VSIX in a Nuget package, I simply needed to upload the extensions to the Visual Studio Extensions Gallery. There really is no need for a 2 minute video on uploading the package that was created. So now I’ll be off to thinking about my next random coding Video topic.

Regardless you may now download my project and item templates from the Visual Studio Gallery, but it’s incredibly incomplete as I no longer develop Prism apps.

I probably should delete it, but maybe I’ll get back around to it.

Confuzzled…

So I was preparing materials for my “Random Coding 3” video episode and this time the subject was relating to Conflicademia in regards to the loading performance of Android and how to optimize your build in Unity so that the game has reasonable loading performance.

However, as I was prepping my material and generating the relevant evidence to prove why this session improves the performance, I disabled all my “tweaks” and re-launched the game on my phone and to my surprise, the game was still loaded in a respectable time.

I still have no clue why it just works now, though it’s good for my game, it ruined my “Random Coding – Session #3″…

So I will spend time re-creating the performance issue to prevent getting caught by it again, but I don’t think it’ll be the next Random Coding series until performance becomes a problem again and I have some hard evidence on it.

Until then, I did have some other Random Coding video ideas, so I’ll move forward with those soon. Also, I’ll get back to completing the tutorial level.