DCSIMG
Alex Golesh's Blog About Silverlight Development

Windows 8 Live Tiles – take 2

Quite some time ago I blogged about Live Tiles & Toast Notifications Windows 8 feature.

About a week ago I was delivering Windows 8 training and as a part of this course was delivering a sessions about Live Tiles and Windows 8 PLM (PLM = Process Lifetime Management, session which discusses when Windows 8 runs apps and some point about Windows 8 background tasks). The PLM session mentions, that Windows 8 apps are permitted to run background tasks, but they will be executed approximately once in 2 hour and will be getting few seconds of CPU time. I’ve also mentioned, that some apps, which got user permission to run under the lock screen will be able to run the background tasks based on system timer, but those apps will be scheduling to run once in 15 minutes as minimum timeslot between the execution. Right after the PLM session, at the break, one of my students came to me and asked how “clock” live tiles applications (already few published in the Store) are working. I had to admit, that I never saw this apps before and was not aware about them and how do they working. The student pointed out on one of them and after installing the app I saw that the app go a live tile with current clock and it updates the tile once in a minute. I have to admit, I was intrigued…

I checked the app permissions – it used background permissions, but this was not enough to update a tile once in a minute (remember – the minimum timeslot for such apps are 15 minutes). Then (after briefly chatting about this with my friend and colleague from MS DPE) I assumed that app probably uses push notifications. After further thoughts I failed also this option as the app is free and pushing 1440 messages daily per client is way above free limit of push notifications. I double checked myself by disconnecting network connections on my laptop to make sure. The app keep working and updated the tile. And suddenly it hit me – the app uses Scheduled Toast Notifications! It is possible to schedule many future toasts (I don’t remember exact number, but way more than 15 (needed for background service with lock screen permissions) and more than 120 (needed for regular background service). I tried to repro the app and here it is – for the sake of simplicity I didn’t create images of all minutes per day (actually half is enough as analogue clock has the same presentation once in 12 hours). Also I decided to make a sample without background service as for my demo it was not rally needed.

So I’ve create the super simple UI which gets a count number from user:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBox x:Name="txtCount" Text="10" MaxHeight="40" MaxWidth="40" HorizontalAlignment="Left"/>
    <Button Content="Set" Click="Button_Click_1" Grid.Row="1"/>
</Grid>

And here is button click event handler:

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    //Remove old scheduled notifications as we are starting new countdown
    var oldNotifications = TileUpdateManager.CreateTileUpdaterForApplication().GetScheduledTileNotifications();
    foreach (var item in oldNotifications)
        TileUpdateManager.CreateTileUpdaterForApplication().RemoveFromSchedule(item);
 
    //Parse user input and get current time
    int val = int.Parse(txtCount.Text);
    DateTime startTime = DateTime.Now;
 
    //Set "Ready, Set, Go!" tile - displayed immediately
    ITileSquareText01 tile0 = TileContentFactory.CreateTileSquareText01();
    tile0.TextHeading.Text = "";
    tile0.TextBody1.Text = "Ready!";
    tile0.TextBody2.Text = "Set!";
    tile0.TextBody3.Text = "Go!";
 
    TileNotification theTile0 = new TileNotification(tile0.GetXml());
    TileUpdateManager.CreateTileUpdaterForApplication().Update(theTile0);
 
    //Loop and schedule required number of tiles
    for (int i = 1; i <=val; i++)
    {
        ITileSquareBlock tile = TileContentFactory.CreateTileSquareBlock();
        //Tile main presentation is the number of current counter and will be presented to user when the tile is shown
        tile.TextBlock.Text = i.ToString();
        tile.TextSubBlock.Text = "Counting...";
 
        //Create scheduled tile notification and schedule it to run once in 5 seconds staring from now
        //Note: from my checks, it is possible to schdule the tiles once in a seconds, but some of them were skipped (about each 2-3)
        ScheduledTileNotification scheduledTile = new ScheduledTileNotification(tile.GetXml(), startTime.AddSeconds(i * 5));
        TileUpdateManager.CreateTileUpdaterForApplication().AddToSchedule(scheduledTile);
    }
 
    //Create a tile with "All done" mesage
    ITileSquareText01 tile1 = TileContentFactory.CreateTileSquareText01();
    tile1.TextHeading.Text = "All Done!";
    tile1.TextBody2.Text = "Countdown stopped";
 
    //It is scheduled to run 5 seconds after last count ;)
    ScheduledTileNotification scheduledTile1 = new ScheduledTileNotification(tile1.GetXml(), startTime.AddSeconds((val + 1) * 5));
    TileUpdateManager.CreateTileUpdaterForApplication().AddToSchedule(scheduledTile1);
}

Note: In this sample I am using NotificationsExtensions – the free windows component created by Microsoft and distributed for free as a part of Windows 8 SDK samples.

That’s it! Wow! So simple, but super creative! The video of my sample running (sorry for ugly UI):

My sample running and updating live tile every ~5 seconds

Smile

Clock app schedules the tiles using different tile template and points to images distributed with app. IMO it schedules 60-120 notifications, and every time background task runs adjust slightly the time and reschedules the tiles. I saw few times that the tile “skips” a minute sometime and jumps two minutes or stays on same minute instead of changing an image which makes me thing that at this time background task was running and adjusted an tiles schedule.

 

Enjoy and stay tuned!

//Alex

What’s New in Windows Phone 8 (8 out of 8)–Wallet

Windows Phone 8 adds new interesting feature – the Wallet – which helps users to manage their virtual cards (membership, credit, debit), coupons and use them for in-app and real-world transactions.

The documentation states, that Wallet helps users to:

  • Collect coupons, credit cards, memberships, loyalty cards, and more in one place.
  • Manage the payment instruments that they use in the app and music store.
  • Link items in the Wallet to apps on their phone.
  • Make contactless transactions, using Near-Field Communication (NFC), in some markets

Wallet exposes APIs which enable developers to create, read, write, and delete in-Wallet items from application. It also enables update items by using agents and interact with the user through messages and custom fields. The application and agents could connect to application’s server side functionality to provide updates about new items, bill availability and update balance of stored Wallet items. Let’s overview how to integrate application with Wallet.

In this post I will overview application with following scenario: free application for “DevCorner Friends” club members, which provides club members with different coupons. In addition the club provides users with debit and credit cards. All those items will be stored in the Wallet.

Note: in sake of simplicity this application will fake server-side functionality.

 

Getting started

To use any Wallet related functionality the app should specify the following capabilities in the application manifest:

ID_CAP_WALLET – required to use all APIs from Microsoft.Phone.Wallet.

ID_CAP_WALLET_PAYMENTINSTRUMENTS – addition capability required to use PaymentInstrument and OnlinePaymentInstrument classes (credit and debit cards, online payments such as PayPal)

 

Membership card

As you remember from scenario the app is targeted for club members, so very first operation would be to check membership card in the Wallet:

private WalletTransactionItem LoadMembership()
{
    return Wallet.FindItem("membership") as WalletTransactionItem;
}

The following code snippet uses FindItem function from the Wallet object to check for specific item in the Wallet items connected/linked to the application.

Note: we will see more functions provided by Wallet object later in the post.

If card was not found application presents simple UI informing user, that this application could be used only with membership card:

image

Navigating to purchase page user is presented with standard in-app purchase screen suggesting to pay for membership (to get more info about in-app purchases functionality see my this post):

image

This app uses standard in-app purchase mechanism to buy membership and fulfills by saving new membership card into the Wallet:

private async void btnPurchase_Click(object sender, RoutedEventArgs e)
{
    var receipt = await Store.CurrentApp.RequestProductPurchaseAsync(productInfo.ProductId, true);
 
    if (productInfo.ProductType == Windows.ApplicationModel.Store.ProductType.Durable &&
        Store.CurrentApp.LicenseInformation.ProductLicenses[productInfo.ProductId].IsActive)
    {
        //Fulfill purchased durable
        NavigationService.Navigate(new Uri("/MembershipPage.xaml", UriKind.Relative));   
    }
 
    //...
}

MembershipPage is used to collect information need to create membership card – this includes fields required by the Wallet and custom fields required by our application and/or related server side functionality:

image

To save collected info we will be using new Task from Microsoft.Phone.Tasks namespace – the AddWalletItemTask:

AddWalletItemTask addWalletItemTask = new AddWalletItemTask();
addWalletItemTask.Completed += addWalletItemTask_Completed;
//...
 
private void addWalletItemTask_Completed(object sender, AddWalletItemResult e)
{
    if (e.TaskResult == Microsoft.Phone.Tasks.TaskResult.OK)
    {
        MessageBox.Show(e.Item.DisplayName + " was added to your wallet!");
 
        //...
    }
    else if (e.TaskResult == Microsoft.Phone.Tasks.TaskResult.Cancel)
    {
        MessageBox.Show("Cancelled");
 
        //...
    }
    else if (e.TaskResult == Microsoft.Phone.Tasks.TaskResult.None)
    {
        MessageBox.Show("None");
 
        //...
    }
}
 
private void btnSignUp_Click(object sender, RoutedEventArgs e)
{
    try
    {
        WalletTransactionItem membershipItem;
        membershipItem = new WalletTransactionItem("membership");
        membershipItem.IssuerName = "DevCorner";
        membershipItem.DisplayName = "DevCorner Friends Membership Card";
        membershipItem.IssuerPhone.Business = "+1 (425) 623 7371";
        membershipItem.CustomerName = FirstNameInput.Text + " " + LastNameInput.Text;
        membershipItem.AccountNumber = Guid.NewGuid().ToString();
        membershipItem.BillingPhone = PhoneNumberInput.Text;
        membershipItem.IssuerWebsite = new Uri("http://blogs.microsoft.co.il/blogs/alex_golesh");
        membershipItem.CustomProperties.Add("email", new CustomWalletProperty(EmailInput.Text));
        membershipItem.DisplayAvailableBalance = "100 credits";
        membershipItem.DisplayBalance = "100";
        BitmapImage bmp = new BitmapImage();
        using (System.IO.Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("WalletSample.Images.MembershipCard.png"))
            bmp.SetSource(stream);
 
        membershipItem.Logo99x99 = bmp;
        membershipItem.Logo159x159 = bmp;
        membershipItem.Logo336x336 = bmp;
        addWalletItemTask.Item = membershipItem;
        addWalletItemTask.Show();
    }
    catch (Exception ex)
    {
        MessageBox.Show("There were the following errors when saving your membership to the wallet: " + ex.Message);
    }
}

The following code snippet uses WalletTransactionItem object, fills the properties (predefined in application such as IssuerName, DisplayName, etc. and user inputs such as CustomerName, BillingPhone, etc.). In addition it uses CustomWalletProperty to extend standard properties with “email” property required by application/server side.

When WalletTransactionItem object is fully initialized the code snippet uses AddWalletItemTask to save new card to the the Wallet:

image

The result saved into the Wallet:

imageimage

Clicking on “open app” or message (right upper part, is available) takes user back to the application.

After membership card was purchased and in the Wallet the application should present valued club member with promised coupons/deals.

 

Deals

As you remember, when user starts the app it checks for membership card presence in the Wallet. If card does exists there the app is going to present the deals available for user:

membershipCard = LoadMembership();
 
if (null == membershipCard)
{
    //Membership is not found, suggest to purchase one
    //...    
}
else
{
    //Membership found
    await GetCoupons();
    //...
}

Note: In some case it makes sense to do additional checks such as membership card validity, expiration date, etc.

private async Task GetCoupons()
{
    List<ProductListing> products = new List<ProductListing>();
 
    var results = await Store.CurrentApp.LoadListingInformationByKeywordsAsync(new string[] { "coupon" });
 
    foreach (var product in results.ProductListings)
    {
        //Check is coupon already in the Wallet
        Deal coupon = Wallet.FindItem(product.Value.ProductId) as Deal;
        if (coupon == null)
            //Add product only if it is not in wallet anymore
            products.Add(product.Value);
    }
 
    lstCoupons.DataContext = products;
 
    //...
}

Note: This sample uses in-app purchase logic to present to user available deals and filters out the deals already present in the Wallet. This functionality is related to application’s business logic.

The resulting main screen:

image

Tapping on the coupon reveals same product screen as for membership card which enables purchasing the coupon:

image

The process of coupon fulfillment is similar to creating a new membership card:

