Lessons Learnt Using the Windows Phone Camera API : Part 2

A few months ago I wrote a post about some of the stuff I learnt working with the Windows Phone camera API for Foundbite, here’s some more I’ve learnt since….

Disable Camera Buttons

Initiating a photo capture can sometimes take a bit of time, especially if you’re focusing as well, and I found even if you give the user some loading feedback it’s quite likely they might try to press the button more than once. If they do this the phone will try to initiate another camera capture which will most likely throw an InvalidOperationException. In Foundbite, after suffering from many of these exceptions, I’m disabling the on screen button and the physical camera button when the capturing process is occurring.

Dispose the Camera

You may have noticed that if you don’t dispose an instance of the PhotoCaptureDevice whenever you leave the camera page it’ll cause a whole host of problems, including giving a nasty bug where the camera feed goes green- often needing a phone restart to right itself.

In the OnNavigatedTo event on the camera page I declare a new instance of the camera and in the OnNavigatedFrom I .Dispose() the PhotoCaptureDevice which has stopped this from occurring completely.

Don’t Assume All Phones Have the Same Resolutions

It’s best to assume that every phone has different resolutions available to avoid any unexpected problems when setting the resolution. I was initialising the camera in Foundbite using the 640 x 480 resolution which I though every phone would have as the minimum. However, it seems the new Nokia Lumia 1020 doesn’t have this low resolution so was causing a crash for that particular device.

I have an idea of what kind of size image I want so I just use this fairly schoolboy method to select the closest available resolution using the widths available and the desired width:

