Блог Сергея Байдачного

Мой блог о технологиях

Posts Tagged ‘Windows Phone 7.5

Контакты и календарь в Windows Phone 7.5

2 комментария

Продолжаю рассказывать про возможности интеграции приложений с Windows Phone 7.5. На этот раз поговорим о календаре и контактах, а именно, о чтении информации из списка контактов и календаря. Если Вы решили сохранить контакт, то тут можно использовать класс SaveContactTask, который позволит инициировать вызов стандартного приложения.

Итак, как я писал ранее, чтобы получить доступ к данным пользователя, необходимо явно запросить это разрешение либо в начале приложения, либо перед самим доступом к данным. При этом должен быть механизм, позволяющий пользователю запретить доступ. В дополнении к этому, манифест приложения должен декларировать следующие возможности: ID_CAP_CONTACTS – для контактов, ID_CAP_APPOINTMENTS – для календаря.

Прописав все возможности и получив доступ со стороны пользователя можно перейти к работе с контактами и календарем. Все необходимые классы содержаться в пространстве имен Microsoft.Phone.UserData. По большому счету тут два основных класса, это Contacts и Appointments. Именно с них начинается работа. Так, необходимо создать объекты необходимых классов, определить обработчики события SearchCompleted и запустить процедуру выбора контактов с помощью метода SearchAsync. С помощью последнего, запускается механизм поиска, заложенный внутри платформы, и разработчик получает доступ к результирующим данным.

Если говорить о параметрах метода SearchAsync, то в случае календаря, это параметры типа DateTime, которые задают промежуток времени, за который нужно выбрать записи. Третий параметр позволяет передать произвольный объект, который будет переброшен обработчику события SearchCompleted. Этот объект можно использовать на свое усмотрение, например, идентифицировать результат запроса по имени (если у Вас много запросов).

В случае контактов, метод SearchAsync также принимает три параметра. Третий параметр также представляет собой произвольный объект, а вот первый и второй – позволяют задать критерии поиска в списке контактов. Так, первый параметр задает строку для поиска (если она не нужна, то можно указать String.Empty), а второй – тип поиска. Тип поиска представляет собой объект перечислимого типа, принимающего одно из значений:

· None – возвращает все контакты;

· PinnedToStart – возвращает все контакты, привязанные к основному окну телефона;

· EmailAddresses – позволяет выполнять фильтрацию по Email адресам;

· PhoneNumber – позволяет выполнять фильтрацию по номерам телефонов;

· DisplayName – позволяет выполнять фильтрацию по имени контакта.

Естественно, что полученные результаты (в виде списка объектов Contact или Appointment) можно обрабатывать дополнительно, используя LINQ или простой перебор.

Таким образом, работа с контактами и календарем не представляет сложности. Вот пример кода, который может выбирать контакты и записи из календаря, задавая фильтры:

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    Microsoft.Phone.UserData.Contacts conts = 
         new Microsoft.Phone.UserData.Contacts();
    Appointments apps = new Appointments();

    conts.SearchCompleted += 
         new EventHandler<ContactsSearchEventArgs>(conts_SearchCompleted);
    conts.SearchAsync("B", FilterKind.DisplayName, "My Search 1");

    apps.SearchCompleted += 
         new EventHandler<AppointmentsSearchEventArgs>(apps_SearchCompleted);
    apps.SearchAsync(DateTime.Now, DateTime.Now.AddDays(7), "My Search 2");

}

void apps_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
{
    try
    {
        appsList.ItemsSource = e.Results;
    }
    catch
    {

    }
}

void conts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
    try
    {
        contsList.ItemsSource = e.Results;
    }
    catch
    {

    }
}

 

В заключении отмечу, что классы Contacts и Appointments имеют свойство Accounts, позволяющее определить доступные источники данных (напомню, что WP 7 может объединять данные из таких источников как Exchange, Facebook, Live и др). Выбирая конкретный контакт или запись в календаре, разработчик получает доступ к аналогичному свойству, позволяющему определить источник данных для конкретного контакта или записи в календаре (кстати, источников может быть несколько).

Written by Sergiy Baydachnyy

08.01.2012 at 10:40

Опубликовано в Windows Phone

Tagged with

Соблюдение политики конфиденциальности при публикации WP 7 приложений

2 комментария

