wpdev

How to update a live tile in a background agent with web data on Windows Phone

scheduledtaskWP

In one of my recent projects, I needed to update the live tile of the app via a background agent with data from a WordPress based web site. I did what I always do when implementing a feature I never used before: researching.

I found tons of example on how to update the live tile periodically, but non of them told me how I can use the data from the web site or where I need to put it in.

In the end, it was Jay Bennet, developer of the fantatsic WPcentral Windows Phone app, who gave me the last hint I needed – where do I start the request for the data I need. Thanks to him for that!

Ok, but let’s start in the beginning. When it comes to web based services, you first need a class (or ViewModel) that can hold your data you receive from your service. I explained that already pretty well here. No matter if you are running your request within your app project or in a PCL, it pretty much always works like this.

After stripping of our class out of the JSON string, we are now able to create our request as well as our Background Agent.

The first thing you need to do is to add a Windows Phone Scheduled Task Agent. Create a new project within your app and choose the project type mentioned before. Then, in your main project, add it as a reference (right click on References/Add Reference/Solution => select your background agent project there. That’s it.

No go to your ‘ScheduledAgent.cs’ file and open it. You will find this code in there:

protected override void OnInvoke(ScheduledTask task)
{
  //TODO: Add code to perform your task in background

  NotifyComplete();
}

And thanks to Jay, I know that this is where all the action (not only updating the tile like in all samples I found) happens. This may sound very trivial for those of you who have experience with that, but if you’re new to it, it may hold you back a bit. However, there are a few points you’ll need to take care of:

    • you only have 25 seconds to perform all action here
    • your task will run every 30 minutes, no way to change that
    • scheduled tasks need to be restarted within 14 days after the current start
    • Battery saver and the OS/the user can deactivate the agent
    • there is a long list of what you are not able to do in here (check MSDN)
    • there are memory limits (check MSDN)

all action needs to be finished before NotifyComplete() is called

Based on this information, I created my task as following:

        protected async override void OnInvoke(ScheduledTask task)
        {
        //performing an async request to get the JSON data string        
            PostsFetcher postfetcher = new PostsFetcher();
            Constants.latestPostsForLiveTileFromWordPressDotComResultString = await postfetcher.GetLatestPostFromWordPressDotComForLiveTileOnPhone();

        //deserialize all data
            var lifetileBaseData = JsonConvert.DeserializeObject<json_data_class_Posts.Posts>(Constants.latestPostsForLiveTileFromWordPressDotComResultString);

            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
        //using Telerik's LiveTileHelper here
                Uri launchUri = new Uri("Mainpage.xaml", UriKind.Relative);
                RadFlipTileData fliptileData = new RadFlipTileData();
                fliptileData.BackContent = lifetileBaseData.posts[0].title;
                fliptileData.WideBackContent = lifetileBaseData.posts[0].title;
                fliptileData.BackTitle = string.Format("{0} {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString());
                fliptileData.Title = "LiveTileTitle";               

                if (lifetileBaseData.posts[0].featured_image != string.Empty)
                {
                    fliptileData.BackgroundImage = new Uri(lifetileBaseData.posts[0].featured_image, UriKind.RelativeOrAbsolute);
                    fliptileData.WideBackgroundImage = new Uri(lifetileBaseData.posts[0].featured_image, UriKind.RelativeOrAbsolute);
                    fliptileData.BackBackgroundImage = new Uri("Images/BackBackground.png", UriKind.RelativeOrAbsolute);
                    fliptileData.WideBackBackgroundImage = new Uri("Images/WideBackBackground.png", UriKind.RelativeOrAbsolute);
                }
                else
                {
                    fliptileData.BackgroundImage = new Uri("Images/PlaceholderBackgroundImage.png", UriKind.RelativeOrAbsolute);
                    fliptileData.WideBackgroundImage = new Uri("Images/PlaceholderWideBackgroundImage.png", UriKind.RelativeOrAbsolute);
                    fliptileData.BackBackgroundImage = new Uri("Images/BackBackground.png", UriKind.RelativeOrAbsolute);
                    fliptileData.WideBackBackgroundImage = new Uri("Images/WideBackBackground.png", UriKind.RelativeOrAbsolute);
                }

                foreach (ShellTile tile in ShellTile.ActiveTiles)
                {
                    LiveTileHelper.UpdateTile(tile, fliptileData);
                }
            });

            NotifyComplete();
        }