if (productInfo.ProductType == Windows.ApplicationModel.Store.ProductType.Consumable &&
    Store.CurrentApp.LicenseInformation.ProductLicenses[productInfo.ProductId].IsActive)
{
    Deal deal = new Deal(productInfo.ProductId);
    deal.DisplayName = productInfo.Name;
    deal.Description = productInfo.Description;
    deal.IssuerName = "DevCorner";
    deal.IssuerWebsite = new Uri("http://blogs.microsoft.co.il/blogs/alex_golesh");
    deal.IsUsed = false;
    deal.MerchantName = "DevCorner";
    deal.TermsAndConditions = "This coupon expires after 7 calendar days from day of purchase.";
    deal.Code = Guid.NewGuid().ToString();
    deal.ExpirationDate = DateTime.Now.AddDays(7);
    deal.NavigationUri = new Uri("/CouponView.xaml?ID=" + productInfo.ProductId, UriKind.Relative);
    BitmapImage bmp = new BitmapImage(new Uri(string.Format("http://qr.kaywa.com/img.php?s=8&d={0}%25+off", productInfo.Tag), UriKind.Absolute));
    bmp.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
    bmp.ImageOpened += async (s, args) =>
    {
        deal.BarcodeImage = bmp;
        await deal.SaveAsync();
    };
 
    //Report fulfillment
    Store.CurrentApp.ReportProductFulfillment(productInfo.ProductId);
 
    //...
}

