광고 수익은 기아대책 서울본부에 기부합니다.

2013.05.24 16:33 잡담

https://www.youtube.com/watch?feature=player_embedded&v=0joucugodMc

'잡담' 카테고리의 다른 글

겨울 왕국 Let it go  (0) 2014.01.27
전화 모니터링 체크 리스트 라고 합니다.  (0) 2013.06.04
NS 윤지 - if yoo love me(130521)  (0) 2013.05.24
댄스~  (0) 2013.05.23
손연재 섹시 댄스  (0) 2013.05.09
Delicate - Damien Rice  (0) 2013.05.06
posted by Town One townone

댓글을 달아 주세요

2013.05.24 16:00 Windows8/Windows Store App

http://cafe.naver.com/metroapp/130

posted by Town One townone

댓글을 달아 주세요

2013.05.24 12:39 Windows8/Windows Store App
http://cafe.naver.com/metroapp/104

 

posted by Town One townone

댓글을 달아 주세요

2013.05.24 11:57 Windows8/WPF

출처 : http://rageworx.tistory.com/894

 

M$.NET/VS2005/C# 에서 USB camera 해상도 설정 관련 사항.

Developement 2010/06/09 10:19

초접사 USB cam 으로 찍은..

WPF 란걸 써야 하는 조건이라면 어쩔 수 없이 개발자들은 M$ 의 덩치크고 메모리킬러 인 .NET + C# 이라는 조건을 받아 들여야 할 것입니다.
WPF 란 이쁘고 화려한 UI 까지는 다 좋은데, 안타깝게도 이 방식은 제가 볼때 Layered Window 위에다 .NET 이 열심시 이미지와 각종 컴퍼넌트 등을 그리고 있는 걸 합니다.
또한 GDI+ 를 wrapping 한 듯한 rendering 속도를 보여 주는 걸로 보아 조금 답답한 면도 있구요.

일단 C# 선생은 제가 볼때 (절대 제 게인적인 생각입니다) 10년 전 부터 제가 써온 Delphi 가 채용하고 있는 Application Framework + 객체지향 개념과 java 등등이 잘 버무려져 있는 무거운 언어 입니다. 다른 점 이라면, WPF 라는 새로운 UI 개념이 탑재 되어 있다는 거겠지요.
Java 처럼 GC(가비지 콜렉터)가 있어서 new 를 볼 수는 있지만 delete 는 보이지 않습니다...
그래서 WPF + 조금 복잡한 application 이 탄생하면 메모리를 한 100MB 는 기본으로 쓰는 듯 합니다.

잡설을 일단 접고, 현재 C# 에서 DirectX 의 DirectShow 를 쓰려면 OpenSource 인 DShow 라이브러리를 사용해야 합니다.
이 방식은 WPF 의 윈도우 핸들에서는 사용할 수 없으며, 표준 window 에만 적용이 될 수 있습니다.

C# 에서는 C/C++ 과는 달리 #include .. 대신에 using namespace 를 사용합니다. 
(이 using 은 Delphi 에서 이미 uses 라는 표준 Pascal 문법과 매우 유사하다는 건 .. 저만의 생각이겠죠?)
제작하는 project root 에 DShow 라이브러리를 넣고 using DShowLibrary; 와 using System.Runtime.InteropServices.ComTypes; 를 선언 함 으로서 DShow 를 사용할 준비가 완료 됩니다.

DShow 를 쓰려면 일단 해당 클래스가 다음 클래스를 상속받는 구조가 되어야 합니다.
IDisposable
ISampleGrabberCB
IDisposable 은 preview 를 위한 윈도우 컨트롤 후 메모리를 날리기 위해 필요한 .Dispose(); 를 위해 필요하고,
ISampleGrabberCB 는 DShow 에서 기정의 한 이미지 및 동영상 캡쳐를 위한 SampleCB, BufferCB 때문에 필요한 부분 입니다.

이제 DShow 로 USB camera 를 생성 하기 위해서는 다음 사항이 먼저 class 내에 정의 되어 있어야 합니다.
        private IBaseFilter _capFilter; 
        private IGraphBuilder _graphBuilder;
        private ICaptureGraphBuilder2 _captureGraphBuilder; 
        private ISampleGrabber _sampleGrabber;
        private IMediaEventEx _mediaEventEx;
        private IVideoWindow _videoWindow;
        private IBaseFilter _baseGrabFilter;
        private IAMStreamConfig _streamConfig;
위 사항은 기본적으로 USB camera 의 영상을 가져오고 캡쳐 하기 위해 필요한 인터페이스들 이 되며, 이는 모두 COM 에서 얻어 오는 구조가 됩니다.

DShow 에서 가장 처음 알아야 하는 것은 바로 USB 영상 장비의 Index 입니다.
이 USB 장비들은 DShow 내의 DsDevice 클래스로 부터, GetDeivcesCat() 함수로 얻어 올 수 있습니다.
간단히 각 장치를 알아 와서 뭔가 한다면 다음 처럼 만들 수 있겠습니다.
foreach (DsDevice ds in DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice))
{
    deviceNames.Add(ds.Name);
}
C# 부터는 foreach() 가 있어서 for() 대신에 유용하게 쓸 수 있는 것이 있어서 단순 목록은 물론, 검색 등에 다양하게 사용이 가능합니다.
각 장치의 순서가 바로 그 장치의 index 가 되며, 이중 필요한 장비를 최기화 한다면 다음 과 같이 할 수 있겠습니다.
_capFilter = CreateFilter(_deviceIndex);
if (null == _capFilter) return S_FALSE;
USB 카메라를 처음 접근 하기 위해서는 CaptureFilter를 먼저 생성해야 합니다.
그런다음, IGraphBuilder 인터페이스를 통해 새로운 필터그래프를 하나 만들어야 합니다.
_graphBuilder = (IGraphBuilder)new FilterGraph();
if (null != _graphBuilder)
{
    ...................
}
새로운 클래스 나 메서드 등을 만들때 외에 일반적인 type-cast 를 한다면, C# 에서는 C/C++ 처럼 type-cast 를 쓸 수도 있지만 "as" 라는 것이 있어서 특정 캐스팅을 다음과 같이 할 수도 있습니다.
_mediaControl        = _graphBuilder as IMediaControl;
이건 마치 VisualBasic 같은 느낌도 듭니다 .. -_-;;
이제 _graphBuilder 가 생성 되었다면 각 중요한 아이들을 잡아 줘야 겠죠.
다음 처럼 할 수 있습니다.
_captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
_sampleGrabber       = (ISampleGrabber)new SampleGrabber();
_mediaControl        = _graphBuilder as IMediaControl;
_videoWindow         = _graphBuilder as IVideoWindow;
_mediaEventEx        = _graphBuilder as IMediaEventEx;
_baseGrabFilter      = _sampleGrabber as IBaseFilter;
이걸로 끝이면 참 편리 하겠지만 DShow 는 좀 더 많은 일을 해야 합니다 .. -_-;;;
다음으로 필요 한 것은 _captureGraphBuilder 에 이미 만들어진 _graphBuilder (FilterGraph 임) 를 지정해 줘야 합니다.
hr = _captureGraphBuilder.SetFiltergraph(_graphBuilder);
DsError.ThrowExceptionForHR(hr);
hr 은 C# 에 HRESULT 형이 없으므로 그냥 int 로 선언 해 쓰면 됩니다.
물론 C/C++ 에서는 HRESULT 를 사용해 주시는게 맞습니다만..
DsError 클래스는 DShow 에서 발생하는 오류를 HR 값을 가지고 Throw Exception 처리를 해 줍니다.
try - catch - finally 라는 개념을 잘 안쓰던 C/C++ 개발자라면 조금 생소한 부분일 수 도 있겠습니디만 ..
이 try -- catch 부분은 80386 CPU 부터 CPU 상에서 지원되는 몇가지 기능을 활용하는 훌륭한 기능 입니다. 나온지 꽤 오래 되었지만 쓸 수 있는 언어가 많지 않았지요.

이제 다음으로 필요한 건, _captureGraphBuilder 에 지정한 _graphBuilder 에 또 다시 제일 처음 생성한 _capFilter 를 이름을 붙여 집어 넣어 줘야 합니다 ... 귀찮지만 해 줘야 합니다 ... 아놔 ...
hr = _graphBuilder.AddFilter(_capFilter, "video device");
DsError.ThrowExceptionForHR(hr);
붙이는 이름은 마음대로 넣어도 됩니다만, 나중에 이름으로 찾아 써야 할 때를 고려 한다면 좋게 지어 넣어 주는 센스를 가지는 것 또한 나쁘진 않습니다.
물론 C# 과 .NET 조합은 모든 문자열이 UniCode 임을 고려 해야 합니다. C++ 에서 LPWStr 형과 동일 합니다.

