wtorek, 22 stycznia 2013

Windows Phone 8 na żywo - odc.3 (rozmowa z telefonem!)

Kontynuacja mojego gadania do telefonu. Tym razem dłuższy dialog… Zapraszam do rzucenia okiem na krótki filmik, który to przedstawia.

Jak zrobić rozmowę? Wystarczy, że umiejętnie wykorzystamy API do zamiany tekstu na mowę i do rozpoznawania mowy. W poprzednio prezentowanej aplikacji dodałem przycisk mikrofonu, który pozwala głosowo odpowiedzieć na pytania zadawane przez telefon i w ten sposób wybrać utwór do zagrania. U mnie sprowadziło się do jednej metody:

        private async void PromptThenPlayVideoByVoice()
        {
            try
            {
                var speechSynthesizer = new SpeechSynthesizer();
                var speechRecognizerUI = new SpeechRecognizerUI();               

                var videoList = GetVideoPhrases(new string[] { "ostatni", "losowy" });
                var confirmationList = new List<string> { "OK", "nie" };

                speechRecognizerUI.Recognizer.Grammars.AddGrammarFromList("videos", videoList);
                speechRecognizerUI.Recognizer.Grammars.AddGrammarFromList("confirmation", confirmationList);
                await speechRecognizerUI.Recognizer.PreloadGrammarsAsync();


                await speechSynthesizer.SpeakTextAsync("Jaki utwór mam zagrać?");
               
                speechRecognizerUI.Recognizer.Grammars["confirmation"].Enabled = false;
                speechRecognizerUI.Settings.ListenText = "Jaki utwór mam zagrać?";
                speechRecognizerUI.Settings.ExampleText = "'Ostatni', 'losowy' lub tytuł";
                speechRecognizerUI.Settings.ShowConfirmation = false;

                var videoResult = await speechRecognizerUI.RecognizeWithUIAsync();

                if (videoResult.ResultStatus == SpeechRecognitionUIStatus.Succeeded
                    && videoResult.RecognitionResult.TextConfidence == SpeechRecognitionConfidence.High)
                {
                    await speechSynthesizer.SpeakTextAsync("Usłyszałam " + videoResult.RecognitionResult.Text + ". Czy prawidłowo?");

                    speechRecognizerUI.Recognizer.Grammars["confirmation"].Enabled = true;
                    speechRecognizerUI.Recognizer.Grammars["videos"].Enabled = false;                   
                    speechRecognizerUI.Settings.ListenText = videoResult.RecognitionResult.Text + "?";
                    speechRecognizerUI.Settings.ExampleText = "'OK' lub 'Nie'";                   

                    var confirmationResult = await speechRecognizerUI.RecognizeWithUIAsync();

                    if (confirmationResult.ResultStatus == SpeechRecognitionUIStatus.Succeeded
                        && confirmationResult.RecognitionResult.TextConfidence == SpeechRecognitionConfidence.High)
                    {
                        if (confirmationResult.RecognitionResult.Text == "OK")
                        {
                            var title = videoResult.RecognitionResult.Text;

                            await speechSynthesizer.SpeakTextAsync("Gram " + title + ".");

                            var files = await ApplicationData.Current.LocalFolder.GetFilesAsync();
                            var file = FindVideoWithTitle(files, title);

                            …

                            if (file != null)
                            {
                                Play(file.Name);
                            }
                        }
                        else if (confirmationResult.RecognitionResult.Text == "nie")
                            await speechSynthesizer.SpeakTextAsync("Przepraszam za pomyłkę.");                       
                    }
                    else
                        await speechSynthesizer.SpeakTextAsync("Nie zrozumiałam twojej odpowiedzi.");
                }
                else
                {                   
                    await speechSynthesizer.SpeakTextAsync("Nie zrozumiałam nazwy utworu.");
                }
            }
            catch(Exception ex)
            {
               
            }
        }

Wnikliwe oko zauważy, że wykorzystałem tutaj proste listowe gramatyki. Warto też dodać, że postanowiłem reużytkować moduł rozpoznawczy i wybrałem opcję z załadowaniem wszystkich gramatyk i ich włączaniem/wyłączaniem w zależności od pytania, które zadaję.

W zasadzie możnaby na tym poprzestać. Ale dorobiłem alternatywny sposób wyzwolenia tego dialogu. W tym celu pozwoliłem sobie dopisać… komendę głosową (obok tej prezentowanej w poprzednim poście):

   <Command Name="play">
      <Example>Graj</Example>
      <ListenFor>Graj</ListenFor>
      <Feedback>Granie na żądanie</Feedback>
      <Navigate Target="/StartPage.xaml"/>
    </Command>

Teraz mogę mówić także “Tuba, graj” (obok “Tuba, (graj) {tytuł}”, “Tuba, (graj) ostatni” czy “Tuba, (graj) losowy”).  Gdy powiem tylko “Tuba, graj”, to aplikacja owszem otworzy się, ale ponieważ nie wie, co chcemy, więc się nas zaczyna pytać –;)  Taki scenariusz trafił właśnie do mojego filmiku.

niedziela, 20 stycznia 2013

Windows Phone 8 na żywo - odc 2 (komendy głosowe)

Dziś napiszę trochę o komendach głosowych w WP8.

W WP 7.x można było używać tylko standardowych poleceń typu “Otwórz kalendarz”. Teraz mamy możliwość definiowania dla naszych aplikacji własnych komend z frazami. Postanowiłem trochę się zabawić i zamienić aplikację z ostatniego posta w szafę grającą spełniającą ustnie wypowiadane życzenia. Pamiętam, że w dzieciństwie podziwiałem jakiś układ elektroniczny przełączający obwód na zadane hasło… Były też bajki o Sezamie… No czy jakoś odwrotnie -;) W każdym razie dziś mała namiastka tego.

Obsługa mowy jest bardzo prosta. Jest to część wysokopoziomowego WinPRT API (btw szkoda że nie ma takiego API w Windows 8).

Zacznijmy od zdefiniowania pliku XML z komendami (najlepiej użyć do tego predefiniowanego szablonu w Visual Studio).  W moim przypadku komendy w języku polskim przedstawiają się w tym pliku następująco:

<?xml version="1.0" encoding="utf-8"?>

<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">

  <CommandSet xml:lang="pl-PL" Name="myPolishCommands">
    <CommandPrefix>Tuba</CommandPrefix>
    <Example>Graj ostatni</Example>

    <Command Name="playVideo">
      <Example>Graj ostatni</Example>
      <ListenFor>[Graj] {video}</ListenFor>
      <Feedback>Gram {video}</Feedback>
      <Navigate Target="/StartPage.xaml"/>
    </Command>

    <PhraseList Label="video">
      <Item>ostatni</Item>
      <Item>losowy</Item>
    </PhraseList>

  </CommandSet>

   …
 
</VoiceCommands>

Ogólnie zakładam mówienie w trzech postaciach: “Tuba, graj ostatni”, “Tuba, graj losowy” lub “Tuba, graj {nazwa utworu}” oraz krótsze wersje tych wypowiedzi bez słowa “graj” (zdefiniowane jest ono w []). Pierwsze dwa przypadki są zdefiniowane w samym pliku XML (fraza “video” o wartościach “ostatni” i “losowy”, wstawianie wartości z frazy oznaczone jest {}). O trzecim przypadku za chwilę. Warto wspomnieć, że w tym samym pliku możemy równocześnie zdefiniować inne wersje językowe komend poprzez inny CommandSet (u mnie “myEnglishCommands” z językiem en-US). Druga rzecz jaką warto dodać, to wygodne przełączanie języka mowy w Ustawienia –> Mowa. Jest to zupełnie niezależne od wszystkich innych ustawień językowych w telefonie.

Należy teraz zarejestrować w systemie zdefiniowane przed chwilą komendy. Czynimy to raz przy uruchomionej aplikacji (przeważnie w obsłudze zdarzenia Load strony startowej).

        async private void RegisterVoiceCommandsAtFirstRun()
        {
            var appSettings = IsolatedStorageSettings.ApplicationSettings;
            if (appSettings.Contains("firstRun")) return;

            Uri uri = new Uri("ms-appx:///VoiceCommands.xml", UriKind.Absolute);
            await VoiceCommandService.InstallCommandSetsFromFileAsync(uri);           

            appSettings["firstRun"] = true;
        }

Na tym etapie po jednokrotnym uruchomieniu aplikacji możemy wrócić do ekranu startowego i przytrzymać dłużej przycisk Start. Pojawi się okno dialogowe do słuchania komend (pierwszy screenshot z poniższych). Jeśli chcemy wiedzieć jakie aplikacje na naszym telefonie wspierają komendy naciskamy “?” i wyświetla się nam odpowiednie okno z pivotem (drugi screenshot). Przechodzimy wtedy do zakładki “aplikacje” (trzeci screenshot). Wróćmy jednak do chwili, gdy jesteśmy słuchani. Wypowiadamy nasze magiczne słowa i jeśli zostaniemy dobrze rozpoznani, to pojawi się okienko z ikoną naszej aplikacji i usłyszymy odpowiedź określającą podejmowaną czynność np. “Gram ostatni” (czwarty screenshot). Następnie aplikacja zostanie otworzona na wskazanej w definicji komendy stronie (u mnie jest to StartPage.xaml)

VC0_PL  VC1_PL  VC2_PL  VC3_PL

