app

Helper class to handle In-App-Products (IAP) licenses on Windows Phone (SL)

Like a lot of other apps, also UniShare got hit by an outage in the licensing system of the Windows Phone Store recently.

There was a workaround to get the licenses back from the store, but even with that, users have left negative votes (even after I posted the workaround and also wpcentral wrote about it a few days later).

The problem with those negative reviews: they tend to remain, even after responding to them (if possible) or having conversation with the users via mail. I totally understand users that are annoyed by such facts – I got hit by it as well with other apps I am using regularly. So I was thinking about a better solution as the recommended way by Microsoft, which says you should check it on every app start.

Rob Irving posted about his solution at the same day wpcentral wrote about it, which is one possible solution. His motive was the same as my solution – improving the user experience with the IAP’s.

However, I am preferring to check the licenses against the Store from time to time to make sure that the licenses are still correct.

Here is my solution (for durable IAP):

First, let’s we need to declare an object for the ListingInformation, which will hold the information that the store returns for our IAP:

ListingInformation IAPListing;

Then, we  need to create these two classes:

        public class IAP
        {
            public string Key { get; set; }

            public string Name { get; set; }

            public string Price { get; set; }

            public ProductType Type { get; set; }

            public string Description { get; set; }

            public string Image { get; set; }

            public bool IsLicenseActive { get; set; }
        }

        public class IAPToSave
        {
            public List<IAP> IAPListToSave { get; set; }

            public DateTime date { get; set; }
        }

The class IAP is the class/model that holds a single IAP item information. The second class is needed for saving the fetched IAP information (we’ll see later how I did it).

Now we have prepared these, we can finally go to the store and fetch the IAP list. I created an async Task that returns a List<IAP> for it:

        public async Task<List<IAP>> GetAllIAP()
        {
            var list = new List<IAP>();

            IAPListing = await CurrentApp.LoadListingInformationAsync();

            foreach (var product in IAPListing.ProductListings)
            {
                list.Add(new IAP()
                {
                    Key = product.Key,
                    Name = product.Value.Name,
                    Description = product.Value.Description,
                    Price = product.Value.FormattedPrice,
                    Type = product.Value.ProductType,
                    Image = product.Value.ImageUri.ToString(),
                    IsLicenseActive = isPackageUnlocked(product.Key)
                });
            }
            return list;
        }

To immediately check if our user has already purchased the item, we are getting a Boolean for it. While we are getting the data from the store, we are using this to fill our IAP class with the desired value (see IsLicenseActive property in the IAP item above).

        public bool isPackageUnlocked(string productKey)
        {
            var licenseInformation = CurrentApp.LicenseInformation;

            if (licenseInformation.ProductLicenses[productKey].IsActive)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

Now we have already all data that we need to display all IAP in our app. The usage is fairly simple:

var iapHelper = new IAPHelper();
var iapList = await iapHelper.GetAllIAP();

You can now bind the iapList to a ListBox (or your proper control/view). Next thing we are creating is our helper that performs the purchase action and returns a result string to display in a message to the user in our IAPHelper class:

        public async Task<string> unlockPackage(string productKey, string productName)
        {
            var licenseInformation = CurrentApp.LicenseInformation;

            string response = string.Empty;

            if (!licenseInformation.ProductLicenses[productKey].IsActive)
            {
                try
                {
                    //opening the store to display the purchase page
                    await CurrentApp.RequestProductPurchaseAsync(productKey);

                    //getting the result after returning into app
                    var isUnlocked = isPackageUnlocked(productKey);

                    if (isUnlocked == true)
                    {
                        response = string.Format("You succesfully unlocked {0}.", productName);  
                    }
                    else
                    {
                        response = string.Format("There was an error while trying to unlock {0}. Please try again.", productName);
                    }
                }
                catch (Exception)
                {
                    response = string.Format("There was an error while trying to unlock {0}. Please try again.", productName);
                }
            }
            else
            {
                response = string.Format( "You already unlocked {0}", productName);
            }

            return response;
        }

You may of course vary the messages that are displayed to the user to your favor.

The usage of this Task is also pretty straight forward:

var iapHelper = new IAPHelper();
string message = await iapHelper.unlockPackage(((IAPHelper.IAP)IAPListBox.SelectedItem).Key, ((IAPHelper.IAP)IAPListBox.SelectedItem).Name);

After that, we need to refresh the LicenseInformation by using GetAllIAP() again to refresh the iapList and of course our ListBox.

My goal was to save the LicenseInformation of my IAP for a limited time so the user is protected for future outages (or situations where no network connection is available). That’s why we need to add another Task to our IAPHelper class:

        public async Task<string> SerializedCurrentIAPList(List<IAP> iaplist, DateTime lastchecked)
        {
            string json = string.Empty;

            IAPToSave listToSave = new IAPToSave() { IAPListToSave = iaplist, date = lastchecked };

            if (iaplist.Count != 0)
            {
                json = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(listToSave));
            }
            return json;
        }