이쯤 오면 대부분 다음엔 바로 _captureGrabber 를 만들고 Stream render 를 설정해 버리는 예제 코드들로 인터넷에 도배가 되어 있을 겁니다.
하지만 이래서는 연결된 USB cam 에 대한 정보를 내가 먼저 알고 뭔가 하기란 어려워 지게 되죠.
그래서!

바로 이 시쯤에서 _streamConfig 을 설정하고, 이로부터 장치가 지원하는 해상도를 알아 오도록 합니다.
가장 중요한 것은 _streamConfig 을 _captureGraphBuilder 로 부터 찾아내 와야 합니다.
COM 에서 가장 많이보는 FindInterface() 함수를 사용합니다.
또한 C# 에서는 IntPtr 이란 것이 있어서 포인터의 주소를 얻어오는 독특한 구조를 가끔 사용함으로 다음 예제에서 처럼 기정의된 구조에 맞춰 사용해 줘야 하는 점도 있습니다.
일단 StreamConfig 을 가져오는 부분이 빈번하게 발생하는 걸 고려 해서 간단히 함수를 만들어 보면 다음과 같은 구조로 되더군요. 물론 더 좋은 방법이 있다는걸 생각해 보셔야 합니다.
01 private IAMStreamConfig GetStreamConfig()
02 {
03     Guid IID_IAMStreamConfig = typeof(IAMStreamConfig).GUID;
04     IAMStreamConfig retSC = null;
05     object pObj = null;
06     int hr = -1;
07  
08     hr = _captureGraphBuilder.FindInterface(PinCategory.Capture,
09                                             MediaType.Video,
10                                             _capFilter,
11                                             IID_IAMStreamConfig,
12                                             out pObj);
13     DsError.ThrowExceptionForHR(hr);
14  
15     if (pObj != null)
16     {
17         retSC = pObj as IAMStreamConfig;
18     }
19  
20     return retSC;
21  
22 }
자, 이제 지원하는 해상도 정보를 얻어 오려면 다음 루틴 처럼 만들 수 있습니다.
01 if(null == _streamConfig)
02     _streamConfig = GetStreamConfig();
03  
04 int iCount, iLen, iSize = 0;
05  
06 if (_streamConfig != null)
07 {
08     hr = _streamConfig.GetNumberOfCapabilities(out iLen, out iSize);
09     DsError.ThrowExceptionForHR(hr);
10  
11     if (iLen > 0)
12     {
13         for (iCount = 0; iCount < iLen; iCount++)
14         {
15             AMMediaType aMM = new AMMediaType();
16  
17             IntPtr pSCC = IntPtr.Zero;
18             pSCC = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(VideoStreamConfigCaps)));
19             VideoStreamConfigCaps aSCC = new VideoStreamConfigCaps();
20  
21             hr = _streamConfig.GetStreamCaps(iCount, out aMM, pSCC);
22             DsError.ThrowExceptionForHR(hr);
23             aSCC = (VideoStreamConfigCaps)Marshal.PtrToStructure(pSCC, typeof(VideoStreamConfigCaps));
24  
25             VideoInfoHeader pVIH = new VideoInfoHeader();
26             Marshal.PtrToStructure(aMM.formatPtr, pVIH);
27             // 이제 여기에서 pVIH 에 있는 bmiHeader 를 보고 해상도와 지원되는 plane, bpp 등을 알아 옵니다.
28             // 그리고 다음 코드를 ...
29  
30             Marshal.FreeCoTaskMem(pSCC);
31             DsUtils.FreeAMMediaType(aMM);
32         }
33     }
34 }

처음 C# 을 쓸대 포인터 에서 구조체/클래스 간으로 전환 하는 부분이 적응이 매우 어려웠었습니다.
Marshal 이라는 게 C# 에서 참 중요한 부분인 듯 하게 느껴지는건 이걸 처음 C/C++ 코드에서 가져올때 인 듯 하네요.
위 코드를 통해서 VideoInfoHeader 를 이용한 지원 해상도와 정보를 알아 왔으니 이젠 해상도를 설정 할 차례 입니다.
해상도 설정은 _streamConfig 에 하게 되며, _streamConfig 에 지정된 해상도는 알아서 _sampleGrabber 에 적용되게 됩니다.

코드를 보면 ...
01 if (null != _streamConfig)
02 {
03     int hr = -1;
04  
05     AMMediaType pDefaultMMT = new AMMediaType();
06  
07     hr = _streamConfig.GetFormat(out pDefaultMMT);
08     DsError.ThrowExceptionForHR(hr);
09  
10     VideoInfoHeader pDefaultVIH = (VideoInfoHeader)Marshal.PtrToStructure(pDefaultMMT.formatPtr, typeof(VideoInfoHeader));
11  
12     foreach(AMMediaType pMMT in _videoResolutionList)
13     {
14         VideoInfoHeader pVIH = (VideoInfoHeader)Marshal.PtrToStructure(pMMT.formatPtr, typeof(VideoInfoHeader));
15         if((pVIH.BmiHeader.Width == width) && (pVIH.BmiHeader.Height == height) &&
16             (pVIH.BmiHeader.Planes == pDefaultVIH.BmiHeader.Planes)&&
17             (pVIH.BmiHeader.Compression == pDefaultVIH.BmiHeader.Compression))
18         {
19             hr = _streamConfig.SetFormat(pMMT);
20             DsError.ThrowExceptionForHR(hr);
21             retBl = true;
22         }
23     }
24     DsUtils.FreeAMMediaType(pDefaultMMT);
25 }

참고 : 위 코드에서 _videoResolutionList는 List<AMMediaType> 객체로 만들어 두었습니다.
나름 안전한 방법을 생각해서 만든 코드이라 복잡합니다만 , 핵심은 바로 _stramConfig.SetFormat(); 함수 입니다. SetFormat() 을 적용할 수 있는 시점은 바로 _captureGraphBuilder 에 RenderStraem() 을 지정하기 전 입니다.
RenderStream() 을 지정하고 나서는 _streamConfig 에 SetFormat() 을 하게 되면 잘못된 미디어 오류가 발생하게 됩니다.

그래서 RenderStream() 을 지정하기 전에 반드시 _streamConfig 에 먼저 해상도 조절을 해 두어야지만 적용이 가능하게 됩니다.

이 부분에 대해서는 구글링을 아무리 해도 나오는 게 없었던지라 ..
노가다 뛰어서 알아내어야 하더군요 .. OTL...
혹시나 해서 포스팅 해 봅니다.
posted by Town One townone

댓글을 달아 주세요

2013.05.24 11:18 Windows8/Windows Store App
http://www.microsoft.com/visualstudio/kor/downloads#d-2012-express

 

posted by Town One townone

댓글을 달아 주세요

2013.05.24 11:13 Windows8/Windows Store App

KOR : http://msdn.microsoft.com/ko-kr/library/windows/apps/windows.media.mediacontrol

EN : http://msdn.microsoft.com/en-us/library/windows/apps/windows.media.mediacontrol.aspx

 

posted by Town One townone

댓글을 달아 주세요

2013.05.24 10:46 Windows8/Windows Store App
MSDN Blogs > Windows 8 앱 개발자 블로그 > Windows 8 앱을 돋보이게 하는 미디어 재생

Windows 8 앱을 돋보이게 하는 미디어 재생

  • Comments 0

Microsoft는 보다 향상된 앱 경험을 제공하기 위해 Windows 8에서 일부 오디오 시스템을 변경하였습니다. 이 글에서는 이러한 변경 사항에 대해 알아보고, 미디어 앱에서 이를 활용하는 방법을 살펴보겠습니다. 이러한 정보가 특히 백그라운드에서 오디오 재생 시 Windows 스토어 앱에서 오디오가 작동하는 방식을 이해하는 데 도움이 되기를 바랍니다. 그럼, 일반 사용자 시나리오에 대한 설명부터 시작하겠습니다.

여러분이 Windows 음악 앱으로 좋아하는 밴드의 노래를 듣고 있는데, 친구가 자신이 좋아하는 달콤한 라이브 버전의 음악 mp3를 전송합니다. mp3를 열자 Windows Media Player가 실행되고 노래를 재생합니다. 그러자 여러분이 좋아하는 음악과 친구가 좋아하는 음악이 동시에 재생됩니다. 그때 학교에서 여동생을 데려올 시간임을 알리는 귀에 거슬리는 경보가 울립니다. 여러분은 짜증스럽게 랩톱을 끕니다. 이제 컴퓨터의 사운드를 보다 효과적으로 관리하는 방법을 알아보겠습니다.

Windows 8 앱에서는 재생 관리자와 미디어 전송 컨트롤을 도입하여 이 문제를 해결했습니다. 재생 관리자는 오디오 스트림에 동작을 할당하는 오디오 범주와 오디오 앱을 사용합니다. 포그라운드에서 수신되는 오디오 스트림은 오디오가 항상 재생되도록 합니다. 하지만 재생 관리자는 스트림에 태그를 지정하여 포그라운드와 백그라운드의 여러 스트림을 처리하는 방법에 대해 지능적인 결정을 내릴 수 있습니다.