Jak aplikacja dowiaduje się, przez jaką komendę została uruchomiona? Komendy mogą mieć przecież różne parametry i zachowanie aplikacji może być nimi uwarunkowane. Twórcy WP8 nie szukali długo, zrealizowali to tak jak każdy inny mechanizm deep linking. Do adresu strony są doklejane parametry w określony sposób. W moim przypadku odczyt przychodzących parametrów został zrealizowany na stronie StartPage w następujący sposób:

        async protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            //…

            if (e.NavigationMode == System.Windows.Navigation.NavigationMode.New)
            {
                if (NavigationContext.QueryString.ContainsKey("voiceCommandName"))
                {
                    string voiceCommandName = NavigationContext.QueryString["voiceCommandName"];

                    switch (voiceCommandName)
                    {
                        case "playVideo":

                            string video = NavigationContext.QueryString["video"];

                            //…                          

                       if (video == "last")
                       {
                          //...
                       }
                       else if (video == "random")
                       {
                          //...
                       }
                      else
                      {
                         //...
                      }

                            //…

                            break;

                        default:
                            break;
                    }
                }
            }

            //…

      }

Jak dodać tytuły klipów zarządzanych przez aplikację do wartości frazy “video”? Zbiór wartości odświeżam korzystając z metody:

        async private Task UpdatePhrasesForVoiceCommands(string voiceCommandSet, string[] startPhrases)
        {
            var phrases = startPhrases.Concat(AllVideos.Select(f => GetTitle(f.Name.Replace(".mp4", "")))).ToList();

            var videoVcs = VoiceCommandService.InstalledCommandSets[voiceCommandSet];
            await videoVcs.UpdatePhraseListAsync("video", phrases);
        }

Tytuł nagrania z YouTube obcinam do słów, które powinny zawierać tytuł utworu (GetTitle). Całość wywołuję w następujący sposób:

await UpdatePhrasesForVoiceCommands("myPolishCommands", new string[] { "ostatni", "losowy" });

Przykładowe uruchomienie aplikacji za pomocą komendy zawierającej nazwę utworu pokazałem na poniższym nagraniu:

P.S  API dla mowy w WP8 obejmuje także zamianę tekstu na mowę oraz rozpoznawanie mowy za pomocą wbudowanych i własnych gramatyk, ale o tym może innym już razem.

piątek, 18 stycznia 2013

Windows Phone 8 na żywo - odc.1 (nowe File API + kilka różnic w stosunku do Win8)

Otwieram serię kilku postów, w których będę się dzielił praktycznymi uwagami związanymi z platformą WP8.

WP8_6

Uczynię to w oparciu o aplikację pobierającą filmy z YouTube, która jest odpowiednikiem wcześniejszej aplikacji na Windows 8.

Stroną startową w WP8 jest pivot z trzema widokami: lista nagrań video, ostatnio używane oraz lista aktualnych pobrań.

WP8_1    WP8_2    WP8_9

Przy dodawaniu nowych klipów wyszukuję je sobie w YouTube i wybrane pobieram. Lokalnie przechowywane pliki również mogę przeszukiwać.

WP8_8    WP8_3

Oczywiście video można odtwarzać –;)

WP8_4

Po tym krótkim wstępie pora na porcję informacji technicznych. Dziś tematem przewodnim będzie kwestia nowego API do lokalnego systemu plików. W drugiej części wspomnę krótko o innych różnicach, które rzuciły mi  się w oczy przy przenoszeniu kodu z Windows 8.

 

File API

Jak powszechnie wiadomo w WP8 mamy podzbiór File API znanego z Windows 8. Wspierany jest folder lokalny, do którego nadal możemy mieć dostęp przez Isolated Storage API z WP 7.x. Trzeba zaznaczyć, że w przeciwieństwie do Windows 8 nie mamy folderów dla synchronizacji zdalnej i  plików tymczasowych, a także znanego z tej platformy API do ustawień aplikacji. WP8 podobnie jak WP7.x ma kilka innych folderów o dedykowanym przeznaczeniu, a z ustawień aplikacji korzystamy przez Isolated Storage API. Dochodzą też bardziej szczegółowe różnice dotyczące obsługi systemu plików. Na nich się dzisiaj skupimy.

Sprawdzanie istnienia

Isolated Storage API z WP 7.x ma proste API do sprawdzenia czy dany plik lub folder istnieje. Nowe WinRT API mimo wielu zalet nie pozwala na bezpośrednią weryfikację takich informacji. Możemy to zrobić w sposób pośredni, posługując się kodem podobnym do poniższego:

           StorageFile storageFile = null;
           bool fileExists = false;
           try
           {
               storageFile = await  StorageFile.GetFileFromPathAsync(…);
               fileExists = true;
           }
           catch (FileNotFoundException)
           {
                fileExists = false;
           }

Wirtualizowany wektor

Windows 8 posiada klasę FileInformationFactory, która tworzy bindowalny wirtualizowany wektor z plikami. Razem z nim otrzymujemy miniatury dla plików oraz dynamiczne filtrowanie w oparciu o zdefiniowane zapytanie. Na ten temat pisałem m.in tutaj. Niestety, w WP8 takiego API nie ma. Przyjrzyjmy się więc bliżej kwestii filtrowania plików oraz wyświetlania ich miniatur.

Filtrowanie

Windows 8 oferuje tzw. file queries, które umożliwiają szybkie wygodne filtrowanie zbioru plików. W WP8 mimo obecności sygnatur takie API nie zostało zaimplementowane. Wyszukiwanie w folderze lokalnym plików, których nazwa zaczyna się od podanej frazy, zmuszony byłem zrealizować ręcznie:

            var files = await ApplicationData.Current.LocalFolder.GetFilesAsync();           

            foreach (var file in files)
            {
                if (file.Name == "__ApplicationSettings" || file.Name.EndsWith(".tmp"))
                    continue;               

                if (file.Name.ToLower().StartsWith(queryText.ToLower()))
                    //dodanie pliku do wyników wyszukiwania
            }

Pliki miniatur dla plików wideo

W Windows 8 mamy metodę w StorageFile do zwrócenia miniatury. WP8 nie implementuje takiego API. W WP7.x nie kojarzę standardowego API w C#, które by to umożliwiało bez odtwarzania. Ponieważ wszystkie filmy są pobierane przez aplikację z YouTube, wybrnąłem z problemu w prosty sposób. Otóż zapisuję dostarczone przez ten serwis miniatury obok właściwych plików wideo.

 

Pora na drugą część podsumowującą inne napotkane różnice w stosunku do Windows 8.

Interfejs użytkownika

  • Win8: kontrolki i rozwiązania typowe dla Win8
  • WP8:  kontrolki i rozwiązania znane w zasadzie z WP7.x

Komunikacja

  • Win8:  HttpClient z wbudowanym async
  • WP8:  WebClient znany z WP7.x bez wbudowanego wsparcia dla async (dopisałem sobie wrapper)

Pobieranie plików w tle

  • Win8: BackgroundDownloader
  • WP8:  BackgroundTransferService znany z WP7.x, z powiększonym limitem plików w kolejce do 25

Odtwarzanie wideo

  • Win8: MediaElement (przeze mnie użyty) lub MediaPlayer (z Player Framework for Windows 8)
  • WP8: MediaElement lub MediaPlayerLauncher (przeze mnie użyty)

niedziela, 6 stycznia 2013

WP8 - gesty, toolkit i coś ponadto

Dziś trochę różnych informacji i ciekawostek związanych z WP8.

Przykłady - oprócz rzeczy, których należy się tam spodziewać warto wspomnieć, że znajdziemy tam przykład prezentowany na BUILD 2012 (PixPresenter) oraz źródła do sesji WP8 Jump Start.

Windows Phone 8 API zawiera znane z Windows 8 klasy FileOpenPicker oraz DataTransferManager! Przy czym można korzystać z nich tylko w aplikacjach natywnych i pozwalają jedynie na funkcjonalności znane z launcherów i chooserów. FileOpenPicker pozwala wybrać jedynie obrazki (odpowiednik zarządzanego PhotoChooserTask).

Kolejna sprawa to pewne zmiany w WP8 w obsłudze gestów. Mało się o tym mówi, a trzeba zaznaczyć że w klasie ManipulationDeltaEventArgs dostajemy właściwość PinchManipulation, co powoduje że z Windows Phone Toolkit został ostatecznie wyrzucony GestureListener. W przykładzie toolkita mamy pokazane jak za pomocą standardowego API obsłużyć takie gesty jak drag, flick oraz pinch (nie wspominam tu tap i hold bo były już w standardowym API dla WP 7.1). Kod nie jest zbytnio złożony, ale wymaga napisania kilku metod pomocniczych - np. do wyliczenia kąta rotacji przy pinch czy kierunku przy flick.

