• 검색 결과가 없습니다.

11주차 - Chapter 04 윈도우폰 7 애플리케이션의 구성과 구현 (계속)

N/A
N/A
Protected

Academic year: 2021

Share "11주차 - Chapter 04 윈도우폰 7 애플리케이션의 구성과 구현 (계속)"

Copied!
99
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

11주차

강 대 기

(2)

런처

런처를 이용하는 애플리케이션 만들기

츄저

츄처를 이용하는 애플리케이션 만들기

(3)
(4)

런처

런처란

EmailComposeTask

MarketplaceDetailTask

MarketplaceHubTask

MarketplaceReviewTask

MarketplaceSearchTask

MediaPlayerLauncher

PhoneCallTask

SearchTask

SmsComposeTask

WebBrowserTask

(5)

런처나 츄저는 기본적으로 윈도우폰의 애플리케이션에서

전화 걸기나 연락처 정보, 문자 보내기 등의 기능들을 활용

해야 할 때, 사용할 수 있는 프레임워크

윈도우폰은 (다른 스마트폰을 표절한 구조인데,) 모든 애플

리케이션들이 샌드박스(sandbox) 안에서 실행됨

따라서, 직접적으로 다른 애플리케이션을 실행시키거나, 연

락처와 같은 공통 저장소 정보에 접근하는 것은 불가능함

따라서, 애플리케이션 프로그램에서 전화를 걸거나 문자를

보내는 것과 같은 공통 기능들을 활용할 수 있도록 하는 프

레임워크가 필요함

참고로, 안드로이드의 경우, 인텐트(Intent), Android

Interface Definition Language (AIDL), 그리고 컨텐트 프

로바이더 (Content Providers) 메커니즘을 통해 이러한 기

능들이나 공통 데이터에 접근 가능함

(6)

사전적인 의미는 예를 들면, 배를 처음 출발시키거나(진수

(進水)) 자동차를 출발시키게 하거나(발진(發進)) 미사일을

쏘게 하는 것을 의미함

컴퓨터에선 특정 컴퓨터 프로그램을 실행시키는 것을 의미

윈도우폰에서는 전화를 걸거나 메시지를 보내는 것과 같은

공통적인 기능을 사용할 수 있도록 제공하는 API 세트

이를 통해 폰 애플리케이션과 같이 빌트인된 애플리케이션

을 독립적으로 실행시킬 수 있음

사용 방법은, 기본적으로

사용하고자 하는 런처 클래스에 대한 새로운 인스턴스를 하나 생

성함

필요에 따라 런처 객체에 대한 속성을 설정함

그리고, 호출함

(7)

1.

EmailComposeTask

2.

MarketplaceDetailTask

3.

MarketplaceHubTask

4.

MarketplaceReviewTask

5.

MarketplaceSearchTask

6.

MediaPlayerLauncher

7.

PhoneCallTask

8.

SearchTask

9.

SmsComposeTask

10.

WebBrowserTask

(8)

새로운 이메일 작성 화면을 보여줌

EmailComposeTask 클래스의 To, Cc, Subject,

그리고 Body 속성값을 설정하면,

에뮬레이터에서는 실행이 안됨

기본적으로 디바이스에 이메일 계정을 설정해야 하지만,

에뮬레이터에서는 설정할 수 없게 되어 있음

(9)

using Microsoft.Phone.Tasks;

EmailComposeTask emailComposeTask = new

EmailComposeTask();

emailComposeTask.To =

"dkkang@dongseo.ac.kr";

emailComposeTask.Subject = "테스트";

emailComposeTask.Body = "안녕하세요.";

emailComposeTask.Show();

(10)
(11)

Windows Phone Marketplace 클라이언트 어플리

케이션을 실행함

ContentIdentifier 속성값으로 설정되어 있는 고

유 식별자(identifier)에 대한 제품 상세정보 페이

지를 보여줌

ContentIdentifier 속성값이 설정되지 않은 경우 호출하

는 애플리케이션에 대한 상세 정보 페이지를 보여줌

ContentType 속성값은 어떤 컨텐츠를 보여줄지

를 설정하는 데, MarketplaceContentType의 열

거값 (Application, Music) 중 하나를 설정함

(12)

// 기본 ContentType 으로 Windows Phone Marketplace

클라이언트 앱을 실행

MarketplaceDetailTask task = new

MarketplaceDetailTask();

task.ContentIdentifier = "0513132001";

task.Show();

// Music ContentType 으로 Windows Phone Marketplace

클라이언트 앱을 실행

MarketplaceDetailTask task = new

MarketplaceDetailTask();

task.ContentType = MarketplaceContentType.Music;

task.ContentIdentifier = "0513132001";

(13)

아직 한국에선 마켓플레이스 기능을 사용할 수 없음

(14)

Windows Phone Marketplace 클라이언트 어플리