예를 들어 음악을 재생 중인 백그라운드 지원 앱을 백그라운드로 이동한 다음 포그라운드에서 음악을 재생할 새 앱을 실행한 경우, 재생 관리자는 백그라운드 앱의 오디오를 음소거합니다. 이는 보다 유연하고 직관적인 사용자 경험을 제공합니다. 사용자는 듣고 싶은 것만 듣고, 듣고 싶지 않은 것은 듣지 않을 수 있습니다. 또한 알림(예: 경보 및 벨소리)용 백그라운드 음악의 지능형 감쇠를 추가하고, 미디어 전송 컨트롤에 손쉽게 액세스하여 시작 및 중지하거나 다음/이전 트랙으로 건너뛰는 등 앱의 원치 않는 소음으로부터 해방될 수 있도록 설계된 시스템을 사용할 수 있습니다.

새로운 기능을 추가하게 된 배경

이전 버전의 Windows에서는 사용자가 여러 응용 프로그램을 동시에 열고 실행할 수 있었습니다. 오디오를 켜 놓은 상태로 하나의 대형 모니터에서 미디어 플레이어를 최소화하고 문서 작업과 웹 검색을 동시에 수행할 수 있었습니다. 또한 두 대의 모니터에서는 훨씬 많은 멀티태스킹을 수행할 수 있었습니다. Windows 8의 새로운 몰입형 환경에서는 화면에 동시에 표시할 수 있는 앱 수가 변경되었습니다. 주 화면과 끌어온 화면에 각각 하나의 앱만 있는 경우 사운드가 재생되는 앱이 배경 스택에 있으면 해당 앱을 찾기가 더 어렵습니다. 이러한 이유로 재생 관리자와 미디어 전송 컨트롤을 개발하게 되었습니다. 이러한 기능이 있으면 필요할 때 음악을 훨씬 쉽게 시작하고 중지할 수 있습니다. 또한 재생 관리자는 사운드를 재생하지 않아야 하는 앱을 음소거할 수 있으므로 사용자가 앱 스택을 뒤로 살짝 밀어 음소거할 필요가 없습니다.

이 환경에는 데스크톱에서 지원하는 오디오 믹서가 없습니다. 데스크톱용 앱이 있지만 관련 앱 볼륨을 조정하기 위해 데스크톱에 팝업하는 것은 편리한 경험이 아니라고 생각했기에 여기에 앱을 표시하지 않기로 했습니다. 대신 앱에 볼륨 컨트롤을 포함하지 않는 것이 좋겠다고 생각했습니다. 전체 볼륨 환경을 간소화하는 데 유용한 사용자 중심의 마스터 볼륨 조절도 이러한 방식이지만 이와 관련한 내용은 여기서 다루지 않습니다.

스트림 범주

시스템에서 오디오 스트림을 들을 수 있는 경우와 들을 수 없는 경우를 관리할 수 있도록 하기 위해 스트림 범주를 추가했습니다. 이를 통해 이제 Windows에서 오디오를 들어야 하는지 여부에 대한 몇 가지 논리적 결정을 내릴 수 있습니다. 오디오 범주에 따라 앱이 '포그라운드'(장치 디스플레이에 앱이 표시됨)에 있거나 '백그라운드'(다른 앱에 의해 앱이 숨겨짐)에 있는 경우 스트림이 처리되는 방식이 결정됩니다. 앱을 시작하거나 화면에서 살짝 밀면 포그라운드로 전환됩니다. 또한 끌어온 경우에도 포그라운드에서 유지됩니다.

예를 들어 몇 가지 부수적인 사운드(대화형 종소리 또는 클릭)를 재생하는 앱은 백그라운드에서 들리지 않는 것이 좋을 수 있습니다. 이는 불필요한 소음일 수 있으므로 재생 관리자는 이 앱이 백그라운드로 전환되는 즉시 이 앱을 음소거합니다. 그러나 음악 재생 목록을 재생하는 미디어 앱은 음악을 들으면서 웹을 검색하거나 작업할 수 있도록 계속 '재생되어야' 합니다.

다음은 오디오 범주 사용 방법에 대한 간단한 설명입니다. Windows 8 앱에서 오디오를 재생하는 가장 간단한 방법은 오디오 태그를 사용하는 것입니다.

<audio controls="controls"> 
<source src="song.mp3"/>
</audio>

JavaScript

audtag = document.createElement('audio');
audtag.setAttribute("id", "audtag");
audtag.setAttribute("msAudioCategory", "BackgroundCapableMedia");
document.getElementById("MediaElement").appendChild(audtag);
audtag.load();

C#

C#에서는 다음과 같이 오디오 범주를 설정할 수 있습니다.

Playback.SetAudioCategory(AudioCategory.BackgroundCapableMedia);
Playback.SelectFile();

선택할 수 있는 여러 오디오 범주가 있습니다. 아래 표에는 각 범주와 관련된 동작에 대한 설명과 함께 사용 가능한 범주가 나와 있습니다. 앱이 각각의 경우에 따라 다르게 동작하기 때문에 어떤 범주를 어떤 스트림과 연결할지 매우 신중하게 결정해야 합니다.

사용 가능한 스트림 범주

스트림 형식

설명

백그라운드 지원 여부

ForeGroundOnlyMedia

포그라운드에서만 작동하도록 설계되었지만 기존 백그라운드 미디어 사운드를 음소거하는 게임 또는 기타 사운드

  • 게임에 필요한 게임 오디오(댄싱 게임, 음악 게임)
  • 영화(백그라운드로 전환되면 일시 중지되도록 설계됨)

지원 안 함

BackgroundCapableMedia

다음과 같은 백그라운드에서 계속 재생해야 하는 오디오용

  • 로컬 미디어 재생
  • 로컬 재생 목록
  • 스트리밍 라디오
  • 스트리밍 재생 목록
  • 뮤직 비디오
  • 스트리밍 오디오/라디오, YouTube, Netflix 등

지원함

Communications

다음과 같은 스트리밍 통신 오디오용

  • VoIP(Voice over IP)
  • 실시간 채팅 또는 기타 통화 유형

지원함

Alert

반복되거나 실행 시간이 긴 경고음

  • 경보
  • 벨소리
  • 벨 울림 알림
  • 기존 오디오를 줄이는 데 필요한 사운드

지원 안 함

GameMedia

게임에서 재생되는 백그라운드 음악

지원 안 함

GameEffects

다음과 같은 기존 오디오와 혼합되도록 설계된 게임 효과음

  • 공 구르는 소리, 엔진 소리 등
  • 캐릭터 간의 대화
  • 음악이 아닌 모든 사운드

지원 안 함

SoundEffects

경고음, 종소리 및 기타 짧은 소리 같은 기존 오디오와 혼합되도록 설계된 사운드

지원 안 함

Other

분류되지 않은 스트림에 사용되는 기본 스트림 범주

지원 안 함

다음은 오디오 스트림을 분류하는 방법을 결정하는 데 도움이 되는 몇 가지 규칙입니다.

  • 여러 스트림 유형을 사용하려면 이동하는 대로 분리되는 오디오 및 비디오 태그를 동적으로 생성하면 됩니다.
  • Communications 범주를 사용할 경우 기본적으로 대기 시간이 짧은 오디오로 자동 설정됩니다. 이를 통해 양방향 통신 앱을 설계할 때 필요한 단계가 한 단계 줄어듭니다.
  • 반드시 필요한 경우가 아니면 짧은 대기 시간 모드를 사용하도록 오디오 태그를 구성하지 마십시오. 이는 통신 스트림이 기본적으로 짧은 대기 시간 모드로 이미 설정되어 있기 때문입니다. 오디오 스트림이 짧은 대기 시간 모드에 있을 때 통신 스트림이 초기화되는 경우 많은 양의 CPU 리소스가 필요합니다.

스트림 범주 및 앱 동작

[앱 동작은 Metro 스타일 앱에서 오디오 재생에 자세히 설명되어 있습니다.]

앱이 소리를 재생할 것인지는 주로 앱이 포그라운드에 있는지 여부에 달려있습니다. 그러나 통신 앱 및 백그라운드 지원 미디어 앱과 같은 다른 고려 사항이 있는 경우에는 상황이 더 복잡해집니다. 하지만 걱정할 필요는 없습니다. 일반적으로 스트림 형식을 기반으로 하는 앱 동작은 설명하기가 매우 쉽기 때문입니다. 그리고 다음 규칙이 적용됩니다.

  • 앱이 포그라운드에 있는 경우 해당 오디오 스트림의 범주에 관계없이 시스템이 음소거되거나 볼륨을 줄이지 않은 이상 앱의 사운드가 항상 재생됩니다.
  • 백그라운드 지원 오디오 앱은 한 번에 하나만 재생될 수 있습니다(단, 포그라운드에 있는 경우에는 두 개 동시 재생 가능).
  • 통신 앱은 통신 스트림 형식의 전화가 걸려 온 경우 다른 시스템 사운드를 항상 감쇠합니다. 백그라운드 음악이 재생될 때 통화하면서 음악을 다시 들으려면 음악 앱을 포그라운드로 가져오면 됩니다(앱을 끌거나 전체 화면을 앞으로 가져오기). 그러면 규칙 1이 적용됩니다.
  • 포그라운드에 있는 앱의 사운드는 포그라운드 스트림이 백그라운드 스트림과 호환되지 않는 경우 백그라운드 지원 오디오와 혼합됩니다. 예를 들어 ForegroundOnlyMedia 스트림은 백그라운드에서 재생되는 BackgroundCapableMedia 스트림을 음소거하지만 GameEffects는 사용자가 음악을 들으면서 게임을 플레이할 수 있도록 BackgroundCapableMedia와 혼합됩니다.