Kilka zdań nt. Windows Phone Toolkit.  Ostatni mój post z nim związany był tu. Cha cha cha, szmat czasu… Przez ten okres zmienił się nazwa (już bez “Silverlight”), adres (obecnie http://phone.codeplex.com/) i sposób instalacji (obecnie tylko przez NuGet),  przybyło parę kontrolek i efektów, niektóre rzeczy zostały wyrzucone lub nie są potrzebne w WP8, bo trafiły do niego. Bawiąc się w historyka, to były po drodze trzy wydania, przy czym dwa ostatnie są najbardziej istotne.

Windows Phone Toolkit - Nov 2011 (7.1 SDK) - brak znaczących zmian, poprawa błędów, pierwsza zapowiedź zamiaru uśmiercenia GestureListener

Windows Phone Toolkit - September 2012 - zmiana nazwy produktu, nowe kontrolki (CustomMessageBox i Rating) i efekty animujące przy tranzycji strony także znajdujące się na niej elementy (SlideInEffect i TurnstileFeatherEffect), poprawa stylowań na bardziej zgodne z systemem, zmiana instalacji na pakiet NuGet

Windows Phone Toolkit - October 2012

image

Zmiany:

  • wsparcie dla WP7.1 i WP8
  • rozszerzenia dla WP8 Map API, w tym kontrolka PushPin (nowa kontrolka Map z SDK z mapami Nokii nie ma takich elementów w standardzie)
  • w WP8 kontrolka LongListMultiSelector, zawierająca widok typu Grid
  • w WP8 usunięto: LongListSelector (obecnie standard), LocablePivot (obecnie Pivot), PerformanceProgressBar (obecnie ProgressBar), GestureListener
  • w WP8 deprecated: MultiselectList (należy używać LongListMultiSelector)
  • szablony kontrolek zaktualizowane do WP8 UI
  • odświeżony framework dla unit testów

Dwa pakiety NuGet:

  • WPtoolkit (Windows Phone Toolkit)
  • WPToolkitTestFx  (Windows Phone Toolkit Test Framework)

sobota, 5 stycznia 2013

Z dokumentacji WP8 (3)

Ostatnia porcja ciekawostek wyłowionych przeze mnie z dokumentacji Windows Phone. Jak się okazuje mimo quirk mode jest całkiem możliwe, że aplikacja WP 7.1 i zachowa się nieco inaczej na WP 8, co w niektórych przypadkach może spowodować, że może się nawet nie uruchomić. Na szczęście są to dość wysublimowane i rzadkie przypadki. Znalazłem też jeden nienagłaśniany fakt, który może ucieszyć właścicieli telefonów z WP 7.x. WP8 nie wspiera radia FM! (przynajmniej na razie). Mamy też klarowne rozliczenie się pomiędzy WinPRT a WinRT, część wspólna to ok 25%. Na koniec tego posta dodałem kilka uzupełniających linków z oficjalnego Windows Phone Developer Blog. Znajdziemy tam m.in opis Windows Phone Toolkit, wskazówki jak skorzystać z nowych możliwości kafli w Windows Phone 7.8 (wpis w manifeście + mało eleganckie wykorzystanie refleksji) i jak wykryć tryb Kid’s Corner.

Koncepcje & architektura

You cannot use the new Simulation Dashboard for apps that target Windows Phone OS 7.1.

App platform compatibility for Windows Phone

A third-party library that is developed for Windows Phone OS 7.1 takes advantage of quirks if it is used in a Windows Phone OS 7.1 app. However, if the library is used in a Windows Phone 8 app, it runs outside of quirks mode.

Breaking changes (mimo kompatybilnościowego trybu quirks)

Windows Phone-specific features

  • Back button navigation: app + ad
  • Background file transfer:
    • WP7.1: do 5 transferów, WP8: do 25 transferów
    • WP8: dla aplikacji w foreground transfery w tle przy sieciach: 2G, EDGE, Standard, GPRS (nie można tego obejść własnym rozwiązaniem)
    • WP 7.1 i 8: transfer w tle niezależny od bycia w foreground dla sieci >= 3G
  • Choosers: brak wyjątku przy drugim Show() podczas nawigacji do choosera
  • DRM:  an app cannot properly consume DRM video as a texture; the video defaults to a black display. In Windows Phone OS 7.1 and earlier versions, DRM protected video is accessible as a texture for composition
  • FM Radio:  Windows Phone 8 does not support the FM radio feature. If you use the FM radio API in a Windows Phone 8 app, a RadioDisabledException will occur.
  • Local database:  In Windows Phone 8, you can no longer access a local database in isolated storage using a read-only connection string, unless you are accessing the installation folder.
  • MessageBox
  • Microsoft.Phone.Media.Extended assembly:  The Microsoft.Phone.Media.Extended assembly that shipped in-ROM on Windows Phone OS 7.1 phone devices is not available on a Windows Phone 8 phone (to nie było publicznie dostępne API, można było korzystać przez refleksję)
  • Networking:  In Windows Phone 8, because the Windows Phone 8 client can handle the Vary header and cache responses, a Web service call may complete much faster than in previous versions.
  • Photo chooser task:  In Windows Phone 8, the photo chooser task creates a directory in the top level of the app’s isolated storage called “PlatformData”.
  • Slider control - zmiany w template parts!
  • TextBox control - not a multi-line TextBox: In apps that target Windows Phone OS 7.1, the TextInput event is raised for Enter key presses that are not handled by the TextBox. In apps that target Windows Phone 8, the TextInput event is not raised for these Enter key presses.
  • Tiles - In Windows Phone 8, creating a Tile by using the Create(Uri, ShellTileData) method inside the Closing handler will throw an InvalidOperationException.
  • UIElement text input events: The TextInput, TextInputStart, and TextInputUpdate events do not occur in Windows Phone 8 and they did occur in Windows Phone OS 7.1. (należy używać zdarzenia KeyDown)
  • VibrateController controller: In Windows Phone OS 7.1, if you called the Stop() method of the VibrateController without previously calling its Start(TimeSpan) method, all vibrations were canceled, including those started by other apps such as the phone or a toast notification. In Windows Phone 8, if you call the Stop() method of the VibrateController without previously calling its Start(TimeSpan) method, nothing happens. No exception is raised.
  • Video play back:  On Windows Phone 8, resuming video play back after locking and then unlocking the phone has changed. On Windows Phone OS 7.1, the video opens in the paused state and the image is visible. On Windows Phone 8, the video opens in the paused state but an empty black box is displayed in place of a frame from the paused video. In both cases, the user has to click Play to resume the video.
  • WebBrowser control: 
    • The UserAgent string associated with the web browser control has changed slightly between Windows Phone OS 7.1 and Windows Phone 8.
    • Control has several changes that affect how content displays in an app (text, bullet items, and drop-down arrows)
    • Using the ScriptNotify method of the Window.External object to call OnContextMenu is not supported in Windows Phone 8. (do pokazania kontekstowego menu należy teraz używać zdarzenia OnMSGestureHold)
  • XNA:
    • Due to changes in when the Game.IsActive property is set, a game may not resume as expected.
    • In Windows Phone 8, the following render formats are not supported.
      • SurfaceFormat.Bgra4444

      • SurfaceFormat.Bgra5551

CLR

  • Finalization - Windows Phone 8 includes a completely different garbage collector than Windows Phone OS 7.1.
  • Floating-point comparisons  - Because of differences in rounding behavior in Windows Phone OS 7.1 and Windows Phone 8, floating point values may differ. This is especially true when performing equality comparisons with a constant and the result of a floating point computation.
  • Support for loading multi-module assemblies - In Windows Phone OS 7.1, the common language runtime loads multi-module assemblies; in Windows Phone 8, it does not.
  • Support for adding mixed-mode assemblies (assemblies that target the desktop version of the .NET Framework) - In Windows Phone OS 7.1, apps with mixed-mode binaries that are not loaded execute successfully; in Windows Phone 8, they do not.
  • Threading (the .NET thread pool, .NET thread scheduling policy, operating system scheduling policy) - In Windows Phone OS 7.1, apps run on a single core, and the scheduler is less aggressive in time-slicing threads in the single core. In Windows Phone 8, applications can run on multiple cores and the scheduler is more aggressive in time-slicing threads (mogą częściej występować błędy z wątkami, wyścigi itp)
  • Common Intermediate Language (CIL) method size - In Windows Phone 8, there is a 256-KB limit on the size of a method's CIL.
  • Access to private nested classes - Windows Phone OS 7.1 allows a class to access its private nested classes; Windows Phone 8 does not.
  • Instance field reads and writes - Instance field reads are optimized by the JIT compiler.
  • Platform invoke marshaling - In Windows Phone OS 7.1, strings are marshaled as Unicode by default; in Windows Phone 8, they are marshaled as ANSI by default.

.NET

  • dużo szczegółowo dobranych przypadków
  • inne kody hash
  • inne kolejności
  • zmiany w serializacji XML

Tryb Quirk w CLR i .NET

  • zapewnienie logiki JIT z poprzedniego systemu
  • ładowanie x86 na procesorach ARM
  • obsługa zduplikowanych definicji generowanych przez obfuskatory

Native code on Windows Phone 8

Windows Phone 8 supports Visual C++ 2012. This is the full version of C++ that is available on the desktop, and the two versions use the same compiler and IDE. This means that your phone app can reuse existing C and C++ libraries that you have developed for other platforms, in addition to third-party libraries and middleware.

Windows Phone 8 supports a limited set of COM and Win32 APIs that are available on the desktop.

Company app distribution for Windows Phone

In Windows Phone 8, the list of root certificates is identical to and automatically synced with the root certificates supported by Windows 8. For the full list of supported Windows Phone 8 root certificates, see Windows and Windows Phone 8 SSL Root Certificates.

Typically Windows Phone 8 apps start very quickly and a splash screen is not necessary.

App memory limits for Windows Phone 8

Web development for Windows Phone

  • pewne różnice między desktopowym IE 10 a IE for Windows Phone OS 8.0
  • pewne różnice w pozycjonowaniu CSS w stosunku do IE z WP 7.1

 

Windows Phone API

.NET API

The .NET API contains classes and types from the System and Microsoft.Phone namespaces. We’ve added functionality for Windows Phone 8, including Microsoft.Phone.Wallet, the ShareMediaTask, Lock screen for Windows Phone 8 enhancements and lots, lots more.

Windows Phone Runtime API

IC619080

  1. The set of Windows Runtime API not supported on Windows Phone 8. The API surface area of Windows Runtime is very large, with over 11,000 members. We’ve adopted a subset for Windows Phone 8 that allows you to build compelling phone scenarios.
  2. The set of Windows Runtime API adopted for Windows Phone 8. This is represented by area 2 in the above diagram and consists of approximately 2,800 members. For some types, we have not implemented certain members. For others we have added additional members to support phone-only features.
  3. We’ve added key APIs needed to build great apps for the phone. These are represented by area 3 in the diagram and total about 600 members. For example, we have brand-new APIs for speech synthesis and recognition, VOIP, and other features.

W dokumentacji WinRT API wspierane elementy w WP8 w Requirements posiadają sekcję “Minimum supported phone”. Cześć API może być widoczna, ale nie została zaimplementowana na WP8. IntelliSense w Visual Studio informuje nas o tym.

Win32 and COM API for Windows Phone

In addition to these APIs, you have access to some Win32 APIs that give you access to low-level features of the platform. This includes Winsock API for low-level networking.

Camera APIs for native code (Windows Phone 8)

 

Linki

http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/11/08/internet-explorer-10-brings-html5-to-windows-phone-8-in-a-big-way.aspx

Internet Explorer 10 for Windows Phone does not support the following:    

  • Inline video
  • Some of the new manipulation views APIs  for touch panning and zooming, with the exception of –ms-touch-action
  • Multi-track HTML5 audio (simultaneous)
  • ActiveX and VBScript
  • Drag-and-drop APIs
  • File access APIs with the exception of blobs which are supported on Windows Phone 8
  • Windows 8 integration features: Link previews, pinned site icons & notifications and support for connecting sites to apps
  • Also in Internet Explorer 10 for Windows Phone, Window.open does not return a valid window object. This is because on the phone each “window” is isolated in its own sandbox.

http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/11/20/windows-phone-toolkit-overview.aspx

http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/11/28/increase-your-app-reach-with-windows-phone-7-8.aspx

To support the new Tile sizes and templates, in your code check if the app is running on Windows Phone 7.8 ( TargetedVersion = new Version(7, 10,8858)). Then if this condition is true, enable the new Tile updates following the guidance in the article Adding Windows Phone 8 Tile functionality to Windows Phone OS 7.1 apps.

http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/01/04/how-to-detect-that-your-app-is-running-in-kid-s-corner.aspx

Enter the ApplicationProfile class, and its single static Modes property. If the current mode is Alternate, that means your app is running in Kid’s Corner.

Z dokumentacji WP8 (2)

Kolejna porcja ciekawostek, które wygrzebałem z dokumentacji Windows Phone. Wymienię kilka najciekawszych: wykrywanie przekleństw przy rozpoznawaniu mowy, współdzielenie prostych UserControl dla Win8 i WP8 (niby nic wielkiego, ale niekiedy taki pomysł może się przydać), debugowanie obrazu MDIL aplikacji, brak weryfikacji capabilities w aplikacjach WP8. Pojawia się też refleksja, że kod z WinRT API nie jest binarnie przenośny. Nawet pliki z tak samo wyglądającym kodem w Win8 i WP8 wymagają osobnych kompilacji na każdą z platform. Pod tym względem .NET w Portable Libraries pozostaje lepszy, choć… czy w sumie dużo tracimy?

Maps

Konwersja: Windows.Devices.Geolocation.Geocoordinate that’s returned when you get your current location to the System.Device.Location.GeoCoordinate expected by the Map control.

You can get an extension method to do this conversion, along with other useful extensions to the Maps API, by downloading the Windows Phone Toolkit.

How to request driving or walking directions for Windows Phone 8

ms-drive-to:?destination.latitude=<latitude>&destination.longitude=<longitude>&destination.name=<name>
ms-walk-to:?destination.latitude=<latitude>&destination.longitude<longitude>&destination.name=<name>

How to provide driving or walking directions for Windows Phone 8

/Protocol?encodedLaunchUri=ms-drive-to%3A%3Fdestination.latitude%3D47.6451413797194%26destination.longitude%3D-122.141964733601%26destination.name%3DRedmond%2C%20WA

Multimedia

Supported media codecs for Windows Phone - w zależności od rodzaju procesora

Lokalizacja

Apps that track location in the background automatically participate in Fast Resume.

When an app running in the background is deactivated, the Deactivated event is raised just like a regular foreground application. Your app can check to see the reason for deactivation in the Deactivated event handler by checking the Reason property.

  • The app stops actively tracking location. An app stops tracking location by removing event handlers for the PositionChanged and StatusChanged events of the Geolocator class or by calling the Stop() method of the GeoCoordinateWatcher class.

  • The app has run in the background for 4 hours without user interaction.

  • Battery Saver is active.

  • Device memory is low.

  • The user disables Location Services on the phone.

  • Another app begins running in the background.

Search extensibility

Windows Phone 7.1: In the Extras.xml file, the AppTitle element is used to specify the title of the app, as you would like it to appear in the apps pivot page of the quick card. With Windows Phone 8, the app title from the Apps list is used instead.

The debugging limitation doesn’t apply to Windows Phone 8 apps. When debugging a Windows Phone 8 app, you can set breakpoints in the URI mapper and use the debugging tools to examine the contents of the deep link URI. Although simulating a search extensibility launch isn’t necessary in Windows Phone 8, you may want to use it as a convenient way to launch your app with a specific URI.

Search registration and launch reference for Windows Phone - dodatkowe pola i nowe karty dla eventów

Speech

System voice commands for Windows Phone 8

If the speech recognizer uses a predefined grammar type and a user speaks profanity, the profanity words within the recognized phrases are encapsulated in <profanity> tags in the speech recognition result's Text property.

If the Windows.Phone.Speech.Recognition.SpeechRecognizerUI class is used, any profanity words are individually censored on the displayed Heard you say screen, but the actual recognition result still will be returned with encapsulated <profanity> tags, as described earlier.

Semantics are info that a grammar author enters when creating an XML format grammar that conforms to the Speech Recognition Grammar Specification (SRGS) Version 1.0. Semantics assign meaning to the contents of an item element or to a ruleref element and the phrases they define. For example, a semantic assignment might assign an airport code to the name of a city in a list of city names that can be recognized. The tag element within the item element defines the semantic value.

<rule id = "flightCities">
    <one-of>
      <item> New York <tag> "JFK" </tag> </item>
      <item> London <tag> "LHR" </tag> </item>
      <item> Beijing <tag> "PEK" </tag> </item>
    </one-of>
  </rule>

A semantic assignment to a ruleref element could indicate that the airport name returned by one rule reference to a list of airports is the point of origin for a flight, and the airport name returned by another rule reference to the same list of airports is the flight's destination. In the following example, the first rule reference to the rule named flightCities is directly followed by a tag element. The tag element creates a property called LeavingFrom for the Rule Variable of the rule named flightBooker, and assigns the recognition result from the flightCities rule to the LeavingFrom property. The second reference to the flightCities rule assigns recognition result from the flightCities rule to the GoingTo property.

<rule id="flightBooker" scope="public">
    <item repeat="0-1"> I want to </item>
    <item repeat="0-1"> fly </item>
    <item repeat="0-1"> me </item>
    <item repeat="0-1"> from </item>
    <ruleref uri="#flightCities" />
    <tag> out.LeavingFrom=rules.latest(); </tag>
    <item> to </item>
    <ruleref uri="#flightCities" />
    <tag> out.GoingTo=rules.latest(); </tag>
  </rule>

  <rule id = "flightCities">
    <one-of>
      <item> New York <tag> "JFK" </tag> </item>
      <item> London <tag> "LHR" </tag> </item>
      <item> Beijing <tag> "PEK" </tag> </item>
    </one-of>
  </rule>

recoResult.RecognitionResult.Semantics["LeavingFrom"].Value

You can also select a speaking voice of a particular language using Speech Synthesis Markup Language (SSML).

Handling errors in speech apps for Windows Phone

Although occasionally you'll encounter a managed exception when dealing with the speech feature, the majority of speech errors are returned in HResult format.

Wallet

To increase the discoverability of your app that integrates with the Wallet, you can define your app as a Wallet extension. This makes your app appear in the other list of apps in the Wallet when the user taps add. The user can then pick your app from that list and the app will be downloaded and installed on the phone. This is another great way to increase the discoverability of your app.

<Extensions> <Extension ExtensionName="Wallet_app_other" ConsumerID="{3860f72b-b8fc-4503-b922-c25f315da9c3}" TaskID="_default" /> </Extensions>

  • ExtensionName: Defines the type of extension you are registering. Valid values for this attribute when registering as a Wallet extension are:

    • Wallet_app_other – for non-specific Wallet items

    • Wallet_app_loyalty – for loyalty cards

    • Wallet_app_membership – for membership cards

    • Wallet_app_transit – for transit cards

    • Wallet_app_payment – for payment cards

    You only need to register once, even if your app is used for multiple Wallet item types. You can register as an extension for multiple Wallet item types if you want by adding multiple Extension elements to the Extensions section in WMAppManifest.xml. Currently, when the user taps other to bring up the Add to Wallet dialog box and look for Wallet extensions, all extensions are returned, regardless of what Wallet item type was defined when registering as an extension.

  • ConsumerID: This should be set to the same value as the ProductID attribute of the App element. This is shown in the preceding code.

  • TaskID: Set this to default.

Vibration

An app that is running in the background cannot vibrate the phone. If your code tries to use vibration while the app is running in the background, nothing happens, but no exception is raised.

.NET API – zgodne z WP 7.x

WinRT API

using Windows.Phone.Devices.Notification;

VibrationDevice testVibrationDevice = VibrationDevice.GetDefault();

testVibrationDevice.Vibrate(TimeSpan.FromSeconds(3));

testVibrationDevice.Cancel();

Globalization & localization

Font and language configuration support for Windows Phone

New project default behavior is that Language properties of the running app are initialized using parameters from the resource file the app loads when it launches (ResourceLanguage and ResourceFlowDirection). This behavior imposes the pattern that the font and text flow direction are aligned with the language of the resource being displayed at run time.

The InitializeLanguage() function in the App.xaml.cs file sets the app's RootFrame.Language based on the value of the AppResoures.ResourceLanguage resource, and its RootFrame.lowDirection based on the value of the AppResources.ResourceFlowDirection resource.

  • If you want to start from scratch, you can comment out the app's InitializeLanguage method call in App.xaml.cs.

  • If you want to globally impose a specific language regardless of which locale the user has chosen for their phone's display language, you can modify the RootLanguage string in each of the app’s .resx files.

  • If you want FlowDirection to globally flow in one direction regardless of traditional direction of the app’s runtime language, you can modify the ResourceFlowDirection string in the apps .resx files.

App Manifest

App capabilities and hardware requirements for Windows Phone

WP8: The FunctionalRequirements element is an optional child of the App element and should immediately follow the Requirements section in the manifest file. Use the FunctionalRequirements element to indicate if the app requires certain hardware functionality, such as the increased memory limit.

How to determine app capabilities

The Windows Phone SDK 8.0 does not contain tools to detect the capabilities required for apps that target Windows Phone 8. When you submit an app that targets Windows Phone 8 to the Store, capabilities are not analyzed and the app manifest file is not regenerated or corrected.

Games

Direct3D for Windows Phone 8

Windows Phone 8 supports a subset of the APIs in the DirectX library. Most notably, the Windows Imaging Component (WIC) and Direct2D libraries are entirely unsupported. The APIs that are supported on the phone are supported at the 9_3 feature level which means that they behave differently than the same APIs running on a device that supports a higher feature level (Microsoft Direct3D 11 introduced the concept of feature levels). There are a few instances where the APIs behave differently on the phone than they do in a desktop app using the 9_3 feature level, particularly around setting up the swap chain for the graphics device.

XAML and Direct3D apps for Windows Phone 8

Direct3D with XAML apps for Windows Phone 8

Direct3D app development for Windows Phone 8

Microsoft Media Foundation for Windows Phone 8

Microsoft Media Foundation (MF) is a framework for audio and video capture and playback for the desktop. Microsoft Media Foundation for Windows Phone is a reimplementation of a subset of the MF APIs. With this feature, Windows Phone 8 apps can implement the following scenarios.

  • Render video to textures in apps that use native code.

  • Display cinematics for games.

  • Play in-game background audio in apps that use native code, such as a game soundtrack.

Native audio APIs for Windows Phone 8

Windows Phone 8 apps can use the WASAPI and XAudio2 APIs to play and process audio and manage audio streams.

XAudio2 is a low-level audio API that you can use to play, mix, and process audio for sound effects in games written in native code. Windows Phone 8 supports the standard XAudio2 feature set you can use on the desktop, although with some exceptions. For example, the desktop supports multiple audio devices, and the phone supports only one. This might affect the parameters you use to call some APIs. Another difference is support for compressed audio data. The XAudio2 interface works only with uncompressed PCM or ADPCM audio data. On the desktop, you can use Microsoft Media Foundation APIs to decompress content into PCM data to use with XAudio2. Windows Phone 8 does not offer these helper APIs, so it will be more difficult to implement a scenario that includes XAudio2 and compressed audio.

You can use the Windows Audio Session API (WASAPI) to manage audio streams in your app. Windows Phone 8 supports a subset of the WASAPI interfaces, and other APIs, that you can use on the desktop. Audio Capture and Render APIs for native code for Windows Phone.

Windows Phone 8 & Windows 8

Windows Phone 8 and Windows 8 platform comparison

Common native API

  • DirectX 11.1
  • XAudio2
  • MediaEngine
  • STL
  • CRT
  • WinSock

Common Windows Runtime API

  • Networking
  • Sensors
  • Proximity
  • Storage
  • DataSaver/Connection Manager
  • Location
  • Touch
  • Online Identity
  • Keyboard
  • Launchers & Choosers
  • In-App Purchase
  • Threading
  • Base Types/ Windows.Foundation

+ speech + VOIP + … = Windows Phone Runtime API

Shared .NET Engine

In Windows Phone 8, the .NET Compact Framework has been replaced by CoreCLR, which is the same .NET engine used on Windows 8. Most new devices are now multicore, and the operating system and apps are expected to be faster because of that technology.

Maximize code reuse between Windows Phone 8 and Windows 8

Portable code is any code that can be compiled once and run on Windows Phone 8 and Windows 8. For example, most of the .NET API is portable between both platforms and can be implemented in a Portable Class Library. Common code is code that uses API that’s common to both platforms, but isn’t portable. For example, code that uses the Windows Runtime API that is common between Windows Phone 8 and Windows 8 can be considered common, but it isn’t portable because the code must be compiled for each platform. It also can’t be used in a Portable Class Library.

Note that the Express versions of Visual Studio 2012 don’t include a Portable Class Library project template. The template is available only in Visual Studio 2012 Pro or greater versions.

Windows Runtime APIs aren’t portable and can’t be used in a Portable Class Library. Binary compatibility is not supported. Your code has to be compiled for each platform.

Sharing XAML UI - pewne rozwiązania dla prostych UserControl:

  • szablony XAML można sprowadzić do jednej postaci
  • umieścić wspierany przez obie platformy XAML
  • wykorzystać Add as Link
  • warunkowa kompilacja importowanych przestrzeni nazw

Klasy partial - w drugiej połowie metody zależne od platformy

Dziedziczenie klas - klasy abstrakcyjne mogą być umieszczane w Portable Library

Interfejsy  - implementacje zależne od platformy

XAML controls comparison between Windows Phone 8 and Windows 8

Testowanie

How to test the retail version of your app for Windows Phone 8

When you build your app in Visual Studio, the code is not compiled into a native image, but into a machine-independent Common Intermediate Language (CIL) binary file. (CIL was formerly known as Microsoft Intermediate Language, or MSIL.) This CIL file is what you submit to the Store when you’re ready to sell your app. At that time, the binary file is converted from CIL to optimized Machine Dependent Intermediate Language, or MDIL. Finally, when the user downloads your app to a device, the MDIL file is linked to produce a native image. These steps are repeated in your development environment whenever you deploy your app to a Windows Phone 8 device.

When you deploy and run your app without debugging, you’re testing it as an optimized native image.

To debug your app as an optimized native image: 

Tools –> Options –> Debugging

Clear options:

  • Suppress JIT optimization on module load
  • Enable Just My Code

Windows Phone Application Analysis

App monitoring is supported only for managed apps - you can’t monitor Direct3D apps.

Profiling Direct3D apps for Windows Phone 8

The native code profiler uses the profiling technology built into Visual Studio 2012 and stores its results in standard .vspx files. You can also profile a Windows Phone Runtime Component project that’s referenced from a C# or Visual Basic project with the native code profiler.

Events raised by the Qualcomm graphics driver are enabled by default.

piątek, 4 stycznia 2013

Z dokumentacji WP8 (1)

Dokumentacja dla najnowszego Windows Phone 8 SDK znajduje się na stronie Windows Phone development. Pomijając dobrze znane już nowe elementy nagłaśniane przy różnych eventach tj. BUILD czy Jump Start, wynotowałem sobie bardziej wysublimowane informacje. Na przykład dużą ciekawostką jest sam VOIP. Nie widziałem z tego jeszcze żadnej prezentacji. Temat okazuje się dość złożony - tworzy się aplikację foreground, komponent WinRT z logiką, 4 agentów…  API do strumieniowania audio jest częścią Win32 API … Co ciekawe strumieniowanie video w C# z kolei jest trywialne. Całość to lawirowanie między elementami w kodzie zarządzanym, WinRT API i kodem stricte natywnym.

Garbage collection

  • The garbage collection heap in Windows Phone 8 has three generations, not two generations as it does in Windows Phone OS 7.1.

  • In Windows Phone 8, the garbage collector has a large object heap (LOH).

  • Background garbage collection is not available in Windows Phone 8.

  • The phone's resource manager invokes a garbage collection when an app approaches the memory cap and will terminate the app if it exceeds the memory cap.

  • The runtime's auto-tuned garbage collection triggers can be impacted by an app's forced garbage collections.

  • In Windows Phone 8, the performance of per-thread allocation by the garbage collector is improved.

Dane

Use “ms-appx:///” when addressing the installation folder with APIs that are in the Windows namespace. For all other APIs, use “appdata:/”.

Use “ms-appdata:///local/” to address the root of the local folder with APIs that are in the Windows namespace. For all other APIs, use “isostore:/” to address the root of the local folder.

Folder PlatformData – PhotoChooserTask

Aplikacje VoIP

When an incoming call arrives for a VoIP app, the built-in phone experience is shown, and the VoIP app appears integrated into the phone.

A Windows Phone VoIP app is comprised of several components that run in one of two processes, and one component that runs outside of any process. The first process is the foreground process that displays the app UI. The second process is a background process that does most of the work of creating, connecting, and managing incoming and outgoing calls.

IC619146

In addition to providing the UI, the foreground app sets up the push notification channel on which incoming calls arrive. It also launches the background process and uses the out-of-process server to pass commands to the components in the background, such as requesting that a call be ended.

The four background agents that a VoIP app uses. These agents are written using managed code and are launched to indicate that a new phase of a VoIP call has begun. In general, these agents have very little code, and just pass the state of the call in to one of the following components that do most of the work.

  • VoipHttpIncomingCallTask. Launched when a new incoming call arrives on the push notification channel. It lets the Windows Phone Runtime assembly know that it should create a new call.

  • VoipForegroundLifetimeAgent. Launched by the foreground app and runs as long as the app is in the foreground. It bootstraps the background process and keeps its process alive so that outgoing calls can be created quickly.

  • VoipCallInProgressAgent. Launched when a call becomes active. It signals the app that it has been allocated more CPU cycles so it can encode and decode audio and video.

  • VoipKeepAliveTask. Runs periodically, every 6 hours by default, whether or not the foreground app is running. This gives the app an opportunity to ping the VoIP service to indicate that the app is still installed on the device. When the user uninstalls the app, this agent no longer runs and the service knows not to send incoming call on the app’s push notification channel.

Windows Phone Runtime assembly - an assembly that does most of the work of connecting and managing VoIP calls using the VoipCallCoordinator and VoipPhoneCall objects. Because this is a Windows Phone Runtime assembly instead of managed, it can call the native APIs to use for audio and video processing.

Native core assembly - many VoIP app developers support multiple platforms, and often have a core library written in C or C++.

Odbieranie rozmowy

  1. The first time the user launches your VoIP app, you create a push notification channel.
  2. To initiate a new incoming call, the VoIP cloud service sends a push notification to the URI for your app’s push notification channel.
  3. The operating system launches your app’s VoipHttpIncomingCallTask agent.
    • The incoming call agent loads the app’s Windows Phone Runtime assembly, if it’s not already loaded.
    • The incoming call agent gets the push notification payload from its MessageBody property, and then passes it in to the Windows Phone Runtime assembly, calling a custom method named something like OnIncomingCallReceived.

    • In OnIncomingCallReceived, your Windows Phone Runtime assembly VoipCallCoordinator.RequestNewIncomingCall, passing in information from the push notification payload such as the calling party’s name and the URI of a contact picture for the caller. This information allows the phone to display the built-in phone UI to the user.

    • The VoipCallCoordinator.RequestNewIncomingCall method returns a VoipPhoneCall object that represents the requested call. Your Windows Phone Runtime assembly should store this object so that it can be used from other methods, and then register handlers for the call object’s AnswerRequested and RejectRequested events.

    • In the AnswerRequested event handler, you can contact your cloud service to let it know that a new call has begun, for example, to indicate that billing for the call should begin. Then, you should call NotifyCallActive to let the system know that the call is now active.

    • If the RejectRequested event handler is called, you know that the call has been rejected and you have 10 seconds to clean up any resources before the operating system will terminate your process, assuming one of the other VoIP background agents isn’t still running.

  4. After you have called NotifyCallActive, the operating system will launch your VoipCallInProgressAgent. When this agent runs, you know that your background process has been allocated more CPU for audio encoding and decoding.

    • Load your Windows Phone Runtime assembly, if it’s not already loaded.

    • In the Windows Phone Runtime assembly, if you haven’t already done so, register handlers for the MuteRequested, UnmuteRequested, and AudioEndpointChanged events.

    • Register event handlers for the EndRequested, HoldRequested, ResumeRequested events of the VoipPhoneCall object you stored while the incoming call agent was running. If you want to, you can register for all of the VoipPhoneCall events when the object is first created.

    • Hook up your incoming video stream to the MediaElement in your foreground app. For a detailed walkthrough of setting up your video stream, see How to implement video streaming for VoIP calls for Windows Phone 8.

    • As your Windows Phone Runtime assembly receives events for changes in the call state, such as HoldRequested or ResumeRequested, take the appropriate action, such as suspending or resuming the streaming of video.

    • When the user presses a button in your UI to end the call, your foreground app calls a method in your Windows Phone Runtime assembly to end the call, which will set the call object to null and then call NotifyCallEnded. You should also do this in EndRequested which is raised when the operating system ends the call, such as when the user answers a VoIP call from a different VoIP app or if the user answers a second cellular call while already on a cellular call and a VoIP call.

Nawiązywanie rozmowy

  1. When your foreground app is launched:
    • Call Launch() to launch your background process. This causes the operating system to spawn the background process for your app and call the OnLaunched() method of the VoipForegroundLifetimeAgent agent. The foreground lifetime agent will be kept alive as long as your app runs in the foreground.

    • From the VoipForegroundLifetimeAgent, load your Windows Phone Runtime assembly if it is not already loaded.

    • Use custom events to let the foreground app know that the background process is ready, and that all assemblies have been loaded. Then, create a reference to your Windows Phone Runtime assembly in the foreground app.

  2. After the user selects a contact to call and then presses the Call button in your app:
    • Call a custom method on your Windows Phone Runtime assembly, named something like MakeOutgoingCall.

    • In MakeOutgoingCall, call the RequestNewOutgoingCall method and then pass the name of the person being called so that it can be displayed in the minimized phone UI.

  3. The RequestNewOutgoingCall method returns a VoipPhoneCall object that represents the requested call. Your Windows Phone Runtime assembly should store this object so that it can be used from other methods, and then it registers handlers for the call object’s AnswerRequested and RejectRequested events.

  4. You should call NotifyCallActive to let the system know that the call is now active.

  5. The operating system will launch VoipCallInProgressAgent. When this agent runs, you know that your background process has been allocated more CPU for audio encoding and decoding. While the VoipCallInProgressAgent is running:

    • Load your Windows Phone Runtime assembly, if it’s not already loaded.

    • In the Windows Phone Runtime assembly, if you haven’t already done so, register handlers for the MuteRequested, UnmuteRequested, and AudioEndpointChanged events.

    • Register event handlers for the EndRequested, HoldRequested, ResumeRequested events of the VoipPhoneCall object that you stored while the incoming call agent was running. If you want to, you can register for all of the VoipPhoneCall events when the object is first created.

    • Hook up your incoming video stream to the MediaElement in your foreground app. For a detailed walkthrough of setting up your video stream, see How to implement video streaming for VoIP calls for Windows Phone 8.

    • When the user presses a button in your UI to end the call, your foreground app calls a method in your Windows Phone Runtime assembly to end the call, which should set the call object to null and then call NotifyCallEnded. You should also do this in EndRequested which is raised when the operating system ends the call, such as when the user answers a VoIP call from a different VoIP app or if the user answers a second cellular call while already on a cellular call and a VoIP call.

ChatterBox VoIP Sample App

Audio streaming for VoIP calls for Windows Phone 8

Windows Phone 8 includes a subset of the Windows Audio Session API (WASAPI) to enable VoIP applications to capture and render audio streams. Your application will use the WASAPI interface IAudioRenderClient for rendering audio and IAudioCaptureClient for capturing audio. These interfaces can be used on the phone in much the same as you would use them in a Windows application. The biggest difference from Windows has to do with the way routing between different audio endpoints is managed.

  • The application is responsible for converting received audio data to PCM before rendering.

  • Captured audio is returned in PCM format. The application is responsible for encoding this to any other format if this is needed for network transmission.

  • The application is responsible for implementing any echo cancellation, noise reduction, or gain control in software.

  • There are no built-in Audio/Video sync mechanisms.

  • Applications have access to only a single microphone input stream. Dual microphones for use in noise suppression or other audio processing are not supported.

How to implement video streaming for VoIP calls for Windows Phone 8

The VoipForegroundLifetimeAgent is launched and its OnLaunched() method is called when your foreground application calls Launch(). In OnLaunched(), create a new instance of the MediaStreamer class specifying an string identifying the stream in the constructor. In the XAML for your foreground application, add a MediaElement in which the video will be displayed. Set the Source property using the following Uri scheme to hook it up to your MediaStreamer: “ms-media-stream-id:MediaStreamer-[streamer ID]”.

protected override void OnLaunched()
{
  MediaStreamer ms = MediaStreamerFactory.CreateMediaStreamer("123");
  string sourceRGBA = @"http://fabrikam.com/Frame_RGBA_320_240.bin";
  RAWMediaStreamSource mss = new RAWMediaStreamSource();
  mss.SetVideoStream(sourceRGBA, 320, 240, "RGBA", 30 * TimeSpan.TicksPerSecond, false);
  ms.SetSource(mss);
}

<MediaElement Source="ms-media-stream-id:MediaStreamer-123"/>

Proximity

When your proximity app is switched to the background, for example, when you answer a call, all published messages and subscriptions are suspended.

The underlying socket that is established for NFC is unprotected. The data channel is not encrypted by default. To encrypt the data being passed over this socket, and thereby reduce the risk of tampering, you can use the value of the SessionKey property on the StreamSocket as a symmetric key. This can be used in a cryptographic library, such as System.Security.Cryptography.AesManaged. This key is known only to the devices that are in proximity to each other.

Reconnect on Windows Phone 8 is supported only for Bluetooth and TCP/IP (Wi-Fi) connections. Your apps will reconnect without tapping the phones together again. If a Windows Phone 8 device attempts to reconnect with a Windows 8 device, it will fail because this reconnect operation is not supported on Windows 8.

Bluetooth

Windows Phone 8 supports Bluetooth 3.1. This is an improved version of Bluetooth that automates the pairing process between Windows Phone 8 and Bluetooth devices, such as phone headsets, car audio systems, speaker docks, and NFC pairing. The following Bluetooth user profiles are supported.

  • Advanced Audio Distribution Profile (A2DP 1.2)

  • Audio/Video Remote Control Profile (AVRCP 1.4

  • Hands Free Profile (HFP 1.5)

  • Phone Book Access Profile (PBAP 1.1)

  • Object Push Profile (OPP 1.1)

  • Out of Band (OOB) and Near Field Communications (NFC)

PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";

Enumerate all paired devices. The PeerInformation.ServiceName will be empty in this case. For many devices, the Bluetooth port over which to communicate is hard coded, so you can use that directly in the ConnectAsync call. If the device is advertising a service, then you can enumerate using the paired option but call ConnectAsync with the GUID of the service you want to use. 

PeerFinder.AlternateIdentities["Bluetooth:SDP"] = "<SDP service guid>";

Find devices using the Service discovery protocol (SDP) that are advertising a service with the given GUID. If any devices are found, the PeerInformation.ServiceName will be equal to the GUID you specified.

If you enumerate by "Bluetooth:Paired", the PeerInformation.ServiceName field will be empty.  It is only populated when you enumerate using "Bluetooth:SDP".

Bluetooth peer-to-peer (P2P) advertisement isn’t enabled if you start, stop, and then restart PeerFinder. Send your app to the background and then bring it to the foreground.

Data Sense API

Installing the Data Sense app and Tile on phones is optional for mobile operators. As a result, users of your app might not have the Data Sense app on their phones. Without the app, users can't enter their data limits.

When users’ data limits are unknown, you can still use the Data Sense API to determine whether they're using a Wi-Fi connection, or roaming. However you can't use the Data Sense API to determine whether they're approaching their data limit, or over their data limit.

You can’t use the Simulation Dashboard to test your Data Sense code by changing the network type from cellular to Wi-Fi or reverse. The Simulation Dashboard does not change the values of the properties that the Data Sense API uses.

When a Wi-Fi connection for which the phone has connection information becomes available, the phone automatically switches from a cellular connection to the Wi-Fi connection. You don’t need to write code to disconnect and reconnect when a Wi-Fi connection becomes available.

Launching, resuming & multitasking

You can use APIs from the Windows.Phone.Management.Deployment namespace to see if other apps from your publisher ID are installed on a phone. If they’re installed, you can also use this API to launch them.

IEnumerable<Package> apps = Windows.Phone.Management.Deployment.InstallationManager.FindPackagesForCurrentPublisher();
apps.First().Launch(string.Empty);

You can use the Launcher.LaunchUriAsync(Uri) method to launch built-in apps via URI. From the user’s standpoint, this works like Launchers for Windows Phone. But this method allows you to launch some built-in apps that you can’t launch with a Launcher. Unlike a Launcher, this feature can be used by native code.

As with a user-initiated launch, the user can still tap the back button to return to your app.

Fast app resume for Windows Phone 8 - zarządzanie stosem nawigacyjnym, wybieramy między resetowaniem stanu a jego przywracaniem

Fast Resume Backstack Sample

Fast Application Switching is supported on lower-memory devices.

For Windows Phone 8 apps, memory and execution time policies are enforced while debugging.

Like Windows 8, Windows Phone 8 uses LaunchFileAsync to launch a file and LaunchUriAsync to launch a URI. However, the way Windows Phone XAML apps receive a file or URI is different. Also, Windows Phone does not have a “default” Store app.

File associations are also used to determine which file types apps can read from an SD card using the external storage APIs.

Sometimes Internet Explorer overrides file associations: it launches the built-in media player to handle all music and video file types. Specifically, any file that has an audio/ or video/ content type. For example, your app can handle a (non-reserved) music and video file when it is launched from an email attachment. But if the same file is launched from Internet Explorer, the built-in media player will handle the file.

You can associate a maximum of 20 file extensions with each file association. If your app reads files from the SD card, you must also specify the ContentType attribute to describe the type of file.

/FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19

Upon launch, map the incoming deep link URI to an app page that can handle the file. If you have multiple pages to handle multiple file types, use a custom URI mapper and the GetSharedFileName method to check the file type before mapping the URI.

SharedStorageAccessManager

Kafelki

Adding Windows Phone 8 Tile functionality to Windows Phone OS 7.1 apps

If you plan to maintain an app that targets Windows Phone OS 7.1, you can use reflection to access Windows Phone 8 APIs that showcase the new Tile functionality. This way, if your Windows Phone OS 7.1 app runs on a phone that supports Windows Phone 8 Tile features, those customers will have access to the new Tile features.

You create and update Windows Phone 8 Tiles in your Windows Phone OS 7.1 app in the same way as a Windows Phone 8 app. The one difference is that you must first update the small, medium, and (optionally) wide default Tile with a local image. On the next update, you can use a local or remote image as usual.

<AppExtra xmlns="" AppPlatformVersion="8.0">
    <Extra Name="Tiles"/>
</AppExtra>

Implementacja za pomocą refleksji.

Lock screen

A user can set your app as the default lock screen background image provider in the phone lock screen settings screen before your app has had a chance to set up the image. For this reason, you should include a default lock screen background image at the root of your main project's XAP package. Name the image DefaultLockScreen.jpg.

Camera & photos

The lens feature can do more than launch an app from the built-in camera. Rich media lenses incorporate data from the local folder or the web to provide a richer and deeper way of engaging with images they have captured. A rich media lens can save a JPG image to the media library to represent each rich media item that it has captured. When viewing that image from the built-in photo viewer, it’s marked with a captured by caption. Then, from the app bar, users can relaunch the rich media experience by tapping the open link.

IC622576

Rich media lenses differ from a traditional camera app because they save additional information about the image in the app’s local folder.

Don’t use the rich media open link for traditional photo editing, which is limited to only bit manipulations on the JPG file that’s in the camera roll. Rich media extensibility is intended for apps that do “rich editing” using additional information that it has about the photo. For example, allowing the user to choose a different photo from a “time shifted” capture, when additional photos are stored in the app’s local folder, would be considered rich editing. Use the open link only when the user can increase their experience of the photo by viewing it inside your app. For traditional photo editing, such as bit manipulations, cropping, brightening, rotating, etc., use the edit or apps link

<Extension ExtensionName="Photos_Rich_Media_Edit"
           ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}"
           TaskID="_default" />

/MainPage.xaml?Action=RichMediaEdit&token=%7Bed8b7de8-6cf9-454e-afe4-abb60ef75160%7D

Photo Extensibility Sample

The Microsoft.Devices.PhotoCamera class gives you the ability to programmatically capture photos in your app. You can use this class to specify the photo resolution and flash settings, and trigger autofocus. For advanced photo capture, the Windows.Phone.Media.Capture.PhotoCaptureDevice class provides an extended set of capabilities and better performance. Use this class to control photo properties such as ISO, exposure compensation, and manual focus position (when available on the phone).

Advanced photo capture for Windows Phone 8  (WinRT)

Windows.Foundation.Size res = SupportedResolutions[0];
this.captureDevice = await PhotoCaptureDevice.OpenAsync(CameraSensorLocation.Back, res);

The initial preview resolution is automatically assigned based on the initial capture resolution and the screen resolution of the phone. Later on, you can set the resolution with the SetCaptureResolutionAsync and SetPreviewResolutionAsync methods. To find out which resolutions are available on the phone, use the GetAvailableCaptureResolutions and GetAvailablePreviewResolutions methods.

Cameras on Windows Phone are optional, so all apps need to check the phone to see if a camera exists. You can use the static property PhotoCaptureDevice.AvailableSensorLocations to check for cameras.

CameraCaptureSequence seq;
seq = cam.CreateCaptureSequence(1);

In this release, the Windows.Phone.Media.Capture.CameraCaptureSequence class supports only single-frame capture.

When capturing photos, you can use the KnownCameraGeneralProperties and the KnownCameraPhotoProperties methods to specify camera and photo settings. Use the SetProperty method to set properties that affect all frames in the capture sequence. Not all properties are supported by each phone. Use the GetSupportedPropertyValues or the GetSupportedPropertyRange method to determine which property values you can use.

// Set camera properties.
cam.SetProperty(KnownCameraPhotoProperties.FlashMode, FlashState.On);
cam.SetProperty(KnownCameraGeneralProperties.PlayShutterSoundOnCapture, true);
cam.SetProperty(KnownCameraGeneralProperties.AutoFocusRange, AutoFocusRange.Infinity);

You can also set properties on an individual frame.

// Set the frame properties.
seq.Frames[0].DesiredProperties[KnownCameraPhotoProperties.SceneMode]
   = CameraSceneMode.Portrait;

The DesiredProperties property is like a “wish list.” Each phone is limited in the number and combinations of properties that it can apply to frames; properties specified with DesiredProperties are not guaranteed. To see which properties were actually used after the capture, use the frame’s AppliedProperties property.

MemoryStream captureStream1 = new MemoryStream();

// Assign the capture stream.
seq.Frames[0].CaptureStream = captureStream1.AsOutputStream();

Use the ThumbnailStream property if you want to display a thumbnail image of the frame after it has been captured.

// Prepare the capture sequence.
await cam.PrepareCaptureSequenceAsync(seq);

Windows Phone 8 provides additional capture methods that you can use with native code.

Advanced capture properties for Windows Phone 8

Capturing video for Windows Phone

The System.Windows.Media.CaptureSource class, used in conjunction the FileSink class, give your app the ability to programmatically record video. For advanced video and encoding settings, the Windows.Phone.Media.Capture.AudioVideoCaptureDevice class provides an extended set of capabilities and better performance. Use this class to control video properties such as encoding settings, torch power, system mute, and manual focus position.

Photo extensibility for Windows Phone

Photo Viewer

IC619198

3 - Extend the photo edit picker (Windows Phone 8 only): Your app can be launched from the edit link and allow the user to edit their photo.

4 - Extend the photo edit picker (Windows Phone 8 only): Your app can be launched from the edit link and allow the user to edit their photo.

Photo Extensibility Sample

Auto-upload apps for Windows Phone 8

Apps that provide auto-upload functionality register for the auto-upload extension and launch to an auto-upload settings page when launched from the Settings app. To perform uploads, an auto-upload app must use a resource-intensive background agent, using the ResourceIntensiveTask class. Unlike other background agents, resource-intensive agents for auto-upload apps do not expire.

Apps that provide auto-upload functionality launch to a settings page when they are launched from the Settings app. In the Settings app, the photos+camera settings page lists an apps link at the bottom of the page. That link launches the auto-upload apps page.

IC600184

<Extension ExtensionName="Photos_Auto_Upload"
           ConsumerID = "{5B04B775-356B-4AA0-AAF8-6491FFEA5632}"
           TaskID="_default"/>

When the deep link URI contains the keyword ConfigurePhotosUploadSettings, launch your app to a settings page on which a user can configure the auto upload.

When you create a resource-intensive agent for your auto-upload app, do not set an expiration time for the task. This will ensure that the agent doesn’t expire if your app hasn’t been opened for 14 days.

Before your app can perform automatic uploads, it will need to provide a way for users to enter their user credentials to the photo storage web service. Your foreground app can use the settings page for this task, but you don’t have to use the same page. For storing user credentials, we recommend encrypting them with the ProtectedData class.

You background agent is responsible for monitoring the media library, and for keeping track of what photos need to be uploaded. It also needs to track upload status so that it can resume an upload if the phone loses connectivity.

Custom contact store

Custom properties are not displayed on the contact card in the People hub, but can be accessed programmatically from your app. The contact store APIs also provide a mechanism for you to enumerate changes between your custom contact store on the phone and a contact store you maintain in a cloud service in order to synchronize the two stores.

The custom contact store APIs only provide access to the contacts created by your app. If your app needs read-access to the phone’s contact store or calendar, there are different APIs that you should use.

Each Windows Phone app can have a single contact store. You open the store by calling CreateOrOpenAsync. The store will be created when you call this method, if it doesn’t already exist. The overloaded version of this method accepts a member of the ContactStoreSystemAccessMode enumeration and a member of the ContactStoreApplicationAccessMode enumeration, which specify how much access the system and other apps have to your contact store. ContactStoreSystemAccessMode.ReadOnly indicates that only your app can modify your contacts. ContactStoreSystemAccessMode.ReadWrite means that the phone can modify your contacts through its built-in contacts experience. ContactStoreApplicationAccessMode.LimitedReadOnly means that other apps can read only the display name and the profile picture of your contacts. ContactStoreApplicationAccessMode.ReadOnly means that other apps can read all of the properties of your contacts. The default settings are ContactStoreSystemAccessMode.ReadOnly and ContactStoreApplicationAccessMode.LimitedReadOnly.

ContactStore store = await ContactStore.CreateOrOpenAsync(
    ContactStoreSystemAccessMode.ReadWrite,
    ContactStoreApplicationAccessMode.ReadOnly);

The StoredContact object has built-in properties for several common pieces of contact data, such as given name and family name. Each contact also has a field that contains a local ID, which is dynamically assigned by the operating system, and a field for storing a remote ID that can be set by your app. You can use the remote and local IDs to associate contacts in your app’s contact store on the phone with a remote contact store in the cloud.

In addition to the fields that are provided by the StoredContact object, you can add more properties by calling GetExtendedPropertiesAsync. This returns a dictionary of key value pairs that you can populate with contact data. You can use the fields of the KnownContactProperties class for key values if you want the fields to be consistent with the phone’s internal contact property names. Or you can specify any arbitrary string as a key.


async public void AddContact(string remoteId, string givenName, string familyName, string email, string codeName)
{
    ContactStore store = await ContactStore.CreateOrOpenAsync();

    StoredContact contact = new StoredContact(store);

    RemoteIdHelper remoteIDHelper = new RemoteIdHelper();
    contact.RemoteId = await remoteIDHelper.GetTaggedRemoteId(store, remoteId);

    contact.GivenName = givenName;
    contact.FamilyName = familyName;

    IDictionary<string, object> props = await contact.GetPropertiesAsync();
    props.Add(KnownContactProperties.Email, email);

    IDictionary<string, object> extprops = await contact.GetExtendedPropertiesAsync();
    extprops.Add("Codename", codeName);

    await contact.SaveAsync();

}

You can update a contact by retrieving it from the store, modifying its properties, and then saving it again. The following code example uses FindContactByRemoteIdAsync to retrieve a contact using its remote ID. You can also call FindContactByLocalIdAsync to retrieve a contact by local ID.


async private void UpdateContact(string remoteId, string givenName, string familyName, string email, string codeName)
{
    ContactStore store = await ContactStore.CreateOrOpenAsync();

    RemoteIdHelper remoteIDHelper = new RemoteIdHelper();
    string taggedRemoteId = await remoteIDHelper.GetTaggedRemoteId(store, remoteId);
    StoredContact contact = await store.FindContactByRemoteIdAsync(taggedRemoteId);

    if (contact != null)
    {
        contact.GivenName = givenName;
        contact.FamilyName = familyName;

        IDictionary<string, object> props = await contact.GetPropertiesAsync();
        props[KnownContactProperties.Email] = email;

        IDictionary<string, object> extprops = await contact.GetExtendedPropertiesAsync();
        extprops["Codename"] = codeName;

        await contact.SaveAsync();
    }
}

Delete a contact by calling DeleteContactAsync and passing in the local ID of the contact to be deleted. If you want to delete a contact based on the remote ID, call FindContactByRemoteIdAsync then use the value of the Id property to call DeleteContactAsync.

async private void DeleteContact(string id)
{
    ContactStore store = await ContactStore.CreateOrOpenAsync();
    await store.DeleteContactAsync(id);  
}

You can query for all contacts in the store by calling CreateContactQuery. The no-argument version of the method returns the default set of fields for each contact, and uses the default ordering. Call GetContactsAsync on the returned ContactQueryResult object to retrieve the list of returned contacts.

async private void DefaultQuery()
{
    ContactStore store = await ContactStore.CreateOrOpenAsync();
    ContactQueryResult result = store.CreateContactQuery();
    IReadOnlyList<StoredContact> contacts = await result.GetContactsAsync();

    ContactListBox.ItemsSource = contacts;

}

If there is a subset of the KnownContactProperties that you know you will need to access, you can create a new ContactQueryOptions and then add property names to the DesiredFields vector to specify that they should be fetched when the query is made.

You can also set OrderBy to change the field used to order the results, but it is recommended that you use the default ordering because that will provide a consistent user experience across apps.

async private void QueryWithDesiredFields()
{
    ContactStore store = await ContactStore.CreateOrOpenAsync();

    ContactQueryOptions options = new ContactQueryOptions();
    options.DesiredFields.Add(KnownContactProperties.Email);

    ContactQueryResult result = store.CreateContactQuery(options);
    IReadOnlyList<StoredContact> contacts = await result.GetContactsAsync();

    ContactListBox.ItemsSource = contacts;
}

If your cloud-based contact store does not use IDs that are guaranteed to be unique, you can add the following class to your project that will help you add a unique tag to your IDs before you save a contact to the store. It will also help you remove the unique tag from the ID after you have retrieved it from the store so that you can get your original remote ID back.

vCard is a standard file format used for electronic business cards. The ContactInformation class exposes the ParseVcardAsync method, which asynchronously parses the vCard at the specified URI, and then returns a populated ContactInformation object.

task<StoredContact^> SaveFromVcard(ContactStore^ store, String^ uriToVcard)
{
    // Invoke the parser on the passed-in URI.
    return create_task(ContactInformation::ParseVcardAsync(ref new Uri(uriToVcard)))
    .then([=] (ContactInformation^ info) -> StoredContact^
    {
        // When that's done, wrap a stored contact around it, save.
        auto contact = ref new StoredContact(store, info);
        create_task(contact->SaveAsync()).get();

        return contact;
    });
}