As I fetch different data from the site, I create a class that holds all request methods. In those methods, I just created an HttpClient that downloads the desired Json string into my app. I take only the first post in the case above, to make the live tile updating also on slow internet connections within the 25 seconds and to not reach any memory limit. In the end, I use Telerik’s LiveTileHelper to create a FlipTile with image and text from the site (the image will be downloaded automatically).

That’s all we need to to in the Scheduled Task Agent. Now we need to implement the agent into our app project.

First thing we should implement is a switch where the user can turn our agent on and off. I used a ToggleSwitch for that, saving the isChecked state as a Boolean to the IsolatedStorage of my app.

Knowing I need to restart the background agent after some time, I implemented the agent handling in App.xaml.cs. This way, I need to write less code as I tend to use separate settings pages. The only thing you need to think of is to set up all objects as static and public.

First, we need to declare a PeriodicTask as well as a name for it:

public static PeriodicTask LiveTileUpdaterPeriodicTask; 
public static string LiveTileUpdaterPeriodicTaskNameString = "LiveTileUpdaterPeriodicTaskAgent";

Now we need to generate a method that handles everything for our background task:

       public static void StartLiveTileUpdaterPeriodicTaskAgent()
        {
        //declare the task and find the already running agent
            LiveTileUpdaterPeriodicTask = ScheduledActionService.Find(LiveTileUpdaterPeriodicTaskNameString) as PeriodicTask;

            if (LiveTileUpdaterPeriodicTask != null)
            {
        //separate method, because we need to stop the agent when the user switches the Toggle to 'Off'
                StopLiveTileUpdaterPeriodicTaskAgent();
        //contains:
        //try
                //{
                //  ScheduledActionService.Remove(App.LiveTileUpdaterPeriodicTaskNameString);
                //}
                //catch { }
            }

        //generate a new background task 
            LiveTileUpdaterPeriodicTask = new PeriodicTask(LiveTileUpdaterPeriodicTaskNameString);

        //provide a description. if not, your agent and your app may crash without even noticing you while debugging
            LiveTileUpdaterPeriodicTask.Description = "This background agent checks every 30 minutes if there is a new blog post.";

        //start the agent and error handling
            try
            {
                ScheduledActionService.Add(LiveTileUpdaterPeriodicTask);
            }
        catch (InvalidOperationException exception)
            {
        //user deactivated or blocked the agent in phone settings/background tasks. Ask him to re-activate or unblock it
                if (exception.Message.Contains("BNS Error: The action is disabled"))
                {
                    RadMessageBox.ShowAsync("it seems you deactivated our Background Agent for the Live Tiles. Please go to settings/background tasks to activate our app again.", "Whoops!", MessageBoxButtons.OK);
                }

        //the maximum of running background agents is reached. No further notification to the user required, as this is handled by the OS
                if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
                {
                    //changing the Boolean to false, because the OS does not allow any new taks
                    isLiveTileActivated = false;
                }
            }
            catch (SchedulerServiceException)
            {
                //if there is a problem with the service, changing the Boolean to false. 
        //feel free to inform the user about the exception and provide additional info
                isLiveTileActivated = false;
            }
        }

In Application.Launching() and in ToggleSwitch_Checked event, call this method. In ToggleSwitch_UnChecked event, call ‘StopLiveTileUpdaterPeriodicTaskAgent()’ instead to stop the agent.

Before we are now able to debug our agent, there are two things left. The first thing is to declare

#define DEBUG_AGENT

in the very first line of ‘App.xaml.cs’ as well as in ‘ScheduledAgent.cs’ before all using statements.

The second thing is adding an if-Debug command to our ‘StartLiveTileUpdaterPeriodicTaskAgent()’ and also to our ‘OnInvoke(ScheduledTask task)’ methods:

#if(DEBUG_AGENT)
 ScheduledActionService.LaunchForTest(LiveTileUpdaterPeriodicTaskNameString, TimeSpan.FromSeconds(60));
 #endif