앱의 범주를 선택한 경우 앱이 예상대로 작동하려면 몇 가지 규칙을 따라야 합니다. 앱의 오디오가 백그라운드에서 재생되도록 하려면 다음과 같이 해야 합니다.

  • 백그라운드 오디오 선언을 앱 매니페스트에 추가합니다.
  • msAudioCategory를 Communications 또는 BackgroundCapableMedia로 설정합니다.
  • 미디어 전송 컨트롤을 위해 앱을 등록해야 합니다(뒷부분에서 자세히 설명).

백그라운드에서 오디오를 재생하지 않는 범주의 경우 백그라운드 지원 미디어 형식을 사용하지 않아도 됩니다. 대신 Other를 선택하거나 GameEffects 또는 다른 관련 형식을 사용합니다.

백그라운드에서 앱을 사용하는 방법에 대한 일반적인 정보는 http://blogs.msdn.com/b/windowsappdev_ko/archive/2012/06/01/10313826.aspx를 참조하세요.

백그라운드 오디오 및 연결된 대기 상태

연결된 대기 상태는 SoC(system-on-a-chip) 장치에서 스마트폰 같은 전원 모드를 지원하는 Windows 8의 새로운 전원 부족 상태입니다. 연결된 대기 상태에서는 장치가 꺼진 것처럼 '보일'뿐 실제로 꺼진 것은 아닙니다. 앱이 계속 백그라운드에서 음악을 재생하고 업데이트를 받고 네트워크를 사용할 수 있습니다. 자세한 내용은 응용 프로그램을 위한 전력 효율성 향상이란 제목의 블로그 글을 참조하세요. 음악 스트리밍 앱의 경우 장치가 연결된 대기 상태에 있을 때 백그라운드 오디오 앱이 네트워크에서 계속 스트리밍하도록 하려면 몇 가지 중요한 단계를 수행해야 합니다.

간단히 말해, 네트워크 연결이 작동하지 않는 경우 앱에서 스트리밍 오디오를 재생할 수 있습니다. 로컬 오디오는 정상적으로 작동하지만 재생 목록을 명령하는 서버가 있는 경우 네트워크가 작동할 때까지 앱에서 다음 노래를 가져오지 못합니다.

장치가 연결된 대기 상태에 있는 동안에도 앱에서 음악을 계속 스트리밍하도록 하려면 다음 세 가지 옵션 중 하나를 사용합니다.

  1. 모든 작업을 자동으로 수행하는 백그라운드 전송 API를 사용합니다.
  2. 소량의 데이터만 전송하면 되는 경우 기존 MF 바이트 스트림을 래핑합니다.
  3. 사용자 지정 Media Foundation 원본 또는 바이트 스트림을 사용합니다.

이러한 옵션에 대한 자세한 내용은 전원 인식 백그라운드 미디어 앱 작성을 참조하세요.

SoundLevel 시스템 알림

SoundLevel 알림을 통해 앱에 사운드를 재생할 수 있는 시점을 알릴 수 있습니다. 재생 관리자를 처음 개발할 때 실제로 음소거되었음을 알리는 알림을 앱에 전송하는 것이 좋을지 확신하지 못했지만, 곧 백그라운드에서 오디오 또는 비디오를 렌더링하고 불필요하게 시스템 리소스를 사용하여 앱이 배터리를 소모할 수 있음을 깨달았습니다. 따라서 SoundLevel 알림을 받도록 앱을 등록한 경우 재생 관리자가 앱의 가청 상태에 따라 다음 세 가지 알림 중 하나를 앱에 전송합니다.

  • SoundLevel(Full) - 앱의 오디오를 들을 수 있음을 의미합니다.
  • SoundLevel(Mute) - 앱의 오디오를 들을 수 없지만 오디오를 재생할 수는 있음을 의미합니다.
  • SoundLevel(Low) - 오디오를 들을 수 있지만 앱이 -28dB 감쇠되어 거의 들리지 않는 상태를 의미합니다.

이제 각 알림이 전송되는 경우와 각 알림에 대한 반응으로 앱에서 수행해야 하는 작업에 대해 알아보겠습니다.

SoundLevel(Full)

SoundLevel(Full) 알림은 다음과 같은 경우에 전송됩니다.

앱에서 수행해야 하는 작업

백그라운드를 지원하지 않는 앱이 백그라운드에서 포그라운드로 전환된 경우

작업이 필요하지 않음

앱이 시작되기 전에 먼저 표시된 경우

작업이 필요하지 않음

SoundLevel(Mute)

SoundLevel(Mute) 알림은 다음과 같은 경우에 전송됩니다.

앱에서 수행해야 하는 작업

백그라운드를 지원하지 않는 앱이 포그라운드에서 백그라운드로 전환된 경우

일시 중지

앱이 재생되는 동안 유사한 다른 스트림 형식이 재생되기 시작한 경우(예: BackgroundCapableMedia가 재생되는 동안 두 번째 BackgroundCapableMedia 스트림이 시작되면 이전 스트림이 음소거됨)

시스템 리소스를 절약하기 위한 일시 중지(일시 중지하지 않을 적절한 사유가 있는 경우 제외)

Communications 스트림 형식이 백그라운드에 있는 경우 다른 Communications 스트림이 포그라운드에서 시작되면 백그라운드의 스트림이 SoundLevel(Mute)됨

통화 대기

SoundLevel(Low)

SoundLevel(Low) 알림은 다음과 같은 경우에 전송됩니다.

앱에서 수행해야 하는 작업

앱에서 오디오를 재생하는 동안 Communications 스트림의 재생이 시작된 경우

사용자가 놓치지 않기를 원하는 콘텐츠를 재생하는 경우 일시 중지합니다. 포그라운드로 전환하지 않을 경우 들을 수 있지만 볼륨이 매우 작기 때문에 일시 중지하는 것이 좋습니다.

 

다음은 SoundLevel 이벤트 등록 및 사용 방법에 대한 예제입니다.

JavaScript

// Create the media control. 

mediaControl = Windows.Media.MediaControl;

// Add event listeners for PBM notifications to illustrate app is
// getting a new SoundLevel and pass the audio tag to the function

mediaControl.addEventListener("soundlevelchanged", soundLevelChanged, false);