As you can see, now is the point where we need the second class I mentioned in the beginning. It has one property for the List<IAP> and a DateTime property that we are saving. I am serializing the whole class to a JSON string. This way, we are able to save it as a string in our application’s storage.

The usage of this Task is as simple as the former ones:

var savedIAPList = await iapHelper.SerializedCurrentIAPList(iapList, DateTime.Now);

The last thing we need to create is an object that helps us indicating if a refresh of the list is needed or not. Like I said, I want to do this action time based, so here is my way to get this value:

        public bool isReloadNeeded(DateTime lastchecked, TimeSpan desiredtimespan)
        {
            bool reloadNeeded = false;

            var now = DateTime.Now;

            TimeSpan ts_lastchecked = now - lastchecked;

            if (ts_lastchecked > desiredtimespan)
            {
                reloadNeeded = true;
            }

            return reloadNeeded;
        }

This method just checks if the desired TimeSpan has passed already and returns the matching Boolean value. The usage of this is likewise pretty simple:

var savedlist = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject<IAPHelper.IAPToSave>(App.SettingsStore.savedIAPList));

if (iapHelper.isReloadNeeded(savedlist.date, new TimeSpan(96, 0, 0)))
{
   //reload the list and perform your actions
}
else
{
   //use savedlist.IAPListToSave and perform your actions 
}

This way, we are able to make sure that all IAPs are available for a minimum of time and protect our users against store outages.

For your convenience, you can download the whole class right here. Just replace NAMESPACE with yours and you are good to go.

Note: I know that this approach does not follow the recommended way of Microsoft. It is up to us to deal with bad reviews if something on the store part is not working. This is my approach to avoid negative reviews because of store outages (at least for a limited time). However, like always, I hope this post is helpful for some of you.

Happy coding!

Posted by msicc in Dev Stories, wpdev, 0 comments

How to work with the user’s music library on Windows Phone

wp_ss_20131111_0002b

I am currently exploring a lot of APIs that I never used before  in my Windows Phone apps as I am adding more features to my NFC Toolkit.

Like I always do, I create sample applications to explore what is possible and then integrate them into my main app.

One of those APIs is the MediaLibrary class on Windows Phone. You might think: there are tons of examples out there, why another post? Well, I agree, there are a lot of samples, but I want to cover a whole scenario.

In my sample, I am getting a list of all Albums stored in Library, start them playing, and display the current playing song as well as handle state managements of the playing song.

First, you will need to add the capabilities ID_CAP_MEDIALIB_AUDIO and ID_CAP_MEDIALIB_PLAYBACK to your app. If you will not do that, every call against the APIs will end up with an NotAuthorizedException.

For any access to the MediaLibrary and the MediaPlayer classes we are using the Namespace “Microsoft.Xna.Framework.Media”. Here our trouble begins already.

Xna is Microsoft’s framework to create games on Windows Phone 7.  As Windows Phone 8 supports also native code, this is mainly used in 7 games. That’s why you might run in some TargetInvocationExceptions while you debug apps that use them.

To avoid this, we need to add a Framework Dispatcher that simulates a game loop for us. Add the following method to your App.xaml.cs:

        private void StartGameLoop()
        {
            GameTimer gameTimer = new GameTimer();
            gameTimer.UpdateInterval = TimeSpan.FromMilliseconds(33);

            gameTimer.Update += delegate
            {
                try
                {
                    FrameworkDispatcher.Update();
                }
                catch
                { }
            };

            gameTimer.Start();

            FrameworkDispatcher.Update();
        }

