Mimic the Game Hub Application Bar with a Behavior on the BindableApplicationBar

A couple of days ago Sébastien Lachance wrote an excellent article about mimicking the application bar of the game hub. Really interesting for one of my applications which makes use of a minimal applicationbar that’s also transparant. However quite often the texts of the menu are difficult to read when they don’t have a solid backgroud. That’s exactly what is solved in the game hub: a transparant applicationbar, but when expanded to view the menu it has a solid background. And Sébastien also found a solution how to fix this in our own applications.

However Sébastien is using the ApplicationBar, I’m using the wrapper around the ApplicationBar, called BindableApplicationBar that’s part of the Phone7.Fx project. So how to solve this?

The ApplicationBar and BindableApplicationBar both implement the IApplicationBar interface which prescribes the StateChanged event that is used by Sébastien in his solution. So it looks like we can use the same event, let’s look a little bit closer…

Seems that the code inside the BindableApplicationBar never fires the StateChanged event, so let’s fix this with a little bit of code in the BindableApplicationBar. Please be aware that you need to use the source version of the BindableApplicationBar to be able to fix this. So let’s subscribe the underlying ApplicationBar first, we do this in t he constructor of the BindableApplicationBar by adding one line.

public BindableApplicationBar()
{
    _applicationBar = new Microsoft.Phone.Shell.ApplicationBar();
    _applicationBar.StateChanged += HandleStateChanged;
    Loaded += BindableApplicationBarLoaded;
}

Now we still need to implement the HandleStateChanged method, which is a pretty straight forward implementation you’ve probably seen thousands of times.

private void HandleStateChanged(object sender, ApplicationBarStateChangedEventArgs e)
{
    if (StateChanged != null)
    {
        StateChanged(this, e);
    }
}

So we now have a BindableApplicationBar that has all the features we need to mimic the ApplicationBar of the game hub. The rest of the implementation could be similar to Sébastien’s code. However I thought this is a typical thing that you can easily implement and reuse in a Behavior. I’m not writing behaviors daily, so I thought giving a look at the blog of the Behavior Master himself, Joost van Schaik. About a year ago he wrote a pattern for safe event detachment in behaviors.

So I started with this pattern as a basis. However my eagerness to make this Behavior perfect by immediately using this pattern caused me a lot of trouble. The pattern also tries to safely remove the events when the AssociatedObject aka Control is unloaded. The control I use is of a special type, the BindableApplicationBar, which immediately calls the unloaded event, don’t know why, but it took me almost an hour to find this out. In the end I did a step back and removed the Safe Pattern, and came to the following behavior. The essence is in the highlighted line where I set the BarOpacity property.

public class TransparantToFillApplicationBarBehavior : Behavior<BindableApplicationBar>
{
    private double? _originalBarOpacity;

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.StateChanged += StateChanged;
    }

    private void StateChanged(object sender, ApplicationBarStateChangedEventArgs e)
    {
        if (!_originalBarOpacity.HasValue)
            _originalBarOpacity = AssociatedObject.BarOpacity;
        AssociatedObject.BarOpacity = e.IsMenuVisible ? 1 : _originalBarOpacity.Value;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.StateChanged -= StateChanged;
        base.OnDetaching();
    }
}

And now you want to use it in your BindableApplicationBar, of course.

<ApplicationBar:BindableApplicationBar Mode="Minimized"
                                        BarOpacity="0.6"
                                        IsVisible="{Binding LoggedIn}" BackgroundColor="{StaticResource PhoneBackgroundColor}">
    <i:Interaction.Behaviors>
        <ApplicationBar:TransparantToFillApplicationBarBehavior />
    </i:Interaction.Behaviors>
    <ApplicationBar:BindableApplicationBarMenuItem Text="about+settings"
                                                    Command="{Binding AboutCommand}" />
</ApplicationBar:BindableApplicationBar>

And the end result is like this. Transparent when the menu is collapsed.

Transparant

And non-transparent when the menu is visible.

Fill

Google Analytics on your Windows Phone App in 1 minute

Yes 1 minute. So let’s start immediately.

1 - Open the NuGet Package Manager Console and type:

Install-Package MSAF.GoogleAnalytics

2 - Next, register a new application / web property inside Google Analytics.

image

Then copy the Property ID that starts with UA-.

3 - Past that Property ID inside the App.xaml at this place.

