2 windows phone geek magazine · 2013-03-03 · 2 windows phone geek magazine ... build great apps...
TRANSCRIPT
2 Windows Phone Geek Magazine
Table of Contents Message from the Editor .................................................................................................................................................................................... 3
What’s new in Windows Phone 8 SDK for developers ...................................................................................................................................... 4
Tiles and Lock Screen Notifications in Windows Phone 8 ................................................................................................................................ 8
Implementing Coupons and Memberships using the Windows Phone 8 Wallet .............................................................................................. 12
Implementing in-app purchasing in Windows Phone 8 .................................................................................................................................... 20
File and URI associations in Windows Phone 8 ............................................................................................................................................... 23
New Launchers in Windows Phone 8 ............................................................................................................................................................... 28
New LongListSelector control in Windows Phone 8 SDK .............................................................................................................................. 30
New Location APIs and Background Location Tracking ................................................................................................................................. 33
Spotlight: Interview with Matt Lacey – Founder of WPUG London ............................................................................................................... 37
Business: How to start a successful mobile app business ................................................................................................................................. 38
WPGeek Component Marketplace – A Great Opportunity for Developers ...................................................................................................... 40
3 Windows Phone Geek Magazine
Message from the Editor
By Yordan Pavlov
What you are reading is the first issue of the Windows Phone Geek
Magazine. This issue is special not only because it’s the first one,
but also because it is dedicated almost entirely to the Windows
Phone 8 SDK. The wait is now over, and we hope that after reading
this magazine you will agree with us that it was worth it. Developers
can now built better, more efficient apps with the new location APIs,
the new LongListSelector and improved Pivot and Panorama con-
trols, and more. And with the new Wallet and in-app purchasing
APIs there are now more ways to make money. We no longer have
to envy other platforms for features like showing notifications on the
lock screen or launching other apps. Finally, Windows Phone 8
shares the same core as Windows 8 and offers access to asignificant
sub-set of Windows Runtime APIs.This opens opportunities for
sharing significant parts of the code-base between your Windows
Phone and Windows apps.
We start with “What’s new in Windows Phone 8 SDK for develop-
ers” which gives you an overview of the new features and capabili-
ties that the new SDK brings. Then we delve deeper into some spe-
cific areas like location, tiles and lock screen notifications, Wallet
and in-app purchasing. There are, however, some areas that are not
covered in details in this first issue of the magazine. Some topics,
like native development and code sharing for example, are so broad
and interesting that could easily fill an entire issue. That is why with
this first issue of the magazine we have tried to give you an over-
view of what’s available. And in future issues we will continue ex-
ploring the Windows Phone 8 platform and how you can use it to
build great apps and even re-use the same code base to create Win-
dows 8 apps.
Besides technical content, each issue of the magazine will also fea-
ture several less-technical, but just as interesting columns. In our
Spotlight column you will find interviews and stories about real
people, real developers and their successes (and sometimes failures).
In this issue, for our Spotlight column we have an interview with
Matt Lacey – the leader of the Windows Phone user group in Lon-
don, UK.
Building great apps is an extremely valuable skill. Unfortunately it is
rarely enough to succeed in making app development your full time
job. In this issue we are introducing our Business column where you
will read advice, tips and techniques to help you with the business
side of making money from apps. Boryana Miloshevska, who is a
co-founder of WindowsPhoneGeek.com and also has a management
degree from University College London (UCL) as well as several
business awards, opens the column with her article “How to start a
successful mobile app business” where she shares advice for mobile
entrepreneurs.
Finally, if there is a topic that you would like to read about, let us
know at [email protected]
Yordan Pavlov is a co-founder of WindowsPhoneGeek.com. He has
an MSc Computer Science as well as MSc Technology Entrepre-
neurship from University College London (UCL). He has many
years of experience building complex software systems and leading
agile teams. He is also a winner of several business awards, includ-
ing the UK RBS EnterprisingU 2012 and UCL Bright Ideas Award
2012.
Disclaimers
Disclaimer of Endorsement
Reference within this magazine to any specific commercial or non-commercial product, process, or service by trade name, trademark, manu-
facturer or otherwise does not constitute or imply an endorsement, recommendation, or favoring by WPGeek.
Disclaimer for Links to External, Third Party Web Sites
Links to external, or third party Web sites, are provided solely for readers' convenience. Links taken to other sites are done so at your own
risk and WPGeek accepts no liability for any linked sites or their content. When you access an external Web site, keep in mind that WPGeek
has no control over its content.
© 2012 WPGeek LTD. All rights reserved.
4 Windows Phone Geek Magazine
What’s new in Windows Phone 8 SDK for developers
By Yordan Pavlov
The Windows Phone 8 SDK includes many new APIs, giving devel-
opers many new opportunities and allowing them to create better
apps. In this article we will take a quick look at all the new APIs and
capabilities in the Windows Phone 8 SDK.
Native development Until now, app developers could only write managed apps and
games for Windows Phone. This changes with Windows Phone 8, as
developers can now write native C++ code and access a significant
subset of the Windows 8 APIs. Ever wanted to use a native library
like SQLite in Windows Phone? We are now a step closer.
Tiles and lock screen notifications Windows Phone 8 comes with 3 types of live tiles, represented by
the following classes:
FlipTileData – this is the regular live tile that we are used to
seeing in Windows Phone 7
IconicTileData – similar to the FlipTile but follows more close-
ly the Windows Phone design principles and displays an icon
instead of an image
CycleTileData – can cycle up to 9 images, similar to the Pic-
tures live tile
Live tiles now also come in three sizes: small, medium and large.
You can control if your primary tile supports the large size in the
WMAppManifest.xml file.
And now the big news – it is now possible for apps to display notifi-
cations on the lock screen. The information comes from the primary
tile and you can enable this feature by editing the WMAppMani-
fest.xml file. When this functionality is enabled, the user can select
to see notifications from your app in the lock screen settings:
For more information on what’s new for tiles in Windows Phone 8,
take a look at the Tiles and Lock Screen Notifications in Windows
Phone 8 article.
New Launchers and Choosers Windows Phone 8 SDK comes with several new Launchers which
are exposed through the following classes:
SaveAppointmentTask – prompts
the user to create a new appoint-
ment
MapsTask – launches the built-in
map app
MapsDirectionsTask – launches the
built-in map app with directions
MapDownloaderTask – launches
the map downloader for the built-in
map app
ShareMediaTask – prompts the us-
er to share a media file
5 Windows Phone Geek Magazine
private void btnLaunchMapsDirections-
Task_Click(object sender, RoutedEventArgs e)
{
MapsDirectionsTask mapsDirectionsTask = new
MapsDirectionsTask();
mapsDirectionsTask.Start = new
LabeledMapLocation("London Victoria", new Geo-
Coordinate(51.495322, -0.144732));
mapsDirectionsTask.End = new
LabeledMapLocation("London Heathrow", new
GeoCoor-dinate(51.471179, -0.454447));
mapsDirectionsTask.Show();
}
For more information on how to use the new launchers, take a look
at the New Launchers in WindowsPhone 8 article.
New Location APIs The Windows Phone 8 SDK comes with new Location APIs ex-
posed through the Geolocator class. Continuous location tracking is
now easier to implement, and you can even track the phone’s loca-
tion in the background, which opens a range of new opportunities.
You can even get the current location more efficiently and improve
battery life using the new GetGeopositionAsync method as shown
in the following code snippet:
Geolocatorgeolocator = new Geolocator();
geolocator.DesiredAccuracyInMeters = 50;
Geoposition position = await
geolocator.GetGeopositionAsync(
maximumAge: TimeSpan.FromMinutes(1),
timeout: TimeSpan.FromSeconds(30));
For more information on using the new Location APIs that come
with the Windows Phone 8 SDK, take a look at the New Location
APIs and Background Location Tracking article.
New Map control Windows Phone 8 comes with a new Map
control that is different from the old Bing
Maps control that was available with
Windows Phone 7.1. The old Bing Maps
control is still available in Windows
Phone 8, but is now obsolete and it is
recommended that you always use the
new Map control.
The new Map control is in the Mi-
crosoft.Phone.Maps.Contols namespace,
in the Microsoft.Phone.Maps assembly,
and in order to use it in XAML you must
add the following namespace:
xmlns:maps="clr-
namespace:Microsoft.Phone.Maps.Controls;assemb
ly=Microsoft.Phone.Maps"
Once you have added the namespace, defining a Map control is as
easy as this:
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<maps:Map x:Name="map" />
</Grid>
Then you can control features of the map like, for example, set the
center and zoom level like this:
this.map.Center = new GeoCoordinate(51.5171, -
0.1362); // London
this.map.ZoomLevel = 12;
The new Map control also supports more advanced features like
displaying custom layers, routes and directions.
In order to consume less memory, it is recommended to use, when-
ever possible, the new map launchers, rather than embedding a Map
control in your app. To learn more about these new launchers and
how to use them, read the New Launchers in Windows Phone 8 arti-
cle.
New LongListSelector control The Windows Phone 8 SDK includes a
new LongListSelector control that im-
plements a jump-list style of UI that is
usually used to display long lists of data.
The control supports full UI and data
virtualization and is actually recommend-
ed even for displaying flat lists.
For a more in-depth look at the new
LongListSelector control and some tips
for porting apps that use the control from
the Windows Phone Toolkit, take a look
at the New LongListSelector control in
Windows Phone8 SDK article.
Wallet and In-App pur-
chasing Windows Phone 8 introduces the Wallet
and together with in-app purchasing
brings new and exciting opportunities for
developers. In-app purchasing supports
the same payment instruments that are
available in the Windows Phone store
and allows developers to work with in-
6 Windows Phone Geek Magazine
app products like in the following code snippet:
// get in-app product by ID
ListingInformation products = await
CurrentApp.LoadListingInformationByProductIdsA
sync(new [] { InAppProductKey });
ProductListing productListing = null;
products.ProductListings.TryGetValue(InAppProd
uctKey, out productListing)
// start product purchase
awaitCurrentApp.RequestProductPurchaseAsync(pr
oductListing.ProductId, false);
The Wallet APIs also allow developers to work with deals, member-
ships and payment instruments. To learn more about the new in-app
purchasing and Wallet APIs take a look at the Implementing Cou-
pons and Memberships using the Windows Phone 8 Wallet and Im-
plementing in-app purchasing in Windows Phone 8 articles.
Finally, you can also implement a special wallet background agent
that updates items in the wallet, linked to your app even when the
app itself isn’t running.
File and URI Associations In Windows Phone 8, you can register file and URI associations for
your app. This little gem in the new SDK allows an app to launch
and pass arguments to other apps. And it’s easy: to launch an app
just use the Launcher class like this:
Launcher.LaunchUriAsync(new
Uri("winphonegeek:?param1=value1¶m2=value2
"));
You register URI associations inWMAppManifest.xml like in the
following code snippet and handle the navigation requests by im-
plementing a URI mapper:
<Extensions>
<Protocol Name="winphonegeek"
NavUriFragment="encodedLaunchUri=%s"
TaskID="_default"/>
</Extensions>
To learn more about file and URI associations read the File and URI
associations in Windows Phone 8article.
New Communication and Proximity APIs
Bluetooth Windows Phone 8 comes with new Bluetooth APIs that allow devel-
opers to do peer discovery and implement app-to-app and app-to-
device communication. Here is a sneak peek into these new APIs:
privateasync void ConnectToPeer()
{
// PeerFinder.Start() is used to
advertise our presence so that peers can find
us.
// It must always be called before
FindAllPeersAsync.
PeerFinder.Start();
var peers = await
PeerFinder.FindAllPeersAsync();
if (peers.Count == 0)
{
MessageBox.Show("No peers
found");
return;
}
// Select a peer. In this example,
let's just pick the first peer.
PeerInformationselectedPeer =
peers[0];
// Attempt a connection
varstreamSocket = await
PeerFinder.ConnectAsync(selectedPeer);
// start communicating with the peer
app
}
Unfortunately, the Bluetooth APIs cannot be tested with the emula-
tor.
NFC Windows Phone 8 supports short-distance (3-4 centimeters) com-
munication with NFC. This type of communication enables many
scenarios like for example: pairing the phone with other devices,
receiving information from smart billboards, mobile payments, and
more. The entry point to the new NFC APIs is the ProximityDevice
class. Here is a code snippet that shows how to subscribe for a mes-
sage:
private void SubscribeForProximityMessage()
{
ProximityDevice device =
ProximityDevice.GetDefault();
if (device!= null)
{
// If NFC is supported
long id =
device.SubscribeForMessage
("WindowsPhoneGeek.ProximityMessageType",
this.OnProximityMessageReceived);
// the id that is returned can
be used to unsubscribe from this message type
}
}
private void
OnProximityMessageReceived(ProximityDevice
sender, ProximityMessage message)
{
Debug.WriteLine("Received from
{0}:'{1}'", sender.DeviceId,
message.DataAsString);
}
7 Windows Phone Geek Magazine
VoIP Windows Phone 8 allows developers to implement a VoIP app and
integrate it with the platform in order to ensure that the user has the
same experience whether he is making a normal phone call or a
VoIP call. To implement a VoIP app that has this level of integration
into the platform, several components are required:
Foreground app – this app is available in the list of apps and
can be pinned to the home screen, as any other app
VoipHttpIncomingCallTask – a background agent that handles
incoming calls
VoipForegroundLifetimeAgent – bootstraps the background
process and keeps it alive, so that outgoing calls can be made
quickly; launched by the foreground app and runs until the app
is in the foreground
VoipCallInProgressAgent – launched when a call is started,
signals the app that more CPU cycles have been allocated and it
can start processing audio and video data
VoipKeepAliveTask – runs periodically and gives the app an
opportunity to ping the VoIP service
Windows Phone Runtime assembly – implements most of the
functionality for connecting and managing VoIP calls; this as-
sembly has access to native APIs for audio and video pro-
cessing and can also call unmanaged C and C++ libraries that
the app might need to use
VoIP cloud service – initiates calls by using push notifications
Speech Launching apps with speech is already available in Windows Phone
7, but Windows Phone 8 significantly extends the speech functional-
ity available to developers by adding speech commands which allow
you to deep link commands to specific pages or actions in your app.
Windows Phone 8 also comes with new speech recognition and text-
to-speech APIs which enable developers to easily allow users to
interact with their apps using speech. Here is a sneak peek into the
new speech recognition and text-to-speech APIs:
privateasync void btnSpeak_Click(object
sender, RoutedEventArgs e)
{
if (this.speechRecognizer == null)
{
this.speechRecognizer = new
SpeechRecognizerUI();
}
// start recognition with default
dictation grammar
SpeechRecognitionUIResultrecognitionRe
sult = await
this.speechRecognizer.RecognizeWithUIAsync();
// display the speech recognition
result
this.txtRecognitionResult.Text =
string.Format("You said: \"{0}\"",
recognitionResult.RecognitionResult.Text);
}
privateasync void btnSpeakText_Click(object
sender, RoutedEventArgs e)
{
SpeechSynthesizer synthesizer = new
SpeechSynthesizer();
awaitsynthesizer.SpeakTextAsync(this.t
bTextToSpeak.Text);
}
New Camera APIs Windows Phone 8 brings many new features and extensibility points
related to camera and pictures. Developers can now create custom
lenses that integrate with the built-in camera app. Working with
photos is even easier with the new GetPreviewImage and GetPath
extension methods on the Picture class and the new ShareMedi-
aTask launcher:
private void
btnLaunchShareMediaTask_Click(object sender,
RoutedEventArgs e)
{
PhotoChooserTaskphotoChooserTask = new
PhotoChooserTask();
photoChooserTask.ShowCamera = true;
photoChooserTask.Completed +=
photoChooserTask_Completed;
photoChooserTask.Show();
}
voidphotoChooserTask_Completed(object sender,
PhotoResult e)
{
ShareMediaTaskshareMediaTask = new
ShareMediaTask();
shareMediaTask.FilePath = e.OriginalFileName;
shareMediaTask.Show();
}
In Windows Phone 7 you could integrate your app in the Photos Hub
and the Share picker, and now, with Windows Phone 8, you can also
integrate your app in the Photo viewer and the Photo edit picker.
Finally, with the advanced capture APIs, you now have fine control
over focus, white balance, exposure and more, and you even have
access to uncompressed photo data.
New Media Library APIs Windows Phone 8 now allows developers to add and remove music
files from the user’s media collection, using the SaveSong and De-
lete methods accessible from the MediaLibrary class. There are
also improvements for background audio.
Download the Full Source code here.
8 Windows Phone Geek Magazine
Tiles and Lock Screen Notifications in Windows Phone 8
By Boryana Miloshevska
Live tiles are one of the signature features of Windows Phone and
are used to represent your app on the start screen of the phone and
give the user quick access to your app. Live tiles also enable apps to
show notifications to the user on the home screen and starting with
Windows Phone 8 – on the lock screen. While, the Primary (or de-
fault) tile appears on the phone’s start screen only when a user pins
your application, secondary tiles are created programmatically by
the application and multiple such tiles can be active at the same time
(to display, for example, the weather in several cities).
Windows Phone 8 brings several new Live Tile features: three new
Live Tile templates; Live Tiles can now support three sizes; infor-
mation from the Primary tile can now be displayed on the lock
screen.
New Live Tile templates Three new Tile templates are available in Windows Phone 8:
Flip – this is the regular live tile that we are used to seeing in
Windows Phone 7
Iconic – similar to the Flip tile but follows more closely the
Windows Phone design principles and displays an icon instead
of an image
Cycle - can cycle up to 9 images, similar to the Pictures live tile
New Live Tile sizes and resolutions Windows Phone 8 supports the following Tile sizes: small, medium,
and wide / large.
NOTE: Tile size is selected by the user from the phone’s home
screen, but you can control which sizes a tile supports. It is recom-
mended that you provide a separate image for each size.
Flip and Cycle Iconic
Small 159 × 159 px 110 × 110 px
Medium 336 × 336 px 202 × 202 px
Wide 691 × 336 px N/A
NOTE: Windows Phone 8 supports two additional resolutions,
WVGA and 720p. All images are scaled by the runtime to work for
these resolutions appropriately.
In this article we will create a sample
application that displays information
about different fast foods using the dif-
ferent types of tiles. In order to demon-
strate how the app can display notifica-
tions on the phone’s lock screen, we will
also implement a background agent that
periodically updates the information dis-
played by the app’s Primary tile. The app
demonstrates all three tile templates:
Flip tile – we will use the flip tile
template for the app’s primary tile
Iconic tile – the sample app also demonstrates how easy it is to
use the iconic tile template
Cycle tile – we will demonstrate how to display a cycle tile that
cycles through several images
Let’s start building the app by making our Main Page look like the
screen-shot above. Here is the XAML code that you have to put in
MainPage.xaml:
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Value,
ElementName=countSlider, StringFormat='Count:
{0}'}" />
<Slider x:Name="countSlider" />
<TextBlock Text="Content:" />
<TextBox x:Name="txtContent" />
<Button x:Name="btnUpdatePrimaryTile"
Content="Update primary tile"
Click="btnUpdatePrimaryTile_Click" />
<CheckBox x:Name="cbEnableTileUpdateAgent"
Content="Enable tile
update agent"
Checked="cbEnableTileUpdateAgent_Checked"
Unchecked="cbEnableTileUpdateAgent_Unchecked"
/>
<CheckBox x:Name="cbEnableIconicTile"
Content="Enable iconic
tile"
9 Windows Phone Geek Magazine
Checked="cbEnableIconicTile_Checked"
Unchecked="cbEnableIconicTile_Unchecked" />
<CheckBox x:Name="cbEnableCycleTile"
Content="Enable cycle
tile"
Checked="cbEnableCycleTile_Checked"
Unchecked="cbEnableCycleTile_Unchecked" />
</StackPanel>
</Grid>
Using the Flip Tile template Since in WMAppManifest.xml, we have selected to use the Flip tile
template for our Primary tile, in order to implement the “Update
primary tile” functionality we will have to use the FlipTileData
class which represents the Flip tile template. Let’s start by imple-
menting the click handler for the button:
private void btnUpdatePrimaryTile_Click(object
sender, RoutedEventArgs e)
{
int count =
(int)this.countSlider.Value;
string content = this.txtContent.Text;
TileUpdateAgent.TileUpdateScheduledAge
nt.UpdatePrimaryTile(count, content);
}
In that click event handler, the actual updating is done by the static
UpdatePrimaryTile method of our TileUpdateScheduledAgent class
(we’ll return to that background agent later). Here is how this meth-
od looks like:
public static void UpdatePrimaryTile(int
count, string content)
{
FlipTileData primaryTileData = new
FlipTileData();
primaryTileData.Count = count;
primaryTileData.BackContent = content;
ShellTile primaryTile =
ShellTile.ActiveTiles.First();
primaryTile.Update(primaryTileData);
}
What this method does in order to update the primary tile is create a
new FlipTileData instance and set the Count and BackContent
properties. Then it retrieves the primary tile from the ActiveTiles
collection of the ShellTile class. (NOTE: the primary tile is always
the first tile, even if it isn’t pinned on the home screen). Finally, we
trigger the update using the Update method of the primary Tile ob-
ject that we just retrieved.
Using the Iconic Tile template Using the new Iconic tile template, is probably the easiest way to
implement a live tile in Windows Phone 8.In our sample app, a sec-
ondary tile that uses the Iconic tile template is created when the “En-
able iconic tile” check box is checked and is removed when the
check box is unchecked. Let’s start by implementing the Checked
and Unchecked event handlers for the check box:
private static readonly string IconicTileQuery
= "tile=iconic";
private void cbEnableIconicTile_Checked(object
sender, RoutedEventArgs e)
{
if (this.ignoreCheckboxEvents)
{
return;
}
Uri tileUri = new
Uri(string.Concat("/MainPage.xaml?",
IconicTileQuery), UriKind.Relative);
ShellTileData tileData =
this.CreateIconicTileData();
ShellTile.Create(tileUri, tileData,
true);
}
private void
cbEnableIconicTile_Unchecked(object sender,
RoutedEventArgs e)
{
if (this.ignoreCheckboxEvents)
{
return;
}
ShellTile iconicTile =
this.FindTile(IconicTileQuery);
if (iconicTile != null)
{
iconicTile.Delete();
}
}
There are several things that deserve attention in the code snippet
above. First, notice how we are adding a query string to the tile’s
URI that will allow us to find the tile later, when we want to remove
(or update) it. Then in order to create the tile, we use the Create
method of the ShellTile class. Finally, to remove the tile, we call the
Delete method of the tile once we have found it using the FindTile
method (which we will show in a moment).
Here is the CreateIconicTileData method that creates the tile defini-
tion using the Iconic tile template:
private ShellTileData CreateIconicTileData()
{
IconicTileData iconicTileData = new
IconicTileData();
iconicTileData.Count = 11;
10 Windows Phone Geek Magazine
iconicTileData.IconImage = new
Uri("/Assets/pizza.lockicon.png",
UriKind.Relative);
iconicTileData.SmallIconImage = new
Uri("/Assets/pizza.lockicon.png",
UriKind.Relative);
iconicTileData.WideContent1 = "Wide
content 1";
iconicTileData.WideContent2 = "Wide
content 2";
iconicTileData.WideContent3 = "Wide
content 3";
return iconicTileData;
}
And this is FindTile method that we are using to find tiles in the
ActiveTiles collection by (part of ) their navigation URI:
private ShellTile FindTile(string partOfUri)
{
ShellTile shellTile =
ShellTile.ActiveTiles.FirstOrDefault(
tile =>
tile.NavigationUri.ToString().Contains(partOfU
ri));
return shellTile;
}
Now if you launch the app and enable the iconic tile, you should see
something like this:
Using the Cycle Tile template The Cycle tile template enables you to create a tile that cycles
through up to 9 different images, similarly to the tile of the built-in
Pictures app.Adding and deleting tiles that use the Cycle tile tem-
plate is done in the same way as with the other tile types. The big-
gest difference is how you create the tile definition. To create the
Cycle tile we are using the CreateCycleTileData method:
private ShellTileData CreateCycleTileData()
{
string[] imageNames = {
"bonfillet.jpg", "bucket.jpg",
"burger.jpg", "caesar.jpg",
"chicken.jpg", "corn.jpg",
"fries.jpg", "wings.jpg"
};
CycleTileData cycleTileData = new
CycleTileData();
cycleTileData.Title = "Cycle tile";
cycleTileData.Count = 7;
cycleTileData.SmallBackgroundImage = new
Uri("/Assets/pizza.lockicon.png",
UriKind.Relative);
cycleTileData.CycleImages =
imageNames.Select(
imageName => new
Uri(string.Concat("/Assets/Images/",
imageName), UriKind.Relative));
return cycleTileData;
}
For the sake of completeness, here is the code for the Checked and
Unchecked event handlers of the “Enable cycle tile” check box. The
only difference is that we are using a different query string in the
navigation URI for the cycle tile:
private static readonly string CycleTileQuery
= "tile=cycle";
private void cbEnableCycleTile_Checked(object
sender, RoutedEventArgs e)
{
if (this.ignoreCheckboxEvents)
{
return;
}
Uri tileUri = new
Uri(string.Concat("/MainPage.xaml?",
CycleTileQuery), UriKind.Relative);
ShellTileData tileData =
this.CreateCycleTileData();
ShellTile.Create(tileUri, tileData,
false);
}
private void
cbEnableCycleTile_Unchecked(object sender,
RoutedEventArgs e)
{
if (this.ignoreCheckboxEvents)
{
return;
}
ShellTile cycleTile =
this.FindTile(CycleTileQuery);
if (cycleTile != null)
{
cycleTile.Delete();
}
}
11 Windows Phone Geek Magazine
If you now run the app and enable the cycle tile, you should see on
the phone’s start screen, a tile that displays fast food images, asin the
following screen-shots.
Showing notifications on the lock screen
Windows Phone 8 allows the user to select the applications from
which to receive notifications on the lock screen. The information
that is displayed on the lock screen actually comes from the app’s
primary tile. In order to enable lock screen notification for your app
you have to edit the WMAppManifest.xml file and change the Ex-
tensions element (which follows the Tokens element) to include the
following extensions:
<Extensions>
<Extension
ExtensionName="LockScreen_Notification_IconCou
nt" ConsumerID="{111DFF24-AA15-4A96-8006-
2BFF8122084F}" TaskID="_default" />
<Extension
ExtensionName="LockScreen_Notification_TextFie
ld" ConsumerID="{111DFF24-AA15-4A96-8006-
2BFF8122084F}" TaskID="_default" />
</Extensions>
After you do that your app will show up as one of the available apps
in the lock screen settings, and if the user selects to receive notifica-
tions from it, you should see something like this:
Updating the primary tile with a back-
ground agent We will complete the sample app by creating a background agent
that updates the app’s primary tile, which also updates the notifica-
tion displayed on the lock screen. Let’s start by creating a new back-
ground agent using the “Windows Phone Scheduled Task Agent”
project template. Then in the OnInvoke method we will update the
primary tile with a random count as shown in the following code
snippet:
protected override void OnInvoke(ScheduledTask
task)
{
Random randomCount = new Random();
int count = randomCount.Next(10, 90);
string content = string.Format("We
have {0} pizzas waiting for you!", count);
UpdatePrimaryTile(count, content);
#if DEBUG
ScheduledActionService.LaunchForTest(
task.Name,
TimeSpan.FromSeconds(30));
#endif
NotifyComplete();
}
We have already discussed the UpdatePrimaryTile method, which is
used to update the tile, earlier in this article.
NOTE: We will not discuss here, how to
start and stop the background agent as this
is not the subject of this article and is also
well documented. There is also a separate
download that contains the full source code
of the sample app.
If you run the sample app and enable the tile
update agent, after a while the Primary tile
will be updated and the updated information
will also be displayed on the lock screen.
Notice how, in the screen-shot on the right,
the notification has changed to “We have 80
pizzas waiting for you!”.
NOTE: When you are using the emulator, you can lock the screen
using the new Simulation Dashboard (VS Menu > Tools > Simula-
tion Dashboard)
Conclusion This article demonstrated the new Tile templates that come with the
Windows Phone 8 SDK. We also showed how to enable lock screen
notifications in your app and how to update them using a back-
ground agent.
Download the Full Source code here.
12 Windows Phone Geek Magazine
Implementing Coupons and Memberships using the Windows Phone 8 Wallet
By Yordan Pavlov
The Wallet in Windows Phone 8 allows app developers to expose their apps to end users in yet another way. By using Wallet APIs develop-
ers can implement coupons and memberships in their apps that take advantage of the security and unified user experience that the Wallet
offers. The following diagram gives a bird’s eye view over the Wallet APIs. In this article we will be using the Wallet, Deal (for coupons)
and WalletTransactionItem (for membership) classes.
13 Windows Phone Geek Magazine
Before we begin Note that in order to use the Wallet APIs demonstrated in this article
you must enable the ID_CAP_WALLET capability for your applica-
tion. To do that, go to WMAppManifest.xml and check the
ID_CAP_WALLET checkbox in the Capabilities tab as shown below:
There are other capabilities that you might need to enable if you are
using other Wallet APIs, but we will not need them in this article.
The app In this article we will build an app that allows users to register their
WindowsPhoneGeek account with the Wallet on the phone and then
exchange GeekPoints for different coupons.
The model Before we can start working with the new Wallet APIs we will cre-
ate several model classes that will make our work easier later.
We will start with a Coupon class that represents a coupon (or deal)
that we have available and an ICouponRepository interface that ex-
poses operations with coupons. In a real app, you would probably
implement a coupon repository that gets the available coupons from
a web service. For the sake of simplicity, we will implement a
MockCouponRepository that just works with a list of coupons in
memory. Here is how the whole coupon model looks like:
When a MockCouponRepository is created using the Create method,
it is populated with the following list of pre-defined coupons:
public static MockCouponRepository Create()
{
DateTime today = DateTime.Today;
List<Coupon> couponList = new
List<Coupon>();
couponList.Add(new Coupon("1", "10%
Off Marketplace Purchase") {
Description = "10% off any
WPGeek marketplace purchase over 10 USD!",
ExpirationDate = today +
TimeSpan.FromDays(30),
Terms = "Valid only for
purchases over 10 USD",
Code = "*WPGCM10P*",
GeekPoints = 10
});
couponList.Add(new Coupon("2", "50% off
AppWall item") {
Description = "50% off your
next AppWall item!",
ExpirationDate = today +
TimeSpan.FromDays(14),
Terms = "Only valid for 1x1
and 2x2 cells.",
Code = "*WPGAW50P*",
GeekPoints = 5
});
couponList.Add(new Coupon("3", "Free component
promotion") {
Description = "Free 7 day
promotion on WPGeek component marketplace!",
ExpirationDate = today +
TimeSpan.FromDays(90),
Terms = "New publishers
only.",
Code = "*WPGCMFRP*",
GeekPoints = 0
});
14 Windows Phone Geek Magazine
couponList.Add(new Coupon("4", "5$ off
marketplace purchase") {
Description = "$5 off your
next WPGeek component marketplace purchase!",
ExpirationDate = today +
TimeSpan.FromDays(30),
Terms = "Valid only for
purchases over 20 USD",
Code = "*WPGCM5US*",
GeekPoints = 50
});
return new
MockCouponRepository(couponList);
}
To have easy access to an ICouponRepository instance we will add
the following property in App.xaml.cs:
private static ICouponRepository
couponRepository = null;
public static ICouponRepository
CouponRepository
{
get
{
if (couponRepository == null)
{
couponRepository =
MockCouponRepository.Create();
}
return couponRepository;
}
}
Similar to our coupons model, we will also implement several clas-
ses to help us work with memberships. We will start with a Mem-
bership class that represents a WindowsPhoneGeek.com member-
ship and an IMembershipRepository interface that exposes opera-
tions with that membership. We will also implement an IsoStore-
MembeshipRepository that stores information about the user’s
membership in isolated storage settings. Here is how our member-
ship model looks like:
Finally, we will add the following property in App.xaml.cs for easy
access to an IMembershipRepository instance:
private static IMembershipRepository
membershipRepository = null;
public static IMembershipRepository
MembershipRepository
{
get
{
if (membershipRepository ==
null)
{
membershipRepository
= new IsoStoreMembershipRepository();
}
return membershipRepository;
}
}
Working with coupons After implementing the model classes, we can now finally start
working with the Wallet APIs and creating the UI of the app. Let’s
start by changing our Main Page to display the current status of the
user’s coupons and membership as well as two buttons to show de-
tails. Here is the code that you must put in MainPage.xaml:
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<StackPanel Orientation="Vertical">
<TextBlock Text="Coupons:"
Style="{StaticResource PhoneTextTitle2Style}"
/>
<TextBlock x:Name="txtCoupons" />
<Button x:Name="btnViewCoupons" Content="View
all" Click="btnViewCoupons_Click" />
<TextBlock Text="Membership:"
Style="{StaticResource PhoneTextTitle2Style}"
/>
<TextBlock x:Name="txtMembership" />
<Button x:Name="btnViewMembership"
Content="Manage membership"
Click="btnViewMembership_Click" />
</StackPanel>
</Grid>
The XAML code above should make
your main page look like the screenshot
on the right, but before you can run the
app we have to write some code in Main-
Page.xaml.cs. In the OnNavigatedTo
method, we will update the current status
for the user’s coupons and membership
by calling the GetCouponStatus and
GetMembershipStatus methods. In the
GetCouponStatus method we will use the
first Wallet method in this article – the
15 Windows Phone Geek Magazine
static GetItemsAsync method that returns all items in the Wallet
linked with the current app. The GetMembershipStatus method, we
will implement later when we discuss working with memberships.
protected async override void
OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
this.txtCoupons.Text = await
this.GetCouponStatus();
this.txtMembership.Text =
this.GetMembershipStatus();
}
private async Task<string> GetCouponStatus()
{
ICouponRepository couponRepository =
App.CouponRepository;
IEnumerable<Coupon> coupons =
couponRepository.GetCoupons();
int couponCount = coupons.Count();
// retrieves the wallet items for this
app
WalletItemCollection walletItems =
await Wallet.GetItemsAsync();
// NOTE: memberships items are also
counted, so we must check for Deals only
int walletCount =
walletItems.Where(walletItem =>
walletItem.GetType() == typeof(Deal)).Count();
DateTime closestExpiration =
coupons.OrderBy(c =>
c.ExpirationDate).First().ExpirationDate;
string status = string.Format("{0}
coupons, {1} in wallet, \nclosest expiration:
{2:d}",
couponCount, walletCount,
closestExpiration);
return status;
}
Note how in the code snippet above we access the coupon repository
through the static App.CouponRepository property that we created
earlier. After retrieving the number of coupons in the repository we
also get all wallet items for the app. However, since the GetItemsA-
sync returns all items in the wallet linked to the current app, includ-
ing memberships, we have to filter the returned items by type in
order to get only the number of deals (or coupons).
Let’s now implement the button click handlers that navigate to the
details pages for coupons and membership:
private void btnViewCoupons_Click(object
sender, RoutedEventArgs e)
{
this.NavigationService.Navigate(new
Uri("/CouponListPage.xaml",
UriKind.Relative));
}
private void btnViewMembership_Click(object
sender, RoutedEventArgs e)
{
this.NavigationService.Navigate(new
Uri("/MembershipDetailsPage.xaml",
UriKind.Relative));
}
The CouponListPage is a very simple page that just displays the
available coupons in a list box control. Here is the XAML:
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<ListBox x:Name="lbCoupons"
SelectionChanged="lbCoupons_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding Title}"
TextWrapping="Wrap" FontSize="{StaticResource
PhoneFontSizeLarge}"/>
<TextBlock Text="{Binding GeekPoints,
StringFormat='Cost: {0} GeekPoints'}" />
<TextBlock Text="{Binding InWallet,
StringFormat='In wallet: {0}',
Converter={StaticResource YesNoConverter}}"
TextWrapping="Wrap"
Foreground="{StaticResource
PhoneAccentBrush}"/>
<TextBlock Text="{Binding Description}"
TextWrapping="Wrap"
Foreground="{StaticResource
PhoneSubtleBrush}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
The XAML code above should make
your CouponListPage look like the
screen-shot on the right. However, before
you can run the app we must write some
code in CouponListPage.xaml.cs to bind
the list of coupons to the list box control
and to navigate to the CouponDetailsPage
when a coupon from the list is selected.
Note in the code snippet below, how we
pass the ID of the selected coupon when
navigating. This ID is used to find and
display the right coupon in the Cou-
ponDetailsPage. Here is the code that you
have to put in CouponListPage.xaml.cs:
public CouponListPage()
{
InitializeComponent();
this.lbCoupons.ItemsSource =
App.CouponRepository.GetCoupons();
}
16 Windows Phone Geek Magazine
private void lbCoupons_SelectionChanged(object
sender, SelectionChangedEventArgs e)
{
Coupon selectedCoupon =
this.lbCoupons.SelectedItem as Coupon;
if (selectedCoupon == null)
{
return;
}
string couponDetailsUri =
string.Format("/CouponDetailsPage.xaml?{0}={1}
", CouponDetailsPage.CouponIDName,
selectedCoupon.ID);
this.NavigationService.Navigate(new
Uri(couponDetailsUri, UriKind.Relative));
this.lbCoupons.SelectedItem = null;
}
In the Coupon Details page, the user can see details about the select-
ed coupon as well as add or remove it from the wallet. Here is the
XAML:
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}"
Style="{StaticResource PhoneTextTitle2Style}"
/>
<TextBlock Text="{Binding GeekPoints,
StringFormat='Cost: {0} GeekPoints'}" />
<TextBlock Text="{Binding Description}"
TextWrapping="Wrap" />
<TextBlock Text="{Binding ExpirationDate,
StringFormat='Expires: {0:d}'}"
Foreground="{StaticResource PhoneAccentBrush}"
Margin="0, 0, 0, 10" />
<Image Source="{Binding Barcode}"
Stretch="None" VerticalAlignment="Center"
HorizontalAlignment="Center" />
<Button x:Name="btnAddToWallet" Content="Add
to wallet"
Visibility="{Binding
InWallet, Converter={StaticResource
ReverseVisbilityConverter}}"
Click="btnAddToWallet_Click" />
<Button x:Name="btnRemoveFromWallet"
Content="Remove from wallet"
Visibility="{Binding
InWallet, Converter={StaticResource
ForwardVisbilityConverter}}"
Click="btnRemoveFromWallet_Click" />
</StackPanel>
</Grid>
Note that in the XAML above we are using two value converters to
control the visibility of the “Add to wallet” and “Remove from wal-
let” buttons so that only one is visible at a time, depending on
whether the coupon is in the wallet or not. Here is how the convert-
ers are defined:
<phone:PhoneApplicationPage.Resources>
<local:BoolToVisibilityConverter
x:Key="ForwardVisbilityConverter"
TrueValue="Visible" FalseValue="Collapsed" />
<local:BoolToVisibilityConverter
x:Key="ReverseVisbilityConverter"
TrueValue="Collapsed" FalseValue="Visible" />
</phone:PhoneApplicationPage.Resources>
In order to find if the current coupon is in the wallet, we use the
static Wallet.FindItem method as in the following code snippet:
protected override void
OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string couponID = null;
if
(!this.NavigationContext.QueryString.TryGetVal
ue(CouponIDName, out couponID))
{
MessageBox.Show("There was a
problem loading the coupon");
return;
}
ICouponRepository couponRepository =
App.CouponRepository;
this.currentCoupon =
couponRepository.FindCoupon(couponID);
// IMPORTANT: ID_CAP_WALLET is
required in order to use the Wallet API
try
{
this.currentCoupon.InWallet =
Wallet.FindItem(couponID) != null;
}
catch (Exception ex)
{
MessageBox.Show("Could
determine wallet state for coupon. Details: "
+ ex.Message);
}
this.DataContext = this.currentCoupon;
}
To implement adding the current cou-
pon in the wallet, we will use the fol-
lowing code that checks if the user has
enough GeekPoints to use the coupon
before adding it to the Wallet:
17 Windows Phone Geek Magazine
private async void btnAddToWallet_Click(object
sender, RoutedEventArgs e)
{
try
{
await
Membership.UpdateGeekPointsBalance(-
this.currentCoupon.GeekPoints);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
this.AddCurrentCouponToWallet();
}
private async void AddCurrentCouponToWallet()
{
try
{
this.btnAddToWallet.Visibility
= Visibility.Collapsed;
Deal deal = new
Deal(currentCoupon.ID);
deal.IsUsed = false;
deal.DisplayName =
currentCoupon.Title;
deal.Description =
currentCoupon.Description;
deal.IssuerName =
WalletMerchantInfo.IssuerName;
deal.IssuerWebsite =
WalletMerchantInfo.IssuerWebsite;
deal.MerchantName =
WalletMerchantInfo.MerchantName;
deal.TermsAndConditions =
currentCoupon.Terms;
deal.Code =
currentCoupon.Code;
deal.ExpirationDate =
currentCoupon.ExpirationDate;
deal.BarcodeImage =
currentCoupon.Barcode;
// NOTE: AddWalletItemTask
cannot be used to add Deal items
await deal.SaveAsync();
this.currentCoupon.InWallet =
true;
}
catch (Exception ex)
{
this.btnAddToWallet.Visibility
= Visibility.Visible;
MessageBox.Show("There was an
error saving the deal in your wallet: " +
ex.Message);
}
}
Note how we use the information from the current coupon to create a
new Deal instance and then call the SaveAsync method on that deal
to actually save it in the Wallet. But we can add the coupon to the
user’s wallet, we have to make sure that he has enough GeekPoints
and update his GeekPoint balance. We do that using the static Mem-
bership. UpdateGeekPointsBalance method, which we will use again
later to implement purchasing additional GeekPoints:
public static async Task
UpdateGeekPointsBalance(int geekPointUpdate)
{
if (geekPointUpdate == 0)
{
return;
}
WalletTransactionItem membershipItem =
null;
try
{
membershipItem =
Membership.LoadMembershipFromWallet();
}
catch (Exception ex)
{
throw new
InvalidOperationException("There was an error
loading membership from your wallet.", ex);
}
int geekPointsInWallet = 0;
CustomWalletProperty
geekPointsProperty = null;
if (membershipItem != null)
{
if
(membershipItem.CustomProperties.TryGetValue(M
embership.GeekPointsKey, out
geekPointsProperty))
{
geekPointsInWallet =
int.Parse(geekPointsProperty.Value);
}
}
int newGeekPointsBalance =
geekPointsInWallet + geekPointUpdate;
if (newGeekPointsBalance < 0)
{
throw new
InvalidOperationException("You do not have
enough GeekPoints in your wallet.");
}
// update GeekPoints balance in wallet
membershipItem.DisplayAvailableBalance
= string.Format("{0} GeekPoints",
newGeekPointsBalance);
geekPointsProperty.Value =
newGeekPointsBalance.ToString();
await membershipItem.SaveAsync();
// update GeekPoints balance in app
App.MembershipRepository.UpdateGeekPoi
nts(newGeekPointsBalance);
}
18 Windows Phone Geek Magazine
Finally, to implement removing the current coupon from the Wallet
we use the static Wallet.Removemethod as shown in the following
code snippet:
private void btnRemoveFromWallet_Click(object
sender, RoutedEventArgs e)
{
MessageBoxResult messageBoxResult =
MessageBox.Show(
"Are you sure you want to
remove this coupon from your wallet?",
"Confirm remove coupon from
wallet", MessageBoxButton.OKCancel);
if (messageBoxResult ==
MessageBoxResult.Cancel)
{
return;
}
try
{
Wallet.Remove(this.currentCoupon.ID);
this.currentCoupon.InWallet =
false;
}
catch (Exception ex)
{
MessageBox.Show("There was an
error removing the coupon from your wallet: "
+ ex.Message);
}
this.currentCoupon.InWallet = false;
}
Working with memberships Since we have already implemented our membership model classes
we will jump straight to MainPage.xaml.cs and implement the Get-
MembershipStatus method that returns a string representing the cur-
rent status of the user’s membership.We will start by adding the
following method in our Membership class in order to retrieve the
membership item from the Wallet. The method uses the static
FindItem method of the Wallet class. We will also add several
string constants that we will be using:
public static readonly string WalletKey =
"Membership";
public static readonly string FirstNameKey =
"FirstName";
public static readonly string LastNameKey =
"LastName";
public static readonly string AccountNameKey =
"AccountName";
public static readonly string GeekPointsKey =
"GeekPoints";
public static WalletTransactionItem
LoadMembershipFromWallet()
{
// Retrieve membership from the
wallet.
WalletTransactionItem membershipItem =
Wallet.FindItem(Membership.WalletKey)
as WalletTransactionItem;
return membershipItem;
}
Now that we have this method, all we have to do in order to check if
the user has an active membership is call Member-
ship.LoadmembershipFromWallet and check that the result is not
null, as shown in the following code snippet:
private string GetMembershipStatus()
{
StringBuilder statusBuilder = new
StringBuilder();
WalletTransactionItem membershipItem =
null;
try
{
membershipItem =
Membership.LoadMembershipFromWallet();
}
catch (Exception ex)
{
MessageBox.Show("There was an
error loading membership from your wallet: " +
ex.Message);
return string.Empty;
}
bool membershipActive = membershipItem
!= null;
statusBuilder.Append("Membership
active: ");
statusBuilder.Append(membershipActive
? "Yes" : "No");
if (membershipActive)
{
string geekPoints =
membershipItem.CustomProperties[Membership.Gee
kPointsKey].Value;
statusBuilder.AppendFormat(",
GeekPoints balance: {0}", geekPoints);
}
return statusBuilder.ToString();
}
Note that in the code snippet above we are
retrieving the amount of GeekPoints that the
user has left from the CustomProperties
collection of the membership item. You can
use the CustomProperties collection to
store any additional information for wallet
items.
We can finally, move to the implementation
of the Membership Details page. This page
allows the user see details for the member-
ship and perform operations like create, add to wallet and remove
19 Windows Phone Geek Magazine
from wallet. Here, in order to add the membership to the wallet, we
will create a new WalletTransactionItem and then use the
AddWalletItemTask to actually prompt the user to add the mem-
bership to the Wallet. Here is the code that does that:
try
{
WalletTransactionItem membershipItem;
membershipItem = new
WalletTransactionItem("membership");
membershipItem.IssuerName =
WalletMerchantInfo.IssuerName;
membershipItem.DisplayName =
WalletMerchantInfo.IssuerName + " Membership
Card";
membershipItem.CustomerName =
this.membership.CustomerName;
membershipItem.AccountNumber =
this.membership.AccountName;
membershipItem.IssuerWebsite =
WalletMerchantInfo.IssuerWebsite;
// add a custom property for
GeekPoints
membershipItem.CustomProperties.Add(Me
mbership.GeekPointsKey,
new
CustomWalletProperty(this.membership.GeekPoint
s.ToString(), "Geek Points"));
membershipItem.DisplayAvailableBalance
= string.Format("{0} GeekPoints",
this.membership.GeekPoints);
BitmapImage wpgImage = new
BitmapImage();
using (System.IO.Stream stream =
Assembly.GetExecutingAssembly().GetManifestRes
ourceStream("WP8WalletSample.Assets.WPGlogo.pn
g"))
{
wpgImage.SetSource(stream);
}
membershipItem.Logo99x99 = wpgImage;
membershipItem.Logo159x159 = wpgImage;
membershipItem.Logo336x336 = wpgImage;
AddWalletItemTask addWalletItemTask =
new AddWalletItemTask();
addWalletItemTask.Item =
membershipItem;
addWalletItemTask.Show();
}
catch (Exception ex)
{
MessageBox.Show("There were the
following errors when saving your membership
to the wallet: " + ex.Message);
}
Note that, in the code snippet above, we have to extract the image
that we use for the logo of the wallet item from the app assembly
before showing the AddWalletItemTask. This is necessary since
the task is external to the app and the image needs to be completely
loaded before the task is shown.
Finally, in order to implement removing the membership from the
Wallet we will use the static Remove method of the Wallet class as
shown in the following code snippet. Before removing the member-
ship from the Wallet it is a good idea to ask the user to confirm that
this is really what he wants.
private void btnRemoveFromWallet_Click(object
sender, RoutedEventArgs e)
{
MessageBoxResult mResult =
MessageBox.Show(
"Are you sure you want to
remove your membership card from your
wallet?",
"Confirm membership removal",
MessageBoxButton.OKCancel);
if (mResult == MessageBoxResult.OK)
{
// get the membership from
wallet
WalletTransactionItem
walletMembershipItem = null;
try
{
walletMembershipItem
= Membership.LoadMembershipFromWallet();
}
catch (Exception ex)
{
MessageBox.Show("There was an
error loading membership from your wallet: " +
ex.Message);
}
// if the membership is still
in wallet, remove it
if (walletMembershipItem !=
null)
{
Wallet.Remove(walletMembershipItem);
this.MembershipItem =
null;
}
}
}
Conclusion The Wallet APIs that come with Windows Phone 8 allow developers
to easily implement coupons and memberships and offer the user an
experience that is unified across all apps. Furthermore, by imple-
menting integration with the Wallet in your app, you are exposing it
to the user in yet another way and offering a more convenient and
integrated experience at the same time.
Download the Full Source code here.
20 Windows Phone Geek Magazine
Implementing in-app purchasing in Windows Phone 8
By Yordan Pavlov
One of the most important features that Windows Phone 8 brings is
in-app purchasing and it’s quite easy to implement. To demonstrate
in-app purchasing, we will extend the Wallet app from the previous
article to allow the user to purchase GeekPoints which he can then
exchange for more coupons.
Adding an in-app product Before you can start offering in-app products in your app, you have
to add them to the app in the Windows Phone Dev Centre. To do
that, in the Dev Cenre Dashboard, go to Apps and select the app for
which you want to add the in-app product. Then in the Products tab
click the “Add in-app product” link:
Then follow the steps to create your in-app product:
NOTE: In order to test in-app purchasing you must change the
Product ID in WMAppManifest.xml to that of an app that has asso-
ciated in-app products in the marketplace.
If you do not know the App ID, you can find it in the Details tab for
the app (in the Windows Phone Dev Centre):
Finally, you have to set the App ID in the WMAppManifest.xml file:
Implementing in-app purchasing After we have created an in-app product for our app, we can now
finally get to the code. The entry point to the in-app purchasing API
is the CurrentApp class which exposes methods for retrieving
product information and licenses. We said earlier that in our sample
app, we will implement purchasing of additional Geek Points.
All you have to do to implement in-app purchasing in your app is:
1. Define your in-app products in the Windows Phone Dev center
– we have already done that
2. Retrieve the available in-app products using either
LoadListingInformationByProductIdsAsync or
LoadListingInformationByKeywordsAsync
3. Prompt the user to purchase the product by using
RequestProductPurchaseAsync
4. Check that the product has been purchased and there is an ac-
tive license in
CurrentApp.LicenseInformation.ProductLicenses
21 Windows Phone Geek Magazine
5. Fulfill the purchase (in our case – increase the number of Geek
Points by 100)
6. Report that the purchases has been fulfilled by calling
ReportProductFulfillment
NOTE: For consumable products, if you do not notify the market-
place (using the CurrentApp.ReportProductFulfillment method)
that the purchase has been fulfilled, the user will not be able to make
another purchase of the same (consumable) product
Here is how the in-app purchasing process is implemented in the
Membership Details page of our Wallet sample app:
public static readonly string InAppProductKey
= "WPGP100";
private async void
btnBuyGeekPoints_Click(object sender,
RoutedEventArgs e)
{
bool isMembershipInWallet =
Membership.LoadMembershipFromWallet() != null;
if (!isMembershipInWallet)
{
MessageBox.Show("You must
first add the membership to your wallet");
return;
}
// get all in-app products for current
app
//ListingInformation allProducts =
await
CurrentApp.LoadListingInformationByProductIdsA
sync(new string[0]);
ListingInformation products = await
CurrentApp.LoadListingInformationByProductIdsA
sync(new [] { InAppProductKey });
// will only load the 100 Geek Points
consumable product
// get specific in-app product by ID
ProductListing productListing = null;
if
(!products.ProductListings.TryGetValue(InAppPr
oductKey, out productListing))
{
MessageBox.Show("Could not
find product information");
return;
}
// start product purchase
await
CurrentApp.RequestProductPurchaseAsync(product
Listing.ProductId, false);
ProductLicense productLicense = null;
if
(CurrentApp.LicenseInformation.ProductLicenses
.TryGetValue(InAppProductKey, out
productLicense))
{
if (productLicense.IsActive)
{
MessageBox.Show("Product purchased");
// add GeekPoints to
membership
await
Membership.UpdateGeekPointsBalance(100);
// notify marketplace
that product has been delivered
CurrentApp.ReportProductFulfillment(In
AppProductKey);
// reload membership
to update UI
this.Membership =
App.MembershipRepository.LoadMembership();
return;
}
}
MessageBox.Show("Product not
purchased");
}
NOTE: to make testing easier, purchasing in-app product in the
emulator is free and does not involve credit card transactions
Conclusion Windows Phone 8 adds in-app purchasing to the list of tools that
developers can use to make money from their apps. Even though in-
app purchasing usually involves several components working to-
gether, implementing it in your apps is not a difficult task. The hard
part, as with everything that involves payment, is to make sure that it
works. In this article we showed how you can test in-app purchasing
in the emulator, but it is recommended that you also cover your in-
app purchasing code with unit tests.
Download the Full Source code here.
22 Windows Phone Geek Magazine
23 Windows Phone Geek Magazine
File and URI associations in Windows Phone 8
By WindowsPhoneGeek team
The Windows Phone 8 SDK comes with a new URI and File associ-
ations feature that allows you to (1) launch files and URIs from your
app and (2) register file and URI associations for your app. This
little gem in the SDK allows developers to launch other apps and
even pass parameters when they do that. The experience for the user
is similar to other platforms – when a file or URI is launched, if
more than one app is registered for it, the user will be asked which
app he wants to use. If an app causes the user to make such a choice
frequently, he may choose to uninstall the app. This is why you must
only register file and URI associations for your app if you can do
something useful.
This article will show you how to launch apps using Files and URIs
and how to register a File or URI association for your app and han-
dle the launch requests.
URI format The most important thing you should know about the URI format is
that it must begin with the URI schema name that the app you want
to launch has registered (in our case this is the “winphonegeek”
name that is registered in the manifest). The schema name is fol-
lowed by “:” and the rest of the URI can be whatever you want to
pass to the launched app. Here is an example:
"winphonegeek:?param1=value1¶m2=value2"
Or if you want to navigate for example to the built inWi-Fi settings,
without passing any parameters:
"ms-settings-wifi:"
When the app is launched, the URI that it will receive will look like
this:
"/Protocol?encodedLaunchUri=winphonegeek:?para
m1=value1¶m2=value2"
Launching apps using URI associations Now that we know how to create URIs for launching apps, we will
create a sample application that launches different built-in apps like
for example the location settings, Wi-Fi settings, lock screen set-
tings, the Wallet, etc. We will also demonstrate how the app can
launch itself (or any other app).
We will create an UriCommand class, which we will use to create a
list of URI commands and display them in list:
public class UriCommand
{
public string Title { get; set; }
public string Uri { get; set; }
public string ImageUri {get;set;}
}
Now, let’s create a list of URI commands to be displayed in the list
control. Note that each UriCommand object has a different URI:
public IEnumerable<UriCommand>
GetUriCommandList()
{
return new List<UriCommand>()
{
new UriCommand() {
Title = "This app",
ImageUri = "/Images/logo.png",
Uri =
"winphonegeek:?param1=value1¶m2=value2"
},
new UriCommand() {
Title = "Location settings",
ImageUri = "/Images/location.png",
Uri = "ms-settings-location:"
},
new UriCommand() {
Title = "WiFi settings",
ImageUri = "/Images/wifi.png",
Uri="ms-settings-wifi:"
},
new UriCommand() {
Title = "Lock settings",
ImageUri = "/Images/lock.png",
Uri = "ms-settings-lock:"
},
new UriCommand() {
Title = "Wallet",
ImageUri = "/Images/wallet.png",
Uri = "wallet:"
}
};
}
We will now create a ListBox control in MainPage.xaml to display
our list of URI commands with a Launch button for each of them:
<ListBox x:Name="lbUriCommands">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Width="70" Height="70"
Fill="{StaticResource PhoneForegroundBrush}">
<Rectangle.OpacityMask>
<ImageBrush ImageSource="{Binding ImageUri}"
Stretch="Fill" />
</Rectangle.OpacityMask>
</Rectangle>
24 Windows Phone Geek Magazine
<TextBlock Text="{Binding Title}"
VerticalAlignment="Center"
Style="{StaticResource PhoneTextTitle2Style}"
/>
<Button Content="Launch" Click="Button_Click"
/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
We can now set the ItemsSource for the list box control in the
MainPage constructor like this:
this.lbUriCommands.ItemsSource =
this.GetUriCommandList();
Finally, let’sadd the following code inside theLaunch button Click
event handler, which actually launches the selected URI using the
Launcher.LaunchUriAsync method:
private void Button_Click(object sender,
RoutedEventArgs e)
{
Button button = sender as Button;
if (button == null)
{
return;
}
UriCommand uriCommand =
button.DataContext as UriCommand;
if (uriCommand != null)
{
try
{
Launcher.LaunchUriAsync(new
Uri(uriCommand.Uri));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
If you now launch the app you should see one of these:
NOTE: We have used an OpacityMask in order to make sure that the
images are displayed correctly in both the dark and light themes.
More about working with OpacityMask you can find here: Creating
theme friendly UI in WP7 using OpacityMask
You should now be able to play with the app and launch some of the
built-in settings apps:
Registering for URI associations In order to register an URI association you will have toinclude a
Protocol element inside the Extensions section in theWMAppMani-
fest.xmlfile:
<Extensions>
<Protocol Name="winphonegeek"
NavUriFragment="encodedLaunchUri=%s"
TaskID="_default" />
</Extensions>
Here is the meaning of the attributes of the Protocol element:
Name: the prefix that you use for your URI schema
NavUriFragment: must always be set toencodedLaunchUri=%s
TaskID: Must always be set to _default
Note that you can register a maximum of 10 (ten) URI associations
per app.
Now that you have registered an URI association for the app, you
have to write some code to handle the launch requests. You do that
by implementing an URI mapper. For this article we have imple-
mented theAssociationUriMapperclass which knows how to handle
URIs with the winphonegeek schema name. Here is the code:
public class AssociationUriMapper :
UriMapperBase
{
public override Uri MapUri(Uri uri)
{
25 Windows Phone Geek Magazine
string uriString =
System.Net.HttpUtility.UrlDecode(uri.ToString(
));
if
(uriString.StartsWith("/Protocol"))
{
return
this.HandleUriAssociation(uriString);
}
else if
(uriString.StartsWith("/FileTypeAssociation"))
{
return
this.HandleFileAssociation(uriString);
}
// if this is not an uri that
we can handle, return original uri
return uri;
}
private Uri
HandleUriAssociation(string uriString)
{
int uriStartIndex =
uriString.IndexOf("winphonegeek:");
if (uriStartIndex < 0)
{
// this is not an URI
that we can handle
return new
Uri("/MainPage.xaml", UriKind.Relative);
}
// get the query string after
the winphonegeek: schema
int queryStartIndex =
uriString.IndexOf("?", uriStartIndex);
string newUri =
"/UriTestPage.xaml";
if (queryStartIndex > -1)
{
string query =
uriString.Substring(queryStartIndex);
newUri += query;
}
// redirect all requests with
the winphonegeek: schema to /UriTestPage.xaml
return new Uri(newUri,
UriKind.Relative);
}
public static readonly string
FileTokenKey = "fileToken";
private Uri
HandleFileAssociation(string uriString)
{
}
}
Note: UriTestPage.xaml is a sample page in our application project.
Our AssociationUriMapperworks by redirecting all launch requests
coming from an URI association (starting with /Protocol) to that
page, together with any query string parameters. You have probably,
noticed the empty HandleFileAssociation method. This is where we
will put the code that processes file association URIs later.
Next, you have to tell your app to use the URI mapper by assigning
an instance of it to the UriMapper property of the RootFrame. You
do that in theInitializePhoneApplicationmethod in App.xaml.cs as
shown in the following code snippet:
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
RootFrame = new PhoneApplicationFrame();
// set an uri mapper that can handle uri
associations
RootFrame.UriMapper = new
AssociationUriMapper();
//..
}
Finally, in the OnNavigatedTo method of the UriTestPage class, we
will show any query string parameters that we have received in a list
box:
protected override void
OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
List<string> queryParams = new
List<string>();
foreach (KeyValuePair<string, string>
param in this.NavigationContext.QueryString)
{
queryParams.Add(string.Format("key:
{0}, value: {0}", param.Key, param.Value));
}
this.lbQueryParams.ItemsSource =
queryParams;
}
For the sake of completeness, here is how the ListBox control is
defined in UriTestPage.xaml:
<!--ContentPanel - place additional content
here-->
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<ListBox x:Name="lbQueryParams" />
</Grid>
If you now launch the app using the URI association you should see
this:
26 Windows Phone Geek Magazine
Launching apps using file associations Launching files is done again using the Launcher class, very similar
to launching URIs. Let’s add a button in MainPage.xaml that will
launch a file when clicked. Change the XAML to look like this:
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<StackPanel Orientation="Vertical">
<Button x:Name="btnLaunchFile" Content="Launch
File"
Click="btnLaunchFile_Click" />
<TextBlock Text="URI associations:"
Style="{StaticResource PhoneTextTitle2Style}"
/>
<ListBox x:Name="lbUriCommands">
<!--ListBox ItemTemplate-->
</ListBox>
</StackPanel>
</Grid>
Let’s now implement the Click event handler for the “Launch file”
button:
private async void btnLaunchFile_Click(object
sender, RoutedEventArgs e)
{
// Access isolated storage.
StorageFolder appFolder =
Package.Current.InstalledLocation;
// Access the bug query file.
StorageFile wpgFile = await
appFolder.GetFileAsync("TestFile.wpg");
// Launch the bug query file.
Launcher.LaunchFileAsync(wpgFile);
}
Note that we are using LaunchFileAsyncmethod instead of Laun-
chUriAsync to launch the file.
NOTE: In the code above, we are using a file called TestFile.wpg,
located in the app’s installation folder. In order to test the app, add a
file with that name in the project and make sure that its build action
is set to Content.
Registering for file associations To register a file association, you must add a FileTypeAssociation
element at the beginning of the Extensions element in the
WMAppManifest.xml file, so that it looks like this:
<Extensions>
<FileTypeAssociation Name="WPG file"
NavUriFragment="fileToken=%s"
TaskID="_default">
<!--<Logos>
<Logo
Size="Small">bug-small-33x33.png</Logo>
<Logo
Size="Medium">bug-medium-69x69.png</Logo>
<Logo
Size="Large">bug-large-176x176.png</Logo>
</Logos>-->
<SupportedFileTypes>
<FileType
ContentType="application/wpg">.wpg</FileType>
</SupportedFileTypes>
</FileTypeAssociation>
<Protocol Name="winphonegeek"
NavUriFragment="encodedLaunchUri=%s"
TaskID="_default" />
</Extensions>
Let’s now write the code that handles file launch request in the
HandleFileAssociation method of our URI mapper:
public static readonly string FileTokenKey =
"fileToken";
private Uri HandleFileAssociation(string
uriString)
{
// get file id
int fileIDIndex =
uriString.IndexOf(FileTokenKey) +
FileTokenKey.Length + 1;
string fileID =
uriString.Substring(fileIDIndex);
// get file name
string fileName =
SharedStorageAccessManager.GetSharedFileName(f
ileID);
// Get file extension
string fileExtension =
Path.GetExtension(fileName);
if (fileExtension == ".wpg")
{
return new
Uri(string.Concat("/FileTestPage.xaml?fileToke
n=", fileID), UriKind.Relative);
}
27 Windows Phone Geek Magazine
return new Uri("/MainPage.xaml",
UriKind.Relative);
}
Note that we are using the SharedStorageAccessManager to get
the file name so that we can check if the file’s extension is one that
we can work with. If the extension is .wpg then the code returns an
URI for the FileTestPage. This is a very simple page that just has
one TextBlock. Here is the XAML for the sake of completeness:
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<TextBlock x:Name="txtFile" />
</Grid>
Finally, in the OnNavigatedTo method of the new FileTestPage we
will write some code to retrieve the file and display its content in the
page:
protected async override void
OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string fileID =
this.NavigationContext.QueryString[Association
UriMapper.FileTokenKey];
string fileName =
SharedStorageAccessManager.GetSharedFileName(f
ileID);
StringBuilder result = new
StringBuilder();
result.AppendFormat("File name: {0}",
fileName);
result.AppendLine();
result.AppendLine("Content:");
StorageFolder localFolder =
ApplicationData.Current.LocalFolder;
IStorageFile file = await
SharedStorageAccessManager.CopySharedFileAsync
(
localFolder, fileName,
NameCollisionOption.ReplaceExisting, fileID);
using (Stream stream = await
file.OpenStreamForReadAsync())
{
using (TextReader reader = new
StreamReader(stream))
{
result.AppendLine(reader.ReadToEnd());
}
}
this.txtFile.Text = result.ToString();
}
Note that we are using the SharedStorageAccessManager class
again to copy the shared file in the app’s isolated storage from where
we can read it.
If you now launch the app and click the “Launch file” button you
should see something like this:
Conclusion URI and file associations in Windows Phone 8 allow you not only to
launch other apps, including built-in ones, but also to accept launch
requests from other apps. However, you must be careful when regis-
tering for URI and file associations and make sure that your app
does something useful with them.
Download the Full Source code here.
28 Windows Phone Geek Magazine
New Launchers in Windows Phone 8
By WindowsPhoneGeek team
Windows Phone 8 SDK offers a set of predefined tasks that enable
applications to access phone functionality (Calendar, Map, SMS,
Camera and more) and perform common tasks such as saving ap-
pointments, downloading map data for offline usage, sharing a me-
dia file on social networks and more. All this is performed via dif-
ferent Launchers and Choosers, each exposing a different API. The
difference between a Launcher and a Chooser is that choosers return
data, while launchers just start an application from the phone but do
not return anything.
NOTE: It is important to consider that when you start a task, a sepa-
rate application is launched to complete the task and your applica-
tion is tombstoned.
This article guides you through the new Tasks in Windows Phone 8
and shows how to use them.
NOTE: All Tasks that are available in Windows Phone 8 can be
found in the Microsoft.Phone.Tasksnamespace. Do not forget to
include this namespace when using any of the Task classes.
SaveAppointmentTask The SaveAppointmentTask launches the built-in calendar applica-
tion and prompts the user to add a new appointment to their calen-
dar. The task API allows you to populate many of the fields of the
new appointment.
private void
btnLaunchAppointmentTask_Click(object sender,
RoutedEventArgs e)
{
SaveAppointmentTask saveAppointmentTask =
new SaveAppointmentTask();
DateTime currentTime = DateTime.Now;
saveAppointmentTask.StartTime =
currentTime.AddHours(1);
saveAppointmentTask.EndTime =
currentTime.AddHours(3);
saveAppointmentTask.Subject = "Meet John";
// appointment subject
saveAppointmentTask.Location = "Office"; //
appointment location
saveAppointmentTask.Details = "Meet John to
discuss product launch"; // appointment
details
saveAppointmentTask.IsAllDayEvent = false;
saveAppointmentTask.Reminder =
Reminder.FifteenMinutes;
saveAppointmentTask.AppointmentStatus =
Microsoft.Phone.UserData.AppointmentStatus.Bus
y;
saveAppointmentTask.Show();
}
MapDownloaderTask The MapDownloaderTask launches the built-in Map application
settings and enables the user to download map data for offline use.
private void btnLaunchMapDownloader-
Task_Click(object sender, RoutedEventArgs e)
{
MapDownloaderTask mapDownloa-derTask = new
MapDownloaderTask();
mapDownloaderTask.Show();
}
MapsTask The MapsTask launches the built-in Map application centered at the
user`s current location. You can set a new location, a search term or
29 Windows Phone Geek Magazine
the map zoom level using the Center, SearchTerm and ZoomLevel
properties as shown in the code snippet.
private void btnLaunchMapsTask_Click(object
sender, RoutedEventArgs e)
{
MapsTask mapsTask = new Maps-Task();
mapsTask.Center = new Geo-
Coordinate(51.5171, -0.1362); // London
// 1 - zoomed out, 20 - zoomedin
mapsTask.ZoomLevel = 7;
mapsTask.SearchTerm = "pizza";
mapsTask.Show();
}
MapsDirectionsTask The MapsDirectionsTask launches the built-in Map application
with driving directions for getting from a starting location to a desti-
nation location. The starting and destination locations can be set as
coordinates using the Start and End properties.
private void btnLaunchMapsDirections-
Task_Click(object sender, RoutedEventArgs e)
{
MapsDirectionsTask mapsDirectionsTask = new
MapsDirectionsTask();
mapsDirectionsTask.Start = new
LabeledMapLocation("London Victoria", new Geo-
Coordinate(51.495322, -0.144732));
mapsDirectionsTask.End = new
LabeledMapLocation("London Heathrow", new
GeoCoor-dinate(51.471179, -0.454447));
mapsDirectionsTask.Show();
}
ShareMediaTask The ShareMediaTask launches a dialog that enables a user to share a
media file. The following code snippet demonstrates how to ask the
user to pick a photo and then share it.
private void
btnLaunchShareMediaTask_Click(object sender,
RoutedEventArgs e)
{
PhotoChooserTask photoChooserTask = new
PhotoChooserTask();
photoChooserTask.ShowCamera = true;
photoChooserTask.Completed +=
photoChooserTask_Completed;
photoChooserTask.Show();
}
void photoChooserTask_Completed(object sender,
PhotoResult e)
{
ShareMediaTask shareMediaTask = new
ShareMediaTask();
shareMediaTask.FilePath =
e.OriginalFileName;
shareMediaTask.Show();
}
Conclusion In this article we discussed which the new tasks in Windows Phone
8 are and how to use them. We showed how to prompt the user to
add a new appointment, how to display a location or directions on a
map and finally, how to share a media file.
Download the Full Source code here.
30 Windows Phone Geek Magazine
New LongListSelector control in Windows Phone 8 SDK
By Boryana Miloshevska
The LongListSelector implements a jump-list style of UI as seen in
the address book of the phone. This type of UI is usually used to
display long lists of data. Up until now, if you wanted to use a
LongListSelector control in your app, you had to use an implemen-
tation of this control from a library like the Windows Phone Toolkit.
This changes with Windows Phone 8, since a LongListSelector
control is now included in the SDK. In this article we will demon-
strate how to use this control, as well as share some important tips
for porting apps that use the LongListSelector from the Windows
Phone Toolkit.
The new LongListSelect control that is now part of the Windows
Phone 8 SDK, implements full UI and data virtualization. In fact, it
is recommended that you use the LongListSelector instead of the
ListBox control, whenever you want to display lists of data, even if
the data does not need to be grouped.
NOTE: Those of you, who are new to Windows Phone, can think of
the LongListSelector as an advanced ListBox that can display both
flat and grouped lists. It helps users to navigate through long lists of
data, by allowing them to jump between different sections of the list
using a quick jump grid that overlays the list when the user selects
one of the group headers.
NOTE: The new LongListSelector is different than the well-known
Windows Phone Toolkit LongListSelector. Although they may look
similar at first sight, the new control exposes different properties,
has different data source requirements and is used in a slightly dif-
ferent way.
Visual structure In the following diagrams you can see the visual structure of the
LongListSelector control:
31 Windows Phone Geek Magazine
NOTE: You can use the LayoutMode property of the JumpListStyle
to display the group headers either in a list or grid layout.
Data source requirements We will create a sample app that displays information about differ-
ent cities grouped by country.
To generate the data source we will use the following method:
private static IEnumerable<City> GetCityList()
{
List<City> cityList = new List<City>();
cityList.Add(new City() { Name = "Milan",
Country = "IT", Language = "Italian", Flag =
new Uri(@"/Images/Italy.png",
UriKind.Relative) });
cityList.Add(new City() { Name = "Roma",
Country = "IT", Language = "Italian", Flag =
new Uri(@"/Images/Italy.png",
UriKind.Relative) });
cityList.Add(new City() { Name = "Madrid",
Country = "ES", Language = "Spanish", Flag =
new Uri(@"/Images/Spain.png",
UriKind.Relative) });
//..
return cityList;
}
Where City is a basic class that exposes the following properties:
To prepare the list of cities to be displayed with the LongListSelec-
tor control we will use the following code to group the cities by
country:
private List<Group<City>> GetCityGroups()
{
IEnumerable<City> cityList =
GetCityList();
return GetItemGroups(cityList, c =>
c.Country);
}
private static List<Group<T>>
GetItemGroups<T>(IEnumerable<T> itemList,
Func<T, string> getKeyFunc)
{
IEnumerable<Group<T>> groupList =
from item in itemList
group item by getKeyFunc(item) into g
orderby g.Key
select new Group<T>(g.Key, g);
return groupList.ToList();
}
NOTE: While the LongListSelector control from the Windows
Phone Toolkit worked fine with data sources that only implement
IEnumerable, the new control requires IList. This is why our
GetCityGroups method returns List and the Group class in the fol-
lowing code snippet inherits List<T> as well. On the other side,
overriding Equals is no longer required for the correct operation of
the jump list. As a result we end up with a very simple Group class:
public class Group<T> : List<T>
{
public Group(string name, IEnumerable<T>
items)
: base(items)
{
this.Title = name;
}
public string Title
{
get;
set;
}
}
The UI We will start building the UI for this example, by defining the tem-
plates for all elements that we identified while discussing the visual
structure of the LongListSelector control.
GroupHeaderTemplate– this template defines how the group
headers look
<DataTemplate x:Key="groupHeaderTemplate">
<Border Width="72" Height="72"
HorizontalAlignment="Left"
Background="{Binding Converter={StaticResource
BackgroundConverter}}" Margin="6">
<TextBlock Text="{Binding Title}"
FontSize="40" Padding="6"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="{Binding
Converter={StaticResource
ForegroundConverter}}" />
</Border>
</DataTemplate>
ItemTemplate– this template defines how list items look
32 Windows Phone Geek Magazine
<DataTemplate x:Key="citiesItemTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Flag}" Height="50"
Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="{Binding Name,
StringFormat='City: {0}'}" FontSize="26" />
<TextBlock Text="{Binding Language,
StringFormat='Language: {0}'}"
Style="{StaticResource PhoneTextSubtleStyle}"
/>
</StackPanel>
</StackPanel>
</DataTemplate>
JumpListStyle – this template defines how the jump list looks
<Style x:Key="LongListSelectorJumpListStyle"
TargetType="phone:LongListSelector">
<Setter Property="GridCellSize"
Value="113,113"/>
<Setter Property="LayoutMode" Value="Grid" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border Background="{Binding
Converter={StaticResource
BackgroundConverter}}"
Width="113"
Height="113" Margin="6" >
<TextBlock Text="{Binding Title}"
FontFamily="{StaticResource
PhoneFontFamilySemiBold}"
FontSize="48"
Padding="6"
Foreground="{Binding Converter={StaticResource
ForegroundConverter}}"
VerticalAlignment="Center"/>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
ListHeaderTemplate – this template defines how the list header
looks
<DataTemplate x:Key="citiesListHeader">
<Border Background="White" Opacity="0.2"
Height="70">
<TextBlock Text="Cities Header"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="Black" />
</Border>
</DataTemplate>
ListFooterTemplate – this template defines how the list footer
looks
<DataTemplate x:Key="citiesListFooter">
<Border Background="White" Opacity="0.2"
Height="70">
<TextBlock Text="Cities Footer"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="Black"/>
</Border>
</DataTemplate>
Finaly, note that the LongListSelector is placed in the “Mi-
crosoft.Phone.Controls” namespace. So, you can declare the control
in this way:
<phone:LongListSelector
x:Name="longListSelector"
IsGroupingEnabled="True" LayoutMode="List"
HideEmptyGroups="False"
ItemTemplate="{StaticResource
citiesItemTemplate}"
GroupHeaderTemplate="{StaticResource
groupHeaderTemplate}"
JumpListStyle="{StaticResource
LongListSelectorJumpListStyle}"
ListHeaderTemplate="{StaticResource
citiesListHeader}"
ListFooterTemplate="{StaticResource
citiesListFooter}" Margin="1,0,-1,0"/>
NOTE: If JumpListStyle is not set, the jump list will not work!
NOTE: You have to set IsGroupingEnabled="True"in order to dis-
play the list of items in groups.
NOTE:LayoutModespecifies whether the LongListSelector is in a list
mode or grid mode.
Finally, in order to display the list of cities, in the MainPage con-
structor in MainPage.xaml.cs, we set the ItemsSource property of the
LongListSelector like this:
this.longListSelector.ItemsSource =
this.GetCityGroups();
Conclusion The LongListSelect control that is now included with the Windows
Phone 8 SDK is an efficient implementation of the jump-list style UI
and supports full UI and data virtualization. It is actually recom-
mended to use the LongListSelector control instead of ListBox even
for displaying flat lists of data. This article demonstrates how to use
the new LongListSelector control. We also showed how the data
source requirements are different from the LongListSelector control
that comes with the Windows Phone Toolkit.
Download the Full Source code here.
33 Windows Phone Geek Magazine
New Location APIs and Background Location Tracking
By Boryana Miloshevska
Windows Phone 8 SDK offers a set of new run-time location APIs
for getting the current location of the phone. Another new feature
that is available is the background location tracking, which enables
apps to continue tracking location in the background even after the
user exits the app.
Before we begin If you want to use the location APIs in your app, you will need to
enable the location capability; otherwise your app may not work
correctly or may fail certification.
You can do this by editing the WMAppManifest.xmlfile and adding a
Capability element for ID_CAP_LOCATION inside the Capabilities
element:
Or alternatively you can use the visual designer: double click on
WMAppManifest.xmlandcheck the ID_CAP_LOCATIONcheckbox
in the Capabilities tab as shown below:
Finally, before we can get to the code, we will add the following
code in MainPage.xaml:
<StackPanel Orientation="Vertical">
<Button x:Name="btnGetCurrentLocation"
Content="Get current location"
Click="btnGetCurrentLocation_Click" />
<TextBlock Text="Current location:" />
<TextBlock x:Name="txtLocation" />
<CheckBox x:Name="cbEnableLocationTracking"
Content="Enable location
tracking"
Checked="cbEnableLocationTracking_Checked"
Unchecked="cbEnableLocationTracking_Unchecked"
/>
<TextBlock Text="Status:" />
<TextBlock x:Name="txtStatus" />
</StackPanel>
New API for getting the current location Windows Phone 8 includes new location APIs designed for apps that
do not need to track the phone’s location continuously but rather
only rarely need to retrieve the current location. In fact, if your app
does not need to continuously track location, using the API demon-
strated in the following code sample is recommended as it saves
battery and therefore improves user experience.
34 Windows Phone Geek Magazine
The new location APIs are exposed through the Geolocator class. In
order to get the phone’s current location we simply call the GetGe-
opositionAsync method. As demonstrated in the code bellow, you
can also set the desired accuracy and maximum age of the returned
coordinates (in meters), as well as the timeout (how much you are
willing to wait). Note that this is an asynchronous method which
returns IAsyncOperation<Geoposition> rather than just a Geoposi-
tion object, but calling it is easy using the new async and await
keywords. For now, it is enough to know, that all code after an await
statement will execute only after the asynchronous call has finished.
In our case this is the line where we format the coordinates using the
GetCoordinateString method and display the result in the txtLoca-
tion text block.
NOTE: Include the following namespace:
using Windows.Devices.Geolocation;
private async void
btnGetCurrentLocation_Click(object sender,
RoutedEventArgs e)
{
this.btnGetCurrentLocation.IsEnabled =
false;
Geolocator geolocator = new Geolocator();
geolocator.DesiredAccuracyInMeters = 50;
try
{
Geoposition position = await
geolocator.GetGeopositionAsync(
maximumAge: TimeSpan.FromMinutes(1), timeout:
TimeSpan.FromSeconds(30));
this.txtLocation.Text =
this.GetCoordinateString(position.Coordinate);
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Location is disabled in phone
settings.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
this.btnGetCurrentLocation.IsEnabled =
true;
}
}
private string
GetCoordinateString(Geocoordinate coordinate)
{
string positionString = string.Format("Lat:
{0:0.0000}, Long: {1:0.0000}, Acc: {2}m",
coordinate.Latitude,
coordinate.Longitude, coordinate.Accuracy);
return positionString;
}
New APIs for location tracking NOTE: You should use location tracking only if it is necessary for
your app to work correctly. Have in mind that this could cut down
the battery life of the phone. So, if your app requires only the current
location then is it recommended that you use the GetGeopositionA-
sync method instead.
The Geolocator class also exposes new APIs for continuous loca-
tion tracking. In order to do continuous location tracking in your
app, you just need to subscribe to the PositionChanged event of an
instance of the Geolocator class. Similar to retrieving one-off loca-
tion data, you can control settings like the desired accuracy and
movement threshold as demonstrated in the following code snippet.
private void
cbEnableLocationTracking_Checked(object
sender, RoutedEventArgs e)
{
if (App.Geolocator == null)
{
App.Geolocator = new Geolocator();
App.Geolocator.DesiredAccuracy =
PositionAccuracy.High;
App.Geolocator.MovementThreshold =
100; // 100 meters
App.Geolocator.StatusChanged +=
geolocator_StatusChanged;
App.Geolocator.PositionChanged +=
geolocator_PositionChanged;
}
}
Thegeolocator_PositionChanged event handler will be called when-
ever the change in the phone’s location is greater than the value set
to the MovementThreshold property. In the handler of the Posi-
tionChanged event, we have access the phone’s current location
through the event arguments as demonstrated in the next code snip-
pet. It is important to check if the app is tracking location in the
background, and do not do any UI updates if it is. Also, if the app is
running in the foreground, then we must use the Dispatcher to up-
date the UI since the PositionChanged event handler is not executed
on the main thread.
void geolocator_PositionChanged(Geolocator
sender, PositionChangedEventArgs args)
{
string positionString =
this.GetCoordinateString(args.Position.Coordin
ate);
if (!App.RunningInBackground)
{
// IMPORTANT: the event handler is
called on a worker thread,
// so we must use the Dispatcher to
update the UI from the main thread
Dispatcher.BeginInvoke(() =>
{
this.txtLocation.Text =
positionString;
});
}
else
35 Windows Phone Geek Magazine
{
Microsoft.Phone.Shell.ShellToast toast
= new Microsoft.Phone.Shell.ShellToast();
toast.Content = positionString;
toast.Title = "Location: ";
toast.NavigationUri = new
Uri("/MainPage.xaml", UriKind.Relative);
toast.Show();
}
}
When implementing location tracking in your app, you can also sub-
scribe to the StatusChanged event of the Geolocator to be notified
of changes in the status of location tracking. You can then access the
current status from the arguments of the StatusChanged event han-
dler as demonstrated in the following code snippet. This event han-
dler is again not executed on the main thread so it is important to use
the Dispatcher if you want to update the UI.
void geolocator_StatusChanged(Geolocator
sender, StatusChangedEventArgs args)
{
if (App.RunningInBackground)
{
return;
}
string status = "";
switch (args.Status)
{
case PositionStatus.Disabled:
// the application does not have
the right capability or the location master
switch is off
status = "location is disabled in phone
settings";
break;
case PositionStatus.Initializing:
// the geolocator started the
tracking operation
status = "initializing";
break;
case PositionStatus.NoData:
// the location service was not
able to acquire the location
status = "no data";
break;
case PositionStatus.Ready:
// the location service is
generating geopositions as specified by the
tracking parameters
status = "ready";
break;
case PositionStatus.NotAvailable:
status = "not available";
// not used in WindowsPhone,
Windows desktop uses this value to signal that
there is no hardware capable to acquire
location information
break;
case PositionStatus.NotInitialized:
// the initial state of the
geolocator, once the tracking operation is
stopped by the user the geolocator moves back
to this state
status = "not initialized";
break;
}
// IMPORTANT: the event handler is called
on a worker thread,
// so we must use the Dispatcher to update
the UI from the main thread
Dispatcher.BeginInvoke(() =>
{
this.txtStatus.Text = status;
});
}
Implementing background location
tracking To implement background location tracking in your app, you must
first edit the WMAppManifest.xml file and change the DefaultTask
element to look like this:
<DefaultTask Name="_default"
NavigatioPage="MainPage.xaml">
<BackgroundExecution>
<ExecutionType
Name="LocationTracking" />
</BackgroundExecution>
</DefaultTask>
Then in App.xaml, add an event handler for the RunningInBack-
ground event as in the following code snippet:
<shell:PhoneApplicationService
Launching="Application_Launching"
Closing="Application_Closing"
Activated="Application_Activated"
Deactivated="Application_Deactivated"
RunningInBackground="PhoneApplicationService_R
unningInBackground" />
Next in App.xaml.cs add the following properties and the event han-
dler for the RunningInBackground event:
public static Geolocator Geolocator { get;
set; }
public static bool RunningInBackground { get;
set; }
private void
PhoneApplicationService_RunningInBackground(ob
ject sender, RunningInBackgroundEventArgs e)
{
RunningInBackground = true;
}
Finally, in the Activated event handler in App.xaml.cs set the Run-
ningInBackground property to false:
private void Application_Activated(object
sender, ActivatedEventArgs e)
{
RunningInBackground = false;
36 Windows Phone Geek Magazine
}
You should check the value of the RunningInBackground property
in your Geolocator event handlers and make sure that you are not
updating the UI when your app is tracking the phone’s location in
the background.
It is recommended that you unsubscribe from Geolocator events
when your app is removed from the navigation journal as demon-
strated in the following code snippet:
protected override void
OnRemovedFromJournal(JournalEntryRemovedEventA
rgs e)
{
this.StopLocationTracking();
}
private void StopLocationTracking()
{
App.Geolocator.PositionChanged -=
geolocator_PositionChanged;
App.Geolocator.StatusChanged -=
geolocator_StatusChanged;
App.Geolocator = null;
}
Finally, when your app is re-launched it is recommended that, in
order to provide consistent experience for the user, you clear the
navigation history. If you have created your app using the new Win-
dows Phone 8 project templates, your project already includes code
that does this and you do not need to add such code manually. How-
ever, if you are upgrading an existing app, you might need to im-
plement this in the RootFrame.Navigated event handler in
App.xaml.cs, as shown in the following code snippet.
void RootFrame_Navigated(object sender,
NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.Reset)
{
RootFrame.Navigated +=
ClearBackStackAfterReset;
}
}
void ClearBackStackAfterReset(object sender,
NavigationEventArgs e)
{
RootFrame.Navigated -=
ClearBackStackAfterReset;
if (e.NavigationMode != NavigationMode.New &&
e.NavigationMode != NavigationMode.Refresh)
{
return;
}
while (RootFrame.RemoveBackEntry() != null) ;
}
Here is how our sample app looks. Note that on the second screen-
shot, the location is shown using toast notification when the app is
tracking location in the background.
Conclusion Windows Phone 8 exposes new location APIs that allow developers
to use the hardware more easily and more efficiently. This translates
in increased battery life and improved user experience. Windows
Phone 8 also allows developers to implement background location
tracking which enables scenarios like navigation apps and more.
Download the Full Source code here.
37 Windows Phone Geek Magazine
Spotlight: Interview with Matt Lacey – Founder of WPUG London
This section is dedicated for interviews with key
members of the Windows Phone development
community. In this issue of the WindowsPhon-
eGeek Magazine we interview Matt Lacey, who
is the founder of the London Windows Phone
User Group (WPUG).
1.Matt, tell us about yourself? I'm currently a part-time stay-at-home dad and part-time freelance
developer. I've been a professional developer since the late 90's and
before switching to freelance work, I have worked at a variety of
companies, of various sizes and in various industries but have spent
the last 8 years or so focusing on a number of projects which fall
under the category of Mobile development, including apps, websites,
and mobile payments.
2. How did you come up with the idea to
start the WPUG? I've been involved with user groups for many years, as both an at-
tendee and organizer, and had always wanted to attend a group with
a focus on mobile development with Microsoft technologies as that's
what I'd spent a lot of time working with, but knew and had met very
few people on the same boat. The announcement of WP7, in Feb
2010, provided a new level of interest in the area that such a group
became feasible. As no-one else was organizing such a group I did.
3. Tell us more about the WPUG? We've had meetings most months since July 2010. Meetings are a
combination of presentations, demos and people sharing their expe-
riences.
We typically meet in a bar and the social aspect this brings is a key
part of the meetings.
Meetings are a combination of presentations, demos and people
sharing their experiences.
4. Why do you think people come to the
WPUG meetings? I say that the meetings exists 'to help people learn from and with
each other' and people attend for a variety of reasons, including: to
learn more about the platform; learn what others have done, how
well it worked and what they can do in their own apps to avoid the
same problems or learn from them. We also have sessions covering
tools, techniques, design and other aspects of building apps for the
phone.
In addition to the presentation side of the meetings people also say
that they attend because they like to meet people who are in the
same boat as them or doing similar things. There are quite a few
people developing apps in their own time and would never meet
anyone else who is doing the same as them if they didn't attend.
People attend for a variety of reasons: to learn more about the plat-
form; learn what others have done, how well it worked and what
5. What do you think about Windows
Phone 8? Windows Phone 8 looks set to bring some exciting and much needed
features to the platform and hopefully it will see some growth in
market share. I'm looking forward to seeing what will be made
available to developers and hopefully the new SDK will allow the
creation of more apps of a higher quality and a better integrated ex-
perience with the platform.
6. Any thoughts about the future of Win-
dows Phone? As mobility becomes more and more important to companies like
Microsoft I expect this to mean that it will continue to be a platform
that is invested in and supported for, at least, the next few years.
We're also at an exciting juncture in the industry as both consumers
and manufacturers are still only adjusting to a world of increased
mobile computing and learning how PCs, tablets and pocket sized
computing devices are used in compliment with each other. There
are potentially exciting time ahead and I'm keen to see where things
go.
More about WPUG you can find at the official web site:
http://wpug.net/ , Twitter: @wpug
You can also visit Matt Lacey`s blog: http://blog.mrlacey.co.uk/
38 Windows Phone Geek Magazine
Business: How to start a successful mobile app business
By Boryana Miloshevska
This article guides you through the basic steps of turning your Win-
dows Phone app idea into a successful business.
The developer approach What most developers do when they have an idea about an app is
just to start coding, without even thinking about customers, target
market or revenue streams. All the business aspects of the project are
an afterthought. This approach can be summarized as: “I will do the
app, because I can.”
The “business people” approach On the other side, what business people usually do is the opposite.
Since they do not have any coding skills, they start with identifying
customer segments, determining the target market, creating a busi-
ness plan, identifying revenue streams, etc. This approach can be
summarized as: “I will pay someone to do the app for me, only if I
can prove that my idea is feasible and profitable.”
The best of both worlds The perfect match is a developer who knows how to validate his idea
and either prove that it is feasible and will make money, or if not –
quickly move on to a better idea! Being able to do that will save you
a lot of wasted time and disappointment.
The key to success First of all, you must have a plan. It does not necessarily have to be a
complete business plan but you have to at least start with a simple
plan of how you will reach your customers and how you are going to
make money. These are the most important things that you must do
before you start investing any time, money and effort in a new app.
Questions you should ask yourself
Who are my customers?
It is important to know what your target market is. On a macro level
you could divide your target audience into end users (B2C business
model) or enterprise customers (B2B business model). Once you
have determined your broad target market, you have to narrow your
target customer segments by grouping them based on, for example,
age, gender, interests, etc. The goal is to find out exactly what your
target segment is and how you can re-segment it into smaller pieces.
Example:
Idea: Windows Phone app that offers users different discounts based
on their current location
Business Model: B2C
Target Market: Windows Phone users that like shopping and are
looking for deals
Re-segmented target market:
1. Women between 20 and 25 of age, who like shopping offline
2. People who are always looking for discounts or deals no mat-
ter what they are buying
3. People who are interested in high street fashion
4. People who do not have enough money but are big fans of
shopping
5. Other….
How can I reach my customers?
Once you have identified who your target customers are, the next
step is to find out how to reach them. You will probably ask why?
Well, that is how the successful business is build and how the “busi-
ness people” usually work. First, find customers that are willing to
pay for your product and only after that, invest time and money in
building the product! (see “Entrepreneur’s Guide to Customer De-
velopment” by Brant Cooper & Patrick Vlaskovits)
So, what is the deal? Go find your customers and talk to them.The
goal is to identify people who are going to use your app and can give
you feedback. They might be even willing to be your early adopters.
Where? Well, there are a number of approaches that you can use, for
example: events, meet-ups, social networks, web, etc.
39 Windows Phone Geek Magazine
Does my app solve a real problem?
Next, your goal is to find a narrow segment of people who not only
like your idea but “love” it, otherwise it is not worth implementing
the app. Your app should solve a real problem and offer something
that your target customers really need, otherwise no one is going to
use it.
Who are my competitors?
Once you have a better understanding of your customers, you have
to explore the competition. Find who else is doing not only apps
similar to your idea, but also slightly different apps, and determine
how successful your competitors are. The key point here is to find a
narrow niche where you can dominate. Try to find if there is any-
thing that your app can offer that others` can`t. Even if you have no
competitors or believe that you have no competitors, if your business
model does not have a strong competitive advantage then it is not
feasible, since it is easy to be imitated and anyone can become your
competitor, especially if he/she has more money to invest. So, your
goal is to build your app based on the identified customers` needs in
such a way that it can satisfy their needs and as a result customers
would choose your app instead of any competitive app.
Am I ready to start?
This is a very hard question, because you must consider all the con-
sequences that come once you become an entrepreneur. In short, you
will have to invest all your time (you will probably have to quit your
job), efforts and some money. The important thing you should con-
sider is that you will probably have to wait at least one year or so in
order for a business to start generating profit, since in the beginning
the costs are much higher than the generated revenue. Stories of
people who started making money after just a few months are usual-
ly a myth and have nothing in common with reality. Note that even
if you develop an app on your own, your efforts and work should
also be consider as a cost, since profit is not the generated money,
but rather what is left after you subtract all costs and expenses.
So, the risk is huge, and the probability to fail – high, especially if
you do not have any savings or other sources of revenue. Here is the
breaking moment where you have to choose whether to become an
entrepreneur and give up your old life with all its benefits like a
good job, excellent salary and financial security. Or if you are not
ready to do so, then you should abandon your business idea, because
the risk is too high. Note that if you try to build a business while you
work for someone else that can`t be called a sustainable business,
since once your competitors spot the opportunity that you have iden-
tified with your app idea, they will spend all their time and efforts to
overtake the market and you will probably lose the battle.
Conclusion In this article I summarized a few important steps you should take in
order to quickly assess a business opportunity in the context of Win-
dows Phone apps. Building a successful business is a complex task
and there is no formula that can guarantee 100% success. Before you
start exploring a business opportunity, you should first prove that
your idea is feasible and profitable, and after that you must invest all
your time and efforts pursuing this opportunity!
Boryana Miloshevska is a co-founder of WindowsPhoneGeek.com
and a few other startups. She has a business degree from University
College London (UCL), MSc Technology Entrepreneurship and
MSc Computer Science, She is a winner of several business awards,
including the UK RBS EnterprisingU 2012 and UCL Bright Ideas
Award 2012. She is also the author of the hugely popular books for
Windows Phone Development: "Windows Phone Toolkit In Depth”.
40 Windows Phone Geek Magazine
WPGeek Component Marketplace – A Great Opportunity for Developers
By WindowsPhoneGeek team
Building great Windows Phone apps is not easy. That is why devel-
opers, during their career, collect tools and components to help them
with certain tasks. The WPGeek Component Marketplace makes
finding the right tools and components much easier by organizing all
components that are available for Windows Phone. Now you can
browse through tons of UI controls, development tools, SDKs, ap-
plication templates and all kinds of components and tools you can
use to make awesome apps.
On the other hand, the Component Marketplace is an opportunity for
developers, to make additional money from existing reusable code
which they have already written for their apps. Both paid and free
components can be published to the component marketplace for
FREE.
Publishing paid components Developers can sell their work via the component marketplace and
make additional money from existing code. The submission process
is straight forward and component listings are approved within three
business days. If you are not sure how to price or license your work,
just let us know and we will do all this for you at no charge. Win-
dowsPhoneGeek.com takes the industry standard commission only
when a sale is done. This covers:
Initial testing of your component
VAT taxes
Payment processing
Marketing
Publishing free components The WPGeek Component Marketplace also gives developers the
opportunity to contribute to the Windows Phone development com-
munity by publishing/suggesting FREE components. You can sub-
mit any free or Open Source library/tool/etc. that you find helpful
and want to be listed.
Authors can moni-
tor the performance
of their component
listings and track
the number of pur-
chases / downloads
as well as the ratings
of their components.
Conclusion Currently the Component Marketplace has 100 listing with thou-
sands of components inside. There, developers can find popular pro-
jects like the Coding4Fun Free Toolkit as well as some less popular
but just as useful components like the Epub Reader for Windows
Phone.
The interest in the Component Marketplace is growing fast and
thousands of developers are browsing through the components daily.
It is also listed in the Microsoft Windows Phone Developer center:
http://dev.windowsphone.com/en-us/featured/partners