function soundLevelChanged() {

// Catch SoundLevel notifications and determine SoundLevel state. If it's muted, pause the player.

var soundLevel = Windows.Media.MediaControl.soundLevel;


switch (soundLevel) {

case Windows.Media.SoundLevel.muted:
log(getTimeStampedMessage("App sound level is: Muted"));
break;
case Windows.Media.SoundLevel.low:
log(getTimeStampedMessage("App sound level is: Low"));
break;
case Windows.Media.SoundLevel.full:
log(getTimeStampedMessage("App sound level is: Full"));
break;
}

C#

// add new handlers
MediaControl.SoundLevelChanged += MediaControl_SoundLevelChanged;
MediaControl.PlayPauseTogglePressed += MediaControl_PlayPauseTogglePressed;
MediaControl.PlayPressed += MediaControl_PlayPressed;
MediaControl.PausePressed += MediaControl_PausePressed;
MediaControl.StopPressed += MediaControl_StopPressed;

// save current handlers
SoundLevelChangedHandler = MediaControl_SoundLevelChanged;

string SoundLevelToString(SoundLevel level)
{
string LevelString;

switch (level)
{
case SoundLevel.Muted:
LevelString = "Muted";
break;
case SoundLevel.Low:
LevelString = "Low";
break;
case SoundLevel.Full:
LevelString = "Full";
break;
default:
LevelString = "Unknown";
break;
}
return LevelString;
}

캡처 및 루프백

또한 캡처 및 루프백에 대한 몇 가지 고려 사항을 추가했습니다. 먼저, 캡처 기반 앱을 만들려는 경우 'Other' 범주를 사용하여 캡처 스트림에 태그를 지정하거나 시스템에서 해당 범주를 할당해야 하지만 더 중요한 것은 캡처 스트림을 다른 범주로 분류할 수 없다는 점입니다. Communications 앱의 경우 렌더 스트림의 레이블을 Communications 스트림으로 지정하면 캡처 스트림에 태그를 지정하지 않아도 됩니다.

또한 시스템에서 SoundLevel(Mute)을 전송한 경우 렌더링, 캡처 및 루프백이 모두 음소거됩니다.

표시 여부 알림을 사용하지 않는 이유

앱 표시 여부는 앱 가청 여부와 밀접한 연관이 있지만 앱을 들어야 하는 시점을 알고 있는 경우 SoundLevel 이벤트만 수신해야 합니다. 표시 여부 이벤트를 사용하면 앱의 가청 상태가 해당 표시 상태와 동기화되지 않을 수 있습니다.

미디어 전송 컨트롤

[전체 사용 설명서는 시스템 전송 컨트롤을 참조하세요.]

전역적으로 사용 가능한 미디어 전송 컨트롤(다음 그림 참조)을 추가하면 음악 앱의 음악을 간편하게 재생하고 제어할 수 있습니다.

시작 화면
그림 1 미디어 전송 컨트롤의 시작 화면 보기

미디어 전송 컨트롤
그림 2 - 앨범 아트와 메타 데이터만 표시하도록 잘린 미디어 전송 컨트롤의 보기

MTC UI(미디어 플랫폼 팀에서 친근하게 지칭하는 이름)를 사용하면 앱이 백그라운드에서 일시 중단된 경우에도 사용자가 포그라운드/백그라운드에 관계없이 오디오를 재생/일시 중지할 수 있습니다. 이 UI는 사용자가 키보드 또는 슬레이트에서 볼륨 단추를 누른 경우에 호출됩니다. 새로운 몰입형 환경과 데스크톱 등 모든 곳에 표시되며, 잠금 화면에도 표시될 수 있습니다. 이는 해당되는 경우 앱에서 사용할 수 있고 사용해야 하는 Windows 8의 유용한 추가 기능입니다.

처음 시나리오(여러 오디오가 한꺼번에 재생되어 사용자가 랩톱을 종료한 시나리오)를 상기해 보면 우리가 이와 같은 전역 전송 컨트롤이 필요하다고 느낀 이유를 알 수 있을 것입니다. 데스크톱과 같이 여러 창을 전환할 필요가 없으므로 사용자는 사운드를 재생하는 앱을 신속하게 중지할 수 있습니다. MTC UI를 볼륨 컨트롤에 연결하는 것이 직관적이며, 이 경우 사용자의 시스템을 한 번의 단추 누름으로 재생하는 것에 대한 많은 아이디어를 얻을 수 있을 것이라고 생각했습니다.

다음은 미디어 앱, 특히 백그라운드 지원 앱을 사용하는 경우 컨트롤에 연결하는 방법입니다.

JavaScript:

// Assign the button object to MediaControls
MediaControls = Windows.Media.MediaControl;

// Add event listeners for the buttons
MediaControls.addEventListener(“playselected”, play, false);
MediaControls.addEventListener(“pauseselected”, pause, false);
MediaControls.addEventListener(“playpausetoggleselected”, playpausetoggle, false);

C#

using Windows.Media;
MediaControl.SoundLevelChanged += MediaControl_SoundLevelChanged;
MediaControl.PlayPauseTogglePressed += MediaControl_PlayPauseTogglePressed;
MediaControl.PlayPressed += MediaControl_PlayPressed;
MediaControl.PausePressed += MediaControl_PausePressed;
MediaControl.StopPressed += MediaControl_StopPressed;

다음 코드 조각은 MediaControl 개체에 이벤트 수신기를 추가하여 이전 트랙 및 다음 트랙 단추를 사용하도록 설정하는 방법을 보여 줍니다.

JavaScript

// enable the previous track button
MediaControls.addEventListener(“previoustrackselected”, previoustrack, false);

// enable the next track button
MediaControls.addEventListener(“nexttrackselected”, nexttrack, false);

C#

MediaControl.NextTrackPressed += MediaControl_NextTrackPressed; 
MediaControl.PreviousTrackPressed -= MediaControl_PreviousTrackPressed;

아티스트 메타 데이터 및 아트워크를 플라이아웃에 추가할 수도 있습니다. 자세한 내용은 위에 언급된 백서를 참조하세요.

MTC UI는 사용 중인 미디어 앱으로 채워지며, 시스템에서 이를 제거할 때까지 UI가 채워진 상태로 유지됩니다. UI가 지워지는 경우는 다음과 같습니다.

  1. 사용자가 앱을 닫은 경우
  2. 사용자가 앱 전환 목록에서 최근에 사용한 앱을 지운 경우
  3. 시스템에서 리소스를 확보하기 위해 앱을 종료한 경우
  4. 앱이 충돌한 경우
  5. 사용자가 컴퓨터를 종료한 경우
  6. 앱이 MTC 컨트롤을 등록 취소한 경우

요약

우리는 새로운 폼 팩터 및 사용자 경험과 함께 완전히 새로운 오디오 패러다임을 Windows 8에 적용하기 위해 열심히 노력했습니다. 오디오 범주는 Windows에 시스템에서 앱을 적절히 처리할 수 있는 컨텍스트를 제공합니다. 앱이 백그라운드 오디오를 재생해야 하는 경우 사용자는 범주를 설정하고 미디어 재생 컨트롤을 연결하여 매니페스트에서 선언하기만 하면 됩니다.

SoundLevel 알림은 사용자가 앱을 들을 수 있는지 알려 줍니다. 이를 통해 백그라운드에서 오디오를 들을 수 없는 경우 해당 오디오를 일시 중지하여 배터리 수명을 절약하는 데 필요한 정보를 얻을 수 있습니다.

미디어 전송 UI는 볼륨 상태를 표시하며, 사용자가 오디오를 신속하게 시작 및 중지하고 미디어 앱에서 아티스트 정보를 가져올 수 있도록 합니다.

이러한 새 기술을 앱에 사용하여 사용자에게 뛰어난 오디오 경험을 제공하시기 바랍니다. 간단한 구현만으로 사용자에 놀라운 경험을 제공할 수 있습니다.

- Windows 프로그램 관리자, Johnny Bregar

posted by Town One townone

댓글을 달아 주세요

2013.05.24 10:45 Windows8/Windows Store App
http://msdn.microsoft.com/en-us/library/windows/hardware/hh770517

 

posted by Town One townone

댓글을 달아 주세요

2013.05.23 15:36 Windows8/WPF

Windows 8 앱 개발 이야기 - 메트로 스타일 앱의 패키징과 배포

[레벨:29]ivoryguard
2012.03.26 08:11:12 (*.161.132.45)
6607
1 / 0

 

이번 글에서는 우리가 개발한 메트로 스타일 앱을 어떻게 패키징하고 배포하는지 살펴보도록 합니다.

 

 

 

메트로 스타일 앱의 배포 방식의 이해

 

윈도우 응용 프로그램의 경우 보통 .exe나 .msi와 같은 설치 파일로 패키징해서 배포합니다. 사실 윈도우 응용 프로그램의 배포는 단순히 파일만 복사해주면 되는 것이 아니라 ActiveX 컴포넌트를 레지스트리 등록하고, 시작 메뉴 등록하고 각종 세팅 등을 해주고, 거기에 설치 가능 여부 확인 및 조건부 설치 등 매우 복잡합니다. 그래서 Install Shield와 같은 전문 설치 파일 생성 프로그램에서는 다양한 배포 옵션을 제어하기 위해서 전용 스크립팅 기능까지 제공하는 것이 일반적이죠. 뭐 간단한 .NET Framework 윈도우 응용 프로그램은 XCOPY 배포도 가능합니다만…

 

이에 비해 모바일 기기용 앱들은 보통 배포에 필요한 파일들을 하나의 파일로 압축해서 배포하는 경우가 많습니다.

예를 들면, 안드로이드는 *.apk, Windows Phone 7은 *.xap 파일 형식으로 모든 파일을 압축해서 배포하게 되지요.

 

여기서 잠깐

*.apk와 *.xap 파일 모두 ZIP 형식으로 압축되어 있기 때문에 기존 압축 유틸리티로 압축을 풀어서 안의 내용을 볼 수 있습니다.


 

 

메트로 스타일 앱도 이와 비슷하게 배포에 필요한 모든 파일을 *.appx라는 파일로 묶어서 배포하게 됩니다. 물론 *.appx 파일 역시 ZIP 압축 형식입니다.^^

 

예를 들면 HelloWorld 앱의 .appx 파일을 압축 프로그램으로 열어보면 다음과 같이 표시됩니다.

 

image_37.png

 

 

 

메트로 스타일 앱에는 .appx 이외에 .appxupload 라는 파일 형식도 있습니다. *.appxupload은 Windows Store에 등록하는데 사용되는 파일로 프로그램 파일인 *.appx와 다른 필요한 파일들을 다시 압축한 파일입니다.

 

 

 

 

따라서, 메트로 스타일 앱의 배포 과정을 그림으로 표현하면 다음과 같이 됩니다.

 

image_2.png

 

 

 

실질적으로는 앱을 등록하는 방법에는 크게 2가지가 있습니다.

  • Visual Studio 11에는 현재 열린 프로젝트를 바로 Windows Store에 업로드해주는 기능이 있습니다.
  • Microsoft 의 메트로 스타일 앱 등록 사이트에 로그인해서 별도로 만들어놓은 .appxupload 파일을 등록합니다.

 

 

 

 

 

 

Package Manifest 설정하기

 

모바일용 앱을 설치할 때 보면 이 앱이 어떤 권한들을 사용하는지 표시해준 다음 설치하게 합니다. 일반적으로 모바일 기기에서는 각 앱이 사용할 수 있는 권한을 제한하고 어떠한 권한들을 사용하는지 사용자에게 확인을 받게 함으로써 보안성을 높이고 있습니다. 예를 들어서, 어떤 앱이 사용자 몰래 GPS를 켜서 사용자의 이동 경로를 몰래 수집할 수도 있겠죠. 그래서 GPS를 사용하는 앱은 설치 시 또는 실행 시 이 프로그램이 위치 정보를 사용한다는 것을 사용자에게 알려주도록 되어 있습니다.

 

메트로 스타일 앱에도 마찬가지로 각 기능의 사용 여부를 지정하는 옵션이 있는데, 바로 Package Manifest에서 이러한 옵션을 설정하게 됩니다. 참고로, 배포를 위한 패키지 생성에 앞서서 반드시 Package Manifest를 먼저 설정해야 합니다.

 

 

 

 

Visual Studio의 Solution Explore에서 Package.appxmanifest를 더블클릭하면 다음과 같은 창이 뜹니다.

 

image_4.png

 

 

 

 

 

Application UI에서는 프로그램의 표시 이름, 설명, 초기 레이아웃, 로고, 스플래시 이미지 등 프로그램의 정보와 모양을 지정할 수 있습니다.

 

image_6.png

 

 

 

 

 

 

Capabilities 탭을 보시면 각 기능의 허용 여부를 지정할 수 있습니다. 예를 들어서 이 프로그램 인터넷에서 정보를 가져오는 RSS 리더라면 반드시 “Internet (Client)” 를 체크해야만 서버에서 RSS 피드를 읽어올 수 있습니다. 이 외에도 위치 정보, 웹 캠, 외장 저장소 등이 접근 권한도 지정할 수 있지요.

 

image_8.png

 

 

 

 

이처럼, 개발하는 앱이 사용하는 기능에 따라서 Capabilities를 설정해줘야 앱이 해당 기능을 사용할 수 있습니다. 한 가지 재미있는 것은 “Enterprise Authentication”인데, Active Directory를 사용하는 엔터프라이즈 인트라넷 환경에서 도메인 크레덴셜을 사용하여 인트라넷 리소스에 접근할 수 있는 권한도 설정이 가능합니다. 이러한 옵션은 다른 모바일 앱에는 없는 옵션으로 기존 윈도우 환경을 배려하고 있네요.

 

 

 

 

Declarations 탭에서는 현재 앱의 추가적인 속성을 정의합니다.

예를 들면, 다음과 같이 파일을 여러 때 이 앱이 지원하는 파일 형식을 지정할 수가 있습니다.

 

image_thumb_4.png

 

 

 

 

마지막으로 Packaging 탭에서는 패키지 생성과 관련된 속성을 지정합니다. 여기에 설정되는 값들은 대부분이 Windows Store를 위한 것들이죠.

 

image_12.png

 

 

 

 

 

 

 

 

 

Visual Studio로 배포 패키지 생성하기

 

 

이제 배포를 위한 Package Manifest 설정이 끝났으면 실제 패키지를 만들어봅시다.

 

Visual Studio의 Project 메뉴 –> Store 메뉴를 보시면 패키징 및 배포와 관련된 메뉴들을 찾을 수 있습니다.

 

image_16.png

 

 

 

 

 

하나씩 살펴보도록 하죠.

 

  • Open Developer Account
    개발자 계정 페이지를 엽니다. 아쉽게도 현재는 아래 나라의 개발자만 접근이 가능합니다.
    근데, 제가 알기로는 Windows 8 컨슈머 프리뷰에서는 이 나라들의 개발자라고 하더라도 허가된 일부 개발자들만 앱을 올릴 수 있는 것으로 알고 있습니다.(확인 필요) 애플의 앱스토어에 앱을 올리려면 개발자 등록을 해야 하는데, 이와 비슷하다고 생각하시면 됩니다.
    image_18.png

 

 

  • Reserve App Name
    자기가 스토어에 올릴 프로그램 이름을 예약하는 기능입니다. 이 기능 역시 한국에서는 아직 안됩니다.
    예를 들어서 어떤 개발자가 “My Hello World”라는 앱을 개발할 계획을 가지고 있을 때 남들이 이 이름을 먼저 사용하지 못하게 미리 확보할 수 있다는 것이죠. 참고로, 앱 이름 예약의 유효기간은 12개월이며 이 기간 내에 앱을 등록하지 않으면 만료됩니다.

 

  • Edit App Manifest
    현재 프로젝트의 Package Manifest를 편집합니다. 위에서 이미 설명했죠.

 

  • Associate App With the Store
    이 기능 역시 우리는 아직 사용할 수가 없습니다. 설명에 따르면  Developer Windows Live ID로 로그인 한 다음 Store쪽의 정보와 현재 프로젝트의 앱을 연결하여 결제 및 알림 시나리오를 테스트할 수 있도록 해준다고 하는군요.

 

  • Capture Screenshots

    앱의 화면을 캡쳐해주는 기능인데 사실은 그냥 시뮬레이터를 실행해줄 뿐입니다. 시뮬레이터에 있는 Capture Screen 버튼을 누르는 것은 우리 몫이죠^^

 

  • Create App Package
    현재 프로젝트를 실제로 패키징 해주는 메뉴입니다.

 

 

 

Create App Package 메뉴를 클릭하면 다음과 같은 창이 뜹니다.

 

image_20.png

 

 

첫번 째 옵션은 Developer Windows Live ID가 필요하므로 아직 사용할 수가 없습니다.

두번 째 옵션을 선택하면 Windows Store를 거치지 않고 로컬에서 테스트할 수 있는 패키지를 생성해줍니다.  현재로서는 이 기능만 사용이 가능합니다.

 

 

 

“Create a package to use locally only”를 선택한 후 Next를 누르면 다음과 같은 화면이 나옵니다.  이 화면에서는 로컬 테스트용 패키지를 생성할 때의 옵션을 지정할 수 있습니다.

각 플랫폼 별로 Configuration을 선택할 수 있으며, 맨 아래에 있는 옵션을 선택하면 앱이 다운되었을 때 분석하는데 도움을 주는 Public Symbol 파일(*.appxsym)을 생성해줍니다.  대부분의 경우 기본값을 사용하면 되겠지요.

 

image_thumb_10.png

 

 

 

 

 

Create 버튼을 클릭하면 다음과 같이 패키지가 잘 생성되었다고 알려줍니다.

화면에 있는 생성 경로를 마우스로 클릭하면 생성된 패키지 폴더가 열립니다.

 

image_thumb_11.png

 

 

 

 

 

 

생성된 폴더를 열어보니 다음과 같이 파일과 폴더가 생성되어 있군요.

 

image_thumb_12.png

 

 

 

 

 

생성된 파일들을 하나씩 살펴보도록 합시다.

 

Create App Package 메뉴에서 자동으로 버전 증가 옵션을 체크하면 위 스크린샷과 같이 패키지를 만들 때마다 버전이 올라가면서 각 버전별로 파일과 폴더가 생성이 됩니다. 그리고, 잘 보시면 각 버전마다 “앱이름.appxupload”“앱 이름” 폴더가 생성되어 있습니다.

 

첫 부분에서 말씀 드렸듯이 .appxupload는 Windows Store용 등록 파일입니다. 이 파일을 “Uplaod App Package” 메뉴를 통해 Windows Store에 올리는 것이죠.

.appxupload 파일을 압축 프로그램으로 열어보면 다음과 같이 실제 앱이 들어있는 .appx 파일과 디버깅용 심볼 테이블 정보를 담고 있는 .appxsym이 들어있음을 보실 수 있습니다.

 

image_thumb_13.png

 

 

 

 

이번에는 생성된 폴더 쪽을 보도록 하죠.

 

image_thumb_14.png

 

 

 

 

 

각 파일에 대한 설명은 다음과 같습니다.

  • Add-AppxDevPackage.bat – 개발용 머신에 설치하기 위한 배치 파일, 해당 머신에 Developer License 필요
  • HelloWorld_1.0.0.9_AnyCPU_Debug.appx – 실행에 필요한 파일이 ZIP 형식으로 압축된 파일
  • HelloWorld_1.0.0.9_AnyCPU_Debug.appxsym – 디버깅용 심볼 파일
  • HelloWorld_1.0.0.9_AnyCPU_Debug.cer – 보안 인증 파일

 

 

 

Add-AppxDevPackage.bat 는 개발용 로컬 머신에 설치하기 위한 배치 파일로 Windows Store를 거치지 않고 로컬에서 바로 앱을 설치할 수 있게 해줍니다. 그냥 더블클릭하면 다음과 같이 관리자 권한으로 실행하라고 친절히 알려줍니다.^^;

 

image_thumb_15.png

 

 

 

 

그렇다고 자기 PC에서 바로 관리자 권한으로 실행하면 오류가 나는데, 이미 자기 PC에서는 Visual Studio에서 빌드하면서 앱이 등록이 되어 있기 때문입니다.  따라서 테스트할 다른 머신에 생성된 폴더를 통째로 복사한 다음 Add-AppxDevPackage.bat 를 관리자 권한으로 실행해야 합니다.

 

 

 

앞 부분에서 .appx에 실제 앱 파일들이 포함되어 있다고 했는데,  HelloWorld_1.0.0.9_AnyCPU_Debug.appx 를 압축 프로그램으로 열어보면 다음과 같이 exe 파일을 비롯한 여러 개의 파일이 안에 들어있습니다.

 

image_thumb_16.png

 

 

 

 

여기서 잠깐

앱을 개발하다 보면 이미지와 같은 외부 리소스를 사용하는 경우가 많습니다.

예를 들면, 아래와 같이 accept.png를 프로젝트에 등록하면 기본적으로 Build ActionContent로 됩니다.

 

image_thumb_18.png

  

이렇게 Content로 등록된 파일들은 빌드시 debug/release 폴더에 복사가 되며 .appx로 패키징할 때도 같이 포함이 됩니다. 다음 스크린 샷을 보시면 .appx에 포함되어 있음을 확인하실 수가 있습니다.

image_thumb_19.png


 

 

 

 

 

좀 장황하게 설명했는데, 정리하면 다음과 같습니다.

 

1) Visual Studio의 Sotre->Create App Package 메뉴 클릭