케이션을 실행함

ContentType 속성값으로 설정되어 있는 콘텐츠

(15)

using Microsoft.Phone.Tasks;

MarketplaceHubTask task = new

MarketplaceHubTask();

task.ContentType =

MarketplaceContentType.Music;

task.Show();

(16)

아직 한국에선 마켓플

레이스를 사용할 수 없

(17)

Windows Phone Marketplace 클라이언트 어플리

케이션을 실행해서, 호출한 애플리케이션의 리뷰

페이지를 보여줌

(18)

using Microsoft.Phone.Tasks;

MarketplaceReviewTask task = new

MarketplaceReviewTask();

(19)

아직 한국에선 마켓

플레이스를 사용할

수 없음

따라서, 마켓플레이

스에 대한 요청을 거

부함

또한 호출한 애플리

케이션은, 우리가 임

의로 만든 것으로 등

록되어 있지 않으므

로, 의미 있는 결과를

기대할 수 없음

(20)

Windows Phone Marketplace 클라이언트 어플리

케이션을 실행해서, SearchTerms 속성값으로 설

정된 검색어에 대한 검색 결과 화면을 보여줌

(21)

MarketplaceSearchTask task = new

MarketplaceSearchTask();

task.SearchTerms = "Game";

task.Show();

MarketplaceSearchTask task = new

MarketplaceSearchTask();

task.ContentType =

MarketplaceContentType.Music;

task.SearchTerms = "michael jackson";

task.Show();

(22)
(23)

윈도우 폰에서 각종 미디어(비디오, 오디오 등)를 재생하는

역할

Controls 속성은 MediaPlaybackControls 열거형 타입 객

체로, 화면에 표시되는 제어기 버튼의 종류를 선택할 수 있

게 함 – None, Pause, Stop, FastForward, Rewind, Skip,

All

Location 속성은 미디어 파일이 어디에 저장되어 있는지를

나타내는데, 보통 WP7용 실버라이트 프로그램을 작성하게

되면 개발자가 조작할 수 있는 파일은 프로그램이 인스톨되

어 있는 경로(다시 말하면, 프로그램에 포함된 리소스 파일)

혹은 격리된 저장소의 경로에 있는 파일들임

열거값은 None, Install, Data 중 하나

MediaLocationType.Install 열거형 멤버는 재생할 미디어가 프로

그램이 인스톨 되어있는 경로를 의미함

MediaLocationType.Data는 격리된 저장소를 의미함

미디어 파일이 인터넷에 있는 파일 경우는

(24)

MediaPlayerLauncher launcher = new

MediaPlayerLauncher();

launcher.Media = new

Uri("mov\\testwmv.wmv", UriKind.Relative);

launcher.Location = MediaLocationType.Install;

launcher.Controls = MediaPlaybackControls.All;

launcher.Show();

(25)

화면의 UIElement를

클릭하면 잠시 보여

지거나 음성이 나오

다가 사라짐

윈도우폰 에뮬레

이터의 알려진 문

제점

코덱 및 에뮬레이터

의 한계로 동영상이

안나올 수 있음

(26)

폰 애플리케이션을 실행하여

PhoneNumber 속성에 설정된 전화번호와

DisplayName 속성에 설정된 이름으로

(27)

PhoneCallTask task = new PhoneCallTask();

task.PhoneNumber = "0513132001";

task.DisplayName = "동서대학교";

task.Show();

(28)

에뮬레이터는 가짜(fake)

GSM 네트워크을 가지고

있으므로, 실제 전화는 걸

리지 않지만, 전화가 걸리

는 것처럼 시뮬레이션 됨

(29)

검색 애플리케이션을 실행하여

SearchQuery 속성값으로 설정된 검색어로

(30)

SearchTask task = new SearchTask();

task.SearchQuery = "강대기";

(31)
(32)

문자 메시지 애플리케이션을 실행하여 새로운 메

시지 작성하는 화면을 보여줌

이 때 SmsComposeTask 클래스의 To와 Body 속

성값을 설정하면 수신 번호와 메시지 내용을 미리

입력된 화면에 보여줌

(33)

SmsComposeTask task = new

SmsComposeTask();

task.To = "0513132001";

task.Body = "윈도우폰7으로 동서대에 접속!";

task.Show();

(34)
(35)

Tombstone 을 설명하면서 이미 언급한 API

인터넷 익스플로러 애플리케이션을 실행해

윈도우폰 SDK 7.0까지는 URL 속성값으로 설정된

URL 주소를 탐색함

윈도우폰 SDK 7.1부터는 Uri 속성값으로 설정된

Uri 주소를 탐색함

(36)

WebBrowserTask task = new WebBrowserTask();

task.Uri = new Uri("http://naver.com/");

(37)
(38)
(39)

런처를 이용하는 애플리케이션 만들기

프로젝트 생성 및 화면 디자인