Add this after adding the task to the SchedulerService in our agent starter and before ‘NotifyComplete()’ in ‘ScheduledAgent.cs’.

If you run the project now in Debug mode, your agent will be debugged and forced to run after 60 seconds. If you run the project in Release mode, Visual Studio will throw an ‘Access Denied’ error, so make sure you set it up correctly.

If you follow all steps above, you will be able to add a Live Tile updated via background agent very easily to your app.

As always, I hope this real world scenario will help some of you.

Until then, happy coding!

Posted by msicc in Archive, 7 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 in Archive, 1 comment

Add your app: List of uri associations for Windows Phone

While development of my NFC Toolkit, I came to the point where I needed to launch apps from my code.

On Windows Phone, this is only possible via custom uri association and needs to be implemented by the developer of an app.

If you want your app to be launchable from other apps, you need to implement a custom uri assocation like descriebed here in the MSDN Documentation.

Users are demanding often apps to be launched from other apps – it is not much work to do, so I recommend you are implementing those features into your app(s). Over time,  your app will be getting more recognition amongst users of other apps and improves the user experience a lot.

To make it easier for everyone of us, please add your app here: http://developer.nokia.com/Community/Wiki/URI_Association_Schemes_List

Let’s make this list a basic resocurce for everyone of us!

Until then, happy coding!

Posted by msicc in Archive, 3 comments

The very weird way of checking if Bluetooth or Location is enabled

BT_GPS_WP_Blog

As I am in constant development of new features for my NFC Toolkit, I came to the point where I needed to detect if Bluetooth and Location is enabled or not.

I searched about an hour across the internet, searched all well known WPDev sites as well as the MSDN Windows Phone documentation.

The solution is a very weird one.

As I change the opacitiy of an Image depending on the stauts (on/off), I created the following async Task to check:

private async Task GetBluetoothState()
 {
 PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";

            try
 {
 var peers = await PeerFinder.FindAllPeersAsync();

                Dispatcher.BeginInvoke(() =>
 {
 BluetoothTileImage.Opacity = 1;
 });
 }
 catch (Exception ex)
 {
 if ((uint)ex.HResult == 0x8007048F)
 {
 Dispatcher.BeginInvoke(() =>
 {
 BluetoothTileImage.Opacity = 0.5;
 });
 }
 }
 }

As you can see above, we are searching for already paired devices with the Proximity API of Windows Phone. If we don’t have any of our already paired devices reachable, and we don’t throw an exception with the HResult of “0x8007048F”, Bluetooth is on. If the exception is raised, Bluetooth is off.

In a very similar way we need to check if the location setting is on:

private async Task GetLocationServicesState()
 {
 Geolocator geolocator = new Geolocator();

try
 {
 Geoposition geoposition = await geolocator.GetGeopositionAsync(
 maximumAge: TimeSpan.FromMinutes(5),
 timeout: TimeSpan.FromSeconds(10)
 );

Dispatcher.BeginInvoke(() =>
 {
 LocationStatusTileImage.Opacity = 1;
 });

}
 catch (Exception ex)
 {
 if ((uint)ex.HResult == 0x80004004)
 {
 Dispatcher.BeginInvoke(() =>
 {
 LocationStatusTileImage.Opacity = 0.5;
 });
 }
 else
 {
 //tbd.
 }

}
}

For the location services, the HResult is “0x80004004”. We are trying to get the actual GeoLocation, and if the exception is thrown, location setting is off.

On Twitter, I got for the later one also another suggestion to detect if the location settings is enabled or not, by Kunal Chowdhury (=>follow him!):

geoLocator.LocationStatus == PositionStatus.Disabled;

This would work technically, but PositionStatus has 6 enumarations. Also, as stated here in the Nokia Developer Wiki, this can be a battery intese call (depends on the implementation). I leave it to you which one you want to use.

Back to the header of this post. Catching an exception to determine the Status of wireless connections just seems wrong to me. I know this is a working “solution” and we can use that. But it could have been better implemented (for example like the networking API).

I hope this post is helpful for some of you.

Until then, happy coding!

Posted by msicc in Archive, 0 comments

How to select an item of (Rad)ListPicker control via speech recognition

