Flurry Analytics Portable

We all know about Flurry Analytics, and we know how we can use this with Xamarin in iOS and Android, as well as on Windows Phone.

Well, now there is a portable version that allows the analytics to be implemented in portable class libraries! The portable API abstracts away all the platform differences, but keeps all the power of the Flurry!

This can be found on NuGet and on GitHub.

Features

The features of the portable API are the same as the native API’s, as the portable is more of an abstraction than anything else. So along with all the native features, there are a few nice new once that make the API easier to use.

This is the primary advantage of this library, it allows the analytics to be implemented in portable projects. This is especially useful if you are using a cross-platform framework, such as MvvmCross. There is a sample that you can check out that makes use of all the features.

Starting Sessions

Although the library is portable, each platform needs to start the analytics session natively/differently:

For iOS, it is very simple call StartSession from the AppDelegate:

    AnalyticsApi.StartSession("[API KEY]");

For Android, there are two ways to do this. Either by overriding the OnStart and OnStop methods from each Activity:

    // in OnStart
    AnalyticsApi.StartSession(this, "[API KEY]");

    // in OnStop
    Analytics.EndSession(this);

Or, by using the IActivityLifecycleCallbacks for the Application. This way allows you to start and end the session without having to implement the logic in each Activity. However it is only available from API Level 14 / Android 4.0 / Ice Cream Sandwich.

For Windows Phone, starting the session is done by attaching the StartSession method call to the Launching and Activated events:

    PhoneApplicationService.Current.Launching += (sender, args) => AnalyticsApi.StartSession();
    PhoneApplicationService.Current.Activated += (sender, args) => AnalyticsApi.StartSession();

For each of the platforms, there is also a way to pass the key in to the API, but only start the session later:

    // somewhere in the code
    AnalyticsApi.ApiKey = "[API KEY]";

    // and then a little later
    AnalyticsApi.StartSession();

There is also a boolean property, IsSupported, that will return true if the platform supports Flurry Analytics:

    if (!Analytics.IsSupported)
        Debug.WriteLine("PLatform does not support Flurry, nothing will be tracked.");

Setting Up Analytics

There are a few methods that hide the platform differences. Some examples of this are in the setting of user details, such as SetAppVersion, SetUserId, SetLocation, SetAge and SetGender.

Not only that, there are a few methods that specify how Flurry should communicate, such as SetSessionContinueTimeout and EnableSecureTransport.

Usually these methods should be called before starting the session.

Logging Events & Errors

Along with tracking basic analytics, events and errors can be tracked. There are a few methods that support this: LogPageView, LogEvent, LogTimedEvent, EndTimedEvent and LogError.

Logging timed events has been made much easier by implementing a new pattern for doing this. By calling LogTimedEvent in a using block, you can end the event in case of any exceptions as well as removing an extra call:

    using (AnalyticsApi.LogTimedEvent("EventId"))
    { 
        // perform a long running task
    } 

Before, you would have to ensure that you called EndTimedEvent to avoid any problems:

    try
    {
        AnalyticsApi.LogTimedEvent("EventId");
        // perform the long running task
    }
    finally
    {
        AnalyticsApi.LogTimedEvent("EventId");
    }

Parameters can also be passed with the events using a simple Dictionary:

    var parameters = new Dictionary<string, string> 
    {
        {"ParameterKey", "ParameterValue"}
        {"AnotherParameterKey", "AnotherParameterValue"}
    };
    AnalyticsApi.LogEvent("EventId", parameters);

MVVMCross Startup Crashes

Have you every used MvvmCross in your app, only for it to crash on startup when launching without the debugger? Well it happened for me quite a few times, and its because I was having a brain fart…

After launching the app many times and trying to somehow gain knowledge magically due to repeating the same thing over and over, I decided to add some “logging”:

    // Code to execute if a navigation fails
    private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
    {
        MessageBox.Show(e.Exception.ToString()); // <- LOGGING!
        if (System.Diagnostics.Debugger.IsAttached)
        {
            // A navigation has failed; break into the debugger
            System.Diagnostics.Debugger.Break();
        }
    }

    // Code to execute on Unhandled Exceptions
    private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
    {
        MessageBox.Show(e.ExceptionObject.ToString()); // <- LOGGING!
        if (System.Diagnostics.Debugger.IsAttached)
        {
            // An unhandled exception has occurred; break into the debugger
            System.Diagnostics.Debugger.Break();
        }
    }