Логично, что при попытке использовать камеру, микрофон, Location API и механизмы по доступу к контактам, разработчик должен запросить разрешение у пользователя. При этом, многие политики (например, для приложений, использующих Location API), отображаются еще на этапе установки приложения. Но независимо от того, что отобразил Marketplace, функционал, запрашивающий у пользователя информацию, должен быть реализован внутри приложения.

В зависимости от типа приложения, запросить права на доступ к тем или иным данным можно по-разному. Например, если пользователь создает запись, к которой могут быть привязаны текущие GPS координаты пользователя, то в форме создания записи достаточно поставить галочку «Добавить к записи мое местоположение» (или как-то так). В этом случае разрешение, которое дает пользователь, тесно интегрировано в интерфейс приложения и не отвлекает внимание пользователя всякими всплывающими окнами.

Но если GPS данные используются в главном окне приложения и в зависимости от них формируется интерфейс, то запросить разрешение у пользователя нужно с помощью отдельного окна, которое отобразиться перед формированием основного окна приложения. При этом, если пользователь согласился на определение своего местоположения, то в настройках приложения должен быть функционал, отключающий это разрешение. В противном случае приложение не будет сертифицировано.

Обращаю Ваше внимание на то, что «индусы», проверяющие приложения, не всегда понимают, используется ли местоположение на том или другом экране. Например, мы публиковали приложение, которое отображает записи на карте, сделанные в привязке к GPS. При этом в главном окне отображалась карта, которая использовала уже сохраненные пользователем данные (на что было получено разрешение при создании соответствующих записей) и никоем образом не требовала определения новых GPS данных на основном экране. «Индусы» не разобрались и вернули приложение. В этом случае нужно отправить приложение на повторную сертификацию, «разжевав» работу Вашего приложения в специальном поле Developer’s Notes, присутствующем при публикации приложения в интерфейсе Marketplace. Ведь тестируется интерфейс, а не код вашего приложения и информации не всегда достаточно.

Но описанная мной выше ситуация понятна и предсказуема. Но существует еще одна причина, по которой Ваше приложение может не пройти сертификацию. Дословно это может звучать так: Your application failed the Marketplace prohibited application policy check. При этом комментариев к подобной ошибке всегда минимум. Оказывается, чтобы решить это проблему с сертификацией, достаточно внутри Вашего приложения разместить произвольный текст (абсолютно авторский), который будет доступно рассказывать пользователю, чего будет происходить с его контактами, GPS положением и т .д. Текст может располагаться в том же окне, где пользователь дает свое разрешение или Вы можете разместить ссылку на другую страницу или даже адрес в Интернет, где будет опубликован Ваш текст. Вот этот текст и будет являться необходимой политикой конфиденциальности.

Быстрой публикации Вам.

Written by Sergiy Baydachnyy

07.01.2012 at 17:30

Опубликовано в Windows Phone

Tagged with

Сохранение рингтонов из приложения в WP 7.5

leave a comment »

 

Один из популярных способов заработать деньги на пользователях устройств, это продавать уникальные мелодии звонков для их телефонов. Этот бизнес настолько развит в Украине, что реклама соответствующих служб присутствует и на центральных каналах телевидения. Правда, чтобы заниматься подобным бизнесом, необходимо договориться с мобильным оператором, получить короткий номер и решить много других вопросов.

Но если мы говорим о Windows Phone 7.5, то реализовать подобный бизнес тут значительно проще, так как в обновлении платформы появилась возможность устанавливать мелодию звонка из приложения. Это делается с помощью класса SaveRingtoneTask, который инициирует вызов стандартного Windows Phone приложения, позволяющего как сохранить мелодию в общем списке, так и установить мелодию конкретному контакту.

Прежде чем переходить к реализации примера, следует отметить, что в Windows Phone 7.5 присутствуют следующие ограничения на мелодии звонка:

· Мелодия должна быть сохранена в виде mp3 или wma формата;

· Размер файла должен быть менее 1 Мб;

· Продолжительность аудио должна быть менее 40 секунд;

· Файл не должен быть защищен DRM.

Если все эти условия выполнены, то мелодия может быть установлена.

Посмотрим на то, что должен обычный пользователь сделать, чтобы сохранить мелодию звонка на свой телефон. Итак, если Вы обычный пользователь и у Вас есть mp3 (кстати, его нужно еще найти), который Вы хотите загрузить в телефон, то нужно выполнить следующие действия:

1). Преобразовать mp3 файл таким образом, чтобы он удовлетворял критериям выше. Это можно сделать с помощью Expression Encoder или другого аналогичного приложения. Естественно, пользователь ничего о подобных приложениях не знает (как и об ограничениях);

2). Как только у пользователя есть готовый mp3 или wma, то его необходимо синхронизировать с телефоном. Для этого файл добавляется в коллекцию с музыкой, доступной через Zune, после чего необходимо перейти к редактированию файла и установить свойство Genre в значение ringtone (если файл не удовлетворяет критериям, то его тип поменять нельзя).

image

3). Подключить телефон к компьютеру и синхронизировать созданную мелодию с телефоном.

Как видите, задача не тривиальная и вряд ли под силу простому пользователю. Но это означает, что приложения по установке мелодий будут не только популярны, но и позволят заработатьJ

А вот теперь приведем код примера. Начнем с интерфейса:

 

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="Ringtone Sample" 
             Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="PageTitle" Text="Ringtones" Margin="9,-7,0,0" 
             Style="{StaticResource PhoneTextTitle1Style}"/>
        <MediaElement Name="mp"></MediaElement>
    </StackPanel>

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <ListBox Name="ringList">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock FontSize="32" Text="{Binding RingtoneName}"></TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Grid>

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Images/appbar.check.rest.png" 
             Text="Ringtone" Click="ApplicationBarIconButton_SetRing_Click"/>
        <shell:ApplicationBarIconButton IconUri="/Images/appbar.transport.play.rest.png" 
             Text="Play" Click="ApplicationBarIconButton_Ringtone_Click"/>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

 

Тут мы добавили список, который будет отображать доступные мелодии. Тут можно ввести такие поля, как описание, автор категория и др., но это Вы сделаете сами. Далее в приложении присутствует ApplicationBar, который содержит две кнопки. Первая кнопка позволяет установить выделенную мелодию в качестве звонка телефона, а вторая – проиграть мелодию прямо в приложении. Чтобы иметь возможность проиграть мелодию, мы также разместили MediaElement. В нашем случае он не имеет визуального отображения.

Определим класс, который будет хранить информацию о мелодиях:

 

public class RingtoneItem
{
    public string RingtoneName { get; set; }
    public string RingtonePath { get; set; }
}

 

А теперь перейдем к коду.

В первой части мы загрузим все доступные мелодии, которые поставляются прямо с приложением. В полноценной версии приложения, Вы наверняка будете выбирать список мелодий из какой-то службы, а потом предлагать загрузить ту или другой мелодию в изолированное хранилище и только после этого давать прослушать мелодию. В нашем случае все гораздо примитивнее.

Во второй части приложения мы обрабатываем событие нажатия на кнопки в Application Bar и проигрываем мелодию, либо вызываем метод Show объекта типа SaveRingtoneTask. Обратите внимание, что при передаче параметра этому объекту, правило формирования Uri отличается от принятого внутри приложения. Чтобы Uri смог быть разобран внешним приложением, его необходимо формировать с помощью приставки appdata: или isostore:, в зависимости от того, где находится Ваш файл с мелодией (внутри приложения или загружен в IsolatedStorage).

Вот полный код основной страницы:

SaveRingtoneTask saveRing;
List<RingtoneItem> list = new List<RingtoneItem>();

public MainPage()
{
    InitializeComponent();

    saveRing = new SaveRingtoneTask();
    saveRing.Completed += 
         new EventHandler<TaskEventArgs>(saveRing_Completed);

    list.Add(new RingtoneItem() { 
         RingtoneName="Mission Impossible",
         RingtonePath="/Ringtones/mission.wma"});
    list.Add(new RingtoneItem() { 
         RingtoneName = "Va Bank", 
         RingtonePath ="/Ringtones/vabank.wma" });

    ringList.ItemsSource = list;

}

void saveRing_Completed(object sender, TaskEventArgs e)
{
    string statusText="";
    if (e.TaskResult == TaskResult.OK)
    {
        statusText = "Save completed.";
    }
    else if (e.TaskResult == TaskResult.Cancel)
    {
        statusText = "Save cancelled.";
    }
    MessageBox.Show(statusText);
}

private void ApplicationBarIconButton_Ringtone_Click(object sender, EventArgs e)
{
    if (ringList.SelectedIndex >= 0)
    {
        mp.Source = 
           new Uri(((RingtoneItem)ringList.SelectedItem).RingtonePath, 
                     UriKind.Relative);
        mp.Play();
    }
}