This one is a short follow up to my post from yesterday about speech recognition in Windows Phone 8 apps.

I made the first steps with speech recognition in the last few  days with speech recognition, coming to the point where I had to select Items from a (Rad)ListPicker control (tried both, the Windows Phone Toolkit one as well as the Telerik one).

I was then realizing that calling the SelectedItem or the SelectedIndex does not work. By my app’s design the ListPicker has the IsExpanded property set to true, so there was one problem: in this state, it accepts only touch input.

Today I found a quick solution for this problem. If you rely on the input of the ListPicker control, just make sure that its IsExpanded state is false. You then will be able to set the SelectedItem or the SelectedIndex via code.

As always, I hope this will be helpful for some of you.

Happy coding!

Posted by msicc in Archive, 0 comments

Make your app listening to the user’s voice

speech_recognition_WPLogo

In one of my recent projects, I added speech recognition to start the app as well as for using the app. This blog post gives you a short overview on what’s possible and how to do it.

How to start your app with certain conditions:

Any app can be started by the simple voice command “open [AppName]” on Windows Phone. But what if we want to start certain functions when calling our app via speech? Then you’ll need a so called Voice Command Definition (VCD) file. This is a xml file that tells the OS to launch a certain function of your app.

Before we can start, please make sure you enabled ID_CAP_SPEECH_RECOGNITION, ID_CAP_MICROPHONE, and ID_CAP_NETWORKING capabilities in your app manifest.

Let’s have a look at a VCD with two different launch arguments:

<?xml version="1.0" encoding="utf-8"?>

<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
 <CommandSet xml:lang="en-US">
 <CommandPrefix>speech test app</CommandPrefix>
 <Example> speech test app</Example>

<Command Name="open MainPage">
 <Example> open the MainPage </Example>
 <ListenFor> open the MainPage </ListenFor>
 <ListenFor> bring me to Mainpage </ListenFor>
 <ListenFor> let me see my MainPage </ListenFor>
 <Feedback> loading Mainpage....</Feedback>
 <Navigate />
 </Command>

<Command Name="open SettingsPage">
 <Example> open the settings page</Example>
 <ListenFor>open settings</ListenFor>
 <ListenFor>bring me to settings page</ListenFor>
 <ListenFor>let me see my settings page</ListenFor>
 <Feedback>opening settings ...</Feedback>
 <Navigate />

</Command>

</CommandSet>
 </VoiceCommands>

As you can see, the syntax is pretty easy to use. Here is some short explanation about the commands:

  • <CommandPrefix> is for telling the OS how to launch your app
  • <Command Name=”xxx”> is for telling the OS which launch parameter should be passed to your app
  • <ListenFor> defines which speech cases you want to allow to let the OS launch your app (pretty important point)
  • <Example> Text entered here is shown in TellMe’s speech Window and on the “What can I say?” page
  • <Feedback> this is the answer of TellMe to the user

The next part is to load the VCD file once the app starts. Therefore, you will need to add the VCD file in the App constructor. I created an async Task for that:

private async Task InitializeVoiceCommands()
 {
 await VoiceCommandService.InstallCommandSetsFromFileAsync(new Uri("ms-appx:///VoiceCommandDefinitions.xml"));
 }

It is recommended that you set “Copy to Output Directory” property of the VCD file to “Copy if newer”.

Now that we have implemented and loaded our VCD file, let’s have a look on how we can open our app based on the arguments. Based on that VCD file, our app gets key/value pairs of the launch arguments. The implementation is pretty easy in a few lines of code:

if (NavigationContext.QueryString.ContainsKey("voiceCommandName"))
 {
   string voiceCommandName = NavigationContext.QueryString["voiceCommandName"];
   switch (voiceCommandName)
    {
       case "open MainPage":
       //let the App launch normally
       //you can also pass other launcharguments via the VCD file that could launch other functions
       break;

       case "open SettingsPage":
       //let the App lauch immediately to the settings page
       NavigationService.Navigate(new Uri("/SettingsPage.xaml", UriKind.Relative));
       break;
     }
 }

And with this few lines we already added our app with individual voice commands to the speech function of the OS.

 

Using your app with in app voice commands:

