Ad Platform for Windows Phone 7 with launch in Australia

Hey there good people of the internet, 

A while back I blogged about my Adventure Initiation about  2 to 3 weeks into it there was a minor hiccup in the form of an announcement that an Ad Platform being made available for Windows Phone 7.  In the spirit of finishing something that I gave so much to start I am pleased to announce that I have just had my showcase application for Windows Phone 7 certified. 

Just like any other new business you have to be able to perform all roles.  I guess its time to interview myself :)  

Whats is this showcase application?  

Well it is a preview application for AdGAC my Ad Platform for Windows Phone 7

Hold on I read Adventure Initiation you really left your paid employment to build an Ad Platform, are you crazy?  

You need to be  >= a little crazy to make steps forward.  

Well your interviewing yourself so you can tick the crazy box 

It would be my pleasure :)  

Why AdGAC? 

AdGAC, yep the name was inspired by the great .NET GAC :) .  But moreover it stands for Global Ad Community.  One of the biggest things I found I really really, really really, really did not like about advertising was the content rarely connected with anything I was interested in.  So what I did was integrate a toolbar into my Ad Control to allow me, the end user, the choice to personalise my ad experience thus helping with the prioritisation of content.  Furthermore if I configure it once it will it will travel between applications :) .  I see it as a win win win – win^3 – scenario for end users, advertisers and developers.  End users say what they want and hence will be engaged with the advertisers that want to connect with them and developers still make their hard earned cash. 

So what about a demo? 

I have made it so you can download the AdGAC preview application or you can search for it through marketplace using either “adgac” or “advertise” .  Sure, while the containing application is not beautiful it serves the purpose I built it for, that is, a vehicle to demonstrate the beauty of AdGAC Ad Platform i.e the advertisements and engagement model.  Be sure to use the flick up gesture to get your toolbar to personalise your profile for better matched content – note the effectiveness of this will become more apparent as more Ads are made available.  Here are some screenshots. 

AdGAC preview application

AdGAC preview application

AdGAC preview application

AdGAC preview application

What media types are supported for advertiser campaigns? 

We support text, image and animated gifs of dimensions 480×80 px 

What ways can Advertisers target their campaigns to capture the correct audiences attention? 

Currently we have 5 options available and some more under development.  The five available are: 

  1. by audience Interest
  2. by audience Gender
  3. by audience Age
  4. by Device Manufacturer
  5. by Audience Location

You can find more information here 

In what way can the end users interact with the Advertisers ad content , in other words what click action types / calls to action? 

Currently we have 5 options available and some more under development.  The five available are: 

  1. click to Website – good for directing traffic to your website
  2. click to Call – useful for directing calls into your corporate call centre e.g Charity organisations or Pizza companies
  3. click to SMS compose – useful for SMS promotions
  4. click to Marketplace Detail – useful for driving downloads of a single application or music that is available through Microsoft Marketplace
  5. click to Marketplace Search – useful for driving downloads of all your applications or music that is available through Microsoft Marketplace

You can find more information here 

How do you create campaigns and register applications? 

I  also built an accompanying website used by Developers to manage their applications  and  and Advertisers to manage their advertising campaigns www.AdGAC.com

AdGAC website Advertising for Windows Phone 7

AdGAC website Advertising for Windows Phone 7

Looks like you’ve been pretty busy? 

Surely have :)  

Where to now? 

  • Well I have opened the site for registrations of interest.  I would like to gauge stakeholder interest [ thats you :) ]  and would like to run a closed alpha to gather some feedback.   So if you’re a Developer or Advertiser and would like to be involved in the closed alpha then please do jump on the site www.AdGAC.com and go to the developer or advertiser tab and press Register or go direct through here Register and fill out the form
  • This release is streamlined to get the platform out for some feedback.  I have a whole bunch more ambitious ideas and the passion to implement them so stay tuned :)

Thanks for your time Nick 

No problems 