private void ApplicationBarIconButton_SetRing_Click(object sender, EventArgs e)
{
    if (ringList.SelectedIndex >= 0)
    {
        saveRing.Source = new Uri(
             "appdata:"+((RingtoneItem)ringList.SelectedItem).RingtonePath);
        saveRing.Show();
    }
}

Written by Sergiy Baydachnyy

05.01.2012 at 15:10

Опубликовано в Windows Phone

Tagged with

Информация об устройстве и сети в Windows Phone 7.5

with one comment

Еще одно нововведение в Windows Phone 7.5, это возможность определить информацию о возможном подключении к сети, а также параметры самого устройства. Тут можно выделить два класса с большим количеством статических методов и свойств.

Первый класс DeviceNetworkInformation, который находится в пространстве имен Microsoft.Phone.Net.NetworkInformation, поддерживает следующие свойства:

· CelluralMobileOperator – позволяет вернуть имя мобильного оператора (только строку);

· IsCelluralDataEnabled – возвращает true, если активирована передача данных через сеть оператора;

· IsNetworkAvailable – возвращает true, если имеется хоть какой-то доступ к сети;

· IsWiFiEnabled – возвращает true, если на телефоне активирована возможность подключения к WiFi;

· IsCelluralDataRoumingEnabled – позволяет проверить, включен ли на телефоне роуминг для передачи данных через сеть мобильного оператора.

Как видно, методы выше достаточно примитивны и не отвечают на вопрос, есть ли доступ в данный момент через WiFi или передача ведется через мобильного оператора. Ведь включение на телефоне WiFi не гарантирует его наличие. Иными словами, назначение этих свойств исключительно информационное, позволяющее сделать интерфейс приложения более дружественным для пользователя.

Если Вы все же хотите получать информацию об изменениях в соединении и определять тип соединения, то Вам поможет статическое событие класса DeviceNetworkInformation. Это событие NetworkAvailabilityChanged, передающее обработчику в качестве параметров объект типа NetworkInterfaceInfo, который содержит всю возможную информацию о текущем подключении. Кстати, чтобы получить информацию о всех возможных подключениях, можно воспользоваться классом NetworkInterfaceList, а текущее подключение можно получить через класс NetworkInterface. Но, в отличии от класса DeviceNetworkInformation, перечисленные выше классы были и в версии 7.0.

Второй класс, из рассматриваемых нами, это DeviceStatus, позволяющий определить множество интересных параметров, связанных с устройством. Тут присутствуют следующие статические свойства:

· ApplicationCurrentMemoryUsage – позволяет определить, сколько памяти использует приложение в данный момент;

· ApplicationMemoryUsageLimit – возвращает количество памяти, которое может быть (всего) использовано приложением;

· ApplicationPeakMemoryUsage – позволяет вернуть пиковое значение памяти, которая была использована в ходе работы приложения;

· DeviceFirmwareVersion – определяет версию прошивки;

· DeviceHardwareVersion – определяет версию аппаратного обеспечения (устройства);

· DeviceManufacturer – возвращает имя производителя устройства;

· DeviceName – возвращает имя устройства;

· DeviceTotalMemory – возвращает общее количество памяти;

· IsKeyboardDeployed – позволяет проверить, готово ли клавиатура к использованию (например, выдвинута из телефона);

· IsKeyboardPresent – определяет наличие клавиатуры;

· PowerSource – определяет, использует ли устройство батарею или подключено к сети.

Как видно, тут можно получить много полезной информации, которую использовать не только во время работы пользователя с приложением, но и во время тестирования.

Кроме перечисленных статических свойств, класс DeviceStatus содержит два статических события, позволяющих определять изменения, связанные с клавиатурой и источником энергии. Первое событие KeyboardDeployedChanged, а второе – PowerSourceChanged.

Written by Sergiy Baydachnyy

03.01.2012 at 09:26

Опубликовано в Windows Phone

Tagged with

Интеграция с камерой

leave a comment »

 

В первой версии Windows Phone (7) разработчик имел очень ограниченный доступ к камере. Фактически вся работа сводилась к вызову стандартного приложения по работе с камерой с помощью класса CameraCaptureTask. Объекты этого класса обладают методом Show, способным инициировать стандартное приложение по работе с камерой (и деактивировать Ваше), а с помощью обработчика события Completed можно было получить отснятое изображение. Подобный подход хорош, если Вам не нужна тесная интеграция с камерой и не хочется делать дополнительную работу.