We now learned how to start our app with certain conditions. However, this is not how we are using the speech recognition within our app.

There are several ways on how you can implement in app voice commands. I will show you two of them.

First of all, using the Windows button does not work in app. You will need to add a dedicated button to start the voice recognition.

Let’s start with a List<string> or string[] array, and launch the SpeechRecognizerUI:

            try
            {
                //initalize speech recognition
                SpeechRecognizerUI speech = new SpeechRecognizerUI();

                List<string> InAppCommandList = new List<string>
                {
                       "goto home",
                       "goto settings",
                        "set name",
                        "set age",
                        //add more to that list as you need
                };

                //load the List as a Grammar
                speech.Recognizer.Grammars.AddGrammarFromList("InAppCommandList", InAppCommandList);

                //show some examples what the user can say:
                speech.Settings.ExampleText = " goto home, goto settings, set name, set age ";

                //get the result
                SpeechRecognitionUIResult result = await speech.RecognizeWithUIAsync();

                //delegate the results
                switch (result.RecognitionResult.Text)
                {
                    case "goto home":
                        //your code here
                        break;
                    case "goto settings":
                        //your code here
                        break;
                    case "set name":
                        //your code here
                        break;
                    case "set age":
                        //your code here
                        break;
                }
            }
            catch (System.NullReferenceException)
            {
                //do something with the Exception
            }

 

As you can see, there are only a few steps needed:

  • initalize speech recognition
  • load the List<string>/string[] as a Grammar
  • get the result
  • delegate the results

You might have noticed that I wrapped the code into a try/catch block. I needed to do that as I often got a NullReferenceException on closing without voice input or also if no text was heard. This way, your app will not crash.

There is also another way to add a Grammar to the speech recognition engine: SRGS (Speech Recognition Grammar Specification), which is again a XML file that contains which input is accepted.

While I was working on this app, I noticed that it is pretty powerful – and complex. This is why I decided to mix both methods to get things done (you know, timelines and such). I will dive into that topic deeper and then write another blog post about it. But for now, I’ll show you a simple example.

In this case, I wanted the SpeechRecognizerUI to only accept numbers as input. This is how my SRGS file looks like:

<?xml version="1.0" encoding="utf-8" ?>

<grammar version="1.0" xml:lang="en-US" root="Command" 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="Command" scope="public">
 <item repeat="1-20">
 <ruleref uri="#Numbers"/>
 </item>
 </rule>

<rule id="Numbers">
 <one-of>
 <item >1</item>
 <item >2</item>
 <item >3</item>
 <item >4</item>
 <item >5</item>
 <item >6</item>
 <item >7</item>
 <item >8</item>
 <item >9</item>
 <item >0</item>
 </one-of>
 </rule>

</grammar>

If you add a SRGS file as to your project, the correct structure is already implemented. You only need to set the root to the first rule you want to be executed. In my case, I defined a rule with the id Command in a public scope (this way, you would also be able to call it from another Grammar).

The rule returns items that will occur minimum 1 time and maximum 20 times. Basically, this defines the range of the input length.

To make the SpeechRecognitionUI only accepting numbers, I defined another rule that contains a list of numbers. the <one-of> property defines here that any of the numbers is accepted. With <ruleref uri=”#Numbers”/> I am telling my app to accept any of the numbers as often as they occur until the count of 20.

Now let’s have a look on how to implement this Grammar into our app and connect it to our SpeechRecognizerUI:

 SpeechRecognizerUI speech = new SpeechRecognizerUI();

            //generate a Numberonly Input Scope based on a SRGS file
            //the ms-appx:/// prefix will not work here and return a FileNotFoundException!
            Uri NumberGrammarUriPath = new Uri("file://" + Windows.ApplicationModel.Package.Current.InstalledLocation.Path + @"/NumberOnlyGrammar.xml", UriKind.RelativeOrAbsolute);

            speech.Recognizer.Grammars.AddGrammarFromUri("NumberGrammarUriPath", NumberGrammarUriPath);

            SpeechRecognitionUIResult speechRecognitionResult = await speech.RecognizeWithUIAsync();

            if (speechRecognitionResult.ResultStatus == SpeechRecognitionUIStatus.Succeeded)
            {
                //using Regex to remove all whitespaces
                string NumberInputString = Regex.Replace(speechRecognitionResult.RecognitionResult.Text, @"\s+", "");
                // do somethin with the string
            }