<analytics:GoogleAnalyticsService WebPropertyId="UA-12345-6" />

That’s it. Yes, totally. And? Did you do it under the minute?

Background information

I’ve been in contact with Michael Scherotter for some time about NuGet and MSAF, thanks for the support Michael. Basically the MSAF project is really powerful and can be applied to your Windows Phone project quite easily when you know how to do this. I’ve written about it a couple of times. However when we upgraded to Mango all dlls were upgraded except the Google.WebAnalytics dll. The mismatch in versions was causing a lot of problems because some libraries were asking for a 7.0 version of System.Windows.Interactivity and some were asking for the 7.1 version. I fixed that for the NuGet release, everything is 7.1 based.

Advanced tracking

I also added the code to track a little bit of basic information. You can find that in the GoogleAnalyticsService class in the Analytics folder after applying the NuGet package. There is support for up to 5 Custom Variables. Yes I removed the AppId/ProductId that’s included by default leaving only 4 Custom Variables. You can still add the AppId Custom Variable by your own choice, but I removed it because I have one Google Analytics Web Property per App, so it was useless.

When you want to track your analytics from for example your ViewModel you do something like this.

IAnalyticsTracker tracker = new AnalyticsTracker();
tracker.Track("EventCategory","EventName","EventValue optional");

Reset the back of your Tile through push

Have you ever created the back of your tile with a Push notification? You just add some xml in the Notification Message that you send to the Notification Channel.

<wp:BackBackgroundImage>http://someurlinthewild.com/BackTileBackground.png</wp:BackBackgroundImage>
<wp:BackTitle>Back</wp:BackTitle>
<wp:BackContent>Content</wp:BackContent>

Yeah that’s easy. Ever tried to get rid of it using a Push notification? Yeah, trying to push without content. Thought that should work as well, didn’t. Leaving the full Xml elements from the Push Notification? Didn’t work either. You explicitly have to add an attribute Action and give it the value Clear, like this:

<wp:BackBackgroundImage Action="Clear"></wp:BackBackgroundImage>
<wp:BackTitle Action="Clear"></wp:BackTitle>
<wp:BackContent Action="Clear"></wp:BackContent>

This works for the Title and Count properties for the front of your tile as well. This can all be found in the documentation for Push Notifications as well, but today it took me some time to figure this out.

Unified Ad for Windows Phone - Part 4 - GenericAdProviderForXaml

Alright, we have signed up to a lot of Ad Providers in Part 1, setup the Unified Ad control in Part 2 and even implemented the Remote Ad Provider configuration in Part 3. What’s next?

The Generic Ad Provider for Xaml

Think of the Generic Ad Provider as a very simple AdProvider. It can show Xaml and that’s basically it. You could use this Ad Provider for example to market your own applications within your own applications. So a piece of Xaml with a little bit of text and an HyperlinkButton that links to a Uri. And after a minute the Ad Provider will rotate to the next Ad Provider. The Xaml can be much more complex, we will come up to that in a moment. But first see a small example Ad in Xaml.

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      Width="480"
      Height="80"
      Background="{StaticResource PhoneBackgroundBrush}">
    <Border BorderBrush="{StaticResource PhoneAccentBrush}"
            BorderThickness="1">
        <Grid>
            <TextBlock Text="WP Unified Ad"
                       Foreground="{StaticResource PhoneAccentBrush}" Margin="0"
                       VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="35"/>
            <HyperlinkButton NavigateUri="http://wpunifiedad.codeplex.com"
                             HorizontalAlignment="Stretch"
                             VerticalAlignment="Stretch">
            </HyperlinkButton>
        </Grid>
    </Border>
</Grid>

Where do we put the Xaml?

Ideal it would be on a remote server. But if you don’t have the remote server or you want to have a fallback ad in case the remote server isn’t available you can use the OfflineContent property of the GenericAdProvider.

If you do have the remote server you can set the XamlUri property to the remote Url. In case you want to some more intelligent stuff, like a special ad for each country, or making sure you do something special for the current application, you can make use of the format parameters. The first {0} argument will be replaced by the ApplicationID and the second {1} argument will be replace by the CountryCode. So let’s say I have a server app that returns ads for me, my XamlUri could be configured like this:

http://someurlontheinternet.com/ProvideAd?Country={1}&AppId={0}

If you don’t need one or both arguments you could omit them off course.

Using Phone Styles