А вот в Windows Phone 7.5 разработчик получил значительно больше возможностей. При этом слово «больше» явно преуменьшает тот набор функциональности, который можно использовать сегодня. По большому счету Вы можете без труда написать собственное приложение по работе с камерой, позволяя пользователю устанавливать различные настройки. При этом речь идет как о создании фотографий, так и о полном доступе к данным, поступающим на камеру. Давайте рассмотрим новые механизмы более детально.

Начнем с того, что для использования камеры в своем приложении необходимо обязательно задекларировать такую возможность. Это делается с помощью Capability элемента с именем ID_CAP_ISV_CAMERA, который прописывается в манифесте приложения (WMAppManifest.xml). При этом данная декларация позволяет использовать как стандартную, так и фронтальную (лицевую) камеру (по выбору пользователя через интерфейс приложения). Декларация прописана по умолчанию в шаблоне проекта Visual Studio, поэтому Вам вряд ли нужно будет выполнять этот шаг. Но если Вы решили использовать именно фронтальную камеру, так как именно с помощью нее можно выполнить некоторые функции Вашего приложения, то необходимо задекларировать еще одну возможность, с именем ID_HW_FRONTCAMERA. При этом нужно помнить, что не все телефоны оснащены лицевой камерой. Последняя возможность не декларируется по умолчанию, поэтому ее потребуется прописать явно.

Теперь необходимо определиться, какое приложение Вы хотите реализовать. Дело в том, что в Windows Phone 7.5 появилось сразу два API по работе с камерой. Первое API является частью платформы Windows Phone и позволяет реализовать приложение по съемке фотографий. Второе API является частью SilverLight 4 и позволяет обрабатывать весь аудио и видео поток, поступающий на камеру. Преимущество первого API – возможность обрабатывать события, связанные с фокусом, вспышкой и другими элементами телефона. Преимущество Silverlight API – его универсальность. В любом случае оба API можно комбинировать.

Начнем наш обзор с Windows Phone API. Тут выделяют три основных класса: PhotoCamera, PictureDecoder, Extentions. Основную работу выполняет первый класс. А вот два других являются вспомогательными и позволяют преобразовать объект типа WriteableBitmap в JPEG и наоборот. Фактически второй и третий классы реализуют мостик между Silverlight и объектом типа PhotoCamera. При этом, Silverlight 4 не поддерживал стандартных механизмов преобразования BMP изображений в JPEG, что затрудняло работу разработчиков при создании веб-приложений. Но телефон ведь не только позволяет снимать изображение с камеры, но и преобразовывать его в JPEG. Именно поэтому такая возможность стала доступна и разработчику, как открытый API уже существующих в устройстве возможностей.

Не буду детально останавливаться на PictureDecoder и Extensions, а лишь отмечу, что первый класс обладает двумя статическими методами, позволяющими получить готовый WriteableBitmap, получив в качестве параметров ссылку на поток с файлом JPEG. А вот второй класс является расширителем класса WriteableBitmap и позволяет добавить в интерфейс последнего два метода (LoadJpeg и SaveJpeg). Иными словами Вы можете использовать эти методы, как методы экземпляров типа WriteableBitmap.

Теперь перейдем к основному классу – PhotoCamera. Тут есть два небольших правила-рекомендации. Объект типа PhotoCamera правильно создавать и инициализировать внутри перегруженного метода OnNavigatedTo. Уничтожать данный объект следует внутри метода OnNavigatingFrom. Это позволит гарантировать, что все ресурсы будут освобождены своевременно, если приложение поддерживает навигацию на другие страницы. Создание самого объекта типа PhotoCamera не вызывает затруднений – тут присутствует конструктор без параметров, а также конструктор, который принимает тип камеры (обычная или фронтальная).

Я не смог найти ни одного устройства с фронтальной камерой в своих запасниках, поэтому не смог проверить, можно ли получать изображение с обеих камер одновременно. Но если можно, то это позволит создать много интересных приложений. Фронтальную камеру сегодня поддерживает HTC Titan, HTC Radar и Samsung I8350. Если у Вас одно из этих устройств, попробуйте проверить и написать.