We are again calling the SpeechRecognizerUI, but this time we are loading our XML formatted SRGS file as Grammar. Notice that loading the file only works with the way above. Using the “ms-appx:///” prefix will return a FileNotFoundException and crash your app.

Instead of AddGrammarFromList we are using AddGrammarFromUri to load the file.

By checking the SpeechRecognitionUIStatus, we are performing actions only if the recognition was succesful based on our SRGS Grammar. If you want to perform other actions on non-success status, you will be able to implement the following enumerations:

  • Succeeded (0)
  • Busy (1)
  • Cancelled (2)
  • Preempted (3)
  • PrivacyPolicyDeclined (4)

As you can see, basic speech recognition is fast to implement. As always, I hope this post is helpful for some of you.

I also recommend to read these pages on MSDN about speech for Windows Phone: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207021(v=vs.105).aspx

Happy coding everyone!

Posted by msicc in Archive, 1 comment

How to modify the Background of a Telerik RadListPicker Control

In one of my current projects, I needed to change the Background of the Popup on a Telerik RadListPicker control. While it took me some time, I want to share how to achieve that to make it easier for you.

First, you need to create a copy of the RadListPicker Template. You can use either Blend or Visual Studio 2012 to achieve this.

In Blend just go to the menu and choose Object -> Edit Style -> Edit a Copy. In Visual Studio, right click on your RadListPicker in the Designer Window and choose Edit Template -> Edit a Copy.

Now you will find a new Style within your Application.Resources in App.xaml.

To change the style you have to modify two parts, the PopupHeader and the Popup itself.

To change the Background of the PopupHeader search for telerikPrimitives:RadWindow x:Name=”Popup” . Under that, you will find a Grid.

In this Grid, you will need to set the Background to the desired Color or Brush you want to use:

<Grid Background="#FF0A0D38" telerik:RadTileAnimation.ContainerToAnimate="{Binding ., ElementName=PopupList}">

To change the Background of the List in you ListPicker, you will have to style the Background of the underlying RadDataBoundListBox Control:

<telerikPrimitives:RadDataBoundListBox x:Name="PopupList" CheckModeDeactivatedOnBackButton="False" DisplayMemberPath="{TemplateBinding DisplayMemberPath}" IsCheckModeActive="{Binding SelectionMode, Converter={StaticResource SelectionModeToBooleanConverter}, RelativeSource={RelativeSource TemplatedParent}}" telerik:InteractionEffectManager.IsInteractionEnabled="True" ItemContainerStyle="{TemplateBinding PopupItemStyle}" Grid.Row="1" Style="{TemplateBinding PopupStyle}">
   <telerikPrimitives:RadDataBoundListBox.Background>
      <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
          <GradientStop Color="#FF0A0D38" Offset="0"/>
          <GradientStop Color="#FF9FCFEC" Offset="1"/>
      </LinearGradientBrush>
   </telerikPrimitives:RadDataBoundListBox.Background>
</telerikPrimitives:RadDataBoundListBox>

As you can see, the I changed the Background to a GradientBrush to match the rest of the application.
The result looks like this:

wp_ss_20131021_0001

As always, I hope this will be helpful for some of you.

Happy coding!

Posted by msicc in Archive, 1 comment

How to save a List or a Collection on a NFC tag

 

WP8_NFC_PostLogo

As I am currently working again on my NFC app, I needed to save an ObservableCollection to a tag. My first attempts resulted in a heavily overlong string that I wasn’t able to save.

Anyways, after a short convo on Twitter, I went for the right way – serialize to JSON.

The first thing you’ll need for that is the JSON.NET library, which you can get here or via the NuGet package manager in Visual Studio.

After that, you will be able to save your List or ObservableCollection in a few easy steps.

One thing I need to recommend is to make the names in your class/viewmodel as short as possible. Here is my example:

public class ListItems
    {
        //ListItems
        public string i { get; set; }
        //isChecked
        public bool iC { get; set; }
    }

You will need every space you can get on your tag, so you really should go for a similar way like I did above.

