What we have learnt during the development of Speak Reminder and Group Tiles

So it’s been a while since we published Group Tiles and Speak Reminder to the Windows Phone Store. In case you did not know, Group Tiles is an app to create header tiles on the Start Screen to separate your messy tiles into distinguishable parts, and Speak Reminder is an app leveraging the Voice commands functions of Windows Phone 8 to help you create quick reminders.

You can download the 2 by scanning or clicking on the 2 QR code below:

Group Tiles

Speak Reminder

 

We did get a significant number of users of those apps, around 30 thousands for Group Tiles and 3 thousands for Speak Reminder. That is great not just because of all the encouragement and opportunity of that user base, but our users also help us to identify so many small bugs that were not stated on the Windows Phone Dev Center.

Group Tiles

Ok I will start with this guy first. This was really a big success for us. First day, we have 16 downloads, rather in line with our previous apps on Windows Phone, but then second day, we have more than 600. We were so amazed by the number and then shocked on the day this app was featured on WMPowerUser, almost 3000 in a single day.

Unfortunately, we did not prepare for that “success”. Our host provider constantly complained us abusing the shared server and suspended our account. We then realized the problem in our telemetry service (yes, I build one for our app instead of using an existing service like flurry to get more control and also to learn more about those kinds of problems). Somehow it went crazy consuming all the CPU resources, even though only a simple insert command is execute with the entity framework.

Back at that time I was so naïve and write the very “simple” lines as below to insert an information log to a project:

info.Project = project;
project.Infoes.Add(info);
context.Infoes.Add(info);
context.SaveChanges();

What could go wrong anyway? The first 2 lines were for the association between the 2 entities. The third line were to add that new info entity to the database and the last were to save all changes. I then had to profile each line of my code (there some other processing as well) to find the culprit, and it turned out to be the second line was not only unnecessary but also very dangerous:

project.Infoes.Add(info);

Instead of just marking the association, this would query all the info records of this particular project (which is around 10,000 at that time) every time a new one was inserted (at a crazy rate of around 1 time per second). Removing that line and everything worked exactly as expected.

We then moved all the telemetry modules to Azure Web Sites and SQL Azure, and were very happy with what those 2 provided, including very useful monitoring information on the dashboard.

So there were also two other small bugs that was detected by our users, one are very easy to identify and the other are more difficult to identify and fix.

IOException & IsolatedStorageException

This one was so straight forward although I doubt not many apps check for that. The app simply could not save the tile images when there is not enough space on the phone, and it could not save any settings as well, so be careful of this case if you put something important into the isolated settings.

ArgumentException – XcpImports

This was the full stack of that exception:

at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
at MS.Internal.XcpImports.SetValue(IManagedPeerBase obj, DependencyProperty property, DependencyObject doh)
at MS.Internal.XcpImports.SetValue(IManagedPeerBase doh, DependencyProperty property, Object obj)
at System.Windows.DependencyObject.SetObjectValueToCore(DependencyProperty dp, Object value)
at System.Windows.DependencyObject.SetEffectiveValue(DependencyProperty property, EffectiveValueEntry& newEntry, Object newValue)
at System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)
at System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value, Boolean allowReadOnlySet)
at Microsoft.Phone.Controls.PhoneApplicationFrame.System.Windows.Controls.IFrame.set_Content(Object )
at System.Windows.Navigation.NavigationService.CompleteNavigation(DependencyObject content, NavigationMode mode)
at System.Windows.Navigation.NavigationService.<>c__DisplayClass7.b__4()

There was not much information inside the exception to identify what had caused the crash. It happened in all our apps and we could not reproduce the problem at all.

I left it there for a while until I suddenly reproduced the crashes with the same exception: we navigated to a page inside the OnNavigatedTo function of another page, which sometimes caused both page to appear (one just overlay on the other), then the app would crash if the user press back button. The problem was slightly overcame by putting the navigation inside Loaded event handler instead, and now the crash rarely occurs.

Speak Reminder

We were very careful in implementing with the new speech feature of Windows Phone. There is a post here http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662934(v=vs.105).aspx stating how to handle speech error. However, they only handle the function call, which is definitely not enough.

There are 2 other places that you will have to wrap with try catch block. The first one is the SpeechRecognizer, SpeechRecognizerUI and SpeechSynthesizer constructors, and the second one is the function call to register the VCD file with the system. Below are the exceptions that we have met in Speak Reminder

Exception (Exception from HRESULT: 0x800455BC) – SpeechRecognizer, SpeechRecognizerUI, SpeechSynthesizer constructors

    at Windows.Phone.Speech.Recognition.SpeechRecognizerUI..ctor()

As the documentation on Dev Center, this error code means “The requested language is not supported.” And this will happen on a new phone (or sometimes after you reset the phone) when the speech is activated, a language is chosen, but the language pack is not actually downloaded and installed on the phone. The user will have to go to phone settings to choose another speech language and then switch back again to see the message prompt for installing the language pack.

ArgumentException (Value does not fall within the expected range.) – SpeechRecognizer, SpeechRecognizerUI, SpeechSynthesizer constructor

    at Windows.Phone.Speech.Recognition.SpeechRecognizerUI..ctor()

This one is rather strange and is not documented on Dev Center. This also happens on new phone; sometimes there is no selected speech language. The user just have to choose one and this should be ok.

FileNotFoundException (The system cannot find the file specified. (Exception from HRESULT: 0x80070002)) – InstallCommandSetsFromFileAsync

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

This one is very strange and I have not found the exact reason or solution for this. Would be very grateful if someone can tell me how to handle this case (except from silencing the error or just show a useless error message). I found something about missing XML files on some phones, but I am not too sure about that.

DirectoryNotFoundException (The system cannot find the path specified. (Exception from HRESULT: 0x80070003)) – InstallCommandSetsFromFileAsync

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

This one is the same as the above.

Conclusion

It is a great opportunity for me to improve my skills when there is that large number of users, and I am very happy about that. On other lesson that I have learnt about Windows Phone Dev Center is that the automatic crash reports of the system usually lack of information (for example inner exception or stack trace), so you should try to report it yourself.

One thought to “What we have learnt during the development of Speak Reminder and Group Tiles”

  1. Regarding FileNotFoundException: I encountered this error and it seems that it appears when a phone doesn’t have the required language pack downloaded (Settings -> speech -> Speech language). Downloading the selected speech package solves this problem.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.