(40)

목표 : 런처를 이용한 간단한 애플리케이션을 만듬

비쥬얼 스튜디오 2010을 사용해 Launcher라는

Windows Phone Application 프로젝트를 하나 생

성함

다음 슬라이드처럼 화면을 디자인함

각 버튼에 대한 이벤트 핸들러를 적절한 이름으로

(41)
(42)

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<Button Content="MediaPlayerLauncher" Height="72"

HorizontalAlignment="Left" Margin="6,42,0,0"

Name="MediaPlayerLauncherButton" VerticalAlignment="Top" Width="447"

Click="MediaPlayerLauncherButton_Click" />

<Button Content="PhoneCallTask" Height="72" HorizontalAlignment="Left"

Margin="6,120,0,0" Name="PhoneCallTaskButton" VerticalAlignment="Top"

Width="447" Click="PhoneCallTaskButton_Click" />

<Button Content="SearchTask" Height="72" HorizontalAlignment="Left"

Margin="6,198,0,0" Name="SearchTaskButton" VerticalAlignment="Top"

Width="447" Click="SearchTaskButton_Click" />

<Button Content="SmsComposeTask" Height="72"

HorizontalAlignment="Left" Margin="6,276,0,0" Name="SmsComposeTaskButton"

VerticalAlignment="Top" Width="447" Click="SmsComposeTaskButton_Click" />

<Button Content="WebBrowserTask" Height="72"

HorizontalAlignment="Left" Margin="6,354,0,0" Name="WebBrowserTaskButton"

VerticalAlignment="Top" Width="447" Click="WebBrowserTaskButton_Click" />

</Grid>

(43)

using Microsoft.Phone.Tasks; 으로 네임스페이

스 추가

Ian1.wmv 를 “프로젝트에 추가”

속성탭에서 Build Action 속성을 Content

(44)

private void MediaPlayerLauncherButton_Click(object sender, RoutedEventArgs e) {

MediaPlayerLauncher launcher = new MediaPlayerLauncher(); launcher.Media = new Uri("Ian1.wmv",UriKind.Relative);

launcher.Location = MediaLocationType.Install; launcher.Controls = MediaPlaybackControls.All; launcher.Show();

}

private void PhoneCallTaskButton_Click(object sender, RoutedEventArgs e) {

PhoneCallTask task = new PhoneCallTask(); task.PhoneNumber = "0513132001";

task.DisplayName = "동서대학교"; task.Show();

}

private void SearchTaskButton_Click(object sender, RoutedEventArgs e) {

SearchTask task = new SearchTask(); task.SearchQuery = "강대기";

task.Show(); }

(45)

private void SmsComposeTaskButton_Click(object sender,

RoutedEventArgs e)

{

SmsComposeTask task = new SmsComposeTask();

task.To = "0513132001";

task.Body = "윈도우폰7으로 동서대에 접속!";

task.Show();

}

private void WebBrowserTaskButton_Click(object sender,

RoutedEventArgs e)

{

WebBrowserTask task = new WebBrowserTask();

task.Uri = new Uri("http://naver.com/");

task.Show();

}

(46)
(47)
(48)

츄저

CameraCaptureTask

EmailAddressChooserTask

PhoneNumberChooserTask

PhotoChooserTask

SaveEmailAddressTask

SavePhoneNumberTask

(49)

공통적인 가능들을 제공하는 빌트인 애플리케이션을

독립적으로 실행시키는 기본방식은 런처와 동일함

츄저는 런처와 달리 츄저를 호출한 어플리케이션으로

특정 형태의 데이터를 리턴함

츄저를 호출하는 애플리케이션은 츄저 작업에 대한 리

턴값을 받기 위해서, 해당 츄저의 객체를 해당 폰 어플

리케이션 페이지(PhoneApplicationPage)의 멤버 변

수로 선언

츄저의 작업이 완료되었을 때, 발생되는 Completed

이벤트를 위임받아 이에 대한 핸들러를 구성해야 함

이렇게 구성되는 이벤트 핸들러를 통해 해당 츄저 작

업에 대한 확인/취소 여부와 작업에 관련된 데이터를

받게 됨

(50)

사용자가 카메라 애플리케이션을 실행시킨 후 사

진을 찍으면, Completed 이벤트를 발생시키고 찍

힌 사진에 대한 이미지 데이터를 PhotoResult 객

체를 통해 해당 이벤트 핸들러에 전달해 줌

(51)

<Grid x:Name="ContentPanel" Grid.Row="1"

Margin="12,0,12,0">

<Button Content="Shoot!" Height="72"

HorizontalAlignment="Left" Margin="140,40,0,0"

Name="button1" VerticalAlignment="Top"

Width="160" Click="OnCameraCaptureTask" />

<Image Height="303" HorizontalAlignment="Left"

Margin="39,176,0,0" Name="myImage"