2) “Create a package to use locally only”를 선택하여 로컬 테스트용 패키지 생성

3) 생성된 폴더를 테스트할 머신으로 복사 후 Add-AppxDevPackage.bat를 관리자 권한으로 실행

 

 

 

생각보다 간단하죠?

 

그런데, 이렇게 보니 마치 안드로이드에서 APK 파일만 복사해서 설치하는 되는 것처럼 Windows Store를 거치지 않고 마구마구 배포되는 거 아닌가 싶은 생각이 드는군요. MS가 바보가 아닌 이상 이렇게 둘 리가 없겠죠? 그래서 Developer License라는 기능이 있습니다.

 

 

 

 

 

 

 

 

Developer License에 대하여…

 

 

로컬 테스트용 패키지는 Windows Store를 거치지 않고 배포할 수 있는 대신 배포하는 머신에는 반드시 Delveoper License가 있어야 합니다.

Developer License라고 하니 좀 거창해 보이면서 추가 비용이 들 것 같은 느낌을 주는데, 공짜이며 우리가 원하는 만큼 마음대로 발급할 수 있습니다. 심지어는 Windows Store 등록을 위한 계정도 없어도 됩니다.

 

 

 

 

 

Developer License 발급받기

 

관리자 권한으로 커맨드 창을 실행한 다음 “powershell”을 입력하여 PowerShell을 실행합니다.

 