After you are done with that, you only need one line of code to convert your List/Collection for writing on your tag:

var ListToSave = JsonConvert.SerializeObject(ItemsList);

Now you will be able to save it as a Text record or  whatever record type you need to save it to.

Deserializing the JSON string works also with only one line of code:

ItemsList = JsonConvert.DeserializeObject<ObservableCollection<ListItems>>(StringFromYourTag);

Then you set the ItemsSource of your ListBox to that (or whatever else the List/Collection is for).

I my case, I was able to save a Collection of 25 items to my tag (writable size 716 bytes) with having still about 200 bytes left in this way.

As always, I hope this will be helpful for some of you.

Happy coding!

Posted by msicc in Archive, 0 comments

Getting productive with WAMS: How to handle erroneous push channels

WAMS

As I wrote already in my former article ‘Getting productive with WAMS- about the mpns object (push data to the user’s Windows Phone)’, I needed to add some more detailed error handling to the mpns object on my Mobile Service.

There are two error codes that appear frequently: 404 (Not Found) and 412 (Precondition Failed).

The 404 error code

happens when the push channel gets invalid. Reasons for that can be uninstall or reinstall of the app, or also a hard reset of the users device. In this case, we are following the recommendation of Microsoft to stop sending push notifications via this channel.

There might be several ways, but I prefer to work with SQL queries.  This is how I delete those channels within error: function(error):