Stretch="Fill" VerticalAlignment="Top"

Width="374" />

(52)

public partial class MainPage : PhoneApplicationPage

{

private CameraCaptureTask cameraCaptureTask;

// Constructor

public MainPage()

{

InitializeComponent();

this.cameraCaptureTask = new CameraCaptureTask();

cameraCaptureTask.Completed += new

EventHandler<PhotoResult>(cameraCaptureTask_Complet

ed);

(53)

private void OnCameraCaptureTask(object sender, RoutedEventArgs e)

{

try

{

this.cameraCaptureTask.Show();

}

catch (System.InvalidOperationException ex)

{

MessageBox.Show("An error occurred.");

}

}

void cameraCaptureTask_Completed(object sender, PhotoResult e)

{

if (e.TaskResult == TaskResult.OK)

{

BitmapImage bmp = new BitmapImage();

bmp.SetSource(e.ChosenPhoto);

this.myImage.Source = bmp;

}

}

}

(54)
(55)

리스트 형태로 연락처를 보여주는 Contacts 애플

리케이션을 실행한 후, 사용자가 하나의 연락처를

선택하면 Completed 이벤트를 발생시키고 선택

된 연락처에 대한 이메일 주소의 데이터를

EmailResult 객체를 통해 해당 이벤트 핸들러에

전달해 줌

(56)

<Grid x:Name="ContentPanel" Grid.Row="1"

Margin="12,0,12,0">

<Button Content="Choose!" Height="72"

HorizontalAlignment="Left" Margin="63,180,0,0"

Name="EmailAddressChooserButton"

VerticalAlignment="Top" Width="326"

Click="OnEmailAddressChooserTask" />

<TextBox Height="72" HorizontalAlignment="Left"

Margin="49,102,0,0"

Name="EmailAddress_TextBox" Text="Email

Address" VerticalAlignment="Top" Width="353"

/>

(57)

private EmailAddressChooserTask task; // Constructor

public MainPage() {

InitializeComponent();

this.task = new EmailAddressChooserTask(); task.Completed += new

EventHandler<EmailResult>(emailAddressChooserTask_Completed); }

void emailAddressChooserTask_Completed(object sender, EmailResult e) { if (e.TaskResult == TaskResult.OK) { this.EmailAddress_TextBox.Text = e.Email; } }

private void OnEmailAddressChooserTask(object sender, RoutedEventArgs e) {

this.task.Show(); }

(58)
(59)

리스트 형태로 연락처를 보여주는 Contacts 애플

리케이션을 실행한 후, 사용자가 하나의 연락처를

선택하면 Completed 이벤트를 발생시키고 선택

된 연락처에 대한 전화번호의 데이터를

PhoneNumberResult 객체를 통해 해당 이벤트

핸들러에 전달해 줌

(60)

<Grid x:Name="ContentPanel" Grid.Row="1"

Margin="12,0,12,0">

<Button Content="Choose!" Height="72"

HorizontalAlignment="Left" Margin="63,180,0,0"

Name="PhoneNumberChooserButton"

VerticalAlignment="Top" Width="326"

Click="OnPhoneNumberChooserTask" />

<TextBox Height="72" HorizontalAlignment="Left"

Margin="49,102,0,0"

Name="PhoneNumber_TextBox" Text="Phone

Number" VerticalAlignment="Top" Width="353"

/>

(61)

private PhoneNumberChooserTask task; // Constructor

public MainPage() {

InitializeComponent();

this.task = new PhoneNumberChooserTask(); task.Completed += new

EventHandler<PhoneNumberResult>(phoneNumberChooserTask_Completed); }

void phoneNumberChooserTask_Completed(object sender, PhoneNumberResult e) { if (e.TaskResult == TaskResult.OK) { this.PhoneNumber_TextBox.Text = e.PhoneNumber; } }

private void OnPhoneNumberChooserTask(object sender, RoutedEventArgs e) {

this.task.Show(); }

(62)
(63)

Photo Picker 애플리케이션을 실행시킨 후, 사용

자가 하나의 사진을 선택하면 Completed 이벤트

를 발생시키고 선택된 이미지에 대한 데이터를

PhotoResult 객체를 통해서 해당 이벤트 핸들러에

게 전달해 줌

(64)

<Grid x:Name="ContentPanel" Grid.Row="1"

Margin="12,0,12,0">

<Image Height="204" HorizontalAlignment="Left"

Margin="102,177,0,0"

Name="PhotoChooserTaskImage" Stretch="Fill"

VerticalAlignment="Top" Width="259" />

<Button Content="Choose!" Height="72"

HorizontalAlignment="Left" Margin="102,82,0,0"

Name="PhotoChooserTaskButton"

VerticalAlignment="Top" Width="259"

Click="OnPhotoChooserTask" />

(65)

private PhotoChooserTask task; // Constructor

public MainPage() {

InitializeComponent();

this.task = new PhotoChooserTask();

this.task.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed); }