image_42.png

 

 

Show-WindowsDeveloperLicenseRegistration 를 입력하면 다음과 같이 “동의” 창이 뜹니다. 

 

image_thumb_20.png

 

 

 

 

“I Agree”를 클릭하면 로그인 계정의 비밀 번호를 물어본 다음 잠시 기다리면 다음과 같이 라이센스가 발급되었다고 나옵니다.

간단하죠?

 

image_46.png

 

 

 

 

 

Developer License 관련하여 다음과 같은 명령도 사용할 수 있습니다.

  • Get-WindowsDeveloperLicense : 현재 머신의 Developer License 정보를 표시합니다.
  • Unregister-WindowsDeveloperLicense : 현재 머신의 Developer License를 제거합니다.

 

 

 

그런데 위 스크린샷의 내용을 보니 발급한지 31일 후에 만료되는 것으로 나오네요?

네 맞습니다. Developer License는 머신 단위로 생성이 되며 발급 후 31일이 지나면 만료됩니다….. 엥?

그럼 딸랑 한 달밖에 못쓴다는 건가요?

 

걱정마세요! Developer License는 계속해서 갱신할 수 있습니다.^^

한 달이 지난 후에 위에서 설명한 것처럼 다시 발급받으면 됩니다.

 

참고로, Visual Studio 11을 실행할 때 Developer License가 없거나 만료되었으면 자동으로 안내 창이 뜨면서 갱신이 되니 Developer License의 유효기간이 31일이라고 해서 개발에 문제가 되지는 않습니다.

 

 

여기서 잠깐

리모트 디버깅을 위해 다른 머신에 리모트 디버거를 설치하면 기본적으로 Developer License가 생성이 됩니다. 이 역시 유효기간은 31일이므로 Developer License가 만료되면 PowerShell을 이용하여 갱신해야 합니다.


 

 

 

Developer License와 보안

 

Developer License는 머신 단위로 발급이 되며 발급 될 때 Microsoft 의 서버와 통신하게 됩니다. 또한 Microsoft에서 발급된 Developer License를 모니터링할 수 있다고 합니다. 만약 계약 사항을 위반하여 사용하는 사례가 발견되면 해당 Developer License가 취소될 수 있다고 하는군요.

 

또한, Developer License가 설치되어 있는 머신에는 우리가 만든 앱 뿐만 아니라 다른 사람이 만든 앱도 Windows Store를 거치지 않고 설치될 수 있기 때문에 아무래도 보안의 위협이 생길 수가 있습니다.

 

이러한 이유들로 인해 Developer License는 꼭 테스트가 필요한 머신에서만 발급하실 것을 권장합니다.

 

 

 

 

 

 

 

 

Windows App Cert Kit 사용하기

 

 

개발한 앱을 Windwos Store에 올리게 되면 심사를 받게 되는데, Windowns App Cert Kit을 이용하면 우리가 만든 앱의 기본적인 기능을 미리 테스트하여 심사 전에 문제점을 미리 발견할 수 있도록 도와줍니다.

 

Windowns App Cert Kit은 다음과 같은 사항들을 자동으로 테스트하고 결과를 알려줍니다.

 

  • Package Manifest가 다음 요구 조건을 만족하는지 테스트함
    - Number of tiles
    - Number of apps per package
    - App type
    - ResourceID not listed
    - OSVersionHighestTested
  • 메트로 스타일 앱에서 지원하지 않는 API를 사용하는지 테스트함
  • 앱이 얼마나 빨리 실행되고 대기 상태로 들어가는지 테스트함
  • Manifest에 정의된 언어에 대한 언어 리소스가 잘 포함되어 있는지 테스트함
  • 보안에 문제가 있는지 테스트함
  • 앱이 다운되거나 멈춰버리는 지 모니터링함

 

 

 

Windowns App Cert Kit를 실행하면 다음과 같은 창이 뜹니다.

 

image_48.png

 

 

 

 

잠시 기다리면 현재 머신에 설치되어 있는 앱의 목록이 표시됩니다.

목록에서 우리가 만든 앱을 선택한 후 Next를 클릭합니다.

image_50.png

 

 

 

 

 

그러면, 다음과 같이 검사를 진행합니다. 이 때 테스트를 하는 동안 앱을 사용하지 말라고 하는군요.

실제로, 테스트 도중에 앱이 자동으로 실행되는 것을 보실 수가 있습니다.

 

주의사항!: 절대로 가만 놔두셔야 합니다. 안 그러면 제대로 테스트가 수행되지 못해서 무진장 오래 걸리거나 실패합니다.

 

image_52.png

 

 

 

 

 

한참을 기다리면 XML된 리포트을 어디에 저장하겠느냐고 물어봅니다.

저장한 XML 리포트를 열어보면 다음과 같이 테스트 결과를 보여줍니다.

 

image_58.png

 

 

 

 

왜 실패했나 봤더니 다음과 같이 디버그 모드로 컴파일되어 있다고 알려주는군요.

사실, 이 외에도 실패한 테스트가 몇 개 더 있는데, 그 부분은 아직 구현을 안해서 그런 겁니다.

 

image_60.png

 

 

 

여기서 잠깐

Windowns App Cert Kit은 다음과 같이 커맨드라인으로도 실행할 수 있습니다.

appcert.exe reset
appcert.exe test -apptype metrostyle -packagefullname [package full name] -reportoutputpath [report file name]

 

여기서, appcert.exe는 기본적으로 C:\Program Files\Windows Kits\8.0\App Certification Kit 폴더에 위치합니다.

posted by Town One townone

댓글을 달아 주세요

2013.05.23 15:30 Windows8/WPF