Note: this sample uses free online QR generator (http://qrcode.kaywa.com/).

Resulting coupon in the Wallet:

imageimage

Last part – the application provides a page to show in-Wallet coupons. Loading the Wallet items:

private async void LoadCoupons()
{
    var myWalletItems = await Wallet.GetItemsAsync();
 
    var coupons = from walletItem in myWalletItems
                  where walletItem is Deal
                  select walletItem;
 
    lstCoupons.DataContext = coupons;
    
    //...
}

Note: this code snippet uses additional functionality GetItemsAsync to get all the associated items from the Wallet.

image

Selecting specific coupon shows the details:

image

This page enables user to use the coupon using AppBar button:

if (MessageBox.Show("Use the coupon?", "My Coupons", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
    currentCoupon.IsUsed = true;
    await currentCoupon.SaveAsync();
 
    MessageBox.Show("Coupon used. Feel free to remove it form your wallet");
    NavigationService.GoBack();
}

Note: currentCoupon object is a Wallet Deal.

Used coupon reflected in the Wallet:

image

Once coupon is used it could be programmatically removed from the Wallet:

image

if (MessageBox.Show("Remove used coupon?", "My Coupons", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
    Wallet.Remove(currentCoupon.Id);
    NavigationService.GoBack();
}

 

Payment Instruments

In addition to membership card and related deals, the application provides user with credit and debit cards.

image

Those cards implemented using PaymentInstrument class.

Note: using PaymentInstrument requires additional capabilities defined in application manifest (see above).

Working with PaymentInstrument is similar to working with other Wallet items:

var cards = from item in await Wallet.GetItemsAsync()
            where item is PaymentInstrument
            select item as PaymentInstrument;

Each PaymentInstrument has PaymentInstrumentKinds property which identifies its type:

public enum PaymentInstrumentKinds
{
    // No card is defined.
    None = 0,
    // Credit card.
    Credit = 1,
    //  Debit card.
    Debit = 2,
    //  Card used for credit and debit purchases.
    CreditAndDebit = 3,
    //  INICIS payment instrument. INICIS is an electronic payment gateway service company.
    Inicis = 64,
}

Note: in addition to PaymentInstrument, the Wallet supports OnlinePaymentInstrument with supported OnlinePaymentInstrumentKind:

public static class OnlinePaymentInstrumentKind
{
    // An AliPay™ payment.
    public const string AliPay = "AliPay";
    // A consumer-defined payment type.
    public const string ConsumerStoredValue = "ConsumerStoredValue";
    // A mobile operator payment.
    public const string MobileOperator = "MobileOperator";
    // A PayPal™ payment.
    public const string PayPal = "PayPal";
}

OnlinePaymentInstrument are not discussed in this post.

Saving PaymentInstrument to the Wallet is identical to other types of Wallet items – using AddWalletItemTask Task:

if (MessageBox.Show("This card is not in your wallet yet. Do you want to copy this card to the wallet?", 
                    "Add new card?", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
    addWalletItemTask.Item = theCard;
    addWalletItemTask.Show();
}

Saved card in the Wallet:

imageimageimage

The card page in application shows same information as in the Wallet:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    string passedID = "";
    if (NavigationContext.QueryString.TryGetValue("ID", out passedID))
    {
        // Set the current deal.
        currentCard = Wallet.FindItem(passedID) as PaymentInstrument;
 
        // Set the data context to current deal.
        DataContext = currentCard;
 
        // Set the expiration text
        txtBalance.Text = "Balance: " + (currentCard.PaymentInstrumentKinds == PaymentInstrumentKinds.Debit ? currentCard.DisplayAvailableBalance : currentCard.DisplayAvailableCredit);
 
        lstTransactions.ItemsSource = currentCard.TransactionHistory.Values;
 
        if (currentCard.CustomProperties.ContainsKey("BillPosted"))
        {
            txtInfo.Visibility = Visibility.Visible;
            txtInfo.Text = "New bill is posted. Please pay it now";
 
            // Set the page's ApplicationBar to a new instance of ApplicationBar.
            ApplicationBar = new ApplicationBar();
 
            // Create a new button and set the text value to the localized string from AppResources.
            ApplicationBarIconButton appBarButton = new ApplicationBarIconButton(new Uri("/Images/PayBill.png", UriKind.Relative));
            appBarButton.Text = AppResources.appbar_buttonPayBillText;
            appBarButton.Click += appBarButton_Click;
            ApplicationBar.Buttons.Add(appBarButton);
        }
        else
        {
            ApplicationBar = null;
            txtInfo.Visibility = Visibility.Collapsed;
        }
    }
}

The code snippet above gets PaymentInstrument from the Wallet, binds transactions history ListBox to TansactionHistory object. Lastly, it checks for custom property “BillPosted” (will be added later in case of credit card) and suggest user to pay the bill:

imageimage

Paying the bill (in case of credit card) is a new page:

image

Paying bill involves your application’s business logic (probably contacting server side and performing transaction), but after it is done updating the card in the Wallet is simple:

if (currentCard.CustomProperties.ContainsKey("BillPosted"))
    currentCard.CustomProperties.Remove("BillPosted");
 
currentCard.Message = "";
currentCard.DisplayAvailableCredit = "1000";
currentCard.DisplayCreditLimit = 1000.ToString("C");
await currentCard.SaveAsync();

Note: CustomProperties is collection of properties associated with WalletItem which could be used to store application-specific info.

Through the post I presented the screenshots with transactions, messages and also credit card bill. In this last part I will show how to keep your wallet item updated.

 

Wallet Agent

The WalletAgent is special type of background agent which associated with the application and used by the Wallet to update wallet items. The agent is created as standard Scheduled Task Agent:

image

Once added, it should be referenced from the main application:

image

This is special type of agent which executed automatically and doesn’t requires any additional code from user (unlike standard scheduled agent). To implement it, ScehuledAgent must derive form WalletAgent class:

public class ScheduledAgent : WalletAgent
{
    //...
}

Also, this walled doesn’t supports Invoke overload, but requires to overload OnRefreshData function:

protected override void OnRefreshData(RefreshDataEventArgs args)
{
    //...
}

To add some message to user while processing the card se the following code snippet:

foreach (var item in args.Items)
{
    WalletTransactionItem membershipCard = item as WalletTransactionItem;
    if (null != membershipCard) //membership card
    {
        if (int.Parse(membershipCard.DisplayBalance) >= 50)
        {
            //Fake a deal for member...
            membershipCard.Message = "You might be interested in special deal for you. Click here to check it out!";
            membershipCard.MessageNavigationUri = new Uri("/MainPage.xaml", UriKind.Relative);
 
            //Fake usage
            membershipCard.DisplayBalance = (int.Parse(membershipCard.DisplayBalance) - 50).ToString();
            membershipCard.DisplayAvailableBalance = membershipCard.DisplayBalance + " credits";
 
            await membershipCard.SaveAsync();
        }
        else
        {
            membershipCard.Message = "You balanse is low. It is a time to fill it in. Click here to buy some credits!";
            membershipCard.MessageNavigationUri = new Uri("/Helpers/ProductsView.xaml?tag=credits", UriKind.Relative);
 
            await membershipCard.SaveAsync();
        }
    }
}

Note: this sample fakes transactions locally, while real app should get this information from application’s server side component.

Now let’s see how to add transactions and bills:

PaymentInstrument card = item as PaymentInstrument;
if (null != card)
{
    //Fake tranasaction -- pretend getting this data from server side component
    int transactionAmount = rnd.Next(-50, 0);
 
    WalletTransaction transaction = new WalletTransaction();
    transaction.Description = "Fake transaction";
    transaction.DisplayAmount = transactionAmount.ToString("C");
    transaction.TransactionDate = DateTime.Now;
 
    if (card.PaymentInstrumentKinds == PaymentInstrumentKinds.Credit) //DevCorner CreditCard
    {
        //Update balance
        int newBalance = int.Parse(card.DisplayAvailableCredit) + transactionAmount;
 
        card.DisplayAvailableCredit = newBalance.ToString();
        card.TransactionHistory.Add("FakeTransaction_" + transaction.TransactionDate, transaction);
 
        if (newBalance < 100)
        {
            //Signal new bill is available
            CustomWalletProperty billPostedProperty = new CustomWalletProperty("true");
            if (card.CustomProperties.ContainsKey("BillPosted"))
                card.CustomProperties.Remove("BillPosted");
 
            card.CustomProperties.Add("BillPosted", billPostedProperty);
 
            card.Message = "New bill posted. Click here to pay the bill.";
            card.MessageNavigationUri = new Uri("/PayBill.xaml?ID=" + card.Id, UriKind.Relative);
        }
    }
    else //Debit cards and other types of supported PaymentInstruments
    {
        //...
    }
 
    await card.SaveAsync();
}

The code snippet above creates new WalletTransaction object and populates it with info to be presented in the Wallet. Based on application’s logic, if card balance less than 100, the code adds new CustomWalletProperty which is used to signal user about new bill availability in the application. In addition, the code snippet uses same Message and MessageNavigationUri properties to show new bill info in the Wallet.

image

Note: Don’t forget to signal process completion by calling NotifyComplete();

Note: The simplest way to execute/debug WalletAgent is to select “refresh” command of your wallet item:

image

Now we have a complete application for scenario described at the beginning of the post.

 

Video of working app:

Sample wallet app

 

Enjoy and stay tuned,

Alex

What’s New in Windows Phone 8 (7 out of 8)–In-App-Purchases

This post talks about new monetization feature in Windows Phone 8 – In-App-Purchases (IAP). According to multiple industry sources (link1, link2, link3) IAP can actually make more money that free/ad-supported application. Let’s see how to add this feature to application. In this post I will show how to build simplest “virtual” shop app. All IAP functionality process allocated in Windows.ApplicationModel.Store namespace.

First let’s understand the terminology associated with IAP process.

Product – something you are selling in application. Unlike Windows 8, in Windows Phone 8 we got two different product types: Durable and Consumable.

Durable – a Product that is purchased once and owned by the user/application.

Consumable – a Product that is purchased and used multiple times. This Product could be purchased again and again when user needs it.

Products are organized into Product List which managed through application’s settings on Dev Center Dashboard.

image

image

image

Purchase – the process of buying a Product.

License – a set of definitions describing the product type, whether it is active and its expiration date. Associated with each Product.

Receipt – a proof of purchase which used to verify that user Purchased the Product.

Fulfillment - the process of giving the user the Product he/she Purchased. Depends on application logic, but must me reported to marketplace. Available only for Consumables and plays key role in Product Purchase process - new Consumable cannot be Purchased again without reporting previous successful fulfillment.

 

Working with Catalog

Current application licensing info and associated product list is obtained using CurrentApp class. This app provides key functionality of searching catalog (by keyword or productId), purchasing the products and report fulfillments. The following code snippet searches all products by keywords:

string[] keywords = new string[] { "tuxedo", "luxary", "wearing" };
var items = await Store.CurrentApp.LoadListingInformationByKeywordsAsync(keywords);

Next code snippet shows how to search specific products from product list:

string[] productIds = new string[] { "Durables.Tuxedo", "Durables.LuxaryWatch", "Consumables.CherryPie" };
var products = await Store.CurrentApp.LoadListingInformationByProductIdsAsync(productIds);

In addition to search functionality, CurrentApp class also provides access to full product list which is accessible through CurrentApp.LicenseInformation.ProductLicenses class. Each item in ProductLicenses is an object from ProductLicense class. This class enables querying product state by providing ExpirationDate, IsActive and IsConsumable properties. The following code snippet loads not purchased durables from product catalog:

private async void LoadDurables()
{
    List<string> productIDs = new List<string>();
 
    //Search all not purchased durables from catalog
    var res = from item in Store.CurrentApp.LicenseInformation.ProductLicenses
              where !item.Value.IsConsumable && !item.Value.IsActive
              select item;
 
    //Build productId list
    foreach (var item in res)
        productIDs.Add(item.Value.ProductId);
 
    //Bring not purchased products info (names, proces, etc.) from catalog and assign it to istbox
    var durables = await Store.CurrentApp.LoadListingInformationByProductIdsAsync(productIDs.ToArray());
    lstDurables.DataContext = durables.ProductListings;
}

In addition, this code snippet loads all product listings (info about the products) and shows them as list of products:

image

Loading consumables (also shown on screenshot) is similar:

private async void LoadConsumables()
{
    List<string> productIDs = new List<string>();
 
    var res = from item in Store.CurrentApp.LicenseInformation.ProductLicenses
              where item.Value.IsConsumable
              select item;
 
    foreach (var item in res)
        productIDs.Add(item.Value.ProductId);
 
    var consumables = await Store.CurrentApp.LoadListingInformationByProductIdsAsync(productIDs.ToArray());
 
    lstConsumables.DataContext = consumables.ProductListings;
}

Let’s see how to present the product on screen. On sample app screen (see above), when user changes selection we will be navigating to different screen with selected productId as navigation parameter:

NavigationService.Navigate(new Uri("/ProductInfo.xaml?PID=" + selectedItem.ProductId, UriKind.Relative));

Let’s see the sample ProductInfo page. I will be presenting product details on page as follows:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <TextBlock Text="{Binding Name}" Grid.ColumnSpan="2" Style="{StaticResource PhoneTextTitle2Style}" />
    <TextBlock Text="{Binding Description}" TextWrapping="Wrap" Grid.Column="0" Grid.Row="1" Style="{StaticResource PhoneTextSmallStyle}" />
    <StackPanel Grid.Column="0" Grid.Row="2" Orientation="Vertical" Margin="0, 10">
        <TextBlock Text="Product type:" Style="{StaticResource PhoneTextSmallStyle}" />
        <TextBlock Text="{Binding ProductType}" Style="{StaticResource PhoneTextSmallStyle}" />
    </StackPanel>
    <StackPanel Grid.Column="0" Grid.Row="3" Orientation="Vertical">
        <TextBlock Text="Purchase price:" Style="{StaticResource PhoneTextSmallStyle}" />
        <TextBlock Text="{Binding FormattedPrice}" Style="{StaticResource PhoneTextLargeStyle}"  FontWeight="Bold"/>
    </StackPanel>
    <Image Source="{Binding ImageUri, Converter={StaticResource StoreToImageUriConverter}}" Grid.Column="1" Grid.Row="1" Grid.RowSpan="3" VerticalAlignment="Top"/>
    <Button Grid.Row="4" Grid.Column="0" Content="Buy now" x:Name="btnPurchase" Click="btnPurchase_Click" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
    <Button Grid.Row="4" Grid.Column="1" Content="Cancel" x:Name="btnCancel" Click="btnCancel_Click" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
</Grid>

When application navigates to the page it searches product info from product list as follows:

protected override async void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    string productId = NavigationContext.QueryString["PID"];
 
    var pi = await Store.CurrentApp.LoadListingInformationByProductIdsAsync(new string[] { productId });
    productInfo = pi.ProductListings.First().Value;
 
    this.DataContext = productInfo;
    base.OnNavigatedTo(e);
}

This code produces the following results:

image

image

Now the interesting part – “Buy now button handler which does actual product purchase:

private async void btnPurchase_Click(object sender, RoutedEventArgs e)
{
    var receipt = await Store.CurrentApp.RequestProductPurchaseAsync(productInfo.ProductId, true);
 
    //Parse receipt
    //...
 
    if (productInfo.ProductType == Windows.ApplicationModel.Store.ProductType.Durable)
    {
        if (Store.CurrentApp.LicenseInformation.ProductLicenses[productInfo.ProductId].IsActive)
        {
            //Fulfill purchased durable -- app logic
            //...
        }
    }
    else if (productInfo.ProductType == Windows.ApplicationModel.Store.ProductType.Consumable)
    {
        if (Store.CurrentApp.LicenseInformation.ProductLicenses[productInfo.ProductId].IsActive)
        {
            //Fulfill purchased consumable -- app logic
            //...
 
            //Report fullfillment
            Store.CurrentApp.ReportProductFulfillment(productInfo.ProductId);
        }
    }
 
    NavigationService.GoBack();
}

Previously purchased (durable) products could be retrieved from listing as follows:

List<string> productIDs = new List<string>();
 
var res = from item in Store.CurrentApp.LicenseInformation.ProductLicenses
          where item.Value.IsActive
          select item;
 
foreach (var item in res)
    productIDs.Add(item.Value.ProductId);
 
var durables = await Store.CurrentApp.LoadListingInformationByProductIdsAsync(productIDs.ToArray());
lstPurchases.DataContext = durables.ProductListings;

 

Developing/Testing IAP scenarios

Working IAP is a server-based commerce. It relies on communication with Microsoft’s backend services to list products, enumerate licenses and process purchases. It may also rely on your servers to deliver purchased in-app products if needed. When purchasing the product (published application) marketplace will perform real transaction with client’s account. In development cycle it is not always possible to deploy application to marketplace (especially as public application).  It is possible to deploy application as Beta on marketplace. Beta applications support full IAP mechanism through marketplace with only one difference - although the user experience shows prices as entered into Dev Center, all in-app purchases made from beta apps are free. This approach is strongly recommended once you application is in somewhat ready state. But what to do during initial development stages? Windows 8 provides CurrentAppSimulator class for this work. Unfortunately this functionality didn’t made it into Windows Phone 8. To overcome this, we want to use mock library which closely mimics Store APIs.

This library exists and could be downloaded here.

To work with this library it must be referenced on all pages which are using Store functionality as follows:

#if DEBUG
    using MockIAPLib;
    using Store = MockIAPLib;
#else
    using Store = Windows.ApplicationModel.Store;
#endif

From now on, to test real marketplace functionality all you need is to compile your app as Release. While the library closely mimics store APIs it must be initiated with as it doesn’t uses server-based information from marketplace. It should be initiated from XML-based product catalog as follows:

<?xml version="1.0" encoding="utf-8" ?>
<ProductListings>
  <!-- Durables-->
  <ProductListing Key="Tuxedo" Purchased="false" Fulfilled="false">
    <Name>Tuxedo</Name>
    <Description>Classic tuxedo</Description>
    <ProductId>Durables.Tuxedo</ProductId>
    <ProductType>Durable</ProductType>
    <FormattedPrice>$299.99</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Durables/Tuxedo.png</ImageUri>
    <Keywords>wearing;tuxedo</Keywords>
    <Tag>Pre-order only!</Tag>
  </ProductListing>
  <ProductListing Key="ButterflyCollar" Purchased="false" Fulfilled="false">
    <Name>Butterfly Collar</Name>
    <Description>Classic Butterfly Collar</Description>
    <ProductId>Durables.ButterflyCollar</ProductId>
    <ProductType>Durable</ProductType>
    <FormattedPrice>$19.99</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Durables/ButterflyCollar.jpg</ImageUri>
    <Keywords>wearing;butterfly;collar</Keywords>
    <Tag></Tag>
  </ProductListing>
  <ProductListing Key="LuxaryWatch" Purchased="false" Fulfilled="false">
    <Name>Luxary Watch</Name>
    <Description>Luxary Watch</Description>
    <ProductId>Durables.LuxaryWatch</ProductId>
    <ProductType>Durable</ProductType>
    <FormattedPrice>$19999.99</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Durables/LuxaryWatch.jpg</ImageUri>
    <Keywords>watch;luxary</Keywords>
    <Tag>Special order, call for availability!</Tag>
  </ProductListing>
 
  <!--Consumables-->
  <ProductListing Key="LemonPie" Purchased="false" Fulfilled="false">
    <Name>Lemon Pie</Name>
    <Description>Delicious Lemon Pie</Description>
    <ProductId>Consumables.LemonPie</ProductId>
    <ProductType>Consumable</ProductType>
    <FormattedPrice>$2.99</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Consumables/LemonPie.jpg</ImageUri>
    <Keywords>food;desert;lemon;pie</Keywords>
    <Tag>Calories: 405 | Total Fat: 21.5g | Cholesterol: 47mg</Tag>
  </ProductListing>
  <ProductListing Key="CherryPie" Purchased="false" Fulfilled="false">
    <Name>Cherry Pie</Name>
    <Description>Delicious Cherry Pie</Description>
    <ProductId>Consumables.CherryPie</ProductId>
    <ProductType>Consumable</ProductType>
    <FormattedPrice>$3.49</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Consumables/CherryPie.jpg</ImageUri>
    <Keywords>food;desert;cherry;pie</Keywords>
    <Tag>Calories: 506 | Total Fat: 27.5g | Cholesterol: 4mg</Tag>
  </ProductListing>
  <ProductListing Key="NYSteak" Purchased="false" Fulfilled="false">
    <Name>New York Steak</Name>
    <Description>Superb New York Steak</Description>
    <ProductId>Consumables.NYSteak</ProductId>
    <ProductType>Consumable</ProductType>
    <FormattedPrice>$12.99</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Consumables/NewYorkSteak.jpg</ImageUri>
    <Keywords>food;meat;new york;steak</Keywords>
    <Tag>Calories: 624 | Total Fat: 28g | Cholesterol: 106mg</Tag>
  </ProductListing>
  <ProductListing Key="CaesarSalad" Purchased="false" Fulfilled="false">
    <Name>Caesar Salad</Name>
    <Description>Caesar Salad Supreme</Description>
    <ProductId>Consumables.CaesarSalad</ProductId>
    <ProductType>Consumable</ProductType>
    <FormattedPrice>$5.99</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Consumables/CaesarSalad.jpg</ImageUri>
    <Keywords>food;salad;Caesar;starters</Keywords>
    <Tag>Calories: 384 | Total Fat: 33.5g | Cholesterol: 18mg</Tag>
  </ProductListing>
  <ProductListing Key="RedWine" Purchased="false" Fulfilled="false">
    <Name>Cabernet Sauvignon</Name>
    <Description>Glass of Cabernet Sauvignon Red Wine</Description>
    <ProductId>Consumables.CabernetSauvignon</ProductId>
    <ProductType>Consumable</ProductType>
    <FormattedPrice>$9.99</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Consumables/RedWine.jpg</ImageUri>
    <Keywords>wine;drink;cabernet sauvignon</Keywords>
    <Tag></Tag>
  </ProductListing>
  <ProductListing Key="MadameClicquot" Purchased="false" Fulfilled="false">
    <Name>Madame Clicquot Champange</Name>
    <Description>Glass of Madame Clicquot Champange</Description>
    <ProductId>Consumables.MadameClicquot</ProductId>
    <ProductType>Consumable</ProductType>
    <FormattedPrice>$24.99</FormattedPrice>
    <ImageUri>ms-appdata:///Images/Consumables/MadameClicquot.jpg</ImageUri>
    <Keywords>wine;drink;champange;madame clicquot;luxary</Keywords>
    <Tag></Tag>
  </ProductListing>
</ProductListings>

Note: in real scenarios it is recommended to get product images from app’s server-side storage as the approach shown in this sample relays on having all possible product images in application package which is not recommended and prevents from extending product list after publishing the app.

Initialization code (in my case it is in App.xaml.cs:

#if DEBUG
            //Use Mock API instead of real store
            MockIAP.Init();
            MockIAP.RunInMockMode(true);
 
#if DONT_PRESERVE_LICENSE_INFO
            // Clear the cache every time. Remove this to have persistence.
            MockIAP.ClearCache();
#endif
 
            var sri = App.GetResourceStream(new Uri("MockupLincenseInfo.xml", UriKind.Relative));
            System.Xml.Linq.XDocument doc = System.Xml.Linq.XDocument.Load(sri.Stream);
            string xml = doc.ToString();
 
            MockIAP.SetListingInformation(1, "en-us", "IAP Sample by Alex Golesh", "$12.99", "IAP Sample");
 
            MockIAP.PopulateIAPItemsFromXml(xml);
#endif

Note: DONT_PRESERVE_LICENSE_INFO is pragma defined in the app and controls whether mock library preserves previous purchases between debug runs. Preserving cache makes library behave as real marketplace does.

When purchasing using mock library it presents message box as follows:

image

 

That’s it for now. Next time I will blog about Wallet functionality.

 

Stay tuned,

Alex

What’s New in Windows Phone 8 (6 out of 8)–Location services and maps

Windows Phone 8 brings long awaited updates to location services and brand new map control (with associated services) which is based on Nokia maps.

Location services

So what’s new in location services. First of all – the new WinRT API which is shared with Windows 8. To use location services application must declare the following capability in application manifest:

<Capability Name="ID_CAP_LOCATION" />

The “main” class – Geolocator – belongs to Windows.Devices.Geolocation namespace and enables location tracking in good old “events” way and also new async model as follows:

Geoposition currentPosition = await geoLocator.GetGeopositionAsync();
// or
Geoposition currentPosition = await geoLocator.GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(30));

Note: geoLocator is an instance of Geolocator object. Second call limits the results age and awaiting timeout.

The object itself could be activated as follows:

if (geoLocator == null)
{
    geoLocator = new Windows.Devices.Geolocation.Geolocator();
    geoLocator.DesiredAccuracy = Windows.Devices.Geolocation.PositionAccuracy.High; //Request high accuracy from GPS device
    geoLocator.DesiredAccuracyInMeters = 1; //Must have very precise for walking/running/biking tracking. Could use values of 50-100 for car
    geoLocator.ReportInterval = 1000; //1 second between updates usually is needed for constant updates for scenarios such as walking/running/biking tracking.
    geoLocator.StatusChanged += geoLoc_StatusChanged; //Subscribe for status changes
    geoLocator.PositionChanged += geoLoc_PositionChanged; //Subscribe for continues position changes updates
}

The PositionChanged result brings information such as CivicAddress, Coordinate information with Latitude, Longitude, Speed, Heading, Accuracy, Altitude, etc. fields which crucial for location-aware applications.

Sample code snippet for PositionChanged event:

if (position.CivicAddress != null)
    Debug.WriteLine(string.Format("City = {0}, Postal Code = {1}, State = {2}, Country = {3}",
                                  position.CivicAddress.City, 
                                  position.CivicAddress.PostalCode, 
                                  position.CivicAddress.State, 
                                  position.CivicAddress.Country));
 
Dispatcher.BeginInvoke(() =>
{
    txtLat.Text = position.Coordinate.Latitude.ToString();
    txtLon.Text = position.Coordinate.Longitude.ToString();
    txtSpeed.Text = position.Coordinate.Speed.HasValue ? position.Coordinate.Speed.ToString() : "UNKNOWN";
    txtHeading.Text = position.Coordinate.Heading.HasValue ? position.Coordinate.Heading.ToString() : "UNKNOWN";
});

Note: this sample code simply outputs the info on screen. While this change in API is interesting, the real power comes with ability to track the location when application is not active – works in background.

Background Execution

As you probably remember, on Windows Phone only one app runs in the foreground – the one which is visible on screen. When user navigates away from an app (either by pressing the Start button or by launching another app) the current app is suspended and may be terminated and tombstoned. In Windows Phone 8, a location-tracking app can continue to run in the background after the user navigates away, as long as the app continues to actively track location. This feature is absolutely must for scenarios such as an app that provides turn-by-turn directions. Let’s see how to enable the background execution.

First of all – to work in background the application must actively track the location: use Geolocator.

Also, to successfully use the Geolocator application must declare location capability (ID_CAP_LOCATION) as described above.

Next, application must require background execution in DefaultTask definition in application manifest as follows:

<DefaultTask Name="_default" NavigationPage="MainPage.xaml">
  <BackgroundExecution>
    <ExecutionType Name="LocationTracking" />
  </BackgroundExecution>
</DefaultTask>

Note: If more than one application requires background execution, only last one will be allowed to work in background. All previous/other “background executions” will be stopped.

Last, but not least, the application must handle RunningInBackground event which raised when location-tracking application transitions to background. When this event is raised, the application should stop all tasks that are not related to location tracking, including updates to the app’s UI. Subscribing to this even is done through App.xaml:

<shell:PhoneApplicationService
    Launching="Application_Launching" Closing="Application_Closing"
    Activated="Application_Activated" Deactivated="Application_Deactivated"
    RunningInBackground="PhoneApplicationService_RunningInBackground"/>

Handling the event in code:

public static bool isRunningInBackground = false;
 
private void PhoneApplicationService_RunningInBackground(object sender, RunningInBackgroundEventArgs e)
{
    isRunningInBackground = true;
 
    //Stop all unnecessary processes
}
 
private void Application_Activated(object sender, ActivatedEventArgs e)
{
    isRunningInBackground = false;
}

In my simple scenario, the location updates from background execution will be used to update application’s main tile:

FlipTileData ftd = new FlipTileData()
{
    Count = updatesCount,
    Title = "Position updated",
    BackTitle = position.Coordinate.Timestamp.ToLocalTime().ToString(),
    BackContent = string.Format("New position is LAT: {0}, LON: {1}",
                          position.Coordinate.Latitude,
                          position.Coordinate.Longitude),
    WideBackContent = string.Format("New position is LAT: {0}, LON: {1}. Moving with speed of {2} m/s with course of {3}°",
                          position.Coordinate.Latitude,
                          position.Coordinate.Longitude,
                          position.Coordinate.Speed.HasValue ? position.Coordinate.Speed.ToString() : "UNKNOWN",
                          position.Coordinate.Heading.HasValue ? position.Coordinate.Heading.ToString() : "UNKNOWN"),
};
 
mainTile.Update(ftd);

Those updates produces the following results:

imageimage

Note: please see the video at the end of this post to see the application working in background

Maps

In additional to great improvements to location services described above, Windows Phone 8 switches map component to Nokia maps. The new control could be found in Microsoft.Phone.Maps.Controls namespace (Microsoft.Phone.Maps assembly) and could be instantiated either from XAML or code behind. Sample XAML initialization:

<Controls:Map HorizontalAlignment="Center" VerticalAlignment="Center"
              Width="450" Height="400" x:Name="map"
              PedestrianFeaturesEnabled="True" LandmarksEnabled="True" ZoomLevel="17"/>

Note: the controls namespace defined in XAML’s header file as follows:

xmlns:Controls="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"

Once defined, the map’s properties could be also altered from code behind:

map.Pitch = 40;

Map supports different cartographic modes (Road, Hybrid, Areal, Terrain), color modes (Light, Dark), presenting landmarks/pedestrian features, pitch and rotation:

image

In addition, map supports multiple overlay layers which could be presented over map (car icon on image above) as follows:

BitmapImage bitmapImage = new BitmapImage(new Uri("/Images/car.png", UriKind.Relative));
Image img = new Image();
img.Source = bitmapImage;
 
mapOverlay = new MapOverlay();
mapOverlay.PositionOrigin = new Point(0.5, 0.5);
mapOverlay.Content = img;
mapOverlay.GeoCoordinate = map.Center;
 
MapLayer MyLayer = new MapLayer();
MyLayer.Add(mapOverlay);
map.Layers.Add(MyLayer);

Last, the map provides services, such as GeocodeQuery, ReverseGeocodeQuery and RouteQuery. Latter could be used to calculate (and display on ap) route between two given geo coordinates as follows:

RouteQuery routeQuery = new RouteQuery();
routeQuery.QueryCompleted += routeQuery_QueryCompleted;
 
void routeQuery_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)
{
    Route theRoute = e.Result;
    MapRoute calculatedMapRoute = new MapRoute(theRoute);
    map.AddRoute(calculatedMapRoute);
}
 
private void btnShowRoute_Click(object sender, RoutedEventArgs e)
{
    if (!routeQuery.IsBusy)
    {
        List<GeoCoordinate> routeCoordinates = new List<GeoCoordinate>();
        routeCoordinates.Add(new GeoCoordinate(48.860339, 2.337599)); //Eiffel Tower coordinates
        routeCoordinates.Add(new GeoCoordinate(48.8583, 2.2945)); //Louvre coordinates
 
        routeQuery.Waypoints = routeCoordinates;
        routeQuery.QueryAsync();
 
        map.Center = new GeoCoordinate(48.8583, 2.2945); //Center map on first coordinates
    }
}

Clicking the “Show Route” button calculates the route and shows it on map:

image

The navigation instructions are also available and could be presented to user as follows:

//...
List<string> legsList = new List<string>();
foreach (RouteLeg leg in MyRoute.Legs)
{
   foreach (RouteManeuver routeManeuver in leg.Maneuvers)
   {
      legsList.Add(routeManeuver.InstructionText);
   }
}
 
//lstRouteList is a list showing the legs
lstRouteList.ItemsSource = legsList;

Working sample application video:

Sample location aware application

 

Next time I will blog about in-app-purchases (IAP) and new Windows.ApplicationModel.Store namespace shared with Windows 8.

 

Stay tuned,

Alex

What’s New in Windows Phone 8 (5 out of 8)–Quick tip: creating hybrid applications

One important feature in Windows Phone 8 is ability to develop high performance applications using Direct3D graphics and C++. While this feature clearly targets game developers, many applications could also gain performance combining native code with C++ components. Moreover, even when developing XAML/C# applications, it is possible to fully leverage modern GPU in Windows Phone 8 device by mixing XAML flexibility with Direct3D graphics.

Note: Pure native development using Direct3D are not covered in this post.

Let’s overview two other options: first is to use Direct3D graphics is XAML/C# application. Windows Phone 8 SDK provides very good starting point for such application:

image

Application created with this template combines standard Windows Phone 8 XAML application and WinRT native component. To integrate Direct3D surface into managed application, use new DrawingSurface XAML element. As standard XAML element it supports all standard XAML properties incl. Projection and RenderTransform and plays nicely with other XAML elements in layout. The following code snippet, for example, produce image below:

<Grid x:Name="LayoutRoot" Background="Transparent">
    <DrawingSurface x:Name="DrawingSurface">
        <DrawingSurface.Projection>
            <PlaneProjection CenterOfRotationX=".5" CenterOfRotationY=".5" CenterOfRotationZ=".5" 
                                RotationX="-30" RotationY="30" RotationZ="30"/>
        </DrawingSurface.Projection>
        <DrawingSurface.RenderTransformOrigin>
            <Point X=".5" Y=".5"/>
        </DrawingSurface.RenderTransformOrigin>
        <DrawingSurface.RenderTransform>
            <CompositeTransform Rotation="-25" ScaleX=".7" ScaleY="-1" TranslateY="20"/>
        </DrawingSurface.RenderTransform>
    </DrawingSurface>
    <Canvas>
        <TextBlock x:Name="textBlock" Text="Hello from Windows Phone 8!" HorizontalAlignment="Center" VerticalAlignment="Top" FontSize="25"
                    Canvas.Top="100" Canvas.Left="500"/>
    </Canvas>
    <Button Content="About" VerticalAlignment="Bottom" HorizontalAlignment="Center" Click="Button_Click_1"/>
</Grid>

image

The whole idea of this “mix” is very similar to hybrid Silverlight & XNA applications introduces back in Windows Phone 7.5.

The DrawingSurface is initialized with Windows Phone Runtime object that implements the IDrawingSurfaceProvider interface. The default templates provides sample of such component which implements 3D cube render. For more info please refer to documentation.

Second option available for developers is to integrate/reuse native code containing business logic with Windows 8 other other platforms. Also, in many cases integrating native code (especially for complex algorithmic manipulations) could add noticeable performance boost to application. Let’s see how to achieve this.

My sample application uses “heavy” math calculations as managed component:

namespace ManagedLibrary
{
    public class ManagedCalculator
    {
        public long Factorial(long n)
        {
           
            long nfac = 1;
 
            for (int i = 2; i < n + 1; i++)
            {
                nfac *= i;
            }
 
            return nfac;
        }
    }
}

As you see, this code calculates factorial for given number.

Note: the factorial calculation was not implemented as recursive function to be fully compatible with native code presented below.

The managed library used to calculate the factorials – let’s pretend it is a part of application’s business logic – as follows:

ManagedCalculator calc = new ManagedCalculator();
 
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
 
long ticks = 0;
for (int j = 0; j < numOfTrials; j++)
{
    sw.Start();
    for (int i = 0; i < maxRuns; i++)
        calc.Factorial(rnd.Next(maxFactorialOf));
    sw.Stop();
 
    ticks += sw.ElapsedTicks;
    sw.Reset();
}
 
txtManaged.Text = "Average calculation time was " + ticks / numOfTrials + " ticks";

This code snippet invokes factorial calclation for fandom number given number of runs (maxRuns) for known number of trials (numOfTrials) and caluclates average runtime (in ticks).

Let’s have exact same functionality as managed WinRT component. To do it, we need to add new project and reference it from the applcation:

image

The header file for this component looks super simple:

namespace NativeLibrary
{
    public ref class NativeCalculator sealed
    {
    public:
        NativeCalculator();
        int64 Factorial(int64 n);
    };
}

And implemntation class is also very simple:

#include "pch.h"
#include "NativeLibrary.h"
 
using namespace NativeLibrary;
using namespace Platform;
 
NativeCalculator::NativeCalculator()
{
}
 
int64 NativeCalculator::Factorial(int64 n)
{
    long nfac=1;
 
    for(int i=2; i < n+1; i++)
    { 
        nfac *= i; 
    }
 
    return nfac;
}

Note, that factorial code is exact the same as in managed code.

Once native component is ready it could be referenced from main app:

image

and used as standard managed component:

NativeCalculator calc = new NativeCalculator();
 
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
//Warm up run
calc.Factorial(10);
 
long ticks = 0;
for (int j = 0; j < numOfTrials; j++)
{
    sw.Start();
    for (int i = 0; i < maxRuns; i++)
        calc.Factorial(rnd.Next(maxFactorialOf));
    sw.Stop();
 
    ticks += sw.ElapsedTicks;
    sw.Reset();
}
 
txtNative.Text = "Average calculation time was " + ticks / numOfTrials + " ticks";

Note, that again, only difference is the type of created object.

Runnig this application reveals interesting facts – the bigger number we are trying to calculate factorial for, the bigger gain in performance we are getting with native code.

With maxFactorialOf = 10 the results are not in favor of native code:

image

If setting the maxFactorialOf = 100, the results are different and while still comparable, the native code clearly wins:

image

Setting maxFactorialOf = 1000 shows, that native is clearly faster – in this case almost twice faster than managed code:

image

Setting maxFactorialOf = 10000 allwos native code shine and beat native code completely:

image

Does it means, that all calculations (even smallest one) should be moved to managed code, just because it is faster? Not necessary. If you are migrating from another platform and have logic already written using native code then the answer probably yes (giving the fact, that native development not as easy as managed one). If you already using managed code your probably not necessary will gain major performance boost just by rewriting some of the business logic as native library. You could try, but “your mileage may vary”. One thing is for sure – it could introduce more bugs related to new native component.

 

That’s it for this post. Next time I will blog about location services and new map functionality.

 

Stay tuned,

Alex

What’s New in Windows Phone 8 (4 out of 8)–Protocol handler and file extensions

This post is dedicated to new extensibility feature – ability to associate file extension and protocol type to automatically launch your app when another app launches a specific file type or URI. When launched, a deep link URI is used to send the file (a reference to the file) or URI to application. You can also use the association launching API to launch another app in the same way.

File type association is useful when your app need automatically launch on invoking specific file type from email attachment, NFC tag, text message, another application.

Protocol association is useful when your application need automatically launch on invoking specific URI, such as mailto://, http://, etc.

File associations

Registration to file type (file extension) achieved via FileTypeAssociation element in Extensions element of application manifest. The following code snippet registers application to handle files with “.smpl” and “.sample” extensions:

<FileTypeAssociation Name="SampleLaunch" TaskID="_default" NavUriFragment="fileToken=%s">
  <!--<Logos>
    <Logo Size="Small">small.png</Logo>
    <Logo Size="Medium">medium.png</Logo>
    <Logo Size="Large">large.png</Logo>
  </Logos>-->
  <SupportedFileTypes>
    <FileType>.smpl</FileType>
    <FileType>.sample</FileType>
  </SupportedFileTypes>
</FileTypeAssociation>

Please note optional Logos section (commented in sample) – this section lists an image file to appear beside a file. The files in this section sized/used as follows:

Size Image dimensions Usage
Small 33x33 Email attachments
Medium 69x69 Office hub files list
Large 176x176 IE download list

When the application is launched to handle a particular file type, a deep link URI passed to the application. The URI looks like the following:

/FileTypeAssociation?fileToken={TOKEN_GUID}

Within the URI, the FileTypeAssociation string designates that the source of the URI is a file association and the fileToken parameter contains the file token GUID. Those parameters could be easily parsed and rerouted to internal handler page.

Usually, to handle multiple URI types application defines URI mapper class which parses the inbounding URI and reroutes to application’s page. The sample URI mapper class to handle such URI could look like the following code snippet:

class CustomUriMapper : UriMapperBase
{
    private static string TargetFilePageName = "FilePage.xaml";
    private static string FileTemplate = "/FileTypeAssociation?fileToken=";
    public override Uri MapUri(Uri uri)
    {
        string tempUri = HttpUtility.UrlDecode(uri.ToString());
 
        if (tempUri.Contains("/FileTypeAssociation"))
                return GetFileMappedUri(tempUri);
 
        return uri;
    }
 
    private Uri GetMappedUri(string uri)
    {
        //...
    }
}

Note: this code is partial, application logic is omitted for code brevity.

To URI mapper class used in app by assigning it to RootFrame.UriMapper property in App.xaml.cs after initializing RootFrame object:

//...
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;
 
RootFrame.UriMapper = new CustomUriMapper();
 
// Handle navigation failures
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
//..

Once application launched from file association, the URI mapper will intercept the URI and reroute (in sample code above) to FilePage.xaml page. To open the file by received file association, use SharedStorageAccessManager from Windows.Phone.Storage.SharedAccess namespace. SharedStorageAccessManager provides access to files that have been shared with a file association:

//Get token from query string
string fileToken = NavigationContext.QueryString["ID"];
//Resolve filename
var filename = SharedStorageAccessManager.GetSharedFileName(fileToken);
//Copy file to local folder
var file = await SharedStorageAccessManager.CopySharedFileAsync(Windows.Storage.ApplicationData.Current.LocalFolder,
                                                                    fileToken + ".smpl", Windows.Storage.NameCollisionOption.ReplaceExisting,
                                                                    fileToken);
//Open local file
var content = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
//...

Testing file association is easy with Launcher class from System.Windows namespace. It provides LaunchFileAsync function which starts default app associated with specified file type:

StorageFile recipeFile = await local.GetFileAsync("SampleFile.smpl");
 
if (null != recipeFile)
    await Windows.System.Launcher.LaunchFileAsync(recipeFile);

Note: this functionality is launched from another application which serves as tester app for real application.

 

Protocol associations

A protocol association allows your app to automatically launch when another app launches a special URI. This special URI could look like the following (using in sample for this post):

sample://showSample?ID=1004

To handle protocol, application must manifest new extra in application manifest must (in Extras section):

<Protocol Name="sample" TaskID="_default" NavUriFragment="encodedLaunchUri=%s" />

In this code snippet “sample” is the name of custom protocol which will be used to launch the application.

Once user clicks on hyper link with this protocol, or other application invokes navigation to such protocol the application starts with following deep link URI passed to the application:

/Protocol?encodedLaunchUri=sample://showSample/?ID=1234

Like in file association scenario, it is easy to intercept such links with URI mapper and reroute to internal page in application:

public override Uri MapUri(Uri uri)
{
    string tempUri = HttpUtility.UrlDecode(uri.ToString());
 
    if (tempUri.Contains("/Protocol"))
        return GetMappedUri(tempUri);
 
    return uri;
}
 
private Uri GetMappedUri(string uri)
{
    //...
}

The major difference from file association is that the amount information in URI is much more limited than in file.

To test the application you can create simple HTML file and host on some webhosting (for example this post uses the following HTML file hosted at http://www.alexgolesh.com/sample.html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Sample launcher</title>
</head>
<body>
    <h1>Protocol and File extenstion handlers sample</h1>
    <div>
        <h2>This section invokes "sample://" protocol for my blog sample.</h2>
        <a href="sample://showSample?ID=1234">Click here to launch blog sample</a>
    </div>
</body>
</html>

Alternatively, protocol handler can be invoking using same Launcher class from System.Windows namespace as for file association. It provides LaunchUriAsync function which starts default app associated with protocol:

Uri uri = new Uri("sample://showSample?ID=1004");
Windows.System.Launcher.LaunchUriAsync(uri);

Note: this functionality is launched from another application which serves as tester app for real application.

Working sample presented at the following vide

Video of file associations and protocol handler sample

Next time I will blog about hybrid applications which combines native and managed code together.

 

Stay tuned,

Alex

What’s New in Windows Phone 8 (3 out of 8)–Voice Recognition

This post dedicated to additional interesting feature in Windows Phone 8 – voice recognition and speech synthesizing.

Speech synthesizing

Let’s start from speech synthesizing. The functionality localized in Windows.Phone.Speech.Synthesis namespace. Using classes in this namespace you can create text-to-speech (TTS) scenarios in your application. The functionality enables read some document identified by URI, string of text with SSML markup or plain text. My sample focuses on plain text scenario.

Class responsible for speech synthesizing is SpeechSynthesizer. To speak plain text use code snippet below:

SpeechSynthesizer synth = new SpeechSynthesizer();
await synth.SpeakTextAsync("Hello from Windows Phone 8");

Speech synthesizer supports changing speech voice from system installed voice. The following code snippet select random voice and speaks out greeting text using this voice:

var voices = Windows.Phone.Speech.Synthesis.InstalledVoices.All;
int voiceNumber = rnd.Next(voices.Count);
synth.SetVoice(voices[voiceNumber]);
 
CultureInfo ci = new CultureInfo(voices[voiceNumber].Language);
string lang = ci.EnglishName;
int pos = ci.EnglishName.IndexOf("(");
if (pos > 0)
    lang = lang.Substring(0, pos - 1);
 
await synth.SpeakTextAsync("Hello from voice of " + voices[voiceNumber].DisplayName + 
                            ". I'm a " + voices[voiceNumber].Gender + 
                            ". I'm specializing in " + lang + " language");

Sometimes, like in snippet above speech process could take some time. In case your application logic needs to cancel speech process, it is advised to use IAsyncOperation instead of new await keyword. The following code demonstrates this approach – user presented with message box and same text synthesized using SpeechSynthesizer. When user closes MessageBox the speech stops:

SpeechSynthesizer synth = new SpeechSynthesizer();
 
string theMessage = "Pages updated. From outside the app, press and hold the Start button and say 'Blog Sample show me last page'";
 
try
{
    var task = synth.SpeakTextAsync(theMessage);
    MessageBox.Show(theMessage);
    task.Cancel();
}
catch (TaskCanceledException TaskEx)
{
    //Ignore the error - expected when cancelling the task
}
catch (Exception ex)
{
    //Some other error...
    //...
}

Now, let’s move to speech recognition.

Speech Recognition

Speech recognition support for applications based on defined list of voice commands and grammars. Also built-in grammar is available. Voice commands and user-defined grammars could be used to build in-app navigation, while built-in grammars could be used to build short message dictation or in-app/web search queries functionality.

Voice commands file is an XML file which defines a list of commands application listens to. Before using speech recognition application must initialize voice commands from file or from code using APIs described later. Voice commands file looks like the following code snippet:

<?xml version="1.0" encoding="utf-8" ?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
  <CommandSet xml:lang="en-us" Name="NavigationCommands">
    <CommandPrefix>Blog Sample</CommandPrefix>
    
    <Example>Show (Page Number) page</Example>
 
    <Command Name="showPage">
      <Example>Show me (some) page</Example>
      <ListenFor>[Show] [me] {pageNames} page</ListenFor>
      <ListenFor>Go to {pageNames} page </ListenFor>
      <Feedback>Navigating to {pageNames} page...</Feedback>
      <Navigate Target="/ThePage.xaml"/>
    </Command>
 
    <Command Name="showAboutPage">
      <Example>Show me the About Page</Example>
      <ListenFor>show [me] the about page</ListenFor>
      <ListenFor>the about page</ListenFor>
      <Feedback>Showing you the About page...</Feedback>
      <Navigate Target="About.xaml"/>
    </Command>
    
    <PhraseList Label="pageNames">
      <Item>First</Item>
      <Item>Second</Item>
      <Item>Third</Item>
    </PhraseList>
  </CommandSet>
 
  <!-- Other CommandSets for other languages -->
 
</VoiceCommands>

Few “special” elements on such file:

{} - Contains the reference to a value from corresponding PhraseList

[] – Designates optional word or words.

Note: for complete reference of available options for VoiceCommand files refer to documentation.

Grammar files also defines the words and phrases that an application will recognize in speech input. Like voice commands, grammars are also using the XML formatted file defined by the Speech Recognition Grammar Specification (SRGS) Version 1.0. Also this file should be loaded before using grammars or initialized from code behind. Sample grammar file looks like:

<?xml version="1.0" encoding="utf-8" ?>
<grammar version="1.0" xml:lang="en-US" root="sampleCommand" tag-format="semantics/1.0" xmlns="http://www.w3.org/2001/06/grammar" 
         xmlns:sapi="http://schemas.microsoft.com/Speech/2002/06/SRGSExtensions">
 
  <rule id="sampleCommand" scope="public">
    Navigate to
 
    <one-of>
      <item> page </item>
      <item> item </item>
    </one-of>
 
    <item repeat="0-1"> in the </item>
 
    <ruleref uri="#pages"/>
 
    <one-of>
      <item repeat="0-1"> pages </item>
      <item repeat="0-1"> items </item>
    </one-of>
  </rule>
 
  <rule id="pages" scope="public">
    <one-of>
      <item> Interesting </item>
      <item> Boring </item>
      <item> New </item>
      <item> Old </item>
      <item> Personal </item>
    </one-of>
  </rule>
</grammar>

Note: For complete descriptions of SRGS grammar elements, refer to documentation.

Now let’s see how to use those files from within application.

To use voice recognition, the application must declare the following capabilities (in application manifest):

<Capability Name="ID_CAP_SPEECH_RECOGNITION" />
<Capability Name="ID_CAP_MICROPHONE" />

Let’s see how to initialize speech recognizer with Voice Commands file:

try
{
    // Set the path to the Voice Command Definition (VCD) file.
    String path = Windows.ApplicationModel.Package.Current.InstalledLocation.Path + "\\VoiceCommands.xml";
    Uri uri = new Uri(path, UriKind.Absolute);
 
    // Load the VCD file.
    await Windows.Phone.Speech.VoiceCommands.VoiceCommandService.InstallCommandSetsFromFileAsync(uri);
 
    //...
}
catch (Exception ex)
{
    //...
}

From now on the application’s commands are available for phone-wide speech commands. This means, that user could long press windows key and say something like: “Blog Sample show second page” or “Blog Sample Go to Third page”. As result to recognized text, the page defined Navigate element of voice command file will be invoked. Also, user could ask phone “What can I say?” and receive list of available commands incl. the applications registered using voice commands:

image

As response to recognized text system provides visual and spoken response:

image

As mentioned before, the page in the app is invoked. Navigation context holds information which helps to support voice recognition scenarios. In case of voice initiated navigation the query string contains recognized voice command (“voiceCommandName”), recognition result (“reco”) and recognized text in PhraseList named element. In case of voice command file defined above, the query string contains the following values:

voiceCommandName = showPage

reco = Blog Sample Show Third page

pageName = Third

Note, that italic information provided based on VCD file.

This information could be used while processing navigation arguments in OnNavigatedTo function as follows:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
 
    if (NavigationContext.QueryString.ContainsKey("voiceCommandName"))
    {
        string voiceCommandName = NavigationContext.QueryString["voiceCommandName"];
 
        switch (voiceCommandName)
        {
            case "showPage":
                string pageNumber = NavigationContext.QueryString["pageNames"];
 
                PageTitle.Text = pageNumber + " page";
                break;
 
            case //...
 
            //...
 
            default:
                break;
        }
    }
}

Last, but not least – modifications to voice commands once loaded. In some case application manipulates with dynamic data which should be exposed in VCD file. In such case the commands list could be dynamically updated as follows:

try
{
    IReadOnlyDictionary<String, VoiceCommandSet> collectionOfCommandSets = VoiceCommandService.InstalledCommandSets;
    VoiceCommandSet targetCommandSet = collectionOfCommandSets["NavigationCommands"];
 
    String[] updatedPagesList = { "First", "Second", "Third", "Fourth", "Fifth", 
                                    "Other", "Interesting", "Boring", "Last" };
 
    await targetCommandSet.UpdatePhraseListAsync("pageNames", updatedPagesList);
 
    //...
}
catch (Exception ex)
{
    //...
}

Notes: The “NavigationCommands” is the name of CommandSet in loaded VCD file and “pageNames” is the PhraseList label in VCD file.

Now let’s see how to recognize the speech from within the application.

Speech recognizers located in Windows.Phone.Speech.Recognition namespace. There are two of them: SpeechRecognizerUI and SpeechRecognizer. SpeechRecognizerUI provides built-in experience while listening to the speech and can show system confirmation after recognition. SpeechRecognizer enables user-defined speech scenarios as it doesn’t show any UI. Before first usage of speech recognizer it must be initialized. Also custom grammar/voice commands should be loaded, otherwise built-in system grammar will be used.

Note: Built-in dictation and web search grammars are large files and they are reside online (not on the phone). The performance may not be as fast as with custom, on-phone grammars.

While initializing speech recognizer application can provide various options, like text to be shown on system UI (in case of SpeechRecognizerUI), showing recognition confirmations (voice and textual), etc.

SpeechRecognizerUI recognizer;
bool speechInitialized = false;
List<string> pagesList = new List<string>();
//...
private void InitializePagesList()
{
    pagesList.Add("First");
    pagesList.Add("Second");
    pagesList.Add("Third");
    pagesList.Add("Fourth");
    pagesList.Add("Fifth");
}
 
private void InitializeSpeechRecognition()
{
    if (this.speechInitialized)
        return;
 
    try
    {
        speechInitialized = true;
 
        recognizer = new SpeechRecognizerUI();
        recognizer.Settings.ListenText = "Navigate to which page?";
        recognizer.Settings.ExampleText = "For example, 'First' or 'Second'";
        recognizer.Settings.ShowConfirmation = true;
        recognizer.Recognizer.Grammars.AddGrammarFromList("pages", pagesList);
    }
    catch (Exception ex)
    {
        //...
    }
}

Alternatively, application could initialize speech recognition from SRGS file (instead of using AddGrammarFromList):

string path = Package.Current.InstalledLocation.Path + "\\CostomSRGSGrammars.xml";
Uri customGrammar = new Uri(path, UriKind.Absolute);
 
recoWithUI.Recognizer.Grammars.AddGrammarFromUri("appCommands", customGrammar);
await recoWithUI.Recognizer.PreloadGrammarsAsync();

Once speech recognizer initialized and configured it could be started as follows:

var recoResult = await recognizer.RecognizeWithUIAsync();

The recognition result provides ResultStatus and RecognitionResult which among other information holds recognized Text and TextConfidence and RuleName. Those parameters could be used in application logic. Next code snippet uses Text and TextConfidence for navigation purposes:

var url = string.Format("/ThePage.xaml?recognizedPage={0}&confidence={1}", 
                        recoResult.RecognitionResult.Text, 
                        recoResult.RecognitionResult.TextConfidence);
NavigationService.Navigate(new Uri(url, UriKind.Relative));

It it important to mention, that application can use more than one speech recognizer object and each once could be initialized with its own grammars.

That is all about voice recognition and speech synthesizing in Windows Phone 8.

 

Next time I will show how to associate application with file extension and handle custom protocol.

 

Stay tuned,

Alex

What’s New in Windows Phone 8 (2 out of 8)–Lock Screen

In previous post I described how to enrich user experience by customizing application tiles. In this post I will show how to enable your application to present some information on phone’s lock screen.

In Windows Phone 8 applications could provide 3 pieces of info on lock screen: application’s icon, count and text. On screenshot below my sample application provides icon, count and some text:

image

If application selected by user, the lock screen could show app icon defined in app manifest, count and text pulled directly from the application's primary tile. The secondary tiles does not have an impact on lock screen.

Let’s see how to achieve it. First of all – icon presented on lock screen must be 24x24 transparent PNG image with white pixels (plus transparent pixels obviously). Once such image created, add it to the application and then open application manifest using XML editor as follows (right click on manifest file and select “Open With…”:

image

Then select XML (Text) Editor:

image

Locate “DeviceLockImageURI” element (within PrimaryToken/Template definition) and specify path to the image:

<DeviceLockImageURI IsRelative="true" IsResource="false">Images\lock_icon.png</DeviceLockImageURI>

To enable application icon and count add new Extensions element and new Extension as follows:

<Extensions>
  <Extension ExtensionName="LockScreen_Notification_IconCount" ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" TaskID="_default" />
</Extensions>

Note:Extension element must be next to Tokens element.

If you plan to provide lock screen with text updates, add the following Extension element to the Extensions section:

<Extension ExtensionName="LockScreen_Notification_TextField" ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" TaskID="_default" />

Note:Your application could use multiple extension elements, but consider providing only those, which are really used by the application.

Also note: As the text pulled directly from the application's primary tile, cyclic tile template shouldn’t be used with LockScreen_Notification_TextField extension as it has no text.

Once application with extensions in manifest deployed to device, user can select the application in Settings/Lock Screen section – application name will be available for selection at notifications sections (detailed and quick status):

image

Note: the settings should be done by user from Settings menu and cannot be defined form code.

Lock screen Background

In addition to information presented above, Windows Phone 8 application could be then chosen lock screen background provider application, so that application can provide the lock screen background.

To enable this functionality your application must declare additional Extension in application manifest (could be used with or without other lock screen extensions):

<Extension ExtensionName="LockScreen_Background" ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" TaskID="_default" />

Once defined (after deployment) user will be able to choose your application form list of the applications with same functionality on the device:

imageimageimage

In addition to this manual method the default lock screen provide could also be changed from code. Let’s see how to request provide lock screen background from code:

//Check if application already lock screen background provider
if (!LockScreenManager.IsProvidedByCurrentApplication)
{
    //No, request to be active lockscreen wallpaper provider
    var res = await LockScreenManager.RequestAccessAsync();
 
    if (res == LockScreenRequestResult.Granted)
    {
        //Request approved
        //...
    }
    else
    {
        //Request rejected
        //...
    }
}

The code snippet checks if lock screen already provided by current application, and if not raises request. This request is raised to user as following message box (system provided):

image

User approval equivalent to Settings change.

Note: user can change this at any time using Settings screen, thus before setting actual background the app should change it it is still current provider.

Now, let’s see how to set lock screen background:

if (LockScreenManager.IsProvidedByCurrentApplication)
{
    string fileName = "ms-appx:///Images/WP1.JPG";
 
    Uri uri = new Uri(fileName, UriKind.RelativeOrAbsolute);
    LockScreen.SetImageUri(uri);
 
    //Lock screen background set
    //...
}

This code snippet verifies that application is still active lock screen background provider and invokes LockScreen.SetImageUri function which changes the background.

In addition, the LockScreen class provides access to current background image URI by LockScreen.GetImageUri function.

 

Simulation Dashboard

New version of Windows Phone Emulator and SDK provides new tool called Simulation Dashboard which enables simulation of various network conditions, lock screen and reminders. This tool located in Tools menu in Visual Studio:

image

image

Use radio buttons in Lock Screen section to simulate locking the screen on emulator.

image

 

That’s it for now. Next time I will show how to integrate voice recognition into your application.

 

Stay tuned,

Alex

What’s New in Windows Phone 8 (1 out of 8)–Tiles

One of the most noticeable feature of Windows Phone 8 is change of main screen with 3 different tile types:

image

Each tile could be one out from 3 types available sizes – small, normal and wide. Also, each type could be form 3 different types – Iconic, Flip and Cycle.

All 3 sizes and all 3 types are available for 3rd party developers. Let’s see how to use this interesting feature in the application.

So what are the sizes? The sizes are:

Small

image

Medium

image

Wide

image

What about 3 types? The types are:

Flip – this tile flips from front to back exposing front and back content

image image

Iconic – this tile mimics Metro design

image

Cycle – this tile cycles through collection of local images (up to nine images could be defined)

imageimage 

It is important to mention, that all “interesting” tile functionality such as cycling images and flipping available only for medium and wide tiles. In case of Flip/Cycle tiles, small tile shows static image as defined in application manifest (see below).

To switch between different tile sizes tap and hold on the tile. In addition to “unpin” icon from previous version new version shows additional icon which enables size change:

imageimageimage

Working with the tiles

Main tile type (template) is defined via application manifest:

image

Also manifest is used to enable support for wide tile (“Support for large Tiles” checkbox) and define initial tile graphics. It is important to define main tile type which suites best your application’s needs as it cannot be changed later.

For best results it is important to provide tile graphics according to expected sizes, though wrongly sized graphics will be presented anyway with possible visual distortions. The sizes are:

Tile Size Flip Tile Cycle Tile Iconic Tile
Small 159x159 159x159 110x110
Medium 336x336 33x336 202x202
Wide 691x336 691x336 N/A

The content of main tile could be changed from code, though, as mentioned before, the tile template couldn’t be changed. The following code snippet changes the content of main app tile:

var mainTile = ShellTile.ActiveTiles.FirstOrDefault();
 
if (mainTile != null)
{
    IconicTileData tileData = new IconicTileData()
    {
        Count = 73,
        BackgroundColor = Colors.Green,
        Title = "Main",
        IconImage = new Uri("/Assets/Tiles/IconicTileMediumLarge.png", UriKind.RelativeOrAbsolute),
        SmallIconImage = new Uri("/Assets/Tiles/IconicTileSmall.png", UriKind.RelativeOrAbsolute),
        WideContent1 = "Wide content 1",
        WideContent2 = "Wide content 2",
        WideContent3 = "Wide content 3",
    };
 
    mainTile.Update(tileData);
}

This code snippet updates main tile using IconicTileData class (as application tile defined in app manifest as Iconic tile – see image above). This snippet uses all possible properties, many of them are optional (such as wide contents for example). The code snippet updates main tile which looks like the following:

Original tile Update tile
image image
image image
image image

* Numbers on small and medium tiles cut due to bug in early build of SDK used while writing this post

The templates used for main tile could be used to create and update also secondary tiles for application.

Let’s see how to create secondary tile using Flip template:

//Flip
FlipTileData tileData = new FlipTileData()
{
    Title = "Flip",
    Count = 12,
    BackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileMedium.png", UriKind.RelativeOrAbsolute),
    BackBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileMedium.png", UriKind.RelativeOrAbsolute),
                
    BackTitle = "Flip back",
    BackContent = "Back content",
                
    SmallBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileSmall.png", UriKind.RelativeOrAbsolute),
 
    WideBackContent = "Wide back content",
    WideBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileLarge.png", UriKind.Relative),
    WideBackBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileLarge.png", UriKind.Relative)
};
 
ShellTile.Create(new Uri(uri, UriKind.Relative), tileData, true);

The code snippet is pretty self-descripting: it creates FlipTileData object, populates properties for front and back of the tile for normal and wide content (in case we want to support wide tile) and invokes ShellTile.Create function. Last parameter (in this case true) defines the support for wide tile. The result produced for this tile looks as follows:

image imageimageimageimage

Now, let us see the code to create third

(and most interesting in my opinion) tile type – cycle.

//Cycle
List<Uri> list = new List<Uri>();
list.Add(new Uri("/Images/WP1.jpg", UriKind.Relative));
list.Add(new Uri("/Images/WP2.jpg", UriKind.Relative));
list.Add(new Uri("/Images/WP3.jpg", UriKind.Relative));
list.Add(new Uri("/Images/WP4.jpg", UriKind.Relative));
list.Add(new Uri("/Images/WP5.jpg", UriKind.Relative));
 
CycleTileData tileData = new CycleTileData()
{
    Title = "Cycle",
    Count = 12,
    SmallBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileSmall.png", UriKind.RelativeOrAbsolute),
    CycleImages = list
};
 
ShellTile.Create(new Uri(uri, UriKind.RelativeOrAbsolute), tileData, true);
 

Most important in this this code block is the CycleImages list for CycleTileData object. It expects IEnumerabe<Uri> object with local images path. Remote images (not on the device) are not supported. The result of this code produces tile which looks like the following illustrations:

imageimageimage

Tiles also could be updated using same push notification mechanism as in previous version. The only change would be in payload sent as new tiles needs more information.

 

That’s it for now. In next post I will how another end-user oriented feature – Lock Screen backgrounds and notifications.

 

Stay tuned,

Alex

Windows Phone 8 SDK available

Just announced at BUILD keynotes – Windows Phone 8 SDK available now! It includes Visual Studio Express 2012 edition for Windows Phone (which also works as add-on for paid versions of Visual Studio 2012), new Hyper-V based Windows Phone emulator and Expression Blend. It could be downloaded from the following location:

http://go.microsoft.com/fwlink/?LinkID=261873

 

Stay tuned for more exciting news to come,

Alex

Working with NFC–Take 2

Some time ago (I’ve blogged about working with proximity devices – NFC – in Windows 8 Consumer preview: http://blogs.microsoft.co.il/blogs/alex_golesh/archive/2012/02/29/windows-8-consumer-preview-and-visual-studio-11-beta-working-with-proximity-device-part-2-11.aspx). Then I’ve talked about a simple way performing NFC communication – using pub/sub communication pattern which is good for exchanging simple messages using PublishMessage and PublishBinaryMessage functions on ProximityDevice class.

Few days ago my client asked me to prepare a demo which uses proximity communication to transfer custom “Items” between two instances of the app (and also Windows Phone 8 version of this app). The app uses complex “items” which includes many textual fields, undefined number of attached images, locations, etc. To achieve this I’ve decided to use 2nd approach to proximity communication briefly described in my previous blog post – the TriggeredConnection and Sockets.

(I had additional “constraints” while engineered the solution: to minimize amount of changes in the app by using existing in-the-app load/save mechanisms and to be compatible as much as possible with Windows Phone 8 app and provide maximum code reuse between the platforms to avoid developing same functionality twice. Please keep in mind, that this blog post is not focused directly on dealing those constraints; I will blog more about sharing the code and my traditional “What’s New” series about Windows Phone 8 in a short while – so stay tuned).

Let’s get started. First of all – the app must specify proximity capability in app manifest:

image

The app has to support two sides of proximity communication – sender and receiver. Both called peers. In both cases, I am using PeerFinder class (form Windows.Networking.Proximity namespace). In my case I’ve decided to use Triggered discovery type which supports Tap-to-Connect scenario I needed for my purposes.

   1: public void StartConnect(string displayName)
   2: {
   3:     if (!String.IsNullOrEmpty(displayName))
   4:     {
   5:         //Optionally name the peer so it could be easily identified 
   6:         //and optionally presented to user
   7:         PeerFinder.DisplayName = displayName;
   8:     }
   9:  
  10:     if ((PeerFinder.SupportedDiscoveryTypes & PeerDiscoveryTypes.Triggered) != PeerDiscoveryTypes.Triggered)
  11:     {
  12:         //The device doesn't support tap-and-send communication
  13:         UpdateConnectionStatus(ConnectionStatus.NotSupported);
  14:         return;
  15:     }
  16:  
  17:     //Subscribe to connection triggers
  18:     PeerFinder.TriggeredConnectionStateChanged += TriggeredConnectionStateChanged;
  19:  
  20:     //Declare alternate identities (if needed and supported)
  21:     if (!PeerFinder.AlternateIdentities.ContainsKey(AlternateIdentityKey))
  22:     {
  23:         PeerFinder.AlternateIdentities.Add(AlternateIdentityKey, AlternateIdentity);
  24:     }
  25:  
  26:     PeerFinder.AllowInfrastructure = true;
  27:     PeerFinder.AllowBluetooth = true;
  28:     PeerFinder.AllowWiFiDirect = false;
  29:  
  30:     //Start listening to proximity events
  31:     PeerFinder.Start();
  32:  
  33:     UpdateConnectionStatus(ConnectionStatus.Ready);
  34: }

The code snippet above starts the connectivity. It uses enables to optionally name the peer so it could be identified by other side, checks that device support required proximity discovery mode and subscribes to connection state changes.

The code above adds AlternateIdentities (see class declaration below). Alternate identities are used to enable communication between different applications and devices. As you remember, my demo requirement was to share the “items” between two instances of the app (which has same identity on all running devices) and Windows Phone 8 version of this app. Enabling the sharing between the app running Windows 8 and the app running on Windows Phone or different app running on Windows 8 requires adding alternate identities. The actual definition of the AlternateIdentityKey in my demo looks as follows:

   1: #if NETFX_CORE
   2:     readonly string AlternateIdentityKey = "WindowsPhone";
   3:     readonly string AlternateIdentity = "{04f1e621-039f-4829-b59f-47e71c6af98d}";
   4: #elif WINDOWS_PHONE
   5:     readonly string AlternateIdentityKey = "Windows";
   6:     readonly string AlternateIdentity = "a4ec8cdf-7759-4709-93af-5d2c2688ee46_cb1hhkscw5m06!App"; //Could be found using Windows.ApplicationModel.Package.Current.Id.FamilyName
   7: #endif

This code is a part of shared code which defines AlternateIdentity for other platform and could also define the AlternateIdentity for other app running on the same platform. When compiled for Windows 8, it adds “WindowsPhone” identity key and the ID of application running on the phone; when compiled for Windows Phone 8 it adds the “Windows” identity key and the full app ID of the Windows 8 app.

Note: The app id could be obtained from app manifest (Packaging tab).
For Windows it will be the value of “Package family name” field + “!” + app ID (the namesapce and name of the App class). It also could be obtained using Windows.ApplicationModel.Package.Current.Id.FamilyName API from within the code.
For Windows Phone app it will be the value of “Product ID”.

This way PeerFinder is aware about other apps which are allowed to connect to this app. Additionally, when two devices are in proximity and the trying to establish the proximity connection, but one of the devices is not running the application (not started or in background) this alternate ID will be using by platform to identify the “target” app and pop up a toast notification asking user’s permission to start the app and establish proximity connection.

When the connection is triggered, every app responds in slightly different way (depending of the app logic). In my case the TriggeredConnectionStateChanged event handler looks as follows:

   1: private void TriggeredConnectionStateChanged(object sender, TriggeredConnectionStateChangedEventArgs e)
   2: {
   3:     switch (e.State)
   4:     {
   5:         case TriggeredConnectState.PeerFound:
   6:             UpdateConnectionStatus(ConnectionStatus.PeerFound);
   7:             break;
   8:         case TriggeredConnectState.Connecting:
   9:             UpdateConnectionStatus(ConnectionStatus.Connecting);
  10:             break;
  11:         case TriggeredConnectState.Listening:
  12:             UpdateConnectionStatus(ConnectionStatus.Listening);
  13:             break;
  14:         case TriggeredConnectState.Canceled:
  15:             UpdateConnectionStatus(ConnectionStatus.Canceled);
  16:             break;
  17:         case TriggeredConnectState.Failed:
  18:             UpdateConnectionStatus(ConnectionStatus.Failed);
  19:             break;
  20:         case TriggeredConnectState.Completed:
  21:             socket = e.Socket;
  22:             UpdateConnectionStatus(ConnectionStatus.Completed);
  23:             break;
  24:     }
  25: }

For most cases my demo just informs the user with different connectivity state changes and when connection established (Completed state) saves a Socket for future use. The main app also listens to connectivity changes and when connection is established switches to either “receive” mode or “send” mode depending on the app logic. In both cases (will show then later in the post) a socket communication will be used to send/receive raw bytes and the actual information should be first converted to bytes representation (in case of send side) and parsed back (in case of receiving side).

To leverage the code we already had in the app I’ve decided to use objects serialized with JSON serializer. This also enabled me to write pretty “abstract” code which sending/receiving the items (you will see later). The next code block has two functions – GetItemStream which serializes my “item” to JSON format and ParseNewItem which deserializes received “item” from stream back to strongly typed object:

   1: public byte[] GetItemStream(Item note)
   2: {
   3:     List<Type> types = new List<Type>();
   4:     //Not required in this case, but should be used to 
   5:     //serializing/deserializing multiple object types
   6:     types.Add(typeof(Item)); 
   7:  
   8:     DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Item)/*, types*/);
   9:     MemoryStream ms = new MemoryStream();
  10:  
  11:     ser.WriteObject(ms, note);
  12:     byte[] json = ms.ToArray();
  13:     var value = System.Text.Encoding.UTF8.GetString(json, 0, json.Length);
  14:     Debug.WriteLine("Serialized JSON object:\n" + value);
  15:     return json;
  16: }
  17:  
  18: private Item ParseNewItem(MemoryStream ms)
  19: {
  20:     List<Type> types = new List<Type>();
  21:     //Not required in this case, but should be used to 
  22:     //serializing/deserializing multiple object types
  23:     types.Add(typeof(Item)); 
  24:     DataContractJsonSerializer des = new DataContractJsonSerializer(typeof(Item)/*, types*/);
  25:     var item = (Item)des.ReadObject(ms);
  26:     item.UniqueId = DataManager.GetUniqueId();
  27:  
  28:     return item;
  29: }

Once the object has been serialized and we got a stream it is ready to be sent.

   1: public async Task SendItemAsync([ReadOnlyArray] byte[] itemBytes, int imagesCount, [ReadOnlyArray] List<byte[]> images)
   2: {
   3:     if (itemBytes != null && socket != null)
   4:     {
   5:         //Start sending the item
   6:         try
   7:         {
   8:             DataWriter dw = new DataWriter(socket.OutputStream);
   9:  
  10:             //Sending item length
  11:             dw.WriteInt32(itemBytes.Length);
  12:             await dw.StoreAsync();
  13:  
  14:             //Sending item bytes
  15:             dw.WriteBytes(itemBytes);
  16:             await dw.StoreAsync();
  17:  
  18:             if (null != images && imagesCount > 0) //The only app-specific part here...
  19:             {
  20:                 foreach (var imageBytes in images)
  21:                 {
  22:                     //Sending image length
  23:                     dw.WriteInt32(imageBytes.Length);
  24:                     await dw.StoreAsync();
  25:  
  26:                     //Sending image bytes
  27:                     dw.WriteBytes(imageBytes);
  28:                     await dw.StoreAsync();
  29:                 }
  30:             }
  31:  
  32:             //Flushing buffers to make sure we pushed all the data over "the wire"
  33:             await dw.FlushAsync();
  34:  
  35:             //Closing DataWriter
  36:             dw.DetachStream();
  37:             dw.Dispose();
  38:         }
  39:         catch (Exception ex)
  40:         {
  41:             Debug.WriteLine(ex.Message);
  42:             //Reset the connection if case of communication error
  43:             StopConnect();
  44: #if NETFX_CORE
  45:             string PeerName = "Win8_NFC Sample";
  46: #elif WINDOWS_PHONE
  47:             string PeerName = "WP8_NFC Sample";
  48: #endif
  49:             //Restart connection
  50:             StartConnect(PeerName);
  51:         }
  52:     }
  53: }

The function is relatively simple and straight forward – user DataWriter class (System.Networking.Sockets namespace) to send bytes over socketed connection. Same goes to images which were prepared in their raw/bytes format. The code snippet which prepares and calls the SendItemAsync looks as follows (and is not shared across platforms):

   1: //Get bytes from current item
   2: byte[] bytes = ProximityManager.Instance.GetItemStream(item);
   3: List<byte[]> images = null;
   4:  
   5: //If item has images attached - prepare images
   6: if (item.Images.Count > 0)
   7: {
   8:     images = new List<byte[]>();
   9:  
  10:     foreach (var imgSrc in item.Images)
  11:     {
  12:         //Read image from local storage
  13:         var filename = imgSrc.Replace("Images/", "");
  14:         var storage = Windows.Storage.ApplicationData.Current.LocalFolder;
  15:         var folder = await storage.GetFolderAsync("Images");
  16:         var file = await folder.GetFileAsync(filename);
  17:         var stream = await file.OpenReadAsync();
  18:         //Prepare image bytes
  19:         byte[] imageBytes = new byte[stream.Size];
  20:         var str = stream.AsStream();
  21:         await str.ReadAsync(imageBytes, 0, (int)stream.Size);
  22:  
  23:         images.Add(imageBytes);
  24:     }
  25: }
  26:  
  27: //Send the item
  28: await ProximityManager.Instance.SendItemAsync(bytes, item.Images.Count, images);

The second part of the equation is to receive a message. Since we know exactly how we sending the message, the receive function looks as follows:

   1: public async void ReceiveItemAsync()
   2: {
   3:     if (socket != null)
   4:     {
   5:         try
   6:         {
   7:             DataReader dr = new DataReader(socket.InputStream);
   8:  
   9:             // Receive the size of the byte array first
  10:             if (await TryLoadAsync(dr, 4))
  11:             {
  12:                 var count = dr.ReadInt32();
  13:                 uint ucount = (uint)count;
  14:  
  15:                 if (await TryLoadAsync(dr, ucount))
  16:                 {
  17:                     byte[] bytesIn = new byte[count];
  18:                     dr.ReadBytes(bytesIn);
  19:  
  20:                     //Save/parse new item
  21:                     MemoryStream ms = new MemoryStream(bytesIn);
  22:                     Item theItem = ParseNewItem(ms);
  23:  
  24:                     var imagesCount = theItem.Images.Count;
  25:                     //Receive "attached" images - app-specific functionality
  26:                     if (imagesCount > 0)
  27:                     {
  28:                         for (int i = 0; i < imagesCount; i++)
  29:                         {
  30:                             if (await TryLoadAsync(dr, 4))
  31:                             {
  32:                                 var imgSize = dr.ReadInt32();
  33:                                 uint uimgSize = (uint)imgSize;
  34:  
  35:                                 if (await TryLoadAsync(dr, uimgSize))
  36:                                 {
  37:                                     byte[] imgBytesIn = new byte[imgSize];
  38:                                     dr.ReadBytes(imgBytesIn);
  39:  
  40:                                     MemoryStream imgMs = new MemoryStream(imgBytesIn);
  41:  
  42:                                     var imgName = theItem.Images[i];
  43:                                     imgName = imgName.Replace("Images/", "");
  44:                                     var fileName = await DataManager.SaveImageAsync(imgName, imgMs.AsInputStream(), Windows.Storage.CreationCollisionOption.GenerateUniqueName);
  45:                                 }
  46:                             }
  47:                         }
  48:                     }
  49:  
  50:                     await DataManager.AddFileAsync(theItem);
  51:  
  52:                     //Raise evens, so main app "knows" about new item
  53: #if NETFX_CORE
  54:                     await ((NFCSample.App)App.Current).Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
  55: #elif WINDOWS_PHONE
  56:                     ((WP8_NFC.App)System.Windows.Application.Current).Dispatcher.BeginInvoke((Action)(() =>
  57: #endif
  58:                     {
  59:                         //Raise ItemReceived event
  60:                         if (ItemReceived != null)
  61:                         {
  62:                             ItemReceivedEventArgs args = new ItemReceivedEventArgs();
  63:                             args.NewItem = theItem;
  64:                             ItemReceived(this, args);
  65:                         }
  66:                     }
  67: #if WINDOWS_PHONE
  68:                     )
  69: #endif
  70:                     );
  71:                 }
  72:             }
  73:  
  74:             //Detach a stream and release it
  75:             dr.DetachStream();
  76:             dr.Dispose();
  77:         }
  78:         catch (Exception ex)
  79:         {
  80:             Debug.WriteLine(ex.Message);
  81:             //Reset the connection in case of communication error
  82:             StopConnect();
  83: #if NETFX_CORE
  84:             string PeerName = "Win8_NFC Sample";
  85: #elif WINDOWS_PHONE
  86:             string PeerName = "WP8_NFC Sample";
  87: #endif
  88:             // Restart connection
  89:             StartConnect(PeerName);
  90:         }
  91:     }
  92: }

In this code I am receiving the message parts in exactly the same order as sending them.

Note, that this code is share between Windows 8 and Windows Phone 8.

Last piece of puzzle here – the helper function which reads known amount of bytes from socket:

   1: private async Task<bool> TryLoadAsync(DataReader dr, uint count)
   2: {
   3:     //Get cancellation token 
   4:     cts = new CancellationTokenSource();
   5:     CancellationToken token = cts.Token;
   6:  
   7:     bool result = false;
   8:  
   9:     try
  10:     {
  11:         var countReceived = await dr.LoadAsync(count).AsTask(token);
  12:  
  13:         if (countReceived != count)
  14:         {
  15:             //Connection error - close it
  16:             Debug.WriteLine("Bytes read {0} != {1} total bytes. Communucation error!", countReceived, count);
  17:             //Reset connection
  18:             StopConnect();
  19: #if NETFX_CORE
  20:             string PeerName = "Win8_NFC Sample";
  21: #elif WINDOWS_PHONE
  22:             string PeerName = "WP8_NFC Sample";
  23: #endif
  24:             // Restart connection
  25:             StartConnect(PeerName);
  26:             result = false;
  27:         }
  28:         else
  29:             result = true;
  30:     }
  31:     catch (TaskCanceledException)
  32:     {
  33:         result = false;
  34:     }
  35:     finally
  36:     {
  37:         cts = null;
  38:     }
  39:  
  40:     return result;
  41: }

This is it. Now my class is shared between two apps on multiple platforms and my samples can exchange complex custom items between instances on same and different platforms.

 

To see this demo working – come to BUILD 2.0 conference taking place at Redmond, WA (October 30 - November 2, 2012) or the video I will try to film and publish after the BUILD.

Also – if you are at the BUILD – feel free to find me and say “Hi”. I will be there!

 

Teaser:

I have a massive ‘What’s new in Windows Phone 8” series ready to be published after official release!

 

Stay tuned to more posts to come.

Alex

I’m Microsoft MVP for another year!

About 10 minutes ago, I received an email presenting me with the Microsoft MVP Award in Silverlight!

image

I am very honored to receive an MVP Award for the fourth time in row and I will continue contributing to the online and offline developer community worldwide.

This is a great opportunity and place to thank quite a few people who helped me to win this Award again:

  • My wife and daughter for having so much patience and providing the best support I could only dream about!
  • My current and past managers (David, Ishai, Caro) and coworkers at Sela Group, which is easily the best software company to work for that I could think of;
  • All other peoples who helped me get this MVP award;

Stay tuned for news and  posts on Windows Phone and Windows 8!

Alex

Windows 8 Release Preview

Windows 8 Release Preview (RP) was published and can be downloaded by anyone who want to try this great preview of upcoming OS!

image

More info about it here:

http://windows.microsoft.com/en-US/windows-8/release-preview

Download the version to try from here:

http://windows.microsoft.com/en-US/windows-8/download

For those, who want to grab ISO images links could be found at the following location:

http://windows.microsoft.com/en-US/windows-8/iso

(this link also provides the product key to use)

 

Developers, developers, developers! Updated version version of Visual Studio 2012 Express RC for Windows 8 can be downloaded from the following lcoation:

http://msdn.microsoft.com/en-us/windows/apps/br229516.aspx

Aside tools you can find updated design assets, sample apps and Live SDK!

 

Stay tuned for more updated to come!

Alex

Book review: Microsoft Silverlight 5 and Windows Azure Enterprise Integration

image

As promised here, here is overview of the book I just finished to read.

First of all – my congratulations to author of the book, David Burela, as the book written very clear and describes both, basics and advanced concepts, I very practical and professional way. From other hand, author made this book also enjoyable!

Now about the book itself. It has 12 chapter which overview whole spectrum of possibilities of how to integrate Windows Azure and Silverlight application.

It starts from traditional intro chapters – Intro to Visual Studio, tools, creating Windows Azure account and intro to Windows Azure itself.

Next, 3rd chapter, describes basics of creating Silverlight application and consuming some Azure functionality… While those 3 chapter lack some new info for me personally, I really enjoyed the  way author overviewed the basics because it gives the less experienced audience nice starting point to dive deeper into the book.

In chapters 4-7 authors overviews all possible ways to use Windows Azure services (like Queues, Blob storage, Table storage, SQL Azure) from within Silverlight application. The chapters shows very clean and practical way to use this functionality and gives practical advises of how to make it work. In some cases I felt that presented scenarios is little bit simplified for real world enterprise apps, but from other hand it also enabled very clean sample code and good explanation of the topics.

Second part of the book (chapters 8 – 12) is where I really enjoyed every moment. Those chapters author explained more advanced concepts such as consuming SQL Azure data using RIA Services, consuming OData,  authentication and caching techniques. Again, those chapters presented those concepts in very clear and very practical way.

To summarize, many great information in one place and a lot of walkthrough scenarios makes this book one of my favorites in this specific area. After reading and enjoying this book I can recommend it to anyone who looking for guidance in Silverlight and Azure integration!

More info about the book:

http://www.packtpub.com/microsoft-silverlight-5-enterprise-integration-on-windows-azure/book

 

Stay tuned,

Alex

Books, books, books

Seems like today is “books” day.

Working really hard for last few months, I completely forgot to blog about the book which I took part in!

Announcing: Real World .NET, C#, and Silverlight: Indispensible Experiences from 15 MVPs

cover_image

Few months ago, 15 MVPs from around the globe joined together to write an ultimate resource book for discovering and understanding the C#, .NET 4 Framework and Windows Phone 7.5. Today the book is published, and available at Amazon.com:

http://www.amazon.com/Real-World-NET-Silverlight-Indispensible/dp/1118021967/

Whole book is very good but I especially recommend Chapter 8, written by yours truly Winking smile

image

 

Stay tuned about more interesting updates to come,

Alex

More Posts Next page »