Windows Phone Flashlight: Getting started

I've got my Nokia Lumia 800 for over a month by now and the time has come to start doing what we developers do best, so today I will start building my first Windows Phone application. And because this is my first Windows Phone application lets start with an easy one, at least I hope so. I’ve decided to build a flashlight app that uses the LED on my phone.

Requirements

A simple flashlight app needs:

  • Enable the LED when the app is opened

Getting started

Before we can start developing we need some stuff. Just go to the App Hub and check out the getting started section, here you can download the SDK, sign up for a developer account and explore documentation.

After everything has been installed we can begin.

  1. Create a new Windows Phone Application called Flashlight.
    image
  2. As the target Windows Phone OS version select Windows Phone OS 7.1 (Mango).

Modifying the UI

We now have an empty WP application so lets start customizing it a bit by setting the application name.

  1. Open the MainPage.xaml, select the ApplicationTitle text block and set the text property to FLASHLIGHT (all caps *).
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
    <TextBlock x:Name="ApplicationTitle" Text="FLASHLIGHT" Style="{StaticResource PhoneTextNormalStyle}"/>
  2. And remove the Page Title since we only have one page (and less is more *)

* Following the Windows Phone Design Guidelines.

Turning on the LED with the photo camera

The flash on the phone can be accessed via the PhotoCamera object. So the first thing I tried was to turn on the flash this way. By the way this didn’t work, so if you can skip this part and jump right to the next chapter: Turning on the LED with the video camera.

To use the photo camera you need two objects the PhotoCamera and the VideoBrush. Add them to the MainPage.xaml.cs.

private PhotoCamera _photoCamera;
private VideoBrush _videoBrush;

In the OnNavigatedTo method add the following code to initialize the camera. We will be using the primary camera on the back of the device.

// Check to see if the camera is available on the device.
if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
{
	// Use standard camera on back of device.
	_photoCamera = new PhotoCamera(CameraType.Primary);

	// Event is fired when the PhotoCamera object has been initialized.
	_photoCamera.Initialized += PhotoCamera_Initialized;

	// Add the photo camera to the video source
	_videoBrush = new VideoBrush();
	_videoBrush.SetSource(_photoCamera);
}

As you can see we also want to handle the Initialized event of the camera object. When the camera has been initialized we can turn on the LED. For the LED to be on the camera needs to be active, so we call the focus event.

private void PhotoCamera_Initialized(object sender, CameraOperationCompletedEventArgs e)
{
	// Check if flash mode is supported on the device.
	if (_photoCamera.IsFlashModeSupported(FlashMode.On))
	{
		// Turn the flash on.
		_photoCamera.FlashMode = FlashMode.On;
		_photoCamera.Focus();
	}
}

When we run the application on our device, since the emulator does not have a LED, the LED is turned on when the application starts …and is turned off after a few seconds when the camera has focused.

Lucky for us the camera also has a AutoFocusCompleted event, so lets add some code to turn the LED back on when this event is fired. To the OnNavigatedTo method add the following code.

// The event is fired when auto-focus is complete.
_photoCamera.AutoFocusCompleted += PhotoCamera_AutoFocusCompleted;

Turn the LED back on when the AutoFocusCompleted event fires. And let the camera focus on a new random point.

private void PhotoCamera_AutoFocusCompleted(object sender, CameraOperationCompletedEventArgs e)
{
	// Turn the flash back on.
	_photoCamera.FlashMode = FlashMode.On;
	Random randNum = new Random();
	_photoCamera.FocusAtPoint(randNum.NextDouble(), randNum.NextDouble());
}

Run the application again and behold …we now have a blinking light, not what we wanted. It seems that using the photo camera to build a flashlight is not going to work.

Turning on the LED with the video camera

Well this endeavor seems to end before it actually started since the VideoCaptureDevice object does not have any properties or methods that access the device LED. But I’ve seen apps that turn on the LED on my phone so it must be possible.

After some googling I’ve found a possible solution. Apparently you can access the LED via the VideoCamera object in the Microsoft.Phone.Media.Extended assembly, but since this assembly is not present in the SDK you can not use it. There are two way to use the assembly:

  1. Get the dll and reference it in Visual Studio.
  2. Use reflection.

I chose to go with option 2 as I wanted to keep open the possibility to successfully submit the app to the marketplace.

Note: you can find the Microsoft.Phone.Media.Extended.dll in the emulator WM70C1.en-US.bin. Extract it and look for GAC_Microsoft.Phone.Media.Extended_v7_0_0_0_cneutral_1.dll if you want to take a look inside with Reflector or an open source alternative.

