Update 2: Microsoft has released a much better ad serving solution than AdMob, this was just a stop gap in case nothing official was released. This control is old and busted, check out the Microsoft Ad SDK for the new hotness.
After seeing a project on CodePlex that allowed you to display AdMob ads in a Win Phone 7 application, I decided it would be a good project for another custom control.
Custom Styling, Animation and Templates
The main problem I saw with the existing control was that it didn't take advantage of the styling and "Blendability" of the Win Phone 7 platform. Basically, the control used a web browser control to display an HTML template that was updated with ad information.
Here is an example of three different styles for the same template, the top is the default template, the middle is a text only style, and the bottom shows a fading animation when the ads are refreshing. The animations are helped by utilizing the three states for the AdDisplay control; Loading, Normal and Error.
Custom Ad Providers
Another issue I saw was that it relied solely on AdMob, with very little flexibility for hooking up another Ad service (like a rumored Bing Mobile Ad Service), so I added an adapter pattern to the control.
Here is an example of using the provided AdMob Adapter with the control (notice this can all be done in XAML, no code behind).
<!-- Default template example --> <moad:AdDisplay Height="70" VerticalAlignment="Top" Foreground="White" RefreshSeconds="30"> <moad:AdDisplay.AdAdapter> <moad:AdMobAdapter PublisherId="YourPublisherID" CookieString="YourCookieString" AdKeywords="Boston" UseTestMode="True"/> </moad:AdDisplay.AdAdapter> </moad:AdDisplay>
I'm hoping to put up another post to talk about creating a custom "In-House" ad provider.
You can download the source from my DropBox account, or at the created project on Codeplex called MoAds.
Now Playing - Goodie Mob - Get Rich to This
What's the cookieString needed for and what value would I put?
ReplyDeletethanks,
Sam
The cookie string is a way to uniquely identify a "client". It's used for analytics. It should really be generated from some unique device ID, but in the beta I haven't figured out how we can get a unique id for the phone.
ReplyDeleteMore information about the AdMob request parameters are at: http://developer.admob.com/wiki/Requests. But for the most part, the AdMob Documentation is pretty useless.
The "o" parameter is what you're looking for.
Hi
ReplyDeleteI'm having trouble getting it to work. This is my code:
It is loading, but I dont see any add. What is cookiestring and AdKeywords for?
Thanks
ups, cannot post xaml code here...
ReplyDeletehere is the code I am using:
http://dl.dropbox.com/u/3784027/moads.txt
@anon
ReplyDeleteCheck the previous comments;
"The cookie string is a way to uniquely identify a "client". It's used for analytics. It should really be generated from some unique device ID, but in the beta I haven't figured out how we can get a unique id for the phone."
As for ads not showing up, AdMob is sketchy about showing ads for people with little or no traffic. If you don't get enough traffic/impressions they won't show you any ads. If it is working in test mode, then more than likely admob is just not serving you ads. I'd recommend the MS Ad Control from here; http://advertising.microsoft.com/mobile-apps
Thanks for the great job with the Control Jacob. For people like me living outside the US it is currently the only solution for Ad Supported Trial Versions on WP7.
ReplyDeleteThanks, be sure to check out the follow up post if you are interested in creating your own ad providers:
ReplyDeletehttp://jacob4u2.blogspot.com/2010/08/show-custom-in-house-ads-in-win-phone-7.html
How did you get the publisher id from admob? It requires you to add a site or an app type and WP7 is not an option. How did you get around this?
ReplyDeleteI think I used either the IPhone or Mobile website choice.
ReplyDeleteJacob,
ReplyDeleteThanks for publishing this. Although the MS Pubcenter ad control makes this somewhat obsolete in the US, for outside the US, other ad providers are still necessary, and I would like to make this work.
I have it hooked up and displaying ads, but when I click on the ad, it goes to the wrong tab in the browser and displays a blank screen. Any ideas?
- Rick
I've noticed that happening on other web browser tasks, not just for the ad mob ones. Especially in the emulator. The code that handles the click and starts the web browser task can be found in AdDisplay.cs in a method called HandleAdTouch()
ReplyDeleteOnce I hand off to the web browser task, I really have no control over what happens. But it would be good to check that there is actually an ad URL being parsed and set correctly.
I think there is a memory leak in the control. I have an ad in the second page of my application. Each time I go to the second page and then back to the first page (by closing the 2nd page) I see an increase in the total memory used in my application (between 2mb and 4mb). I noticed that threads created by the control for fetching ads are not terminated when I close the page. So each time I go to the 2nd page I have +1 thread that throws a WebException when I have no connection. So after 10 visits I can see 10 WebExceptions.
ReplyDeleteCan you confirm this? And is there some way that it can be fixed?
@Bill: That seems entirely plausible. I don't stop the timer that refreshes the ads when you navigate to a new page. You can fix this by adding a method called StopRefresh in the AdDisplayControl class. This method should just call adReloadTimer.Stop(). You can either call this before you navigate to the next page, or go ahead and implement the IDisposable interface and call that method on dispose.
ReplyDelete@Bill: Here is some example code you can paste into AdDisplayControl.cs
ReplyDeletepublic void StopRefreshing()
{
adReloadTimer.Stop();
}
public void Dispose()
{
this.StopRefreshing();
}
yes that did the job thanx :)
ReplyDeleteHi Jacob, it's bill again :)
ReplyDeleteI found another thing in your control. It's difficult to reproduce it but it needs to be fixed.
There is a webClient exception about not supported concurrent I/O operations. This exception is raised when the 3G signal is very poor but there is connection. I think the problem is that you try to reuse the same webclient without checking if the previous is completed.
@Bill It looks like you're right about the webclient sharing being the problem. This is actually fixed on the latest codeplex source, but you should be able to copy the changes if you feel up to it. Here is what to do;
ReplyDelete1. Remove the static client property that is shared
2. Remove the constructor stuff dealing with the client property.
3. Replace the last StartService (The main one that does all the work) with this:
public WebHeaderCollection Headers { get; private set; }
/// summary>
/// Starts the service call.
/// </summary>
/// <param name="serviceUri">The service URI.</param>
/// <param name="method">The method.</param>
/// <param name="postData">The post data.</param>
protected virtual void StartServiceCall(Uri serviceUri, HttpMethod method, ContentType type, string postData)
{
var client = new WebClient();
client.Headers = this.Headers;
if (method == HttpMethod.GET)
{
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
// Remove the content type header, in case it messes with our get.
if (client.Headers["Content-Type"] != null)
client.Headers["Content-Type"] = null;
client.DownloadStringAsync(serviceUri);
}
else
{
client.UploadStringCompleted += new UploadStringCompletedEventHandler(client_UploadStringCompleted);
switch (type)
{
case ContentType.UrlEncoded:
client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
break;
case ContentType.JSON:
client.Headers["Content-Type"] = "application/json";
break;
default:
client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
break;
}
client.UploadStringAsync(serviceUri, "POST", postData);
}
}
That should do the trick. Thanks for the input.
@Bill: sorry that was in the BaseJsonService.cs class in the JSonHelpers\Service4u2Lib\Json directory. Around line 229.
ReplyDelete@Bill: Then in the AdMobService.cs you'll get an error about the client not being there, replace the line with this:
ReplyDeletebase.Headers["User-Agent"] = userAgent;
What kind of application did you create at admob? You can check this screenshot. Feel free to make comments there: https://docs0.google.com/drawings/edit?id=1ajmRPp8BImu2sZLxkzwNTD8TqW_K7nHGuerIte8IRn4&authkey=CO6rrvAB
ReplyDelete(I'm outside of US. So, I'm gonna use with your solution)
I used the SmartPhone web. I used my web services site url, but I don't know that it really matters.
ReplyDeleteSo, you just used your personal homepage as URL? However, this URL won't interact with admob at any time later?
ReplyDeleteHi Jacob,
ReplyDeletedoes this control work always ? I get 'connection error' on both the emulator and the device (windows phone 7).
thanks in advance,
Domi
Belgium
Not sure, it's been over 3 years since I've used it.
ReplyDelete