Saturday, March 30, 2013

Where to get icons for your app?

So, you need some icons for use in your app.

If you just need icons for the application bar buttons, then start with the ones that come with the SDK. You'll find them at "C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons\Dark\" and these are also the ones that Blend can add for you.


If you need more then there are a numberof free resources available:

Metro Studio 2 (By SyncFusion)

It's a downloadable app that comes with 1700 FREE icon templates that can be sized and modified as required. You can see all the icons at http://www.syncfusion.com/downloads/IconPackagePopup/Application


The Noun Project

Loads and loads of icons that you can search online. Download what you want in vector formats. Most are creative commons licensed and/or very cheap to license. (I've never paid more than $1.99 for an icon there.)

Modern UI Icons

A collection of almost 1000 free icons. They're availabel sized for the application bar and in vector formats.

iconmonstr

1300+ icons thast are free to use in personal and commercial projects. They're also helpfully categorized to make it easy to find what you're after.



There are also other sources and you could always make your own or commission an icon if you needed something special.

As an extrs tip, it's usually best, as far as possible, to get all your icons for an app from the same source. This helps make it look like they all belong together. If you have small/subtle differences between icons (e.g. differing line weights or the radius on rounded corners) then some people will spot this and will think it looks bad. Remember, the little details matter.






Thursday, March 28, 2013

Microsoft's advice about Panoramas is wrong!



The advice Microsoft's designers will tell you (23:30 into the video) about a page hosting a Panorama control is that the page should not also include the System Tray.
This is wrong!
Let me tell you why.


Consider this scenario:
A person launches your app and upon starting it attempts to load the latest data from a web server or other external source. - Hopefully you'll agree that so far this is a reasonable and common scenario.
After a few seconds no data is displayed and the app still indicates that it is "Loading...". - Again, a common occurrence.
Now what?
Well, the person wonders if the delay is due to not having a connection or maybe they've only got 1 bar on a 2G network. - I hope you still think this is a not unreasonable scenario.
So, having wondered about connectivity, what does our person do?
Well, they swipe down from the top of the screen to reveal the network connectivity indicators that are included in the System Tray.

And it's at this step that we reach the crux of my argument.

If the page includes the System Tray the person will be able to see the state of their connectivity. If they have a connection they'll probably wait a little longer. If not they can, hopefully, do something about it.

But if the page doesn't include the System Tray what can they do?
They can do 1 of two things.
1. They can wait longer, but with the uncertainty of not knowing if the connection is there and if they'll ever get a response (at least until the connection times out.)
2. They can leave the app and check connectivity there.

If 1, you're forcing the person using your app into a situation of uncertainty with your app that can't be a good thing. Uncertainty in what your app will do, or when, is not a feeling you want to instil in people.

If 2, you're forcing people to leave your app when they want to use it. You're also increasing the likelihood that they won't come back. I'd be amazed if you want the people who have downloaded and installed your app to not be using it when they have wanted to.

My advice:
Include the System Tray on any page that has content that comes from a remote source.

Microsoft doesn’t even follow their own advice!
Checking on the WP8.0 device in my pocket I can see that:
While the store, music and video hub, games hub, photos hub and wallet don't include the system tray, the People hub and the Office hub DO include the System Tray

The exception when this isn't true.
My reasoning above is based on a Panorama with dynamic content that is obtained from an external source. Obviously there are apps which use a Panorama control but don't use external content. (I've even written some.) In this scenario there is, potentially, very little value to the including the System Tray and so there may be an argument for not including it.

Yes there is potentially an argument for including a System Tray even if the Panorama uses entirely local content so that it's possible to see things like the clock and battery status. Include it at your discretion in these scenarios.

Disclaimer. Yes the title of this post is quite broad-brush and I'm only talking about a potentially minor issue here. I understand that but small details matter.



tl;dr: DO include the System Tray on Panoramas. Even though Microsoft tell you not to.




Friday, March 22, 2013

10 Tips for designing your mobile APIs

It's common for a mobile application to need to communicate with a web/cloud based service. At its simplest this will be just to retrieve data but it could also include sending data and user authorisation and management.
If you have to build the API that your application will use the following tips may be useful:

1. Version your API (from the very beginning)
At some point in the future the API will need to change. This may be to add, remove or change functionality. When this happens you may have to stop the use of part of the API or allow the consuming application to be clear about which behaviour, and type of response, it is expecting to be returned.
Your API is like a contract between your backend and the apps that use it. Without proper versioning you are risking the situation where one party can change the contract without the other even knowing. Having support for multiple versions of the API you can also continue to support users of your application who haven't been able to upgrade to the latest version of your app that uses the latest version of the app that knows all about the latest API changes.
Without versioning of the API you make it much easier to, inadvertently, stop applications working when changes are made to the API.

2. Don't return more data than you need to
The amount of data that is sent between the application and the server will, to some extent, impact the time it takes for the request to be made and the response to be received. Not only does this impact the amount of time a person spends staring at a loading animation, it may also impact the amount they spend on data charges.

3. Compress the data that is sent and received
In addition to not returning more data than is necessary, by compressing the data that is sent you can experience further benefits in speed and cost of data transfer.

4. Don't require unnecessary steps/requests
It's very common for APIs to be designed to provide separate discrete steps that reflect how the service is intended to be used. Quite often though, such discrete steps aren't the most efficient way of implementing a mobile application.
Let's take a simple example. Imagine the situation where a user has to log in (provide valid credentials) before being able to request data. It would be perfectly reasonable and understandable to think of this as two separate steps:
Step 1: The credentials are provided and, if valid, the API responds with a session token.
Step 2: The session token is passed when the request is made for the data.
That's probably unnecessary though. It would be much better if a single request could be made, passing credentials and the details of the data that is desired and, assuming valid credentials, both the data and a session token, for use in future requests, are returned.
The benefit of this is that fewer requests are faster and cheaper for the person using the app and may also (depending on how it's implemented) lead to simpler application code, which can lower development and support costs.
This may mean that you have to build the API to support both types of usage. This may lead to higher costs to support, document and maintain. But, if you're building your API just (or primarily) for your own use this may be more acceptable.

5. Combine requests (and responses)
In addition to multiple requests being made as part of an authentication or app start up process, it can also be common for multiple requests to be made to retrieve all the data for a single page or view in an application. Making a single request for all the data that a page requires, will be faster and cheaper than making multiple calls. Both factors that will be seen positively by the people using the application.
Again, this can also make the application code simpler. Especially with regard to handling the situations where multiple calls are made and not all of them are successful. If it becomes an all or nothing scenario the exception cases become much simpler.

6. Consider security from the beginning
Security is a massive and potentially complicated subject. This makes it particularly difficult to add on in a hurry in response to a security issue.
Remember to consider: securing data in transit; securing your data at rest; inappropriate or unauthorised use of the API; and potentially malicious or unexpected data having unintended consequences.

7. Plan and implement your caching policy carefully
If the data your API returns doesn't change very often be sure to implement appropriate caching strategies. This could involve keeping data in memory, rather than repeatedly reading it from disk. This should almost certainly involve the caching capabilities that are part of HTTP (assuming that that's the protocol you're communicating over).


If you do implement caching on your server, be sure to offer a way to forcibly invalidate it though.
Also make sure that you implement appropriate caching in the client application that consumes the API. You save time and resources if you can make a call and be told to keep using the data that was returned last time. You save more time and resources if you can avoid making that call in the first place.


8. Integrate analytics
Analytics are an essential part of understanding how an application is used. It's common for calls to an analytics service to be made in addition to the requests for data that are made during normal use of an app. For instance, if the app will attempt to call the server to refresh the displayed data on a page every time that the user navigates to that page then there is redundancy in adding a separate tracking/analytics call to track navigating to that page as well.
At its most primitive, the use of the API can serve as an indication of how and when the application is used. At the other end of the scale there are rich analytics tools and frameworks which can provide very detailed information about how users interact with the app. If you're somewhere in between then think carefully about how or if you're making additional/unnecessary calls purely for the purpose of tracking usage when you could get this from the calls made as part of the usage of the app.

9. Consider names carefully

The names you give the methods, objects, properties and parameters of your API will greatly impact the way those who are using the API understand it. It can be very tempting to use whatever terms or wording first come to mind when creating the API. As with all code though, the words you use play a great part in how the API is understood and expected to behave. Poorly named APIs can be a great source of confusion. Confusion leads to mistakes, mistakes lead to bugs, bugs lead to delays and support costs. Spend time on naming.

10. Don't forget your privacy policy and responsibilities
If you're capturing user data (and if you have logging on your server to record requests then you are) you need to have a privacy policy that details how you'll use the data. You'll also need to think about how you store and protect that data. Especially if it's personal and/or belongs or relates to children.



Wednesday, March 20, 2013

Debugging binding issues is hard. Having simpler code makes it easier.

Recently I had to deal with a strange bug.
Sometimes the menu option to create a secondary tile was not being enabled when it should be.
After analysis I was able to get the most consistent reproduction of the issue on a lower spec device (a Lumia 620). Obviously this isn't acceptable so a solution had to be found.

I tracked the most likely candidate to the `CanPin()` method. You can see the "before" version below.
You'll notice that it "smells" of all sorts of issues. It's also not something that can be debugged or instrumented easily.
It also isn't immediately obvious how it works because it's not easy to read.


There's definitely the possibility for something funny to be going on there.
Could all those checks be being made in an order differently to how they're listed?
Could there be a bug in the logic?
Could the time it takes for them to be run be taking longer than is available to trigger the binding to update?

The only option available is to refactor to make the method clear about what it does and in what order.



And, as if by magic the problem went away.

So what was the problem?
I can't be 100% certain.
But I'm not sure that matters.
That well written, easily understandable code doesn't display unexpected, unintended consequences--that's a good thing. Why badly written, hard to undertand code has certain unintended consequences--isn't a priority for me just now.

This leads me to be reminded of three important lessons:
- Debugging binding issues is hard (Bind to simple properties to help avoid binding issues.)
- Simple code is better (both to debug and to maintain)
- Be sure to test on real devices (both low and high spec)


TL-DR:
Bind to simple properties to help avoid binding issues.
Write code that is easy to read so it's easier to maintain in the future.


3 MiFi topup fail



One of the devices I have to keep me and my devices connected to the Internet is a MiFi unit (portable access point) for (UK network) 3.
I don't use it very often but sometimes I can't use Wi-Fi or Internet sharing from another device. Today was one of those times so I got out the unit and, as I have it on PAYG (because I don't use it enough to justify a contract) I attempted to top up.

I turned on the MiFi unit and paired with a device, a Nokia Lumia 620. All good so far, then I opened the browser to be automatically redirected to the top up site.

1st problem - I was given the full site, as I'd expect on a PC or other large screen device. This meant I had to wait ages for the page to download (over HSDPA) and render on a device which wasn't suited to displaying all that content and wasn't related to the task I was trying to achieve.

2nd problem - I had to go through lots of unnecessary steps/pages to achieve what I wanted. The page I was initially taken to had what looked like 4 big buttons for each of the available top up options. The only problem was they weren't buttons - just images. There was actually a text link to top up but I had to zoom into the page to see it. Clicking the "I want to top up" link redirected me to the account overview page. From there I had to click another I want to top up link. This took me to a page that provided a drop down list for each of the top up options. Selecting from this list caused the page to reload. There were then separate pages for selecting to use my preconfigured credit card and entering the card security code (CVV number). This finally led to another page for...

3rd problem - the 3D secure step in the payment process tried to open a page which had a mime type or other content that the phone couldn't display and so prompted me to visit the store to download an app to view the content. Of course, the problem here is that I couldn't connect to the store as I had no Internet connection. Even if I could connect to the store I doubt my credit card provider has an app that could allow me to complete the in browser transaction. In fact I don't just doubt it - I know it's not possible, at least not without having some Microsoft implemented changes to the browser and as the bank and card provider have nothing in the way of apps in the windows phone store, what are the chances that Microsoft have built something into the OS for them?


Ok, that's a partial HSBC/MasterCard and Microsoft/Internet Explorer failure but still, it's left me a very frustrated and disappointed customer. :(

I ended up getting out my iPad to top up.

So, rather than just moan about the situation, what can we learn from it?


  1. Be smart about the content you serve to devices. Especially ones with small screens.
  2. Remove unnecessary steps, page reloads and redirects from processes. Especially sign up and payment processes.
  3. Provide, simple, easily identifiable short cuts to do often repeated tasks.


Yes these are all obvious and often repeated recommendations. I hope by repeating them again here it'll help someone remember them next time it's appropriate.



Monday, March 18, 2013

Online privacy when building apps for kids

This weekend just gone I was at the Windows Phone 8 Lock-in organised by Dev4Good, so issues around apps for children and young people is on my mind at the moment. That's probably why this caught my eye:

http://momswithapps.com/category/online-privacy/

It's a set of resources relating to online privacy curated specifically for people creating educational apps for children. If you're building apps for this audience they're an invaluable read.

Sunday, March 17, 2013

Azure Mobile Services error: "The request could not be completed. ()"

Having just published my first (Windows Phone - obviously) app using Azure Mobile Services, I thought I'd share something I learnt in the process. When first testing on an actual device (always test on actual devices!) I hit an issue where the MobileServicesClient was failing with the following message being intercepted by the Application level UnhandledExceptionHandler:
"The request could not be completed. ()"

Notice the empty brackets at the end. In most cases (based on similar exceptions that others have reported and Google helped me find) these would include an indicator of the issue. Such as "(Internal Server Error)" or "(Send failure)".

The call stack wasn't much help either:


   at Microsoft.WindowsAzure.MobileServices.MobileServiceClient.CreateMobileServiceException(String errorMessage, IServiceFilterRequest request, IServiceFilterResponse response)
   at Microsoft.WindowsAzure.MobileServices.MobileServiceClient.ThrowInvalidResponse(IServiceFilterRequest request, IServiceFilterResponse response, JToken body)
   at Microsoft.WindowsAzure.MobileServices.MobileServiceClient.<RequestAsync>d__f.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.WindowsAzure.MobileServices.MobileServiceTable.<SendInsertAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.WindowsAzure.MobileServices.MobileServiceTable`1.<InsertAsync>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at RadioNow.MainPage.<OnNavigatedTo>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__0(Object state)


Even when I wrapped all my uses of the client in try..catch blocks this exception was still only getting caught at the application level unhandled exception handler.

Anyway, the issue came down to the devicenot having Wi-Fi enabled and for some reason it wasn't using 3G ro USB passthrough to connect instead.

So, 2 lessons:
1. The WP8 AMS client might throw errors, based on connectivity, that you'll have to catch and deal with at an application level.
2. Be sure to check/test Wi-Fi connections on devices when tethered.



Wednesday, March 13, 2013

AccentComplimentBrush v2.0

Yesterday I showed my new AccentComplimentBrush as a way of having a second color that can be used within an app and will work with whatever accent color has been chosen.

There was one big issue though. It only worked with the default accent colors in Windows Phone 8.

I've just pushed a new version to GitHub that is both forwards and backwards compatible.

It now works on both Windows Phone 7.X and Windows Phone 8.
It also works with operator and manufacturer defined accent colors. In fact it will work with any accent color whatsoever (yes, even for the people who've hacked in their own colors) as it now determines the compliment on the fly, rather than relying on a precomputed list of compliments.

Please enjoy.



Tuesday, March 12, 2013

Using a complimentary accent color


Sometimes you may want to use two colors in an app. If it was just one then I'm sure you'd just go with the Accent color.
The acccent colors all work well when on Black or White.
The problem though is that there is no single other color that can be combined well with any accent color and you probably want black and white elsewhere on the page. What you really want to avoid is a design that looks bad with one (or more) accent color(s).

If only there was a way to have another brush resource available that would adjust to the selected accent color and work in compliment to it.

Introducing the AccentComplimentBrush
It lets you have another SolidColorBrush available via a an Application wide resource that will work with any of the default accent colors. The complimentary color is based on the exact opposite position on the color wheel. See how the two pairs all go together:

The accent color above and it's compliment below.

How do you use it?
Just 2 simple steps

1. Add the resource.
Get the file, add it to your project and then reference it. (Either at the application level or on a specific page.)

    <phone:PhoneApplicationPage.Resources>
        <mrlacey:AccentComplimentBrush x:Key="MustBeSetButCanBeAnything" />
    </phone:PhoneApplicationPage.Resources>

Note the key value I've used above. Resources must have a key, but we don't actually ever use it. Because of this, ReSharper (or equivelent) might try and tell you that the resource isn't used. It is. Usage just can't automatically be detected at design time it because it's implemented with some run time trickery.

2. Use it!
Just refer to it in the XAML.

    <TextBlock Text="accent"
                Foreground="{StaticResource PhoneAccentBrush}" />
    <TextBlock Text="compliment"
                Foreground="{StaticResource AccentComplimentBrush}" />

or in code:

(SolidColorBrush)Application.Current.Resources["AccentComplimentBrush"];


Important!
1. It currently only works with the default accent colors, not any added by the operator or OEM. If you use this and want some help with adding support for any accent color let me know.
2. Because it uses "run time trickery" it doesn't work with the designer (in Visual Studio or Blend). If you know a way that would allow design time support I'd love to hear it.


What do you think? Useful?

Update I've now made a version 2.0 of this code which supports 7.X too and will even work with OEM/MO defined accent colors.





Monday, March 11, 2013

Telford: done! Next it's Bristol.


Last month I talked about Windows Phone 8 development at the university in Telford. Next week it's the UWE in Bristol.

The feedback from Telford was very positive.
There were 3 questions on the feedback form and each was marked on a scale of 1 to 10.

The talk was well delivered and I could understand the concepts discussed: 9.1 / 10
I got something out of this that I could use in a project, either in work or as a hobby project: 8.5 / 10
I would attend one of your talks again: 8.9 / 10


I'm particularly proud of those results considering only 1 person in the room with a Windows Phone 8 device and no one there had any previous experience developing for Windows Phone.


If you're in the Bristol area next Tuesday and are interested in hearing about Windows Phone 8 development,why not come along. More details, registration, etc.

Friday, March 08, 2013

NCLDR on Windows Phone 8

Earlier this week, uber-UK-community-bod and I18n expert, Guy Smith-Ferrier announced the alpha launch of NCLDR.

If you're not familiar with CLDR you can think of it as being like a version of the Globalization parts of the .net framework with lots of added extras. NCLDR is a .net port that allows access to all these lovely goodies.

As is my way and because I was interested if I could use the data in a phone app so I attempted a port/conversion to Windows Phone 8. It's just a POC at the moment, but look, I can get a regex for validating postcodes for each (well most) supported culture(s). If you're capturing a postal or zip code in your app this would allow you to validate it on the device, regardless of which country it was in.


I'll be honest, it wasn't as simple as I'd hoped. There was a lot more work and work arounds needed to get it to work than I would have liked and if Windows Phone support was to be officially added it would be better to add it in early and maybe remove use of some of the types and methods which are not supported on the phone, to aid greater cross platform code reuse.

Here's the changes I had to make to get it to work:

Biggest issue: WP doesn't support BinaryFormatter.
Second but related issue: By switching to using a JSON serializer I was potentially making the data file even bigger. I countered this by only including the minimum I needed in the generated file. This no only made the data file smaller but meant I had to load less and so save on precious memory consumption.

Add missing System elements:
  • CultureTypes
  • DigitShapes
  • ICloneable
  • SerializableAttribute
Replace use of HashTable with Dictionary<string, string>. In:
  • Culture.cs
  • Numbers.cs

Replace verison of string.Compare that was used with a WindowsPhone supported version. In:
  • Calendar.cs
  • CultureData.cs
  • Currency.cs
  • CurrencyPeriod.cs
  • Language.cs
  • MessageSet.cs
  • NumberingSystem.cs
  • NumberingSystemType.cs
  • Numbers.cs
  • PluralRule.cs
  • Region.cs
  • RegionMeasuringSystem.cs
  • CultureInfoExtensions.cs
  • RegionInfoExtensions.cs


Added some null exception handling/wrapping/suppressing to the following (but didn't really look into why it was needed):
  • Language.cs
  • Calendar.cs
  • Region.cs
  • CurrencyPeriod.cs
  • NumberingSystem.cs
  • Script.cs

Hopefully unnecessary disclaimer: This is a quickly hacked together proof of concept on top of alpha code. Use at your own risk...