To my dear tech readers -  you now probably understand why the tech posts this month were fewer then usual I look forward to getting you some more tech when I am back from my holiday early Jan .  Until then, happy Christmas and New Year! 

Kind Regards, 

Nick Harris

Windows Phone 7 News

Hi, 

What a busy month Dec is turning out to be eitherway here are some handy news notices relevant for Windows Phone 7 devs. 

  1. We had our first WP7 dev drinks this week.  It was good to get out and talk about WP7 dev over a few drinks and to demo some WP7 apps in development.
  2. The Windows Phone 7 MSDN Documentation has been updated
  3. Developer payouts for Windows Phone Marketplace will begin in the Last week of January 2011
  4. Visual Basic goes Mobile - WP7 VB RTW.  Although this is a great step forward for VB Developers it still does not come close to when C# went mobile :)
  5. My C# License plate

    My C# License plate. For those of you in Sydney who over the past 3 years thought you seen it flash by - you can now rest assured it's not a figment of your imagination brought on by copious amounts of coding :)

  6. Those of you building WP7 applications leverage Azure should check out the Dec update of the Windows Azure Platform Training Kit
  7. Developer reporting tools which show download and transaction reports are available on App Hub –> My Dashboard — Windows Phone –> Reports
  8. Microsoft Advertising SDK for WP7 now supports XNA games here although as far as I can find out its not yet outside of the US

 

 Nick

How to Reverse Geocode a Location to an Address on Windows Phone 7

I have had a few people recently ask me how to reverse geocode a location to an address on Windows Phone 7.  The answer should be straightfoward but at the moment thats not quite true.

So whats the straightforward answer supposed to be?

Well glad you asked :) It should be to use the CivicAddressResolver class and its ResolveAddressAsync method

Ok so whats the Gotcha?

When you try to resolve an address CivicAddressResolver all you get back is a empty CivicAddress.  Yep the resolve method is not implemented.

So what options do you have?

  1. Wait for the CivicAddressResolver to be implemented. Note: At the time of writing I have not heard of when it will be released.
  2. Use the Bing Maps API to perform your reverse geocode in one of the following ways
    • Add a service reference from your WP7 project to the Bing Maps SOAP API <–  Requires Bing Maps Key to be supplied in code so not ideal as we want to protect this.
    • Call the Bing Maps REST API from within your WP7  project <–  Requires Bing Maps Key to be supplied in code so not ideal as we want to protect this.
    • Either of the above two options but access your  Bing Maps Key on a service and request it over SSL for device use – ensures XAP  does not contain key but still returning it to the device over the wire
    • Proxy the call to the Bing Maps REST API in your own WCF Service so your Bing Maps Key never hits the device <– ideal method until CivicAddressResolver is implemented.

If you would prefer grab the code then reading through here it is – You can download the code from this linked page

The remainder of this post will detail how to go about implementing the last option above i.e Proxy the call to your own service so that the Key is not available on the WP7 device.