This returns a nice little error message:

System.NullReferenceException: Object reference not set to an instance of an object.
  at Cirrious.CrossCore.Mvx.Resolve[TService]()
  at MvvmCrossSample.WindowsPhone.App.<RootFrameOnNavigating>b__0()

So what does that mean? Well, over there I am trying to resolve the IMvxAppStart type:

RootFrame.Dispatcher.BeginInvoke(() => { 
    Mvx.Resolve<IMvxAppStart>().Start();
});

So for some reason, my Setup object wasn’t getting initialized… This is what I had:

    // Show graphics profiling information while debugging.
    if (System.Diagnostics.Debugger.IsAttached)
    {
        // ...

        Setup setup = new Setup(RootFrame);
        setup.Initialize();
    }

Hmm… Maybe the app should start up for the users without debuggers as well? All I needed to do was to move the startup object out of the scope of the if block:

    // Show graphics profiling information while debugging.
    if (System.Diagnostics.Debugger.IsAttached)
    {
        // ...
    }

    Setup setup = new Setup(RootFrame);
    setup.Initialize();

After that, the app worked fine.

In short, don’t just copy-and-paste when using templates, at least read the snippet you are pasting.

Running Mac OS X in Windows 8

Have you ever wanted or needed to run OS X on your Windows PC? I certainly did. As I am a developer of multiple platforms, Android, iOS and Windows, I would like to use one device to develop for all platforms, and of course using Visual Studio.

In order to install Mac OS X in VMWare on a PC, there are a few things that are needed:

  1. the OS X operating system (from an existing Mac)
  2. a Windows machine
  3. UniBeast
  4. VMWare Workstation
  5. Hackintosh VMWare Template for OS X

Now to get started, we have to get the OS X from the physical Mac. The first thing that we are going to do is prepare a bootable USB drive that we will use to install the OS on the VM.
In order to do this, there are a few steps (in order to do anything, we need to make sure that we have downloaded OS Mavericks from the App Store):

  1. Insert a USB Drive of at least 8GB
  2. Use Disk Utility:
    1. Choose USB Drive
    2. Choose Partition (Partition Layout: 1 partition)
    3. Under options choose Master Boot Record
    4. Choose Format (Mac OS Extended (Journaled))
    5. Click Apply
  3. Use UniBeast
    1. Download UniBeast
    2. Run Unibeast
    3. Choose USB Drive
    4. Select Mavericks 10.9
    5. Continue – This takes a while (not less than a minute)

Once we have done this, we should have a bootable USB drive containing Mavericks. Now we need to prepare our Windows machine. As there can only be one instance of hypervisor running, we may have to disable Hyper-V. If you don’t have Hyper-V installed, you can skip this step.

In order to disable Hyper-V, we are going to create a boot profile that will start up our PC without Hyper-V.
The first thing we need to do is to create a copy of our current boot profile. From the command line, execute this command:

    bcdedit /copy {current} /d "Disable Hyper-V"

This command creates a copy of our current profile {current} and creates a new profile with the name Disable Hyper-V. This name could be anything we like. This command will return a GUID that we are going to use in the next step to disable Hyper-V:

    bcdedit /set {INSERT-GUID-HERE} hypervisorlaunchtype off

This command disables Hyper-V for the profile with the GUID {INSERT-GUID-HERE} from the previous command.

If we restart our computer now, we should be presented with two options: “Windows 8.1” and “Disable Hyper-V”. Everytime we wish to use VMWare, we need to start with the “Disable Hyper-V” profile. This profile is exactly the same as the “normal” profile, just without Hyper-V, so you can use this profile for typical development as well.

The next thing to do is install VMWare:

  1. Install VMWare Workstation 10
    (the free VMWare Player will work as well to playback VMs)
  2. Install Hackintosh Template for OS X
  3. Create a Virtual Machine with Workstation 10 Compatibility hardware
  4. Install Operating System Later
  5. Choose OSX 10.9
  6. Add desired Hardware with at least 40 GB disk space allocated to the Virtual Hard Disk.
  7. Run NAT preferably
  8. Insert USB Boot Drive Created on Mac into PC
  9. Boot Virtual Machine
  10. Under VM > Removable Disks > Connect the USB Drive
    (this will remove it from visibility to Windows Host)
  11. Reset the VM
  12. OS X should install

That’s it! You should now have Mac OS X running on your PC!