Предисловие
Купил себе виндофон и решил попробовать написать что-нибудь под него, тем более, что с .NET знаком по роду деятельности. Идею подсказал товарищ с android-приложением фонарик, источником света которого являлась LED вспышка.
Первое решение
Почитал msdn, все показалось просто. Создаем объект
Microsoft.Devices.PhotoCamera
; смотрим, поддерживает ли наше устройство фото-вспышку; если поддерживает, то переключаем PhotoCamera.FlashMode
, по нажатию кнопки. Как сказал бы Ливанов: «Элементарно, Ватсон!». Но не тут-то было.Первый момент, который меня озадачил — инициализация камеры. Просто создать объект
Microsoft.Devices.PhotoCamera
не достаточно. Для этих целей, в уже знакомой статье на msdn, используется установка созданного объекта камеры в качестве источника для VideoBrush
. Это излишняя нагрузка, как мне кажется, но других способов я не нашел (может кто-то из читающих подскажет). К слову сказать, плотно и не искал, ибо мною двигала другая цель.А вот второй момент поставил в тупик описываемый вариант решение. В результате, по нажатию кнопки, мы видим, что дисплей подсвечивается, а LED-вспышка работать не желает. Чтож, печалька.
Второе решение
Начинаем копать дальше… С удивлением узнаю у гугла, что ребята из Microsoft скрыли от непросвещенных некоторые сборки (вот негодяи).
Нашел умельца на codeproject, который хакнул камеру WP7 с помощью скрытых от посторонних глаз возможностей. Но не столь интересен сам пост, сколько ссылки, которые он предоставляет в общее пользование. Идея состоит в том, что бы, как описано в Tom's blog, сделать необходимые сборки доступными и воспользоваться для подсветки, как советует Clarity Consulting Blog,
Microsoft.Devices.VideoCamera
.Реализация
Итак, информации более чем достаточно, приступим к делу. В Tom's blog говориться, что легче всего достать необходимые сборки из «Emulator BIN» или скачать его собственный дамп. Что такое «Emulator BIN» я не понял и долго заморачиваться не стал, воспользовался его наработкой. Берем из архива GAC_Microsoft.Phone.Media.Extended_v7_0_0_0_cneutral_1.dll и, чтобы нам легче было добавлять ссылки в следующий раз на эту сборку, копируем в папку "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone71" (нужны права администратора) с именем Microsoft.Phone.Media.Extended.dll. Естественно, у кого ОС стоит на другом разделе или не 64-разрядная, будут небольшие вариации.
Затем открываем папку с именем RedistList (она лежит в той же директории, что и скопированный только что файл), а в ней файл FrameworkList.xml. Его нужно отредактировать (я это делал в фаре, ибо папка со специфическими правами доступа). Копируем произвольный узел File, например для AssemblyName=«Microsoft.Phone.Interop», удаляем во вновь скопированном узле PublicKeyToken и меняем AssemblyName на Microsoft.Phone.Media.Extended.
Теперь нужно открыть visual studio command prompt и выполнить команду
sn -Vr Microsoft.Phone.Media.Extended.dll
, иначе у нас при построении проекта с этой сборкой будут ошибки.Теперь самое приятное — создание приложения. Достаточно создать обычный Silverlight проект для WP7 и добавить сборку Microsoft.Phone.Media.Extended. В нем будет довольно простенькая разметка, единственное, что здесь достойно внимания, так это контрол CameraVisualizer, он отображает захваченное с камеры изображение (но мы-то помним, что он нам нужен только для инициализации объекта камеры). И чтобы нас не отвлекала картинка на дисплее установим этому элементу полную непрозрачность.
Вот разметка
<phone:PhoneApplicationPage
x:Class="PhoneApp1.MainPage"
...
xmlns:media="clr-namespace:Microsoft.Phone;assembly=Microsoft.Phone.Media.Extended"
...
shell:SystemTray.IsVisible="False">
<Grid x:Name="LayoutRoot" Background="Transparent">
<media:CameraVisualizer x:Name="_cameraVisualizer" Opacity="0" />
<Button x:Name="_btnFlash" Click="ButtonClick" IsEnabled="false">
<Button.Content>
<Image VerticalAlignment="Center" HorizontalAlignment="Center" Width="300" Height="300" Source="Power_On_Off.png"/>
</Button.Content>
</Button>
</Grid>
</phone:PhoneApplicationPage>
Так же интересным фактором является то, что в коде необходимо указать на необходимость использовать LED вспышку
_videoCamera.LampEnabled = true;
и то, что фонарик начинает работать только во время записи с камеры. Точнее говоря, самой записи не будет, то есть поток данных не будет занимать физического пространства.using System.Windows;
using Microsoft.Phone;
namespace PhoneApp1
{
public partial class MainPage
{
private VideoCamera _videoCamera;
public MainPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
InitializeCamera();
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
_videoCamera.Dispose();
_videoCamera = null;
}
private void InitializeCamera()
{
_videoCamera = new VideoCamera(); // Создание объекта камеры
_videoCamera.Initialized += VideoCameraInitialized;
_cameraVisualizer.SetSource(_videoCamera);// Инициализация объекта камеры
}
void VideoCameraInitialized(object sender, System.EventArgs e)
{
_videoCamera.Initialized -= VideoCameraInitialized;
_videoCamera.LampEnabled = true; // Да будет свет!!!
Dispatcher.BeginInvoke(() => { _btnFlash.IsEnabled = true; });
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
// Когда идет запись, фонарик работает. При прекращении записи, он отключается.
if (_videoCamera.IsRecording)
_videoCamera.StopRecording();
else
_videoCamera.StartRecording();
}
}
}
PS: Конструктивная критика в адрес первого топика и моего стиля изложения приветствуется.
Используемые источники
1 msdn
2 codeproject
3 Tom's blog
4 Clarity Consulting Blog
5 xda-developers
UPD Дамы и господа, я прекрасно понимаю, что статья кому-то понравилась, кому-то нет. Но в личку пишут только те, кто положительно отнеслись к посту в целом, но имеют замечания по тем или иным моментам. Убедительная просьба — если минусуете, оставляйте отзыв что не понравилось. Для меня важно на первом этапе понять, что я делаю не так.