Итак, создав объект типа PhotoCamera, следует определить необходимые в приложении события, ассоциированные с этим объектом и задать свойства. Я не буду перечислять основные свойства и события, а просто приведу небольшой пример.

В шаблонный xaml, внутрь элемента Grid с именем ContentPanel, добавим код:

 

   1:   <StackPanel>
   2:       <Rectangle Height="400" Width="400" Margin="12,17,0,0" Name="videoRect" />
   3:   </StackPanel>

 

В файл с кодом добавим следующий текст:

 

   1:  PhotoCamera camera;
   2:  MediaLibrary library;
   3:   
   4:  protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
   5:  {
   6:      if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
   7:      {
   8:          camera = new PhotoCamera(CameraType.Primary);
   9:   
  10:          videoRect.Fill = new VideoBrush();
  11:          ((VideoBrush)videoRect.Fill).SetSource(camera);
  12:          library = new MediaLibrary();
  13:   
  14:          CameraButtons.ShutterKeyHalfPressed += 
  15:  new EventHandler(CameraButtons_ShutterKeyHalfPressed);
  16:          CameraButtons.ShutterKeyPressed += 
  17:  new EventHandler(CameraButtons_ShutterKeyPressed);
  18:          camera.CaptureImageAvailable += 
  19:  new EventHandler<ContentReadyEventArgs>(camera_CaptureImageAvailable);
  20:      }
  21:  }
  22:   
  23:  void camera_CaptureImageAvailable(object sender, ContentReadyEventArgs e)
  24:  {
  25:      string fileName = Guid.NewGuid().ToString() + ".jpg";
  26:      library.SavePictureToCameraRoll(fileName, e.ImageStream);
  27:      Deployment.Current.Dispatcher.BeginInvoke(delegate()
  28:      {
  29:          MessageBox.Show("Image saved");
  30:      });
  31:  }
  32:   
  33:  void CameraButtons_ShutterKeyPressed(object sender, EventArgs e)
  34:  {
  35:      camera.CaptureImage();
  36:  }
  37:   
  38:  void CameraButtons_ShutterKeyHalfPressed(object sender, EventArgs e)
  39:  {
  40:      camera.Focus();
  41:  }
  42:   
  43:  protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
  44:  {
  45:      if (camera != null)
  46:      {
  47:          camera.Dispose();
  48:          camera.CaptureImageAvailable -= camera_CaptureImageAvailable;
  49:      }
  50:  }

 

Если развернуть созданное приложение на устройстве, то мы получим приложение, которое отображает данные с камеры и позволяет сделать и сохранить фотографию в библиотеку изображений:

 

image

 

На картинке я специально повернул телефон так, как он расположен во время съемки. Как видно, чтобы изображение на экране, соответствовало изображению с камеры, нужно элемент, куда мы выводим изображение, повернуть на 90 градусов.

Итак, что мы увидели в данном примере:

1). Изображение можно снимать, используя стандартную клавишу камеры в телефоне. Для этого используется класс CameraButtons, содержащий несколько статических событий, позволяющих нам подключить наш код. Тут и возможность провести фокус (относительно центра или какой-то точки), тут и возможность обработать поток, который связан со сформированным изображением, доступным после завершения съемки.

2). Для работы с камерой есть ряд простых методов, такие как Focus или CaptureImage. Эти методы инициируют некоторый процесс в параллельном потоке, и передают свои результаты в параметрах таких событий как CaptureImageAvailable или AutoFocusCompleted. Поэтому, если Вы хотите изъять фотографию, то нужно определить обработчик первого события. Но изменение интерфейса нужно выполнять, передав управление в интерфейсный поток.

3). PhotoCamera позволяет сохранить изображение в виде потокового объекта, который уже преобразован к формату JPEG. Поэтому, если Вы хотите предварительно обработать изображение, то поток можно преобразовать во WritableBitmap с помощью классов, упоминавшийся выше, обработать и снова преобразовать в JPEG.

Сценарий выше работает если Вы хотите снять обычное изображение с камеры. Но если приложение немного более сложное, например, накладывает дополнительные элементы (например, усы на лица людей в кадре), то необходимо привлечь несколько дополнительных методов объекта типа PhotoCamera. Одним из таких методов является GetPreviewBufferArgb32, позволяющий вернуть текущий фрейм для дальнейших манипуляций. Получив массив данных, разработчик может выполнить их предварительную обработку, преобразовать во WritableBitmap и выдать на экран. В этом случае VideoBrush не используется совсем, а используется объект Image, в который и выводиться очередной WriteableBitmap. Естественно, что обработка каждого следующего фрейма проводиться в методе, который запускают в параллельном потоке. А частота выдачи изображений на экран, зависит от сложности алгоритма, обрабатывающего изображение.