void photoChooserTask_Completed(object sender, PhotoResult e) {

if (e.TaskResult==TaskResult.OK) {

BitmapImage bmp = new BitmapImage(); bmp.SetSource(e.ChosenPhoto);

this.PhotoChooserTaskImage.Source = bmp; }

}

private void OnPhotoChooserTask(object sender, RoutedEventArgs e) {

this.task.Show(); }

(66)
(67)

리스트 형태로 연락처를 보여주는 Contacts 애플

리케이션을 실행한 후, 츄저를 실행할 때 사용자가

선택하는 연락처 이메일 주소를 설정한 이메일 속

성값으로 저장할 수 있게 해줌

Completed 이벤트는 츄저 작업이 종료될 때 발생

되며, 해당 이벤트 핸들러에는 TaskEventArgs 객

체를 통해 이메일 속성값에 대한 저장 여부만

TaskResult 의 열거값 (None, OK, Cancel) 중 하

나로 전달됨

(68)

<Grid x:Name="ContentPanel" Grid.Row="1"

Margin="12,0,12,0">

<Button Content="Choose!" Height="72"

HorizontalAlignment="Left" Margin="62,134,0,0"

Name="SaveEmailAddressTaskButton"

VerticalAlignment="Top" Width="326"

Click="OnSaveEmailAddressTask" />

<TextBlock Height="30"

HorizontalAlignment="Left" Margin="75,237,0,0"

Name="SaveEmailAddressTextBlock" Text=""

VerticalAlignment="Top" Width="300" />

</Grid>

(69)

private SaveEmailAddressTask task;

// Constructor

public MainPage()

{

InitializeComponent();

this.task = new SaveEmailAddressTask();

task.Completed += new

EventHandler<TaskEventArgs>(saveEmailAddressTask_Completed);

}

void saveEmailAddressTask_Completed(object sender, TaskEventArgs e)

{

if (e.TaskResult == TaskResult.OK)

this.SaveEmailAddressTextBlock.Text = "이메일 주소가 저장됨";

else

this.SaveEmailAddressTextBlock.Text = "이메일 주소 저장이 취소됨";

}

private void OnSaveEmailAddressTask(object sender, RoutedEventArgs e)

{

this.task.Show();

}

(70)
(71)

리스트 형태로 연락처를 보여주는 Contacts 애플

리케이션을 실행한 후, 츄저를 실행할 때 사용자가

선택하는 연락처 전화 번호를 설정한 전화번호 속

성값으로 저장할 수 있게 해줌

Completed 이벤트는 츄저 작업이 종료될 때 발생

되며, 해당 이벤트 핸들러에는 TaskEventArgs 객

체를 통해 전화번호 속성값에 대한 저장 여부만

TaskResult 의 열거값 (None, OK, Cancel) 중 하

나로 전달됨

(72)

<Grid x:Name="ContentPanel" Grid.Row="1"

Margin="12,0,12,0">

<Button Content="Choose!" Height="72"

HorizontalAlignment="Left" Margin="62,134,0,0"

Name="SavePhoneNumberTaskButton"

VerticalAlignment="Top" Width="326"

Click="OnSavePhoneNumberTask" />

<TextBlock Height="30" HorizontalAlignment="Left"

Margin="62,321,0,0"

Name="SavePhoneNumberTaskTextBlock" Text=""

VerticalAlignment="Top" Width="300" />

<TextBox Height="72" HorizontalAlignment="Left"

Margin="62,227,0,0" Name="PhoneNumberTextBox"

Text="Phone Number" VerticalAlignment="Top"

Width="326" />

</Grid>

(73)

private SavePhoneNumberTask task; // Constructor

public MainPage() {

InitializeComponent();

this.task = new SavePhoneNumberTask(); task.Completed += new

EventHandler<TaskEventArgs>(savePhoneNumberTask_Completed); }

void savePhoneNumberTask_Completed(object sender, TaskEventArgs e) { if (e.TaskResult == TaskResult.OK) this.SavePhoneNumberTaskTextBlock.Text = "전화 번호가 저장됨"; else this.SavePhoneNumberTaskTextBlock.Text = "전화 번호 저장이 취소됨"; }