If you want to make sure that the advertisements have the same color palette as the Phone settings you can even make use of the usual Phone Resources. Like this example where the Background is set to the PhoneBackgroundBrush and the Border and Text to the PhoneAccentBrush.

<Grid Width="480"
        Height="80"
        Background="{StaticResource PhoneBackgroundBrush}">
    <Border BorderBrush="{StaticResource PhoneAccentBrush}"
            BorderThickness="1">
        <Grid>
            <TextBlock Text="WP Unified Ad"
                        Foreground="{StaticResource PhoneAccentBrush}"
                        Margin="0"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Center"
                        FontSize="35" />
        </Grid>
    </Border>
</Grid>

How to add links

The easiest way to add a link is to put a HyperlinkButton on top of the full Xaml. You don’t have to give it a visual appearance as long as you make it stretch to the full Ad space. Put the Uri you want to link to in the NavigateUri. What? Yes put the Uri in the NavigateUri. But won’t that only work for navigation inside the application, from page to page? Yes but this is improved navigation.

  • http://anythingontheweb.com” and “https://anythingontheweb.com” will start the WebBrowserTask
  • “marketplace://search/some content” will start the MarketplaceSearchTask with “some content” as query.
  • “marketplace://review” will start the MarketplaceReviewTask for the current application.
  • “marketplace://detail” will start the MarketplaceDetailTask for the current application.
  • “marketplace://detail/5f171b43-6ea8-e011-a53c-78e7d1fa76f8” will start the MarketplaceDetailTask for the application with the mentioned ID.

This will enable you to create simple ads that show a webpage. But if you want more, like for example market your other apps you can do this as well.

Complex Ads

I’m not the best designer, but I know a little about Xaml. So I was interested to see if I could get a more complex Ad working. The below Ad for example has a Storyboard attached that changes the opacity of two elements. Sounds easy, it is easy. Just think about what more nice things you can do instead.

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="480"
      Height="80"
      Background="{StaticResource PhoneBackgroundBrush}">
	<Grid.Resources>
		<Storyboard x:Name="Storyboard" AutoReverse="True" RepeatBehavior="Forever">
			<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="One">
				<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
				<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
				<EasingDoubleKeyFrame KeyTime="0:0:3" Value="0"/>
				<EasingDoubleKeyFrame KeyTime="0:0:5" Value="0"/>
			</DoubleAnimationUsingKeyFrames>
			<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Two">
				<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
				<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0"/>
				<EasingDoubleKeyFrame KeyTime="0:0:3" Value="1"/>
				<EasingDoubleKeyFrame KeyTime="0:0:5" Value="1"/>
			</DoubleAnimationUsingKeyFrames>
		</Storyboard>
	</Grid.Resources>
    <Border BorderBrush="{StaticResource PhoneAccentBrush}"
            BorderThickness="1">
        <Grid>
            <Grid x:Name="One">
        		<TextBlock Text="WP Unified Ad"
        			Foreground="{StaticResource PhoneAccentBrush}" Margin="0"
        			VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="35"/>
        	</Grid>
            <Grid x:Name="Two" Opacity="0">
            	<TextBlock Text="by Mark Monster"
            		Foreground="{StaticResource PhoneAccentBrush}" Margin="0"
            		VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="35"/>
            </Grid>
            <HyperlinkButton NavigateUri="http://wpunifiedad.codeplex.com"
                             HorizontalAlignment="Stretch"
                             VerticalAlignment="Stretch"/>
        </Grid>
    </Border>
</Grid>

Unified Ad for Windows Phone - Part 3 - Remote Ad Provider configuration

Did you read the previous parts?

Part 1 – Introduction

Part 2 – Basic Usage

Done? Let’s continue with Part 3, configure the Ad Providers from a remote location.

Step 1, Add the RemoteAdProviderStrategy

Okay, let’s forget about the default AdProviderStrategy. The default just rotates between the different AdProviders, we want more. First we set the AdProviderStrategy property of the AdControl. Just like this.

<Ads:AdControl.AdProviderStrategy>
    <Strategy:RemoteAdProviderStrategy xmlns:Strategy="clr-namespace:MC.Phone.Ads.Strategy;assembly=MC.Phone.Ads" />
</Ads:AdControl.AdProviderStrategy>

Step 2, Create a configuration file