We are going to use two classes from the Media.Extended assembly; VideoCamera and CameraVisualizer.

Create a VideoCamera wrapper

  1. Create a new class called VideoCamera.
    public class VideoCamera { ... }
  2. Add an object to instantiate the reflected VideoCamera object on.
    private object _videoCamera;
  3. In the constructor we set all the fields and create the video camera object.
    // Load the media extended assembly which contains the extended video camera object.
    Assembly mediaExtendedAssembly = Assembly.Load("Microsoft.Phone.Media.Extended, Version=7.0.0.0, Culture=neutral, PublicKeyToken=24eec0d8c86cda1e");
    
    // Get the camera source type (primary camera).
    Type cameraSourceType = mediaExtendedAssembly.GetType("Microsoft.Phone.CameraSource");
    FieldInfo field = cameraSourceType.GetField("PrimaryCamera");
    object cameraSource = Enum.ToObject(cameraSourceType, (int)field.GetValue(cameraSourceType));
    
    // Create the video camera object.
    Type videoCameraType = mediaExtendedAssembly.GetType("Microsoft.Phone.VideoCamera");
    ConstructorInfo videoCameraConstructor = videoCameraType.GetConstructor(new Type[] { cameraSourceType });
    _videoCamera = videoCameraConstructor.Invoke(new object[] { cameraSource });

If you want to check if the primary camera is available you can use the PhotoCamera object (see previous chapter: Turning on the LED with the photo camera)

Wrap the properties and methods we need

By using reflector I’ve seen we will need the following properties and methods of the VideoCamera object:

  • LampEnabled (property)
  • StartRecording (method)
  • Initialized (event)

VideoCamera-ILSpy

  1. Add fields for the properties and methods we want to reflect.
    private PropertyInfo _videoCameraLampEnabledPropertyInfo;
    private MethodInfo _videoCameraStartRecordingMethod;
    private EventHandler _videoCameraInitialized;
  2. Set the fields.
    _videoCameraLampEnabledPropertyInfo = videoCameraType.GetProperty("LampEnabled");
    _videoCameraStartRecordingMethod = videoCameraType.GetMethod("StartRecording");
  3. And tie the Initialized event to a private event handler.
    _videoCameraInitialized = new EventHandler(VideoCamera_Initialized);
    MethodInfo addInitializedEventMethodInfo = videoCameraType.GetMethod("add_Initialized");
    addInitializedEventMethodInfo.Invoke(_videoCamera, new object[] { _videoCameraInitialized });

We can now add the properties and methods to our class to wrap the reflected ones. For example the LampEnabled property would look like this:

public bool LampEnabled
{
	get { return (bool)_videoCameraLampEnabledPropertyInfo.GetGetMethod().Invoke(_videoCamera, new object[0]); }
	set { _videoCameraLampEnabledPropertyInfo.GetSetMethod().Invoke(_videoCamera, new object[] { value }); }
}

And the StartRecording method:

public void StartRecording()
{
	// Invoke the start recording method on the video camera object.
	_videoCameraStartRecordingMethod.Invoke(_videoCamera, new object[0]);
}

Once we have finished wrapping all the properties and methods we need for our video camera we do the same for the VideoCameraVisualizer object.

For the complete implementation you can take a look at the source code (at the end of this post).

Turning the LED on

Now we have wrapped the VideoCamera and the VideoCameraVisualizer we can turn on the LED. But first remove all the PhotoCamera stuff from the MainPage.xaml.cs we’ve added in the previous chapter.

Add two new fields for the VideoCamera and the VideoCameraVisualizer.

private VideoCamera _videoCamera;
private VideoCameraVisualizer _videoCameraVisualizer;

In the OnNavigatedTo method add the following code to initialize the camera. Use the PhotoCamera to test if the primary camera is available.

if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
{
	_videoCamera = new VideoCamera();
	
	// Event is fired when the video camera object has been initialized.
	_videoCamera.Initialized += VideoCamera_Initialized;
	
	// Add the photo camera to the video source
	_videoCameraVisualizer = new VideoCameraVisualizer();
	_videoCameraVisualizer.SetSource(_videoCamera);
}

And when the camera has been initialized we can turn it on.

private void VideoCamera_Initialized(object sender, EventArgs e)
{
	_videoCamera.LampEnabled = true;
	_videoCamera.StartRecording();
}

When we now run the application we get a continues beam of light from the LED. Success at last!! We have our LED flashlight app. It wasn’t as simple as I expected when I started, but we learned a lot. If you want to take a look at the full code, I’ve included the Visual Studio project I’ve created.

Note: the code in the project is sample code and is not intended to be a complete application that can be submitted to the marketplace.

Download the code.