niedziela, 3 sierpnia 2014

Pojedynek z Androidem - odc.1 jak zacząć?

Android?!  Czy ktoś nie podszył się tutaj pode mnie?  Spokojnie, Windows i Windows Phone są zawsze dla mnie numerem jeden, ale pojawiła się myśl, by przyjrzeć się trochę konkurencyjnym platformom, czegoś zupełnie nowego się dowiedzieć i mieć pełniejszy obraz świata mobilnego. Trudno bym stał się nagle super-ekspertem od innych platform czy choćby ich fanem, ale robić notatki z poznawanych rzeczy, dzielić się wrażeniami,  porównywać z Windows przecież mogę. Takie niezobowiązujące posty pisałbym sobie raz na jakiś czas (raczej nie w postaci jednego ciągu). Na pierwszy ogień chciałbym zmierzyć się z Androidem, po pierwsze dlatego, że jest najbardziej popularny (nurtuje mnie co się w nim większości podoba się), po drugie dlatego, że Javę i tak uważam za znacznie bardziej wygodną od Objective-C w  iOS (choć ostatnio obok niego pojawił się Swift), a po trzecie trzy lata temu uczestniczyłem w szkoleniu z Androida, więc coś sobie przypomnę  i będzie łatwiej (zobaczę może też co się zmieniło). Wiem, że nie muszę koniecznie używać Javy i mógłbym posłużyć się C# (Xamarin) lub HTML5 (Apache Cordova), ale przez szacunek dla przeciwnika najpierw chcę zobaczyć go w pełnej krasie, w jakiej widzą go ludzie z jego świata. Gdyby ktoś zaczął naukę pisania na Windows Phone od np. Apache Cordovy to uznałbym to za profanację.

Obejrzałem jakiś pierwszy kurs, co się dowiedziałem?  Poniżej trochę notatek (jeszcze sprzed urlopu), które robiłem, gdy oswajałem narzędzia, by odpalić pierwsze dwa hello world. Czemu dwa? Od 2013 roku Eclipse nie jest już numerem jeden, Google stworzyło alternatywę w postaci Android Studio (na razie w wersji beta z ograniczoną funkcjonalnością). Intuicyjność i ergonomię oceniam nieco niżej niż w Visual Studio, bo w każdym przypadku trzeba coś było zrobić przed założeniem projektu (np. pobrać pakiety w menadżerze, powalczyć z konfiguracją emulatora i wsparciem sprzętowym, przestawić w designerze z najwyższej wersji API na swoją, aby nie mieć błędów itp.). Plusem jest szybkość instalacji i uniwersalność emulacji (a także spora konfigurowalność). Android Studio wgrywa się do ukrytego systemowego foldera, co może jest intuicyjne dla użytkowników Linux, ale nie Windows. Szkoda, że nawet następna wersja Androida 5 wymaga Javy 7, a nie najnowszej 8 (aktualny Android 4.4 wymaga dwie wersje wstecz, czyli Javy 6).

Środowisko

Android Developer Tools (ADT) Bundle

  • Eclipse  (od maja 2013 alternatywa - Android Studio)
  • ADT Plugin (dodatek do Eclipse)
  • Android SDK Tools
  • Android Platform Tools
  • Android Platform
  • obrazy dla emulatora

Java Development Kit (JDK) - sprawdzić wersję wymaganą przez Android SDK

developer.android.com  - odpowiednik MSDN / Windows / Windows Phone Developer Center

Obecne narzędzia wymagają Javy 6 (dwie wersje wstecz w stosunku do bieżącego wydania  Java 8)

AVD (Android Virtual Devices) / emulatory

  • obrazy tworzone na podstawie definicji
  • definicje jako zbiór właściwości (charakterystyki ekranu, fizyczna klawiatura?, GPS?, właściwości podstawowej i frontowej kamery) odpowiadającym prawdziwym urządzeniom lub generycznemu zbiorowi
  • można wprowadzać modyfikacje do niektórych charakterystyk

Android Virtual Device Manager – tworzenie i dostęp do AVDs, możliwość uruchomienia bezpośrednio z Eclipse (m.in ilość RAM, wersja systemu i API, obecność kamer, rozmiar wewnętrznej przestrzeni dyskowej oraz karty SD)

Create AVD - uups brak… obrazów, trzeba wiedzieć, że pobiera się je konfigurując pakiety do pobrania w Android SDK Manager

Przed odpaleniem obrazu można wybrać “Scale display do real size”, aczkolwiek u mnie ta opcja powoduje wyświetlanie dość małego okienka, więc z niej przestałem korzystać. Aha dostaję informację: “Failed to open Hax device”. Emulator się odpala, ale jednak szukam w czym rzecz.  Nie miałem zainstalowanego pakietu Hax w menadżerze SDK, a także wybrałem zły typ obrazu dla mojej wirtualnej maszyny w menadżerze AVM (trzeba wybierać obraz ARM zamiast np. Intel Atom x86).