windows 8 app 개발하려면 어떤 언어와 Library를 사용해야 하나?

왠만히 개발에 관심있는 분이라면 windows 8의 metro style app 이야기를 한번 정도는 들어 보셨을 것 같습니다.
C/C++ 를 사용하거나 C#이나 VB와 같은 .NET Language 혹은 Javascript로 app을 개발할 수도 있습니다.

다양한 App을 개발하려면 기본적으로 Platform이 다양한 기능을 제공해 주어야 함은 물론이고, 그에 맞는 다양한 API를 사용할 수 있어야 할 겁니다. 게다가 각각의 언어들이 windows 8 app을 개발하기 위해서 새로 만들어진 언어나 library가 아니기 때문에 기존에 익숙한 library를 얼마나 많이 활용할 수 있는가는 개발자들의 학습 시간에 큰 영향을 주기 마련이지요.

windows 8 app을 개발하기 위해서 어떤 library를 사용할 수 있는지에 대해서 구체적으로 살펴보고자 합니다.

어떤 언어를 사용하던지간에 windows 8의 metro platform이 가지는 특성을 사용해야 하기 때문에 전용의 API가 제공되어야 합니다. 보통의 경우 개발 언어별로 API를 제공하는 것이 일반적이고, 그러지 않기 위해서 COM과 같은 Binary 규격으로 API를 제공하기도 합니다만 windows 8 metro platform용 API는 단일의 binary로 C/C++, C#/VB, Javas-ript 모두에서 사용할 수 있는 방식으로 만들어졌습니다. 정말 이정도면 삽질도 보통 삽질이 아니었을겁니다. 
이런 이질적인 3개의 언어군(native/managed/script)에서 사용할 수 있는 공통의 binary라니요??? 하지만 마이크로소프트는 Modem COM 이라는 새로운 규격 하에 3개의 언어에서 쓸 수 있도록 단일의 binary를 진짜로 만들었습니다. 그리고 각 언어의 특성과 binary 사이의 간극을 메우기 위해서 language 별 projection layer를 간단히 걸쳐 놓았습니다.
만들다 보니 아무래도 script language와 library 사이에 간극이 가장 컷던 모양입니다. 여러가지 이유로 그럴 수 밖에 없었는데 가장 큰 이유는 아무래도 공통의 binary(library)가 C/C++로 작성되었기 때문이라고 강하게 추측 해봅니다.

이 binary의 이름이 바로 "Windows Runtime" 입니다. 그래서 어떤 언어를 사용하던 Windows Runtime을 사용하여야만 windows 8 app을 개발할 수가 있습니다.

이게 언어별로 구분해서 살펴보겠습니다.

1. C/C++
먼저 C/C++입니다. C/C++은 visual c runtime을 포함하여 win32와 모든 com api가 사용가능 library군에 포함됩니다. 그런데 windows 8 app은 새로운 platform이기도 하거니와 상당히 제약이 많은 platform이기 때문에 모든 api를 다 사용할 수는 없습니다. 그래서 windows 8 app을 개발할 때 사용할 수 있는 api와 사용할 수 없는 app을 구분짓고 header 파일 내를 2개의 영역으로 구분지어 두었습니다.

#pragma region Application Family
이 영역에 선언되어 있는 API들은 windows 8 app과 dekstop app 모두에서 사용할 수 있습니다.
#pragma region Desktop Family
이 영역에 선언되어 있는 API들은 desktop app에서만 사용할 수 있습니다.

Visual Studio를 사용하면 Windows 8 app을 개발할 때에는 #pragma region Application Family 이하에 정의된 API 들만 사용가능하도록 해주고, desktop app을 개발할 때에는 둘 다를 보여주는 식으로 개발자를 도와줍니다.

C/C++에서만 사용할 수 있는 또 하나의 library가 있는데요, Platform이라는 namespace 안에 모조리 구현되어 있고, exception이나 type과 관련되어 있는 내용이 많이 포함되어 있습니다.
Platform namespace에 대해 궁금하신 분이라면 아래 링크를 살펴보시면 되겠습니다.

정리하면 사용할 수 있는 API 군은 크게 3가지로 요약될 수 있겠습니다.
Windows API: Windows Runtime
http://msdn.microsoft.com/en-us/library/windows/apps/br211377.aspx
Win32 and COM API 중 사용할 수 있도록 허용된 API들
http://msdn.microsoft.com/en-us/library/windows/apps/br205757.aspx
Platform namespace 내에 정의된 class와 method 들
http://msdn.microsoft.com/en-us/library/windows/apps/hh710417.aspx

그리고 약간 불편한 사실 두 가지
단일의 runtime을 구성하기 위해서는 언어별로 약간의 고통들을 감수 해야 했습니다. C/C++도 상당한 고통을 치러야 했는데요, 첫번째로 API 사용의 복잡성에 직면하게 되었습니다. 마이크로소프트는 이러한 복잡성을 해결하기 위한 방책으로 CX(Component Extension)이라는 확장 규격을 언어에 추가하였습니다. 따라서 windows 8 app을 C/C++로 개발하려면 가능한 CX 확장 규격을 사용하는 것이 정신 건강에 좋습니다. 이를 기존의 C++과 구분하기 위해서 C++/CX라고 합니다.

나머지 하나는 일반적인 C/C++ 개발 idiom이나 style이 아닌 windows runtime을 사용하기 위한 개발 style을 사용해야 한다는 것입니다. 이는 마치 C/C++을 사용하지만 표현의 방식이 다른 언어인냥 느껴지기도 합니다.
아주 간단한 예를 들어보면 Windows::ApplicationModel::Resources::Management  식의 namespace를 사용하는 등이죠.
이는 C/C++의 언어규격에는 정확히 맞을지 모르나 기존의 C/C++ 개발자들이 즐겨쓰던 방식은 아님에 분명합니다.

2. C#/VB
사실 C#/VB 언어를 사용하던 개발자라면 windows 8 app 개발시에 가장 빠르게 app을 개발할 수 있습니다. Windows Runtime를 사용해야 하는 것은 당연합니다. 여기에 더하여 .NET의 BCL(Base Class Library)중 windows 8 app 개발에 사용할 수 있는 Type들만을 모아서 ".NET for Metro style apps" 라는 library를 만들었습니다. 이름이 이렇다 보니 영문을 읽다 보면 이것이 Library의 이름인지 아니면 매트로 스타일 앱을 위한 .NET이라고 해석되어야 하는 것인지 혼돈 될 수 있는데, 절대로 혼돈하면 안됩니다. BCL 중 windows 8 apps을 개발할 때 사용할 수 있는 subset 만을 모아둔 API군의 이름이 ".NET APIs for Metro style apps"입니다.

Windows API: Windows Runtime
http://msdn.microsoft.com/en-us/library/windows/apps/br211377.aspx
.NET APIs for Metro style apps
http://msdn.microsoft.com/en-us/library/windows/apps/br230232.aspx

3. Javascript
Javascript는 앞서 2개의 언어와는 상당히 간극이 큰 언어임에 분명합니다. 그래서 Javascript를 이용해서 Windows Runtime을 완전히 사용하기에는 쉽지 않았습니다. 그래서 Windows Runtime과 더불어 "Windows Library for JavaScript"라는 녀석을 같이 써야 제대로 app을 개발할 수가 있습니다.
이런 이유로 C/C++이나 C#/VB로 개발하는 코드에 비해서 Javascript code가 상당히 이질적이거나 구조적으로 달라보이게 됩니다.
또한 많은 문서에서 API의 사용 예제를 3가지로 제공하는 경우 C/C++과 C#/VB 그리고 Javascript로 나누어 제공하고, 2가지로 예제를 제공하는 경우 C/C++/C#/VB 그리고 Javascript로 나누어 제공합니다.
대부분의 문서에서 "Windows Runtime and Windows Library for JavaScript" 하나로 묶어 설명하는데 이는 Javascript만으로 Windows Runtime을 사용하기에는 불가능하지는 않으나 너무나 복잡하기 때문입니다.
그외 HTML5와 CSS를 사용할 수 있겠습니다. 이또한 혼돈하지 말아야할 것은 HTML5와 CSS를 사용하고 있지만 정확히는 HTML5와 CSS 규격의 일부를 확장하여 사용하고 있다고 보는 편이 적절해 보입니다. 또한 광의의 의미에서 HTML5는 엄청나게 다양한 API 군을 포함하게 되는데, 아직 recommended가 확정되지 않은 내용이 많고 그 전체를 다 지원하지도 않습니다 지원되는 API 군과 확장 feature를 살펴보시려면 아래의 "HTML/CSS for Metro style apps" 링크를 살펴보시기 바랍니다.

Windows API: Windows Runtime
http://msdn.microsoft.com/en-us/library/windows/apps/br211377.aspx
HTML/CSS for Metro style apps
http://msdn.microsoft.com/en-us/library/windows/apps/br229576.aspx

posted by Town One townone

댓글을 달아 주세요