private void OnSavePhoneNumberTask(object sender, RoutedEventArgs e) {

this.task.PhoneNumber = this.PhoneNumberTextBox.Text; this.task.Show();

(74)
(75)
(76)

츄저를 이용하는 애플리케이션 만들기

프로젝트 생성 및 화면 디자인

각 버튼에 대한 이벤트 핸들러 구성

(77)

Chooser라는 윈도우폰 애플리케이션을 하나 생성

하고 6 개의 버튼(각각의 실행 가능한 츄저를 실행

하도록 하는 버튼)으로 화면을 디자인함

(78)
(79)

using Microsoft.Phone.Tasks; 로

Microsoft.Phone.Tasks를 네임스페이스에 추가

츄저들에 대한 멤버 변수들 생성

각 버튼에 대한 이벤트 핸들러 생성 및 구성

츄저의 Completed 이벤트에 대한 이벤트 핸들러

생성 및 구성

(80)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<Button Content="EmailAddressChooserTask" Height="72"

HorizontalAlignment="Left" Margin="26,52,0,0"

Name="EmailAddressChooserTaskButton" VerticalAlignment="Top"

Width="409" Click="OnEmailAddressChooserTask" />

<Button Content="PhoneNumberChooserTask" Height="72"

HorizontalAlignment="Left" Margin="26,144,0,0"

Name="PhoneNumberChooserTaskButton" VerticalAlignment="Top"

Width="409" Click="OnPhoneNumberChooserTask" />

<Button Content="PhotoChooserTask" Height="72"

HorizontalAlignment="Left" Margin="26,236,0,0"

Name="PhotoChooserTaskButton" VerticalAlignment="Top" Width="409"

Click="OnPhotoChooserTask" />

<Button Content="SaveEmailAddressTask" Height="72"

HorizontalAlignment="Left" Margin="26,328,0,0"

Name="SaveEmailAddressTaskButton" VerticalAlignment="Top"

Width="409" Click="OnSaveEmailAddressTask" />

<Button Content="SavePhoneNumberTask" Height="72"

HorizontalAlignment="Left" Margin="26,420,0,0"

Name="SavePhoneNumberTaskButton" VerticalAlignment="Top"

Width="409" Click="OnSavePhoneNumberTask" />

(81)

private EmailAddressChooserTask emailAddressChooserTask; private PhoneNumberChooserTask phoneNumberChooserTask; private PhotoChooserTask photoChooserTask;

private SaveEmailAddressTask saveEmailAddressTask; private SavePhoneNumberTask savePhoneNumberTask; // Constructor

public MainPage() {

InitializeComponent();

this.emailAddressChooserTask = new EmailAddressChooserTask(); this.emailAddressChooserTask.Completed += new

EventHandler<EmailResult>(emailAddressChooserTask_Completed); this.phoneNumberChooserTask = new PhoneNumberChooserTask(); this.phoneNumberChooserTask.Completed += new

EventHandler<PhoneNumberResult>(phoneNumberChooserTask_Completed); this.photoChooserTask = new PhotoChooserTask();

this.photoChooserTask.Completed +=new

EventHandler<PhotoResult>(photoChooserTask_Completed); this.saveEmailAddressTask = new SaveEmailAddressTask(); this.saveEmailAddressTask.Completed += new

EventHandler<TaskEventArgs>(saveEmailAddressTask_Completed); this.savePhoneNumberTask = new SavePhoneNumberTask(); this.savePhoneNumberTask.Completed += new

EventHandler<TaskEventArgs>(savePhoneNumberTask_Completed); }

(82)

private void OnEmailAddressChooserTask(object sender, RoutedEventArgs e) {

this.emailAddressChooserTask.Show(); }

private void OnPhoneNumberChooserTask(object sender, RoutedEventArgs e) {

this.phoneNumberChooserTask.Show(); }

private void OnPhotoChooserTask(object sender, RoutedEventArgs e) {

this.photoChooserTask.Show(); }

private void OnSaveEmailAddressTask(object sender, RoutedEventArgs e) {

this.saveEmailAddressTask.Email = "dkkang@gmail.com"; this.saveEmailAddressTask.Show();

}

private void OnSavePhoneNumberTask(object sender, RoutedEventArgs e) {

this.savePhoneNumberTask.PhoneNumber = "051-320-1724"; this.savePhoneNumberTask.Show();

(83)

void emailAddressChooserTask_Completed(object sender, EmailResult e) {

if (e.TaskResult == TaskResult.OK) {

MessageBox.Show("선택된 이메일 주소는 "+e.Email+" ("+e.DisplayName+")"); }

}

void phoneNumberChooserTask_Completed(object sender, PhoneNumberResult e) {

if (e.TaskResult == TaskResult.OK) {

MessageBox.Show("선택된 전화 번호는 " + e.PhoneNumber + " (" + e.DisplayName + ")"); }

}

void photoChooserTask_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { MessageBox.Show("이미지 "+e.OriginalFileName+" 가 선택됨"); } }

(84)

void saveEmailAddressTask_Completed(object sender, TaskEventArgs e) { if (e.TaskResult == TaskResult.OK) { MessageBox.Show("이메일 주소가 저장됨"); }

else if (e.TaskResult == TaskResult.Cancel) {

MessageBox.Show("이메일 주소 저장이 취소됨"); }

else {

throw new NotImplementedException(); }

}

void savePhoneNumberTask_Completed(object sender, TaskEventArgs e) {

if (e.TaskResult == TaskResult.OK) {

MessageBox.Show("전화 번호가 저장됨"); }

else if (e.TaskResult == TaskResult.Cancel) {

MessageBox.Show("전화 번호 저장이 취소됨"); }

else {

throw new NotImplementedException(); }

(85)
(86)

에뮬레이터에서 정상적으로 지원되지 않는 런처와 츄

CameraCaptureTask – 프리뷰 화면이 검은색으로만 제공됨

EmailComposeTask – 기능이 제공되지 않음

MarketPlaceReviewTask – LiveID가 없으므로 에러 메시지가

보임

MediaPlayerLauncher – 음악파일이 재생되긴 하지만, 이미더

파일은 렌더링되지 않음

PhoneCallTask – 가짜 GSM 네트워크와 SIM을 사용하므로,

항상 전화 연결이 이루어짐

SmsComposeTask – 가짜 GSM 네트워크와 SIM을 사용하므

로, 항상 메시지 전송이 이루어짐

런처와 츄저는 Tombstone 현상을 발생시킬 수 있음

을 주의할 것

(87)
(88)

푸시 노티피케이션

푸시 노티피케이션 서비스 구조

푸시 노티피케이션 타입

애플리케이션에서 푸시 노티피케이션 사용법

기존 노티피케이션 채널 검색

새로운 노티피케이션 채널 생성

노티피케이션 채널의 URI에 대한 클라우드 서비스로의 전송

Tile과 Toast 노티피케이션에 대한 등록

수신된 푸시 노티피케이션에 대한 처리

(89)

애플리케이션과 백-엔드 서비스(Back-End

Service) 간의 통신 채널

네트워크 서비스와 연계된 백그라운드 상태에서

서비스와 관련한 상태 변화나 이벤트를 받는 애플

리케이션을 구현해야 한다면, 푸쉬 노티피케이션

을 활용하면 됨

특정 애플리케이션에 관련된 새로운 메시지가 있

음을 알려줘 사용자가 해당 애플리케이션을 실행

하도록 하기 위한 트리거(trigger)를 제공받게 해

(90)

구성 요소

클라우드(Cloud) 서비스 (또는 웹 서비스) – 윈도우폰과 통신하는 백-엔

드 서비스

Microsoft Push Notification (MPN) 클라이언트 – 윈도우폰에서 MPN

서버와 프로토콜 통신을 위해 구동되는 서비스

MPN 서비스 – 클라우드 서비스를 대신해 윈도우폰으로 푸시 노티피케이

(91)

푸시 노티피케이션을 받기 원하는 애플리케이션은 MPN 서비스

(또는 서버)에 하나의 노티피케이션 채널 개설을 요청함

MPN 서비스는 요청한 노티피케이션 채널 개설이 완료되면, 노티

피케이션 채널을 구별하기 위한 URI를 애플리케이션으로 리턴함

애플리케이션은 MPN 서비스로부터 전달받은 URI를 클라우드 서

비스로 전송함

클라우드 서비스에서 이 URI를 윈도우폰으로 푸시 노티피케이션을 보내

기 위한 주소로 사용하기 때문임

클라우드 서비스에서는 전달받은 URI 주소로 푸시 노티피케이션

전송이 필요한 경우, XML 형태의 MPN 프로토콜로 메시지를 구

성해 MPN 서비스에 메시지 전송을 요청함

MPN 서비스에서는 클라우드 서비스로부터 전달받은 푸시 노티

피케이션을 타입에 맞게 윈도우폰에 전송함

쉘은 푸시 클라이언트를 통해 수신된 푸시 노티피케이션을 각 타

입에 맞게 처리함

(92)

타일 노티피케이션 (Tile Notification)

스타트 화면에 고정되어 있는 타일(Tile) 화면을 통해서 애플리

케이션 또는 이에 대한 내용을 동적으로 표현해 주는 노티피케

이션 타입

클라우드 서비스에서는 타일의 백그라운드 이미지, 카운터 (또

는 배지), 타이틀 부분에 대한 컨트롤이 가능함

토스트 노티피케이션 (Toast Notification)

현재 사용자 화면에 오버레이되어 보여지는 노티피케이션 타

로우 노티피케이션 (Raw Notification)

애플리케이션에서 푸시 노티피케이션의 사용없이 클라우드 서

비스로부터 메시지를 받기를 원할 때 쓰이는 노티피케이션 타

애플리케이션이 포어그라운드에서 실행되지 않을 때에는 푸시

노티피케이션 서비스에 의해 버려짐

(93)

기존 노티피케이션 채널 검색

새로운 노티피케이션 채널 생성

노티피케이션 채널의 URI에 대한 클라우드 서비스

로의 전송

Tile과 Toast 노티피케이션에 대한 등록

수신된 푸시 노티피케이션에 대한 처리

(94)
(95)

새로운 노티피케이션 채널 생성을 요청하기 전에,

MPN 서버 이전에 생성된 유효한 노티피케이션 채

널이 있는지를 체크함

기존의 노티피케이션 채널 검색은

HttpNotificationChannel 클래스의 Find() 메소드

를 사용함

channel =

HttpNotificationChannel.Find(ChannelName);

HttpNotificationChannel 클래스를 사용하기 위

해서는 Microsoft.Phone.Notification 네임스페

이스를 추가해야 함

(96)

만일 유효한 노티피케이션 채널을 찾지 못했다면, 새로운 노티피

케이션 채널을 HttpNotificationChannel 클래스의 생성자를 이

용해서 생성함

생성자의 패러미터로는 일반적으로 노티피케이션 채널의 인스턴

스를 구별하기 위한 채널 이름과 클라우드 서비스의 이름을 사용

channel = new HttpNotificationChannel(ChannelName,

ServiceName);

이렇게 노티피케이션 채널이 문제없이 개설되면 발생되는

ChannelUriUpdated 이벤트에 대한 핸들러를 추가해야 함

channel.ChannelUriUpdated += new

EventHandler<NotificationChannelUriEventArgs>(channel_Channel

UriUpdated);

이는, 다음에 나오는 Open 메소드가 비동기적으로 동작하기 때문에, 채

널의 개설 여부에 대한 결과를 받기 위해서임

채널이 생성되고, 필요한 이벤트들에 대한 핸들러를 추가하고,

필요한 채널 이벤트들에 대해 가입을 하면, 채널을 개방(open)함

channel.Open();

(97)

클라우드 서비스에서 윈도우폰으로 푸시 노티피케이

션을 보내기 위해서는 노티피케이션 채널에 대한 URI

를 알고 있어야 함

이를 위해, 기존에 사용하던 또는 새로 생성된 노티피

케이션 채널에 대한 URI를 클라우드 서비스로 전송해

야 함

string baseUri =

"http://localhost:8000/RegirstatorService/Register?uri={

0}";

string theUri = String.Format(baseUri,

httpChannel.ChannelUri.ToString());

WebClient client = new WebClient();

(98)

애플리케이션이 실행되지 않은 상태에서도 타일과

토스트의 MPN 메시지를 푸시 노티피케이션으로

받기 위해서 쉘과 해당 애플리케이션 사이를 바인

딩함

if (!_channel.IsShellTileBound)

{

Collection<Uri> uris = new Collection<Uri>();

uris.Add(new Uri("http://chris.59north.com/"));

_channel.BindToShellTile(uris);

}

if (!_channel.IsShellToastBound)

_channel.BindToShellToast();

(99)

수신된 푸시 노티피케이션은 노티피케이션 채널

생성 시 설정한 이벤트 핸들러에서 처리함

// 수신된 푸시 노티피케이션에 대한 이벤트 핸들러

myPushChannel.HttpNotificationReceived += new

EventHandler<HttpNotificationEventArgs>(myPushC

hannel_HttpNotificationReceived);

//푸시 채널에서의 일반적인 에러에 대한 이벤트 핸들러

myPushChannel.ErrorOccurred += new

EventHandler<NotificationChannelErrorEventArgs>(

myPushChannel_ErrorOccurred);

참조

관련 문서

– Banner 클래스라는 기존의 클래스를 이용해서, Print 인터페이스 를 충족시키는(즉, 구현하는) 클래스를 만들고자 한다... 

• 애플리케이션의 여러 자원들과 메인 프레임 클래스, View 클래스, Document 클래스 등을 하나의 묶 음으로 가지는

• 파일 열기를 선택하면 그림과 같이 실행되고 VI를 찾기 위한 열(open) 파일 선택 대화상자가 화면에 나타난다. VI를 선택한 후

적절한 영양은 운동/훈련에 의한 상해를 줄이고, 상해로 부터의 회복 속도를 빠르게 해 훈련에 따른 최적의 신체 상태를 유지시킴.. 적절한 영양의 공급은 경기를

서버 스토리지 네트워크를 하나의 인프라로 구현 베어메탈을 클라우드처럼 빠르게 인프라 구축 및 운영. 를 통한

It is impossible to change the voltage across a capacitor by a finite amount in zero time, for this requires an infinite current through the capacitor.. (A capacitor resists

• 그러나 표본화 정리가 계속 유효하여 표본화 주파수를 f s &gt; 2B가 되도록 선택하면 스펙트럼 중첩이 발생하지 않으며 , 저역통과 필터를 사용하면

-매립지에 폐기된 유기성 물질이 수분, 온도, pH, 미생물 등의 영향을 받아 단계 적으로 분해되어 발생하는데, 혐기성 조건이 형성되는 시기부터 메탄가스와 산