Creating the WCF Service

  1. In Visual Studio 2010 File –> Add New Project –> Select WCF Service Application
  2. Name the Project “ReverseGeocodeService”
  3. On ReverseGeocodeService Right Click –> Add Reference –> Select System.Configuration (we will use this for retrieving your Bing Maps key from configuration).
  4. Set the project to use the local IIS webserver as the host.  On ReverGeocodeService Right Click –> Properties –> Web –> select Use Local IIS Web server and provide a project URL of http://localhost/ReverseGeocodeService
  5. Create the following Folder structure and add the following files within your service
  6. Create your BingLocationResponse class as follows:
  7. Note this class details the how to serialize and deserialize a response from the Bing Maps Rest API and we will use it deserialize the JSON response from the Bing Maps REST API and then also use it both to return a response to the WP7 client

    using System.Runtime.Serialization;
    
    namespace ReverseGeocodeService.Contracts.Data
    {
        [DataContract]
        public class BingLocationResponse
        {
            [DataMember]
            public string authenticationResultCode { get; set; }
            [DataMember]
            public string brandLogoUri { get; set; }
            [DataMember]
            public string copyright { get; set; }
    
            [DataMember]
            public ResourceSet[] resourceSets { get; set; }
    
            [DataMember]
            public string statusCode { get; set; }
            [DataMember]
            public string statusDescription { get; set; }
            [DataMember]
            public string traceId { get; set; }
    
            [DataContract]
            public class ResourceSet
            {
                [DataMember]
                public int estimatedTotal { get; set; }
    
                [DataMember]
                public Resource[] resources { get; set; }
    
                [DataContract(Namespace = "http://schemas.microsoft.com/search/local/ws/rest/v1", Name = "Location")]
                public class Resource
                {
                    [DataMember]
                    public string __type { get; set; }
    
                    [DataMember]
                    public double[] bbox { get; set; }
    
                    [DataMember]
                    public string name { get; set; }
    
                    [DataMember]
                    public Point point { get; set; }
    
                    [DataContract]
                    public class Point
                    {
                        [DataMember]
                        public string type { get; set; }
    
                        [DataMember]
                        public string[] coordinates { get; set; }
                    }
    
                    [DataMember]
                    public Address address { get; set; }
    
                    [DataContract]
                    public class Address
                    {
                        [DataMember]
                        public string addressLine { get; set; }
                        [DataMember]
                        public string adminDistrict { get; set; }
                        [DataMember]
                        public string adminDistrict2 { get; set; }
                        [DataMember]
                        public string countryRegion { get; set; }
                        [DataMember]
                        public string formattedAddress { get; set; }
                        [DataMember]
                        public string locality { get; set; }
                        [DataMember]
                        public string postalCode { get; set; }
                    }
    
                    [DataMember]
                    public string confidence { get; set; }
    
                    [DataMember]
                    public string entityType { get; set; }
                }
            }
        }
    }
  8. Next Define the Interface for your WCF service IGeocodeService.cs and your Geocode Provider that will call out to Bing Maps
  9. IGeocodeService.cs:

    using System.ServiceModel;
    using ReverseGeocodeService.Contracts.Data;
    
    namespace ReverseGeocodeService.Contracts
    {
        [ServiceContract]
        public interface IGeocodeService
        {
            [OperationContract]
            string GetAddress(double latitude, double longitude);
    
            [OperationContract]
            BingLocationResponse GetFullAddress(double latitude, double longitude);
        }
    }
    

    IGeocodeProvider.cs:

    using System;
    using ReverseGeocodeService.Contracts.Data;
    namespace ReverseGeocodeService.Contracts
    {
        public interface IGeocodeProvider
        {
            BingLocationResponse ReverseGeocode(double latitude, double longitude);
        }
    }
  10. Implement your GeocodeProvider.cs
  11. This class will call out to the Bing Maps REST API return its deserialized its response. If you want to see what other options Bing Maps REST API provides you should use this as your starting point and more specifically for the Locations by Point we are using in this example see this

    using System;
    using System.Diagnostics;
    using System.Net;
    using System.Runtime.Serialization.Json;
    using ReverseGeocodeService.Contracts;
    using ReverseGeocodeService.Contracts.Data;
    
    namespace ReverseGeocodeService.Providers
    {
        public class GeocodeProvider : IGeocodeProvider
        {
            private readonly string _bingMapsKey;
            private string _bingMapsRESTUri = "https://dev.virtualearth.net/REST/v1/Locations/{0}?key={1}";
            public GeocodeProvider(string bingMapsKey)
            {
                _bingMapsKey = bingMapsKey;
            }        
    
            public BingLocationResponse ReverseGeocode(double latitude, double longitude)
            {
                BingLocationResponse result = null;
                string formattedLocation = string.Format("{0},{1}", latitude, longitude); //bing maps requires Lat,Long
                var request = HttpWebRequest.Create(string.Format(_bingMapsRESTUri, formattedLocation, _bingMapsKey)) as HttpWebRequest;
                try
                {
                    using (var response = request.GetResponse() as HttpWebResponse)
                    {
                        result = GetResult(response);
                    }
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex.ToString());
                }
    
                return result;
            }
    
            private BingLocationResponse GetResult(HttpWebResponse response)
            {
                BingLocationResponse location = null;
                if (response != null && response.StatusCode == HttpStatusCode.OK)
                {
                    //Deserialize the response and provide the address to the callback action
                    using (var stream = response.GetResponseStream())
                    {
                        DataContractJsonSerializer serialiser = new DataContractJsonSerializer(typeof(BingLocationResponse));
                        location = serialiser.ReadObject(stream) as BingLocationResponse;
                    }
                }
    
                return location;
            }
        }
    }
  12. Finally implement your WCF Service GecodeService.svc.cs as follows
  13. Note that the BingKey is externalised into your config files appSettings, for the example to work you will need to supply your key to the config file.

    using System.Configuration;
    using System.Linq;
    using System.ServiceModel;
    using ReverseGeocodeService.Contracts;
    using ReverseGeocodeService.Contracts.Data;
    using ReverseGeocodeService.Providers;
    
    namespace ReverseGeocodeService
    {
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
        public class GeocodeService : IGeocodeService
        {
            //TODO: set your bingkey in config appsetting named BingKey
            private static IGeocodeProvider _geocodeProvider = new GeocodeProvider(ConfigurationManager.AppSettings["BingKey"]);
    
            public string GetAddress(double latitude, double longitude)
            {
                string formattedAddress = null;
                var geocodeResult = _geocodeProvider.ReverseGeocode(latitude, longitude);
                if (geocodeResult != null
                                && geocodeResult.resourceSets != null
                                && geocodeResult.resourceSets.Any()
                                && geocodeResult.resourceSets.First().resources != null
                                && geocodeResult.resourceSets.First().resources.Any())
                {
                    formattedAddress = geocodeResult.resourceSets.First().resources.First().address.formattedAddress;
                }
    
                return formattedAddress;
            }
    
            public BingLocationResponse GetFullAddress(double latitude, double longitude)
            {
                return _geocodeProvider.ReverseGeocode(latitude, longitude);
            }
        }
    }
  14. Add the appSettings section to your Web.config and supply your Bing Maps API Key
  15. <configuration>
     <appSettings>
        <add key="BingKey" value="Bing Maps Key Here"/>
      </appSettings>
      ...
    </configuration>

    Note: you should encrypt this Key using whatever standard practices you use.