We are starting a new GameTimer and delgate it to our UI using the FrameworkDispatcher.Update() method. By adding it to App.xaml.cs and calling this method in Lauching and Activated event of our app, we have it running through our whole app and are done with this.

There are several methods to this, I found this the most easy version. I would pay credits, but don’t remember where I saw this – sorry.

Before we came to our first call against the MediaLibrary, we need to add a class for our List<T> or ObservableCollection<T>. I don’t know if this is the best practice in this case, but it made working with the List of Albums very easy for me:

        public class AlbumFromStorage
        {
            public string AlbumName {get; set;}

            public string AlbumArtist {get; set;}

            public WriteableBitmap AlbumCover {get; set;}

            public SongCollection AlbumSongs { get; set; }

        }

To use this class, just add a new List<T>/ObservableCollection<T> to the Page class. Do the same for a MediaLibrary object and an AlbumCollection object:

public ObservableCollection<AlbumFromStorage> AlbumsList = new ObservableCollection<AlbumFromStorage>();
public MediaLibrary lib = new MediaLibrary();
public AlbumCollection albumslist;

Now we are prepared for fetching all local stored albums. Add the following code to your corresponding method:

            albumslist = lib.Albums;

            if (albumslist.Count != 0)
            {
                foreach (var item in albumslist)
                {
                    AlbumsList.Add(new AlbumFromStorage()
                    {
                        AlbumArtist = item.Artist.ToString(),
                        AlbumName = item.Name,
                        AlbumCover = PictureDecoder.DecodeJpeg(item.GetThumbnail()),
                        AlbumSongs = item.Songs
                    });
                }

                MusicAlbumListBox.ItemsSource = AlbumsList;
            }
            else
            {
                await MessageBox.Show("It seems you have not stored any music on your phone.", "Sorry :(", MessageBoxButton.OK);
            }

Let me explain the code. First, we are using our AlbumCollection object to asign the MediaLibrary.Albums property. This will give us a collection of all albums. Then we need to check first, if the count in the collection is not 0 (it will throw ugly exceptions if a user doesn’t have any music stored if you won’t to this).

Then we add these albums to our ObservableCollection<AlbumFromStorage> picking the interesting properties of each album for us.

As the thumbnail for the album cover is a Stream, we need to use a WriteableBitmap for calling the GetThumbnail() method. The last step adds our ObservableCollection<AlbumFromStorage> as ItemSource to our ListBox.

This will be the result (based on my current albums list):

wp_ss_20131111_0002

Now all we need to do is to make a tapped album playing with Windows Phone’s media Player.  Add the following code to the Listbox ItemTap Event:

             if (Microsoft.Xna.Framework.Media.MediaPlayer.State != MediaState.Playing)
             {
                 //to delete the recent song (if there is any), just add this
                 MediaPlayer.Stop();

                 var selectedItem = this.MusicAlbumListBox.SelectedItem as AlbumFromStorage;

                 // play the SongCollection of the selected Album
                 MediaPlayer.Play(selectedItem.AlbumSongs);
             }
             else if (Microsoft.Xna.Framework.Media.MediaPlayer.State == MediaState.Playing)
             {
                 MessageBox.Show("You are already playing music. Please stop the music first.");

                 //your own handling could be different here, like asking the user for the desired action and perform  it then

             }

As you can see, I use the MediaPlayer.State property to get the album playing. The album is a SongCollection that holds all songs of the album. I recommend you to stop the last played song (if there is any) first with the MediaPlayer.Stop() method before start playing the first album song with the MediaPlayer.Play() method. Otherwise, it may happen that the user hears a second from the old song.

Very important: you must handle the case that the user has already music playing. If not, your app is likely to not pass certification.

After we started playing the music, we naturally want to display the current song.

To achieve this, we need to add two events to our page constructor: MediaPlayer.ActiveSongChanged and MediaPlayer.MediaStateChanged.