A, i co z klawiaturą sprzętową na emulatorze? Nie widzę jej. No, teraz wybrałem skórkę “Skin with dynamic hardware controls”, już widzę, ale… nie są aktywne, o czym jest informacja.  Ale tak też jest na zdjęciu w szkoleniu, może to i logiczne, obecnie coraz mniej urządzeń z fizycznymi klawiszami poza wyłącz, głośność i coś jeszcze.

New Android Application Project

Uups… mimo wybrania API 19, dostaję komunikat że nie poradzono sobie z renderowaniem dla Androida L Preview (czyli 5). Znalazłem w sieci, że trzeba ikonę w designerze głównej aktywności przestawić na wybrany przez siebie poziom API. Czemu domyślnie podgląd ustawiany jest najwyższą wersję, skoro do tworzenia projektu wybrałem sobie 19 ?

No dobra, chcę zdebugować pierwszą aplikację na emulatorze podobnie jak w przewodniku. Klikam w pluskwę i … nic się nie dzieje. A, trzeba było zaznaczyć właściwy projekt w managerze pakietów, wybrałem debugowanie jako aplikacja Android, potwierdzam sposób logowania przy uruchamianiu i nareszcie mam zdeployowaną app-kę do emulatora!

Debugowanie fizycznego urządzenia wymaga:

  • włączenia debugowania przez USB na telefonie
    • na większości urządzeń z < Android 4.0:  Settings –> Applications –> Debugging
    • na większości urządzeń z Android 4.0 i 4.1: Settings –> Developer Options
    • od Android 4.2 Developer Options domyślnie ukryte (odblokowanie: Settings –> About phone –> Build number (nacisnąć 7 razy)
    • od Androida 4.2.2 specjalne zabezpieczenie (trzeba zaakceptować klucz RSA dla desktopa przy pierwszym połączeniu, potrzebne >=  Android Platform Tools r.16.0.1)
  • instalacji sterowników USB na komputerze
  • urządzenia z aktywnym ekranem (ustawienie Stay awake w Developer Options lub pobrać aplikację stay awake z Google Play, która to czyni)

Narzędzia

desktop                                                                                       | device

Eclipse –> ADB (Android Debug Bridge) Server –> | ADB Daemon –> App

logcat                                                                                                         OS                  logcat

DDMS (Dalvik Debug Monitor Server)

http://developer.android.com/tools/help/index.html

ADB Command Line Utility  [install]\sdk\plaform-tools

adb devices, kill-server, start-server

kopiowanie plików między desktopem a urządzeniem, instalacja/deinstalacja aplikacji

http://developer.android.com/tools/help/adb.html

Linux shell na urządzeniu  (shell, shell komenda)

wiele urządzeń/ADVDs

  • -d – tylko urządzenie (np. adb –d shell ps)
  • -e  - tylko AVD
  • -s identyfikator  (przy wielu tego samego rodzaju)

Logcat

  • Eclipse, adb
  • android.util.Log
    • Silent
    • Assert: Log.wtf
    • Error: Log.e
    • Warning: Log.w
    • Info: log.i
    • Debug: Log.d
    • Verbose: Log.v
  • bufory:
    • main (Eclipse), events (wszystkie systemowe zdarzenia), radio (aktywność radiowa: np. komórka, Wi-Fi)
    • adb logcat –b nazwa

DDMS

  • debugowanie, lista podłączonych urządzeń/emulatorów, ich procesy, narzędzia, Logcat view
  • procesy muszą być debugowalne, aby być widoczne
    • system w wersji debug na emulatorach - wszystkie procesy są widoczne
    • standardowy system na większości urządzeń - proces musi być oznaczony jako debugowalny
  • narzędzia:
    • proces:  zużycie pamięci (heap - ogólnie, alokacja - szczegółowo dla obiektów), aktywność wątków (callstacki), aktywność sieciowa
    • urządzenie/AVD: system plików (nawigacja, kopiowanie do i z komputera, usuwanie pliku/foldera, tworzenie folderu), screen capture, kontrola AVD (sieć: status, prędkość, dane, opóźnienie; telefon dzwoniący, SMS, lokalizacja geograficzna, pobierane danych z GPS)
    •  http://developer.android.com/tools/debugging/ddms.html

Projekt

  • Nazwa projektu rzutuje na pakiet klas i identyfikator w Google Play (wymagana unikalność pakietu)
  • Ikona startowa - domyślna, z clipartu (kolor, kształt, obramówka), z tekstu
  • Atywność
    • UI: blank, fullscreen, master/detail (na tabletach dwie kolumny, na telefonach jedna)
    • Nazwa: nazwy klasy Java
    • Nazwa layoutu: nazwa zasobu XML
    • Typ nawigacji: none, fixed tabs + swipe, scrollable tabs + swipe, dropdown
  • Elementy w Eclipse (Android Studio ma inną strukturę projektu)
    • pliki Java (folder src, struktura pakietu)
    • zasoby (folder res, struktura zasobów)
      • layout  - pliki XML
      • menu – pliki XML
      • values
        • values
          • dimens.xml
          • strings.xml
          • styles.xml
        • values-sw600dp
        • values-sw720dp-land
        • values-v11
        • values-v14
      • drawable - obrazki, animacje
        • drawable-hdpi
        • drawable-ldpi
        • drawable-mdpi
      • AndroidManifest.xml

R.layout.activity_main

skrócone źródła

<RelativeLayout xmlns:android=”…”

    xmlns:tools=”…”

    android:layout_width=”match_parent”

    android:paddingBottom=”@dimen/activity_vertical_margin”

    tools:context=”.MainActivity”>

              <TextView

                          android:layout_width=”wrap_content”

                          android:text=”@string/hello_world”/>

  </RelativeLayout>

         <menu xmlns:android=”…”>

                     <item

                               android:id=”@+id/action_settings”

                               android:title=”@string/action_settings”/>

          </menu>

       <manifest xmlns:android=”…”

                     package=”…”

                     android:versionCode=”1”

                     android:versionName=”1.0”>

                    <uses-sdk

                                  android:minSdkVersion=”8”

                                  android:targetSdkVersion=”19” />

                    <application

                                  android:allowBackup=”true”

                                  android:icon=”@drawable/ic_launcher”

                                  android:label=”@string/app_name”

                                  android:theme=”@style/AppTheme”>

                                  <activity

                                               android:name=”…”

                                               android:label=”…”

                                               <intent-filter>

                                                             <action android:name=”…”/>

                                                              <catgory android:name=”…”/>

                                              </intent-filter>

               </application>

      </manifest>

Budowanie projektu

Plik wynikowy *.apk

Android Asset Packaging Tool (aapt) tworzy:

  • R.java
  • Skompilowane zasoby

Pliki *.java (nasze i generowane) są kompilowane do *.class

Pliki *.class są zamieniane przez narzędzie dex na *.dex (kompatybilne z Android Runtime)

Appkbuilder ze skompilowanych zasobów i plików *.dex tworzy plik *.apk

Kiedy R.java się nie generuje?

  • Build Automatically – opcja
  • Clean projekt
  • Błędy w plikach XML

Android Studio

  • nowe IDE od 2013, bazuje na JetBrain IntelliJ IDEA Community Edition
  • te same narzędzia z Android SDK
  • nie zawiera w sobie zintegrowanego DDMS (otwiera w osobnym oknie)
  •  http://developer.android.com/sdk/installing/studio.html
  • ta sama wersja JDK, co Eclipse
  • Miejsce wgrania: ukryty domyślnie folder systemowy Windows ~\AppData\Local\Android\android-studio
  • Gardle - system buildów
  • AndroidManifest - tylko edytor tekstowy
  • Większa produktywność
  • Większe podobieństwo do Visual Studio
  • Settings -> Appearance -> skórka Darcula (nowoczesny „czarny” wygląd z prezentacji)

Wersjonowanie Androida

Wydanie ma dwa indentyfikatory:

  • Platform version - zbiór aplikacji, właściwości, zachowań (X.Y lub X.Y.Z)
  • API Level - zbiór właściwości udostępnionych developerom (numer int)

Każda wersja platformy wspiera określony level API, a ten sam level API może znaleźć się w kilku wersjach platformy

1.0/1 - 1.6/4 - na początek, zaadaptowane przez większość miłośników gadżetów

2.0/5 - 2.3.7/10 - bardziej przyjazne, początek adaptacji użytkowników

3.0.x/11 – 3.2/13 - tylko na tablety, bardzo ograniczona adaptacja

4.0/14 – 4.4/19 - tablet & telefon, znacznie lepszy UX, szeroka adaptacja

4.4W/20 - Android Wear, zegarki

L Preview /20 - Preview Android 5

Odeszły: 1.0 – 1.5, 2.0 – 2.0.1, 3.0 – 3.1.x, 4.0 – 4.0.2

Maj 2013:

15: 55.9% (w miarę najnowszy)

13: 56% + 0.1%

10: 94.4% + 38.4% (w miarę najwięcej userów)

7: 99.9% + 5.5%

4: 100% + 0.1%

http://developer.android.com/about/dashboards/index.html

Zarządzanie poziomami API

  • AndroidManifest.xml uses-sdk (minimalna i najwyższa przetestowana wersja - target, opcjonalnie najwyższa wersja, którą życzymy sobie wspierać – max, ostatnia jest przydatna, gdy chcemy robić różne wersje aplikacji na różne zakresy API)
  • Kompilator (w większości przypadków kompiluje się z najniższą wspieraną wersją API, choć można i z wyższą, ale trzeba pilnować czy nie mamy niezabezpieczonych wywołań wyższej wersji API)
  • W zależności od maksymalnego poziomu na nowszych urządzeniach/emulatorach może wyświetlać się nowszy interfejs, przy zachowaniu dostępu do najniższej wersji API
  • Android SDK Manager - powinniśmy używać najnowszych Revision Level dla danego poziomu API

sobota, 2 sierpnia 2014

Windows Phone 8.1 Update 1 - zapowiada się bardziej gorący tydzień…

Końcówka urlopu. Odrabiam zaległości związane z przerwą. Zapowiada się świetny tydzień. Powinien zostać udostępniony do pobrania Windows Phone 8.1 GDR 1/ Update 1. Ten kto ma WP 8.1 Developer Preview nie musi się martwić trudnościami aktualizacji do finalnego updatu o nazwie “Cyan”, ponieważ Joe Belfiore ogłosił, że nie trzeba nic robić i poczekać na przyszły tydzień, a wtedy już Update 1 dostaniemy z automatu!  A co przynosi Update 1?  Otóż w przeciwieństwie do poprzednich podobnych aktualizacji trafi do niego kilka znaczących nowych funkcjonalności, a nawet trafi się dodatkowe API.  Ale po kolei. Wymienię to, co najbardziej zwróciło moją uwagę, więcej szczegółów można znaleźć w poniższych linkach. Po pierwsze – żywe foldery (idea folderów podobna do Androida). Od teraz będziemy mogli grupować w nich kafle. Pokazuje to pierwszy wklejony poniżej filmik. Po drugie -  Apps Corner. Aplikacje pracownicze trzymamy w specjalnej piaskownicy, by nie mogły wyciągać naszych prywatnych danych. Aaa… niezależnie od Update’u 1 zapomniałem dodać, że od niedawna została udostępniona aplikacja w wersji beta służąca do personalizacji ekranu wygaszacza (do płynnego działania wymaga 1 GB ramu). Możemy podziwiać niestandardowe układy i animacje, a w przyszłości zostanie ujawnione związane z tym API. To realizacja zapowiedzi z BUILD 2014 odnośnie nieograniczonej personalizacji lock-screen. Po czwarte - wracając ściśle do Update 1 - istotny krok w mobilnym świecie Web. Twórcy IE postanowili, że mobilny Web powinien być przede wszystkim uniwersalny, jak najbardziej przenośny i postanowili zaimplementować funkcjonalności i zachowania znane z mobilnych przeglądarek na Android i iOS, pomijając fakt, że nie są zawarte w standardach Web (trzymanie się jedynie niekompletnych standardów utrudnia pisanie przenośnych aplikacji). Przykładowo część niezbędnych do działania funkcjonalności webkita będzie potrafił wykonać IE, a obsługa starszych zdarzeń dotykowych zostanie dołączona obok nowszych pointer eventów.

 

Live folders na ekranie startowym

 

Live lock screen app

 

Linki

piątek, 18 lipca 2014

Wieczór z Madonną cz.2 (WinJS 2.1 na Windows Phone 8.1)

Od ostatniego posta minął miesiąc, coś ten tytułowy wieczór nam się rozciągnął, ale w końcu piszę część drugą i ostatnią tej mikroserii, którą sobie założyłem.  Zrelacjonuję tutaj swoje praktyczne doświadczenia, a także subiektywne odczucia co do pisania uniwersalnych aplikacji w WinJS na Windows i Windows Phone 8.1. Skupię się na telefonie i WinJS 2.1.

W celach eksperymentalnych pozwoliłem sobie przepisać uniwersalną aplikację XAML/C# z poprzedniego posta na HTML5 i WinJS.

wp81winjs

Co mnie zaskoczyło, co było interesujące, z czym są lub były problemy, już piszę. A więc:

1. Kontrolka AppBar z WinJS ma buga na Windows Phone, otóż… sama znika po przejściu na inną stronę. Nie tylko ja na natrafiłem, społeczność światowa zdążyła założyć już odpowiednie wątki na forach. Co robić?  Zamiast na poszczególnych stronach możemy trzymać ją globalnie w pliku default.html.

<body class="phone">
    <div id="contenthost" data-win-control="Application.PageControlNavigator" data-win-options="{home: '/pages/home/home.html'}"></div>
    <div id="appbar" data-win-control="WinJS.UI.AppBar">
        <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{icon:'add', id:'cmdAdd', label:'Add', section:'global', type:'button'}"></button>
        <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{icon:'find', id:'cmdSearch', label:'Search', section:'global', type:'button'}"></button>
        <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{icon:'microphone', id:'cmdVoice', label:'Voice', section:'global', type:'button'}"></button>
        <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{disabled:true, icon:'download', id:'cmdDownload', label:'download', section:'global'}"></button>
    </div>
</body>

Na poszczególnych stronach włączymy odpowiednie dla danego miejsca komendy. Przykładowo na stronie startowej metoda ready woła kod:

           var appbar = document.querySelector("#appbar").winControl;
            if (appbar) {
                appbar.showOnlyCommands(['cmdAdd', 'cmdSearch', 'cmdVoice']);                            
            }

            …

     var addButton = document.querySelector("#cmdAdd").winControl;
     addButton.addEventListener("click", this.doClickAdd);           

            var searchButton = document.querySelector("#cmdSearch").winControl;
            searchButton.addEventListener("click", this.doClickSearch);           

            var voiceButton = document.querySelector("#cmdVoice").winControl;
            voiceButton.addEventListener("click", this.doClickVoice);

W obiekcie definiującym tę stronę mam oczywiście definicji metod doClickAdd, doClickSearch i doClickVoice. Przy wyładowaniu strony w metodzie unload odpinam się od tych zdarzeń.

2. Stylowanie stron CSS robiło na początku mi niespodzianki, trzeba uważać, najlepiej opierać się na predefiniowanych stylach w projektach Visual Studio. Zdarzało mi się, że po zmianie wysokości sekcji nagłówka, rozepchany nagłówek i część stylowania zostawała po powrocie na stronę startową z pivotem. W końcu postanowiłem na bardziej standardowe rozwiązania i problemy znikły (zamiast pola tekstowego nad tytułem strony zrobiłem go bardziej typowo pod, sprawę ułatwiło też skorzystanie z projektu VS z pivotem zamiast mniej skompilowanego sampla z SDK dla pivota)

3. W WinJS na WP nie ma kontrolki hub (choć jest w XAML). Musimy zadowolić się pivotem, który oficjalnie jest polecany w miejsce huba. Z mniej podstawowych rzeczy zrobiłem sobie pokazywanie AppBar w zależności od aktualnie wyświetlanej sekcji pivota:

            var hub = element.querySelector(".hub").winControl;
            hub.addEventListener("selectionchanged", function (args) {
                if (appbar) {
                    if (args.detail.index === 0) {
                        appbar.disabled = false;
                    }
                    else {
                        appbar.disabled = true;
                    }
                }
            });

4. W WinJS na WP nie ma kontrolki AutoSuggestBox (choć jest to nowość w XAML). Zadowoliłem się zwykłym tekstowym inputem w HTML.

5. Ciężej i jednak mniej wygodnie pisze się kod asynchroniczny w JavaScript za pomocą promis-ów niż przy pomocy async-ów w C#. O ile na typowej stronie czy aplikacji webowej na przeglądarkę nie używa się jeszcze często asynchronicznych metod poza strzałami AJAX-owymi (nie wspominam tu o web workerach), o tyle w Windows niemal każda metoda z API jest asynchroniczna. Stosowanie ciągów then, then, then, done jest całkiem przyjazne, pojawiają się jednak ciekawsze przypadki.

a.  Jak w pętli wywołać n-razy tą samą asynchroniczną metodę ?  Znalazłem fajnego bloga pokazującego odpowiedni pattern.

b. Jak zwrócić zwykłą wartość jako promise by zachować ciąg then, then, …, done?  Możemy wtedy zwrócić  WinJS.Promise.as(wartość).

c. Jak opakować w promise odtworzenie pliku audio? Ponieważ przenosiłem kod będący przeplataniem generowania i rozpoznawania mowy, chciałem za każdym razem poczekać aż telefon powie jakąś kwestię, zanim zacznie nasłuchiwać mojej odpowiedzi. Mając za sobą opakowanie odtwarzania w MediaElement w taska, postąpiłem tutaj podobnie:

var playAudio = function (markersStream) {
            return new WinJS.Promise(function (complete, error, progress) {
                var audio = new Audio();
                var blob = MSApp.createBlobFromRandomAccessStream(markersStream.ContentType, markersStream);
                audio.src = URL.createObjectURL(blob, { oneTimeOnly: true });

                audio.addEventListener('ended', function () {
                    complete();
                }, false);

                audio.play();
            });           
        };   

speechSynthesizer.synthesizeTextToStreamAsync("What song do I play?").then(function (markersStream) {
                return playAudio(markersStream);
            }).then(function () {

               // rozpoznawanie mowy

           }

6.  Gdy chcemy we współdzielonym pliku JavaScript warunkowo wywołać kod w zależności od tego, czy jesteśmy na WP czy na Windows, to robimy warunek na wartość WinJS.Utilities.isPhone.

7. Jeśli chcemy we współdzielonym pliku CSS uzależnić styl od wykonywania na WP, to przed warunkiem dostawiamy klasę .phone.   Przykładowo, gdy ukrywamy na telefonie przycisk Back na stronie  piszemy:

.phone .videoDetails .back-button {
    display: none;
}

Podsumowanie.  Odczucia?  Trochę mniej wygodnie i mniej stabilnie niż w XAML/C# czy WinJS na Windows 8.1.  Nie wiem na ile to kwestia systemu Windows Phone na emulatorze w wersji niefinalnej (btw przy deploywaniu Visual Studio za każdym razem wgrywa WinJS 2.1 na telefon), na ile częściowo inne scenariusze w UI i implementacja większej liczby funkcjonalności wynikających z różnic w API w stosunku do pełnego Windows, a na ile fakt, że mam trochę mieszane uczucia co do samych technologii webowych mających być już tą jedyną i słuszną przyszłością. Ale ogólnie eksperyment udany, technologie webowe zdobyły kolejny bastion.

poniedziałek, 16 czerwca 2014

Wieczór z Madonną cz. 1 (Windows Phone 8.1 XAML)

Kilka uwag, jakie nasunęły mi się w związku z migracją do universal app.

1. Dalej w API WP 8.1 nie działa odczytywanie ikon z plików (np. GetThumbnailAsync ze StorageFile), i to mimo … zapewnień dokumentacji MSDN.  O niestandardowych file queries, czy wirtualizowanych wektorach dla plików znanych z Windows nie ma nawet co wspominać (to akurat zgadza się z dokumentacją)

2. AutoSuggestBox nie jest dokładnym odpowiednikiem SearchBox z Windows 8.1.  Funkcjonalnie jest to jakby TextBox, który możemy zasilić ręcznie podpowiedziami. Przycisk szukaj nie wchodzi w jego skład. Poniżej fragment view modelu, pod który podpiąłem tę kontrolkę:

        private IEnumerable<string> _suggestions;
        public IEnumerable<string> Suggestions
        {
            get
            {
                return _suggestions;
            }
            set
            {
                SetProperty<IEnumerable<string>>(ref _suggestions, value);
            }
        }

        public void GenerateSuggestions(string query)
        {
            ClearSuggestions();         

            var localSettings = ApplicationData.Current.LocalSettings;
            if (localSettings.Values.ContainsKey("VideoSuggestions"))
            {
                var data = (string)localSettings.Values["VideoSuggestions"];
                var list = JsonUtils.Deserialize<List<string>>(data);

                if (!string.IsNullOrEmpty(query))                   
                    Suggestions = list.Where(item => item.StartsWith(query)).ToList();
            }
        }

        public void ClearSuggestions()
        {
            Suggestions = null;
        }

        public async Task SearchFiles(string queryText)
        {
            var filter = !string.IsNullOrEmpty(queryText);

            if (filter)
            {
                var localSettings = ApplicationData.Current.LocalSettings;

                var list = new List<string>();
                if (localSettings.Values.ContainsKey("VideoSuggestions"))
                {
                    var data = (string)localSettings.Values["VideoSuggestions"];
                    list = JsonUtils.Deserialize<List<string>>(data);                   
                    if (!list.Contains(queryText))
                        list.Add(queryText);
                }
                else
                {
                    list.Add(queryText);
                }
                var json = JsonUtils.Serialize(list);
                localSettings.Values["VideoSuggestions"] = json;
            }
            …

       }

Jak widać zasymulowałem zachowanie Searchbox-a polegające na zapamiętywaniu wpisywanych fraz.

XAML prezentuje się następująco:

<AutoSuggestBox x:Name="searchBox"  TextChanged="searchBox_TextChanged" SuggestionChosen="searchBox_SuggestionChosen"
                        ItemsSource="{Binding Suggestions}" PlaceholderText="Search Videos"/>
<AppBarButton Grid.Column="1" Margin="0,-12,0,0" Icon="Find" Click="OnSearchButtonClicked"/>

Połączyłem go z view modelem posiłkując się wstawkami w code-behind strony (pozwoliłem sobie tym razem nie stosować bardziej ortodoksyjnego podejścia MVVM w stylu Caliburn czy Prism):

autosuggestbox

3. Korzystanie z Cortany jest bardzo przyjemne.  Oto fragment mojego pliku z komendami głosowymi:

<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
 
  <CommandSet xml:lang="en-US" Name="myEnglishCommands">
    <CommandPrefix>My Movies</CommandPrefix>
    <Example>Play last</Example>

     …

    <Command Name="findVideo">
      <Example>Find Eminem</Example>
      <ListenFor>Find {text}</ListenFor>
      <Feedback>Searching for {text}</Feedback>
      <Navigate Target="Views/AddNewVideosView.xaml"/>
    </Command>   

    <PhraseTopic Label="text" Scenario="Search">
      <Subject>Music</Subject>
    </PhraseTopic>

  </CommandSet>

Wypowiadam słowa jak niżej:

cortana1

Słowa “Madonna” nie ma w definicji komend. To Cortana sama rozpoznaje (w tym przykładzie optymalnie podpowiedziałem jej by spodziewała się słowa używanego w wyszukiwarkach i związanego z muzyką, ale można też określić, by rozpoznawała dowolnie wypowiedziany tekst). Obsługując aktywację aplikacji za pomocą komendy głosowej przekierowuję na odpowiednią stronę:

        protected override void OnActivated(IActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            if (rootFrame == null)
            {
                rootFrame = new Frame();
                SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
                rootFrame.CacheSize = 1;
                Window.Current.Content = rootFrame;

                if (args.Kind != ActivationKind.VoiceCommand)
                    rootFrame.Navigate(typeof(HomeView));
            }

            Window.Current.Activate();

            base.OnActivated(args);
           
            if (args.Kind == ActivationKind.VoiceCommand)
            {
                var commandArgs = args as VoiceCommandActivatedEventArgs;
                var speechRecognitionResult = commandArgs.Result;                            
                var navigationTarget = speechRecognitionResult.SemanticInterpretation.Properties["NavigationTarget"][0];

                if (!String.IsNullOrEmpty(navigationTarget))
                {
                    Type pageType = Type.GetType(typeof(HomeView).Namespace + "." + navigationTarget.Replace("Views/","").Replace(".xaml",""));
                   
                    if (pageType != null)
                    {
                        rootFrame.Navigate(pageType, speechRecognitionResult);
                    }
                }               
            }
        }

W kodzie strony obsługuję przychodzące polecenie:

madonna

środa, 4 czerwca 2014

Visual Studio “14” CTP !

Ostatnio trafiła pod strzechy przyszła wersja Visual Studio w wersji CTP. Mamy okazję przetestować pierwszą odsłonę przyszłej wersji ASP.NET, której pokaz niedawno można było obejrzeć na TechEd. Dziś sobie zainstalowałem ten pakiet, zgodnie z sugestiami na czystym Windows, by nie mieszać z poprzednimi wersjami. Domyślnie wymagane jest 10GB, a przy instalacji wszystkiego 15GB. Więcej napiszę wkrótce, jak zrobię coś więcej niż założenie pustych, nowych projektów. Jedynie co szybko sprawdziłem, to dynamiczne odświeżanie strony Web po zmianie kodu kontrolera bez jawnej kompilacji (“Roslyn” kompiluje dynamicznie aplikację za każdym razem do pamięci bez tworzenia dll-ek w bin).

image

image

Więcej informacji na:

sobota, 31 maja 2014

Windows Phone 8.1 - dokumentacja MSDN

Dokumentacja w MSDN dla aplikacji WinRT na Windows i Windows Phone także uległa konwergencji. Mamy teraz współdzieloną gałąź Windows Runtime app development, a każda strona, zagadnienie czy uwaga opatrzone są znaczkiem tabletu i/lub telefonu. Dla osób chcących skorzystać z Silverlight 8.x jest osobna gałąź Windows Phone Silverlight development. Poniżej wyrywkowo kilka dodatkowych informacji o WP 8.1, które rzuciły mi się przed oczy. Silverlight 8.1 posiada cztery nowe funkcjonalności dla aplikacji WP 8.1, które nie są dostępne dla stosu WinRT. Oczywiście dokumentacja jest bardzo obszerna i jak zajdzie potrzeba, to warto z niej skorzystać.

 

Aplikacje Windows Runtime

WinJS na WP

brak pewnych kontrolek, m.in DatePicker, TimePicker, Hub (zamiast niego zaleca się używać Pivot), SearchBox, Flyout i Menu (używać Popup), NavBar (używać AppBar), ToolTip (przekierować do następnej strony), brak wsparcia dla drag & drop w ListView

C#/VB/C++ na WP

http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn631755.aspx - helper ContinuationManager + interfejsy dla stron

Funkcjonalności:

  • WP nie wspiera długotrwających notyfikacji toast
  • można wysłać dowolny szablon z notyfikacją toast, ale i tak zawsze wygenerowany zostanie jeden widok
  • DeviceUseTrigger - w WP:
    • nie ma obsługi urządzeń USB, MTP, sieciowych (przewodowych i Wi-Fi), IDeviceIOControl
    • nie jest wymagana zgoda użytkownika
    • limit rejestracji tasków tego typu do 1 (urządzenia z 512 MB RAM) lub 2 (urządzenia z więcej niż 512 MB), nieco inne zasady podczas wykonywania

Silverlight 8.1

Kilka dodatkowych uwag:

  • nie wspiera WalletAgent z WP8 (do NFC trzeba użyć nowego NFC API)
  • lokalizowane kafelki sposobem z WP8 nie wyświetlają napisów jeśli przejdziemy na WNS
  • nie można korzystać z zarządzanych komponentów WinRT (i takich tasków w tle)
  • deklaracja DefaultTask w WMAppManifest.xml jest obowiązkowa (w przeciwieństwie do WP 8)
  • rozmiary AppBar na różnych urządzeniach (ekrany, DPI) w logicznych pikselach Silverlight nie są obecnie jednakowe
  • Silverlight/XNA zablokowany (w WP8 nieoficjalnie można było skorzystać)
  • aplikacje w foreground działają teraz w modelu STA (w WP8 MTA), zadania w tle dalej w MTA
  • jak padnie agent VOIP, to padnie także aplikacja foreground (w WP 8.1 aplikacje VOIP są zarządzane w ramach pakietu, a nie osobnych procesów)
  • trzeba wspierać wszystkie rozdzielczości
  • różnice w zachowaniu Panoramy i http
  • udoskonalony szablon dla projektu HTML5 z Web Browser
  • nie są obsługiwane pełne ścieżki w uri przy XDocument.Load
  • ms-app w parametrze konstruktura Uri
  • inaczej niż w aplikacjach WinRT implementuje się aktywację providera spotkań

Nowe funkcjonalności dostępne tylko w Silverlight 8.1:

Bindowanie kontaktów

You can use the contact bindings feature for Windows Phone Silverlight 8.1 apps to associate contacts from your app’s cloud-based contact store with local contacts on the device. When your app creates a contact binding, a tile for your app is displayed on the Connect pivot for the local contact in the People Hub. You can customize this tile to display images from your web service that are associated with the person. You can provide up to three images and the system will cycle through them. When the user taps your app’s Connect tile, your app is launched and is provided with the ID for the contact binding so you can show the user your app’s content for that person.

http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn642083(v=vs.105).aspx

Rozszerzenia mediów online

If you’re creating an app that uses a web service to host images or videos on behalf of your user, in Windows Phone 8.1 you can integrate your app into the built-in Photos Hub on the phone. Your app will have a tile on the Albums pivot of the Photos Hub that the user can use to quickly explore the online media hosted by your service.

http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn642079(v=vs.105).aspx

Integracja z kartą Me

On the Me card, a user can see their news feed and publish updates or location check-ins on social networks in one location on the phone. When your app is integrated with the Me card, the app appears in a list of apps that a user sees when they tap post an update or check in on the Me card. When the user taps your app name, your app launches and displays a UI in which the user can perform the requested task.

http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn744304(v=vs.105).aspx

Zmiana rozmowy z komórkowej na VOIP

http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn643752(v=vs.105).aspx

One additional step you must take to implement contact bindings for a VoIP call upgrade is specify the value CallUpgradeIdentifier as the value to the AppBindingAttributes property of the bindings you create. After a contact has been bound with your app this way, the contact is then recognized by the system as video-capable.

Zmiany w CallInProgressAgent i w aplikacji

Dodatkowe informacje o różnicach w stosunku do aplikacji WinRT:

Share target:  http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn655125(v=vs.105).aspx  (uwaga! aplikacja taka nie powinna wywoływać  ShareStatusTask, ShareLinkTask i ShareMediaTask, gdyż sama może znaleźć się na liście, co nie jest wspierane)

Appointment provider activation:  http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn655123(v=vs.105).aspx

piątek, 30 maja 2014

Building Apps For Windows Phone 8.1 (JumpStart) - cz.3

Ostatni trzeci dzień Jump Start z czterema sesjami. Można odnaleźć pewne inspiracje do współdzielenia kodu między aplikacjami uniwersalnymi (z projektem Shared), a aplikacją Silverlight. Poza tym trochę bardziej szczegółówych informacji o Silverlight 8.1 np. że chodzi na tym samym runtime co aplikacje WinRT XAML. Należy zwrócić uwagę też na przypinanie w WinRT API kafelków z aktualizacją, które w podejściu wziętym wprost z Windows uśpi aplikację i nie wykona dalszego kodu na telefonie (nie jest to rzecz związana z Silverlight).

 

Building Apps for Windows Phone 8.1: (20) Tooling and Diagnostics

image

 

Building Apps for Windows Phone 8.1: (21) App Packaging, Monetization, and Publication

image

image

instalacja na SD dla aplikacji WinRT i Silverlight

image

image

image

image

 

Building Apps for Windows Phone 8.1: (22) Universal Apps for Windows

Przełączanie podglądu sharowanego XAML między projektem Windows a WP

image

image

image

image

image

image

image

 

Building Apps for Windows Phone 8.1: (23) Silverlight apps on Windows Phone 8.1

image

image

nie ma jeszcze toolkitu dla WP 8.1

dla Silverlight 8.1 ten sam runtime co dla aplikacji WinRT !!! 

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image

image