Creating the Windows Phone 7 Client

Note: this is not an example of how to create an MVVM implementation on WP7  i.e we are focusing on how to reverse geocode a location to an address through the use of a proxy service  to protect your Bing Maps Key as such in this post the client code is kept straightforward to demonstrate usage.

  1. Add a Windows Phone 7 project File --> New Project --> Silverlight for Windows Phone --> Windows Phone Application
  2. Name the project ReverseGeocode
  3. On the project Right Click --> Add Service Reference --> Press Discover.
  4. You should see a window as in the following image.  Provide the Namespace ReverseGeocodeClient and Press OK
  5. Note: If this step is generating an Empty ServiceReferences.ClientConfig then delete the Service References and Service References.ClientConfig. Close all instances of Visual Studio. Open Visual Studio and try to add it again - it worked for me :) . If this still doesn't work then you will need to use SlSvcUtil.exe located in your Program Files (Program Files (x86)) for 64bit machines as follows:
    C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Tools\SlSvcUtil.exe" http://localhost/ReverseGeocodeService/GeocodeService.svc?wsdl
    Take the two files from the output and include them in your project and continue.

  6. Right click on the generated ServiceReferences.ClientConfig and set its Build Action to Content and Copy to Output Directory to Copy if newer
  7. Add a couple of buttons to perform calls out to the service in your MainPage.xaml and a TextBlock to display the result
  8. <phone:PhoneApplicationPage
        x:Class="ReverseGeocode.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
        xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
        FontFamily="{StaticResource PhoneFontFamilyNormal}"
        FontSize="{StaticResource PhoneFontSizeNormal}"
        Foreground="{StaticResource PhoneForegroundBrush}"
        SupportedOrientations="Portrait" Orientation="Portrait"
        shell:SystemTray.IsVisible="True" Loaded="PhoneApplicationPage_Loaded">
    
        <!--LayoutRoot is the root grid where all page content is placed-->
        <Grid x:Name="LayoutRoot" Background="Transparent">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    
            <!--TitlePanel contains the name of the application and page title-->
            <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
                <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
                <TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
            </StackPanel>
    
            <!--ContentPanel - place additional content here-->
            <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
                <Button Click="btnGetAddress_Click" Content="Get Address" Height="72" HorizontalAlignment="Left" Margin="6,6,0,0" Name="button1" VerticalAlignment="Top" Width="270" />
                <TextBlock x:Name="txtAddress" Height="203" HorizontalAlignment="Left" Margin="12,163,0,0" Text="Address goes here" VerticalAlignment="Top" Width="425" />
                <Button Content="Get Full Response" Height="72" HorizontalAlignment="Left" Margin="5,72,0,0" Name="button2" VerticalAlignment="Top" Width="270" Click="btnGetFullResponse_Click" />
            </Grid>
        </Grid>
    
    </phone:PhoneApplicationPage>
  9. Update your codebehind, MainPage.xaml.cs to call out to your new Reverse geocoding service when buttons are clicked
  10. using System;
    using System.Linq;
    using System.Windows;
    using Microsoft.Phone.Controls;
    using ReverseGeocode.ReverseGeocodeClient;
    
    namespace ReverseGeocode
    {
        public partial class MainPage : PhoneApplicationPage
        {
            private GeocodeServiceClient _client;
            private const string NO_RESULT_FOUND = "No Result Found";
            // Constructor
            public MainPage()
            {
                InitializeComponent();
            }
    
            private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
            {
               _client = new GeocodeServiceClient();
               _client.GetAddressCompleted += new EventHandler(client_GetAddressCompleted);
               _client.GetFullAddressCompleted += new EventHandler(_client_GetFullAddressCompleted);
            }
    
            private void btnGetAddress_Click(object sender, RoutedEventArgs e)
            {
                _client.GetAddressAsync(-33.796526, 151.138267);
            }        
    
            private void btnGetFullResponse_Click(object sender, RoutedEventArgs e)
            {
                _client.GetFullAddressAsync(-33.796526, 151.138267);
            }
    
            void client_GetAddressCompleted(object sender, GetAddressCompletedEventArgs e)
            {
                txtAddress.Text = e.Result ?? NO_RESULT_FOUND;
            }
    
            void _client_GetFullAddressCompleted(object sender, GetFullAddressCompletedEventArgs e)
            {
                string result = NO_RESULT_FOUND;
                if (e.Result != null
                                && e.Result.resourceSets != null
                                && e.Result.resourceSets.Any()
                                && e.Result.resourceSets.First().resources != null
                                && e.Result.resourceSets.First().resources.Any())
                {
                    var x = e.Result.resourceSets.First().resources.First();
                    result = string.Format ("Address:\n{0}\nConfidence:\n{1}\n", x.address.formattedAddress, x.confidence);
                }
    
                txtAddress.Text = result;
            }
        }
    }

    Note: I have not done it in this example however when you are finished with your _client you should always call _client.CloseAsync();

Summary:
And there you have it - in the absence of CivicAddressResolver this provides an implementation to reverse geocode a latitude and longitude into an Address on Windows Phone 7 without the need for your Bing Maps key to either be stored in the XAP or retrieved from a service by keeping your key within the context of your WCF proxy service.

You can download the code from this linked page - note you will have to add your Bing Maps Key to the web.config for it to work and also create the virtual directory on local host as detailed in the WCF service steps.

I hope this has helped you save some time :)

Enjoy,
Nick