Within the MediaPlayer_MediaStateChanged event, add the following code:

            if (MediaPlayer.State == MediaState.Playing)
            {
                var activeSong = MediaPlayer.Queue.ActiveSong;
                Dispatcher.BeginInvoke(() =>
                {
                    MusicTileTitleBlock.Text = string.Format("playing:\n{0}\n{1}", activeSong.Name, activeSong.Artist);

                });

            }
            else if (MediaPlayer.State == MediaState.Paused)
            {
                var activeSong = MediaPlayer.Queue.ActiveSong;
                Dispatcher.BeginInvoke(() =>
                {
                    MusicTitleBlock.Text = string.Format("paused:\n{0}\n{1}", activeSong.Name, activeSong.Artist);                    
                });
            }
            else if (MediaPlayer.State == MediaState.Stopped)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    MusicTitleBlock.Text = "music stopped"; 
                 });
            }

This way, we use the MediaState to display the the current state as well as the title and artist. As we are updating the UI thread, as Dispatcher is used to update the Text.

To change the title and the artist of the current playing song, use this code within the MediaPlayer_ActiveSongChanged event:

            var activeSong = MediaPlayer.Queue.ActiveSong;
            Dispatcher.BeginInvoke(() =>
            {
                MusicTileTitleBlock.Text = string.Format("{0}\n{1}", activeSong.Name, activeSong.Artist);

            });

If you want to display also the album image, you will need to cache the image from the ItemTap event before, which would work fine with albums. If you choose Playlists instead of Albums, this will not work out well as you will not be able to get the image from MediaPlayer.Queue.ActiveSong.

I did a lot of research to get this feature(s) working the way they should. I took me several hours to figure everything out exactly, and I hope this post helps some of you out there to save some time on this.

With this post, you will be able to generate the whole experience your users deserve from the beginning to the end.

Until the next post, happy coding!

Posted by msicc, 1 comment
WPDEV: 2 tools that make localization of your Windows Phone apps easy

WPDEV: 2 tools that make localization of your Windows Phone apps easy

Today I want to show you two small tools that will help you to make localizing your apps easier.

 

Localizing in-app strings

The first tool I want you to know about is a tool called “AppTranslator”, made by Xda-Member singularity0821.

To provide the language settings, you need to name the strings in your app. I recommend to use format “x:name”, as sometimes without the “x:” your strings will not be accessible. Then you have to create a .resx file for your “neutral” language. You can find a good tutorial here at MSDN.

Once you have done this, you have to translate all strings and put them in a separate .resx file. Doing this manually in Visual Studio can really be an awful job. This is where the “AppTranslator” comes into the game.

apptranslator_1

As you can see it has a very clean UI. Everything you now have to do is to load your .resx file into the app and start to translate your app really fast:

apptranslator_2

You can save your work at every point, in the end you will get a ready to paste in .resx file.

You can download the tool here at xda.

 

Localizing app title

Ok, now you have localized your app content. But the app title will remain the one that you set in you “neutral language”.

To localize your app title, you have to generate resource-only DLLs. This could be very difficult if you are developing your apps with the VS 2010 Express. You simply can´t do it. An overview of how to do it manually and an explanation can be found here at MSDN.

No need to scream now, as also for this exists a tool from Patrick Getzmann, a German MVP.

AppTitleLocalizer

The tools uses Bing to translate your app title. You can edit all the strings also manually, if you want. Once you´re done, just hit “Save DLLs” and you are ready to integrate them into  your app.

The tool can be downloaded here.

I hope you will enjoy the tools as much as I do.

Posted by msicc in Dev Stories, Windows Phone, wpdev, 3 comments

I learn to tie my shoes – now available on Windows Phone (deal inside)

In January 2011 Internet Security specialist AVG released a study. This study tells us that nowadays children get in touch with technical gadgets much earlier than in the past, while they are not able to manage everyday things like tying their shoes.

The study substantiates this also with figures: around 19% of the 2-5 year old children are able to use smartphone apps, while only 9% know  how to tie their shoes.

As father of two kids, I decided to use the abilities of the little ones, and do something against that alarmingly low now number of kids, who know how to tie shoes.

I hope this app helps you and your children to learn tying of shoes very quick, easy and with fun.