It could very well be that you already have a functional configuration file. When you for example made use of Windows Phone 7 Ad Rotator you already have a configuration file that’s fully compatible with the Unfied Ad. But if you want the full power of the Unified Ad you have to use a different configuration file structure. Xml files explain best by showing an example file.

<?xml version="1.0" encoding="utf-8" ?>
<AdSettings>
  <CountryDescriptors>
    <AdCountryDescriptor Country="US, GB">
      <Probability Value="70" AdProvider="None" />
      <Probability Value="10" AdProvider="AdMob" />
      <Probability Value="10" AdProvider="MobFox" />
      <Probability Value="10" AdProvider="AdDuplex" />
    </AdCountryDescriptor>
    <AdCountryDescriptor Country="DE">
      <Probability Value="15" AdProvider="PubCenter" />
      <Probability Value="15" AdProvider="AdMob" />
      <Probability Value="20" AdProvider="AdDuplex" />
      <Probability Value="50" AdProvider="None" />
    </AdCountryDescriptor>
    <AdCountryDescriptor>
      <Probability Value="20" AdProvider="PubCenter" />
      <Probability Value="20" AdProvider="AdMob" />
      <Probability Value="20" AdProvider="AdDuplex" />
      <Probability Value="20" AdProvider="Smaato" />
      <Probability Value="20" AdProvider="MobFox" />
    </AdCountryDescriptor>
  </CountryDescriptors>
</AdSettings>

Let examine the last AdCountryDescriptor element lines 16-22. Because this AdCountryDescriptor element doesn’t have a Country property this will be the default configuration to fall back to when there isn’t any other that matches the country of the user.

Inside the AdCountryDescriptor elements there are Probabilty elements, they consist of two values: a probability and an AdProvider name. You can best compare the Probabilty with the chance in percentage that the specific Ad Provider is chosen during AdRotation. If you don’t want an AdProvider to be shown during rotation you either put the probability to 0, but better just remove the element. The AdProvider property is the name of the AdProvider that has to be filled in. Currently that would be one of these AdProviders: AdMob, MobFox, AdDuplex, PubCenter, Smaato, InnerActive, None and GenericAdProviderForXaml.

If you want no ads to be displayed for a certain percentage of the time you should use the None AdProvider. In a future post we will discuss the GenericAdProviderForXaml, for now just see it as a remote location where you put some Xaml that will be displayed as an Ad.

So we now have a default configuration, what about specific country configurations? Yes important of course, by specifying the Country attribute of the AdCountryDescriptor element you can specify to which countries a specific configuration belongs. Which could be one country, or multiple countries. Each country is only allowed once in the configuration but you can specify multiple countries for one configuration by separating the country-codes by a “,”. For the country-codes make sure you use the two-letter codes from the ISO_3166-1, so for the UK this is GB.

Step 3, Where to put this configuration file?

Put it somewhere on a webserver where it’s accessible through http or https. Though if you don’t want to configure it remotely but ship this Xml file as part of your application that’s fine as well. But be aware that the only way to change your shipped configuration file is by shipping a new version of your application. But to have local configuration file makes sense even if you have a remote configuration file. When for example your remote config file cannot be accessed (could be any reason) the RemoteAdProviderStrategy will fallback to the local configuration file. So let’s configure the strategy accordingly.

<Ads:AdControl.AdProviderStrategy>
    <Strategy:RemoteAdProviderStrategy xmlns:Strategy="clr-namespace:MC.Phone.Ads.Strategy;assembly=MC.Phone.Ads"
                                        LocalProviderSettingsUri="Ads/AdSettings.xml"
                                        RemoteProviderSettingsUri="http://someurlinthewild.com/ads.xml" />
</Ads:AdControl.AdProviderStrategy>

The RemoteProviderSettingsUri needs to be filled with the remote location url. So put the file somewhere on an internet website, your own is probably the best so that you can easily change it when you want to. The local provider settings can be used as alternative to the remote location in case you don’t want to remotely configure your ads but it could also be used as fallback when the remote url is not available for some reason. For the LocalProviderSettingsUri you need to be aware that it’s an ResourceUri, not an internet Uri. This means that if your xml file has a BuildAction “Content” you can put a simple relative Uri in there, like in the above example. If you would add the Xml file with BuildAction “Resource” you would have to use an Uri like this “/MC.Phone.Ads.Example;component/Ads/AdSettings.xml”.

Hope this explains the Remote Ad Provider configuration a little bit. Please post any questions.