if (error.statusCode === 404)
{
 var sqlDelInvalidChannel = "DELETE from pushChannel WHERE id = " + channel.id;
 mssql.query(sqlDelInvalidChannel, {
 success: function(){
	console.log("deleted invalid push channel with id: " + channel.id);
	},
	error: function(err)
	 {
           console.log("there was a problem deleting push channel with id: " + channel.id + ", " + err)
         }
});

As you can see, this is a very simple approach to get rid of those invalid channels.

The 412 error code

needs some more advanced handling. Microsoft recommends to send the push notification as normal, but the code recommends a delay of 61 minutes to resend. Also, with some research on the web, I found out that often the 412 will turn into a 404 after those 61 minutes (at least I found a lot of developers stating this). This is why I went with a different approach. I am going to wait those 61 minutes, and do not send a push notification to those devices.

For that, I do a simple trick. I am saving the time the error shows up in my push channel table, as well as the  time after those 61 minutes. On top, I use a Boolean to determine if the channel is in the delay phase.

Here is the simple code for that, again within error: function(error):

if (error.statusCode === 412)
{
	var t = new Date();
	var tnow = t.getTime();
	var tnow61 = tnow + 3660000;

	var sqlSave412TimeStamp = "UPDATE pushChannel SET Found412Time=" +  tnow + ", EndOf412Hour=" + tnow61 + ", IsPushDelayed = 'true' WHERE id=" + channel.id;

	mssql.query(sqlSave412TimeStamp);
}

Now if my script runs the next time over this push channel, I need to check if the push channel is within the delay phase. Here’s the code:

if (channel.IsPushDelayed === true)
{
	var t = new Date();
	var tnow = t.getTime();
	var EndofHour = channel.EndOf412Hour;
	var tdelay = EndofHour - tnow;

	if (tdelay > 0)
	{
	 console.log("push delivery on id: " + channel.id + " is delayed for: " + (Math.floor(tdelay/1000/60)) + " minutes");
	}
	else if (tdelay < 0)
	{
	 var sqlDelete412TimeStamp = "UPDATE pushChannel SET Found412Time=0 , EndOf412Hour= 0, IsPushDelayed = 'false' WHERE id=" + channel.id;
	 mssql.query(sqlDelete412TimeStamp);
	}
}

As you can see, I am checking my Boolean that I added before. If it is still true, I am writing a log entry. If the time has passed already, I am resetting those time values to 0 respective the Boolean to false.

The script will now check if the push channel is still a 412 or turned in to a 404, and so everything starts over again.

Other error codes

There might be other error codes as well. I did not see any other than those two in my logs, but for the case there would be another, I simply added this code to report them:

else
{
 console.error("error in Toast Push Channel: " + channel.twitterScreenName, channel.id, error)
}

This way, you can easily handle push channel errors in your Mobile Service.

If you have other error codes in your logs, check this list from Microsoft to determine what you should do: http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff941100(v=vs.105).aspx#BKMK_PushNotificationServiceResponseCodes

Note: there might be better ways to handle those errors. If you are using such a way, feel free to leave a comment with your approach.

Otherwise, I hope this post will be helpful for some of you.

Happy coding!

Posted by msicc in Azure, Dev Stories, 0 comments

Use Telerik RadControls for WP? Then use RadDiagnostics to enable users to find bugs!

I know this is a little provocative title – that is my intention. And of course I will tell you why.

I am participating in several betas for Windows Phone apps. I know some of the developers from Twitter, and had several conversations  about bug finding and solving methods. In the end, we as developers have all one goal: a buttery smooth running app without any bugs.

Some of the betas I use are also using Telerik RadControls. They enable us developers to easily create awesome apps without writing the controls form the ground up. On Top, we are able to customize them for our needs with a bit of XAML manipulation.

One of these controls is RadDiagnostics. RadDiagnostics is catching all unhandled exceptions from your application. And believe me, there will be a ton of it – even if you handle a lot of them already.

I didn’t believe that, too. But then I ran the beta of my TweeCoMinder app for Windows Phone. I tested the app a lot before publishing my beta, including several scenarios like no network connection available, low battery, and so on. At this time, I stumbled over the RadDiagnostics Control in the documentation.
I immediately saw the advantages of using this control:

  • advanced error logging, including a great bunch of information like OS Version, device, network type, and more
  • the app won’t crash even on unhandled exceptions
  • the user feels more integrated in the development process
  • users tend to use the app in other ways than we developers think – and we can’t even get close to catch all those usage scenarios while testing alone
  • there are a lot of users that are really searching for bugs – which is both a good and a bad thing

Let me hook into the last point a bit deeper – as we are able to get the most from it. If users find bugs, they will get either annoyed and stop using our apps or they will talk about it. Let us make them talk about the problems to us, the developer! Like I mentioned above, the RadDiagnostics control makes this very easy for the user.

A MessageBox shows up where the user is asked to send us the report, which is done via email. This has two additional advantages: First, we are able to collect all kind of errors. An even bigger advantage: We are able tor respond directly to the user as we have their mail address. I learned a lot during the first beta versions of TweeCoMinder, be it how users use my app as well as from the coding part – and I was able to continuously improve my app.

Some of you might argue that you don’t want the user to see your code. Really, that is stupid. An average user does not even know what all those lines in of the exception mean. Only developers are able to understand what is going on. Where is the problem? That they see you have an exception at point x? Chances are very high, that they had the same exception at another point and needed them to iron out.

Personally, I don’t have a problem with the fact that the exception is readable for some beta tester/users. I made the experience that users love to give feedback – if you make it very easy for them. RadDiagnostics is a very easy way as it needs only three taps (ok => choose mail account => send button).

As this is a dev post, here is how easy it is to integrate it into your app:

  • Declare the RadDiagnostics in public partial class App : Application
    public RadDiagnostics diagnostics;
  • Initiate Telerik ApplicationUsageHelper in private void Application_Launching(object sender, LaunchingEventArgs e)
ApplicationUsageHelper.Init("0.9.5");
  • call RadDiagnostic in the App() constructor:
diagnostics = new RadDiagnostics();
 {
diagnostics.EmailTo = "yourmail@outlook.com";
diagnostics.EmailSubject = "Here is your email subject";
diagnostics.HandleUnhandledException = true;
diagnostics.Init();
 }

That’s all you need to get it working. A few line of codes that will give you so much input to improve your app, which will result in this message:

ReadDiagnosticsMSG

Once again, if you use RadControls for Windows Phone, then use RadDiagnostics to let users help you finding bugs. You will not get better and more helpful feedback other than this!

You can find the complete documentation of RadDiagnostics here: http://www.telerik.com/help/windows-phone/diagnostics-gettingstarted.html

Another great article that helps you to deeply understand how RadDiagnostics work is over at Kunal Chowdhury’s blog.

Feel free to discuss your sight below in comments. Until then, Happy coding!

Posted by msicc in Archive, 0 comments