The app provides following features:

  • two methods of tying shoes
  • controllable animation that shows tying
  • step by step guide
  • rhymes
  • theme selection (currently standard, boys, girls)
  • German and English language

The app will be available at the price of 99 cent. Like all my other apps, it has of course a trial version.

Trial version provides:

  • the first five steps both in animation and the guide
  • one of four rhymes
  • standard theme

What is coming next?

  • more languages (coming with the next update: Italian, Spanish, Dutch, Russian)
  • more themes
  • themed tiles to pin to start screen

To celebrate the launch of this app, I will start a “Marketplace Roulette”.

Currently, the app is available for free only  via this marketplace link.  I will change the pricing at a suitable moment within the next few days  to the above mentioned 99 cents and make it publically available. Until this moment, you can download it for free only via this link.

Finally, here are some screenshots from the app:

step10_ENGthemes_ENG

If you want to learn more about the app, here is a review on 1800PocketPC.com (written by Saijo George).

Posted by msicc in my apps, 0 comments

Microsoft releases “Experience it!” app in Germany

Screen Capture (86)

Today Microsoft Germany launched a small little app called “Erlebe es!” (experience it) for German Windows Phone users. The app offers similar content as the “Windows Phone Insider” app we already know, except the wallpapers and ringtones.

The app shows the latest news on Windows Phone for customers, as well as their “apps of the week” and “games of the week”.

You can read a short description about the every of the above categories, and apps and games can be downloaded directly to your Windows Phone.

wp-germany-experience-it

Only thing I was missing is the ability to share articles from the app via the integrated social network. I am really wondering about this, as it is really more than easy to integrate this function in your app with a few lines of code. Hopefully Microsoft will bring this functionality with a future update.

The app supports toast notification as well as a live-tile, both of which will be updated once a new article get released.

Posted by msicc in App Reviews, Windows Phone, 0 comments
Help Microsoft to improve voice control on your Xbox

Help Microsoft to improve voice control on your Xbox

WP_000478

Yesterday Microsoft released another Xbox app. It seems this app has been launched worldwide.

The app is named “Voice Studio”, and its goal is to improve the voice recognition and control of our Xbox.

Microsoft is rewarding you

Nice: Microsoft is rewarding you for your help with some Game Points. Check the achievements below:

Unbenannt

A walk through the app:

Before we are starting our little tour, I have to say the text in the screens is German (as my Xbox´s default language is German). I will explain all screens to you, so please don’t mind this. First I want to show you the  startup screen:

WP_000479

After loading has finished, you have to choose between a new or an existing profile. If you (of course on the first start) make a new profile, you have to declare some details about your person:

WP_000480

The name of the player cannot be changed. This is a good move, as it keeps the results anonymous. You have to declare: age, gender, country, state and your own language. Second step is to tell the app something about the room: WP_000481

You have to declare: type of speakers, size of the room, which kind of room (in my case it is the living room) an which kind of flooring you have. Now your Xbox will do some sound tests based on the settings you made. Once this is done (about one minute), you will be able to choose one of the 8 text sets:

WP_000482

After choosing a category, Xbox tells you where your have to go to in your room to speak the test. During the whole test there are some background sounds. The app is now showing you some sentences and words you have to speak:

WP_000488

This sentence means: “crabs can achieve an age of three up to twelve years.” The red lights on the side are signalizing you, that your speech is recognized by the app. Once you finished all sets, your track will be saved. This takes some time:

WP_000490

Once the saving is done, your track will be uploaded to a Microsoft server:

WP_000491

Depending on you internet connection, this may take several time.

Now it is your turn!

The more users are helping with this little app, the more improvements can be done by Microsoft. So download the app, and help Microsoft by only speaking with your Xbox!

Posted by msicc in Xbox, 0 comments

Poll: has this WindowsPhone app too much tiles?

Today I want to ask for feedback for the current state of my app.

I am really a Metro-addicted, and I love to use tiles in my app whenever it is possible.

But for this I want to ask you: has it to much tiles?

Check the video here:

Please choose you answer bellow:

 

Please leave also a comment where you would change, it that is your vote.

Posted by msicc in my apps, Windows Phone, 2 comments