Если говорить про Silverlight 4 API, то тут ничего не поменялось. Работа начинается с классов AudioCaptureDevice, VideoCaptureDevice и CaptureDeviceConfiguration. Эти классы используются для получения ссылок на доступные аудио и видео устройства. Если устройств несколько, то Вы можете предоставить пользователю выбор, с каким устройством работать.

Основным классом является CaptureSource, который позволяет начать запись. Внутри этого класса описаны ссылки на аудио и видео устройства, а также присутствуют такие методы как Start и Stop, позволяющие запустить или остановить работу камеры. Кроме того, объект данного класса может служить источником данных для VideoBrush.

Отличие классов Silverlight API состоит в том, что с помощью них можно выполнять запись изображения в видео-файл (MP4). Для этого используется класс FileSink, который имеет свойства CaptureSource и IsolatedStorageFileName – все, что необходимо для начала записи. При установке свойства CaptureSource соответствующий объект должен быть остановлен. Если Вы хотите написать собственный декодер, то можно использовать такие классы как VideoSink и AudioSink. Последние можно использовать и для передачи аудио и видео в различных системах видео чата.

Written by Sergiy Baydachnyy

01.01.2012 at 22:41

Опубликовано в Windows Phone

Tagged with

Настройка клавиатуры в Windows Phone 7.5

2 комментария

 

Еще одна полезная вещь, о которой я писал ранее, и которую игнорируют многие разработчики – настройка клавиатуры. О возможности установить свой тип клавиатуры можете почитать тут.

В свою очередь хочу отметить, что в Windows Phone 7.5 набор клавиатур был пополнен еще двумя: клавиатура, содержащая только цифры и клавиатура, адаптированная для набора формул. Соответственно Input Scope для первого типа клавиатуры может быть установлен в одно из значений: CurrencyAmount, DateDay, DateMonth, DateYear, Digits, Number, NumberFullWidth, NumericPassword, TimeHour, TimeMinorSec. А Input Scope для второй клавиатуры устанавливается в значение Formula.

Written by Sergiy Baydachnyy

14.12.2011 at 14:42

Опубликовано в Windows Phone

Tagged with

Application Bar в Windows Phone 7.5

leave a comment »

 

Некоторое время назад я писал о работе с ApplicationBar в Windows Phone приложениях https://baydachnyy.com/2011/03/07/windows-phone-7-application-bar/. Как ни странно, сегодня многие разработчики забывают об этом элементе управления, являющимся привычной составляющей любого Silverlight интерфейса в WP – пытаясь городить свои кнопки в основном экране приложения. Но я сейчас не об этом.

Одним из недостатков ApplicationBar было его постоянное присутствие на экране. Как результат, если вы работали с очень динамичным приложением (да, игры бывают и на Silverlight), то была велика вероятность щелкнуть на кнопку в ApplicationBar по чистой случайности. В Windows Phone 7.5 этот недостаток был устранен за счет добавления свойства Mode. Установив это свойство в Minimized, вы получите «свернутую» версию этого элемента управления. И прежде чем нажать на кнопку, пользователь должен будет его развернуть.

Вот небольшой кусочек кода, демонстрирующий работу этого свойства:

 

   1:  <phone:PhoneApplicationPage.ApplicationBar>
   2:        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" Mode="Minimized">
   3:            <shell:ApplicationBarIconButton IconUri="images/appbar.add.rest.png" 
   4:                   x:Name="gpsItem" Text="Установить" Click="ApplicationBarIconButton_Click_1/>
   5:            <shell:ApplicationBarIconButton IconUri="images/appbar.feature.search.rest.png"  
   6:                   x:Name="roadItem" Text="Показать" Click="ApplicationBarIconButton_Click_2"/>
   7:        </shell:ApplicationBar>
   8:  </phone:PhoneApplicationPage.ApplicationBar>

 

А вот то, что останется от ApplicationBar в этом случае:

image

Written by Sergiy Baydachnyy

12.12.2011 at 15:02

Опубликовано в Windows Phone

Tagged with