public static int GetNearestSizeIndex(List<int> widths, int wantedSize)
{
int distanceAway = int.MaxValue;
int index = 0;
for (int i = 0; i < widths.Count; i++)
{
int distance = Math.Abs(widths[i] – wantedSize);
if (distance < distanceAway)
{
distanceAway = distance;
index = i;
}
}
return index;

As I said, pretty basic but in Foundbite I’ve had to limit the size of images to improve image size and upload speed, so this is helpful for selecting the best resolution.

Focus Illumination Mode

The FocusIlluminationMode is the small flash you sometimes see when focusing the camera. I wasn’t aware you could even control this to start off with but to stop annoying your users its best to give them an option to turn this off if they so wish (or keep it on all the time).

Make sure you check that the phone has a flash before allowing the user to manipulate the illumination mode as a Nokia Lumia 520 only has one FocusilluminationMode (off) as it has no flash.

if(camera.IsFlashAvailable()) camera.SetIlluminationMode(Settings.FocusMode.Value);

Which uses these two methods:

public void SetIlluminationMode(FocusIlluminationMode mode)
{
Device.SetProperty(KnownCameraPhotoProperties.FocusIlluminationMode, mode);
}

public bool IsFlashAvailable()
{
return (GetAvailableFlashStates().ToList().Count() > 1);
}

For more help using the camera I found this Camera Explorer sample from Nokia amazingly useful……

Lessons learnt working with pushpins and maps in Windows Phone 8

Given the location-based nature of Foundbite, I’ve had to do a lot of work with pushpins and maps. When I was first starting out I ran into a couple of hurdles with the difference between WP8 and WP7.

Adding a pushpin to a map I can’t remember how exactly I came about this method of adding pushpins (or if it’s completely necessary) but I’ve been adding MapLayers to the map which include several MapOverlay’s each containing objects you want to display at a certain location (in this case pins). Pushpins do have a location property you can set but using a MapOverlay means you can add anything.

MapLayer layer = new MapLayer();
map.Layers.Add(layer);
Pushpin pp = new Pushpin();
MapOverlay overlay = new MapOverlay();
overlay.Content = pp;
layer.Add(overlay);

Setting the overlay (and therefore the pushpin’s) location

You just need to select the correct MapOverlay from the layer. Easy.

layer[x].GeoCoordinate = new GeoCoordinate(Latitude, Longitude);

Changing the pushpin’s style

If you want to change the style of your pushpin, it’s as easy as using the editor in Blend, saving to Application resources in App.xaml and then calling this line of code:

pp.Style = App.Current.Resources["MyStyle"] as Style

Changing the position origin of your pushpin

If you edited the style of your pushpin you might not want it to be placed on the map by its bottom left corner as normal. This can be changed via the PositionOrigin property of the overlay:

overlay.PositionOrigin = new Point(0.5, 1);

This sets the position origin to the bottom middle of the pushpin. (0,0) is the top left.

Get the position of a tap on the map to add a pushpin

Definitely one of the most useful and least used parts of the map control is the ability to get the geo location of a user’s tap on the map. You just need to get the screen coordinate of the click in relation to the map control (measured from the top left again) and then use the handy map method below to convert this to a GeoCoordinate.

var point = e.GetPosition(map);
var location = map.ConvertViewportPointToGeoCoordinate(point);

There’s also ConvertGeoCoordinateToViewportPoint which does the reverse.

I discovered this method after writing a version of the ConvertViewportPointToGeoCoordinate myself over the course of the weekend – so much time wasted!

Hopefully these are useful!

This is a a copy of a post I wrote on my previous blog: http://mendez.quora.com/Working-with-Pushpins-and-Maps-in-Windows-Phone-8?__snids__=196873019%2C196831318&__nsrc__=2#comment327137

Source Control, Team Foundation Service and your Windows Phone app

Source control is really essential when you’re working as part of a team on a software project but it can be just as useful when you’re working alone. This is probably obvious for many experienced developers but this is an article I would have found useful when I was just starting out.

For the development of my first Windows Phone apps such as Travelnapp and YuleTile I just saved my project to a code folder and occasionally backed up to a memory stick (I hadn’t heard of cloud storage at that point). Not only was there a lot to lose if I lost the backup and laptop, but I often found myself stuck with issues resulting from something I’d tampered with but couldn’t remember what.

If a late night’s coding gets the better of me and the next morning the app refuses to work I can now, using source control, look at the changes I made the previous evening and find the offending code.  Or if worse comes to worst, simply go back in time to before my tiredness took it’s toll on my code.

Now, with so many different tools and services available such as Beanstalk, GitHub and BitBucket to host your code repository which should you choose? If you’re largely a sole developer like myself you’ll probably want the cheapest, and it’s for this reason I swapped from Beanstalk to Team Foundation Service to host the Foundbite code repo.

Forget the name, Team Foundation Service is just as suited and useful for sole developers like myself as it is for large complex teams. It’s so easy bullet points are appropriate:

  • It’s free (for up to 5 devs) – yep, it won’t cost you a thing.
  • It’s heavily integrated into Visual Studio – pretty obvious but the ability to compare changes and view changelogs inside visual studio is handy.
  • There’s a nice web interface – The site is nice and easy to use to view changelogs and add new users.

There’s also lots of other features which I haven’t got around to using yet like continuous builds, test execution and agile planning. They’re all a bit foreign to me at the moment but I’m sure I’ll get around to using them eventually.

Have a look over at tfs.visualstudio.com

Response time difference between Windows Azure extra small and small instances

This was originally posted on my old blog.

When Foundbite was in its very early stages I was using the Windows Azure Extra Small instance to host the API and with a very small number of beta testers the response time was more than fine, though did fluctuate a lot.

As the beta expanded and because I get a free allowance for Windows Azure through BizSpark, I decided to move my web role up to a Small Instance. Unlike the Extra Small, the Small instance is not shared with others and I was curious to see the response time gains that could be had. Turns out, they are quite significant:

Although I realise this isn’t a completely fair test as the number of requests and type of requests vary, it’s quite apparent that the response time dropped significantly. I hadn’t expected such a clear distinction.

You can see the difference in size between instances here, I have no idea how much an A7 costs but wow that’s a lot of power!

If you need help choosing an instance size, this article is also really useful.

The above graph was made using New Relic Performance Monitoring which you can get for free using your Azure subscription.

Lessons Learnt Using the Windows Phone Camera API

I’ve been working with the Windows Phone camera API (PhotoCaptureDevice) a lot recently for Foundbite, some of the things I’ve learnt:

Not every Windows Phone has flash

I didn’t realise this until recently when testing with the cheap as chips Nokia Lumia 520. It’s a great device for the price but you need to add a check to your camera code to make sure other flash modes are available before manipulating it.

Here’s a method to get the available flash states and another to check if flash is available for the current device (ie: if there is one or less flash states).

public bool IsFlashAvailable()
{
List<FlashState> flashStates = GetAvailableFlashStates().ToList();
return (flashStates.Count > 1);
}

public IReadOnlyList<FlashState> GetAvailableFlashStates()
{
IReadOnlyList<object> rawValueList = PhotoCaptureDevice.GetSupportedPropertyValues(Device.SensorLocation, KnownCameraPhotoProperties.FlashMode);
List<FlashState> flashStates = new List<FlashState>(rawValueList.Count);foreach (object rawValue in rawValueList) flashStates.Add((FlashState)(uint)rawValue);
return flashStates.AsReadOnly();
}

Update #1: Jay Benett ponts out that this can be done in a far simpler way than I have using LINQ’s .Any() https://twitter.com/JayTBennett/status/370221811423670272

Update #2: Just realised this update 1 method won’t work as even if there isn’t a flash on the device there will still be FlashState.Off in the list.

Update #3:After more discussion, it turns out there is a way to do it using Jay’s method: https://twitter.com/scottisafool/status/371913405080547328. I’m going to stop updating this post now.

In some regions the camera shutter sound can’t be turned off

Foundbite allows you to take a picture at the same time as recording audio so it wouldn’t be ideal if you could hear the shutter sound in every sound clip. It is possible to turn the sound off but in some regions of the world it’s a legal necessity to have this sound on.

It’s therefore a necessity to check that you can turn the sound off before doing so:

private void disableShutterSound()
{
if (!(bool)this.Device.GetProperty(KnownCameraGeneralProperties.IsShutterSoundRequiredForRegion))
this.Device.SetProperty(KnownCameraGeneralProperties.PlayShutterSoundOnCapture, false);
}

It’s possible to turn off the flash that happens when you focus the camera

This setting is called the FocusIlluminationMode and can easily be changed, much like FlashMode, between Auto, On and Off.

Here’s the code to get the current value and change it:

public FocusIlluminationMode GetCurrentFocusIlluminatonMode()
{
return (FocusIlluminationMode)(uint)Device.GetProperty(KnownCameraPhotoProperties.FocusIlluminationMode);
}

public void SetIlluminationMode(FocusIlluminationMode mode)
{
Device.SetProperty(KnownCameraPhotoProperties.FocusIlluminationMode, mode);
}

It’s worth nothing that you should check the flash is available before changing this mode too!
Hopefully these will be helpful and save some time for others playing around with the camera.