Out Of Browser
Pierwszą nowinką nad która chciałby się skupić jest Out Of Browser (OOB), czyli możliwości instalacji aplikacji RIA na lokalnym komputerze. Tym którzy jeszcze o tym nie słyszeli, przypomnę że od wersji Silverlight 3.0 istnieje możliwość stworzenia aplikacji którą będzie można instalować lokalnie na komputerze i korzystać z niej bez uruchamiania przeglądarki, taki OneClick (dla niektórych Java WebStart). Stąd też przyszedł mi do głowy tytułowy skrót RDA -> Rich Desktop Application ;)
Opcja ta jest skierowana przed wszystkim do aplikacji które działają w środowisku bez stałego dostępu do Internetu (z ang. Occasionally Connected). W ten sposób możemy używać aplikacji przez cały czas, nawet gdy chwilowo nie mam dostępu do sieci i otworzenie programu w przeglądarce było by nie możliwe.
Demo
Zaczniemy z grubej rury czyli od istniejącej aplikacji – Run DEMO - Chess!!
Aplikacja ta to szachy stworzone na potrzeby konferencji MIX09, które po zainstalowaniu pozwalają na grę w trybie lokalnym. Aby móc ją zobaczyć i zagrać musimy mieć zainstalowany plugin Silverlight 3.0 SDK (w obecnej wersji jest to Beta 1 spod adresu link).
Grę możemy zainstalować klikać w przycisk "Install Chess Now" lub klikając prawym przyciskiem myszki w aplikacje i wybranie opcji instalacji. W czasie instalacji w systemie operacyjnym Windows mamy do wyboru umieszczenie skrótu do gry na pulpicie lub/i w menu start, natomiast w MACu user ma większą dowolność i może instalować aplikację (skrót) gdzie mu się podoba. W Windows nikt nie zabroni tam także przenieść skrótu do aplikacji w inne miejsce ale nie jest to coś co możemy wybrać podczas instalacji. Jeśli wszystko się uda, to możemy zamknąć przeglądarkę i uruchomić grę z umieszczonego skrótu.
Jak zauważyliście w przykładzie, instalacja nie jest tak dowolna jak w przypadku zwykłych aplikacji, a więc do wyboru mamy tylko miejsce wskazania skrótu do aplikacji. Cała reszta jest schowana przed użytkownikiem i nie pozwala na modyfikację.
Warto wspomnieć, że zainstalowana aplikacja może działać bez dostępu do Internetu i synchronizować swoje dane jak tylko taki dostęp otrzyma. Za przestrzeń do przechowywanie danych możemy wykorzystywać Isolated Storage, który po instalacji aplikacji pozwala na przechowywanie aż 25MB danych bez pytania o zgodę użytkownika, co w przeciwieństwie do 1MB gdy uruchamiamy aplikację w przeglądarce, robi różnicę. Pamiętajmy że zawsze możemy zwiększyć tą przestrzeń, o ile użytkownik wyrazi zgodę. (patrz artykuł o Isolated Storage).
Z poziomu aplikacji bardzo szybko możemy także odinstalować grę, klikamy prawym myszki i wybieramy opcję "Remove this application..". Całość jest dość wygodna w użytkowaniu i nie sprawia większych problemów.
Zróbmy swoją aplikację
W celu demonstracji jak łatwe jest włączenie opcji instalacji RIA na komputerze lokalnym, stworzymy prostą aplikację "Witaj Świecie" która oprócz przywitania się będzie pokazywać czy jest uruchamiana w przeglądarce oraz czy ma dostęp do Internetu.
I. Podstawowa instalacja
Pierwszym krokiem jest otwarcie Visual Studio oraz wybranie nowego projektu SilverlightApplication (może to być także inny typ projektu Silverlight, ale to akurat nie ma znaczenia).
Aby aplikacja mogą być instalowana, program musi być do tego specjalnie stworzony dlatego też otwieramy plik "AppManifest.xaml" z katalogu "Properties". Jeśli mamy zainstalowaną wersję Silverlight 3.0, powinniśmy zobaczyć w środku trochę wykomentowanego kodu.
<Deployment.ApplicationIdentity>
<ApplicationIdentity
ShortName="Out of Browser Silverlight Application"
Title="Window Title of Your Silverlight Application">
<ApplicationIdentity.Blurb>Description of your Silverlight application</ApplicationIdentity.Blurb>
</ApplicationIdentity>
</Deployment.ApplicationIdentity>
Kod ten odpowiada właśnie za włączenie opcji instalacji aplikacji RIA. Wystarczy że odkomentujemy go i nasza aplikacja może być od tej pory instalowana na lokalnym komputerze.
Zanim uruchomimy po raz pierwszy program, dodajmy prosty TextBlock w pliku MainPage.xaml, tak abyśmy widzieli że aplikacja działa.
<UserControl x:Class="SilverlightOOBApplication.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="Witaj Świecie" />
</Grid>
</UserControl>
Teraz możemy uruchomić program. Klikamy prawym przyciskiem myszki w aplikacji i wybieramy "Install Out of Browser Silverlight … onto this computer"
Następnie wybieramy gdzie chcemy aby pojawił się skrót do zainstalowanej aplikacji, czy ma być to pasek menu czy skrót na pulpicie i zatwierdzamy.
W tym momencie powinien pojawić się nasz HelloWorld w okienku. Jeśli zamkniemy program i udamy się na pulpit lub menu start, znajdziemy tam skrót do naszej aplikacji. Wystarczy odpalić go jak zwykły program aby zobaczyć że nasz program działa tak samo ale bez uruchamiania przeglądarki.
II. Dostosujmy instalacje do naszych potrzeb
Przede wszystkim możemy dostosować takie parametry jak krótki opis aplikacji (ShortName) który używany jest chociażby do podpisania skrótu na pulpicie do aplikacji. Tytuł aplikacji (Title) pojawiający się miedzy innymi w oknie aplikacji którą uruchamiamy offline lub podczas instalacji oraz parametr większego opisu (ApplicationIdentity.Blurb) używany jako treść tooltipów.
W celu przetestowania ustawmy ShortName na np. "Welcome App", tytuł na "Witam w aplikacji powitalnej" oraz ApplicationIdentity.Blurb na "To jest aplikacja powitalna", tak jak w zamieszczonym przykładzie poniżej.
AppManifest.xaml:
<Deployment.ApplicationIdentity>
<ApplicationIdentity
ShortName="Welcome App"
Title="Witam w aplikacji powitalnej">
<ApplicationIdentity.Blurb>To jest aplikacja powitalna</ApplicationIdentity.Blurb>
</ApplicationIdentity>
</Deployment.ApplicationIdentity>
Dodatkowo warto pokusić się o własne ikonki. Wstawianie ich jest banalnie proste i jedyne co musimy dostarczyć to obrazki oraz odpowiednie wpisy w pliku AppManifest.xaml. Dostarczane obrazki mogą być typu png i wystarczy je umieścić w projekcie oraz dołączyć w pliku xml. Uwaga, dodane ikonki należy ustawić jako "Content" w projekcie, a nie "Resource". Aby to zmienić, klikamy prawym myszki na ikonce w Visual Studio i przestawiamy wartość "Build Action" na "Content".
Ikonki dodajemy w 4 różnych rozmiarach w celu dostarczenia odpowiednich obrazków dla okna instalacji, skrótu na pulpicie, w menu start itd. W pełni zmodyfikowany kod pliku AppManifest.xaml może wyglądać np. tak:
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Deployment.Parts> </Deployment.Parts>
<Deployment.ApplicationIdentity>
<ApplicationIdentity ShortName="Welcome App" Title="Witam w aplikacji powitalnej">
<ApplicationIdentity.Blurb>To jest aplikacja powitalna</ApplicationIdentity.Blurb>
<ApplicationIdentity.Icons>
<Icon Size="16x16">images/icons/user-16.png</Icon>
<Icon Size="32x32">images/icons/user-32.png</Icon>
<Icon Size="48x48">images/icons/user-48.png</Icon>
<Icon Size="128x128">images/icons/user-128.png</Icon>
</ApplicationIdentity.Icons>
</ApplicationIdentity>
</Deployment.ApplicationIdentity>
</Deployment>
III. Świadomość aplikacji o aktualnym stanie instalacji
W celu wykrycia czy aplikacja została uruchomiona lokalnie, wystarczy w pliku App.xaml.cs w metodzie obsługi eventu "Startup" dodać sprawdzenie na zmiennej "
Application.Current.RunningOffline".
public partial class App : Application
{
public App()
{
this.Startup += this.Application_Startup;
...
}
private void Application_Startup(object sender, StartupEventArgs e)
{
if (Application.Current.RunningOffline)
{
this.RootVisual = new OfflinePage();
}
else
{
this.RootVisual = new MainPage();
}
}
}
A więc zmienna "RunningOffline" dostarczy nam informacji o trybie pracy aplikacji i np. jak w powyższym przykładzie pozwoli na wybranie odpowiedniego wygląda aplikacji.
IV. Świadomość aplikacji o aktualnym stanie połączenia z Internetem
Aby pozyskać informację o tym czy aplikacja ma podłączenie do Internetu, wykorzystamy klasę "NetworkInterface", a dokładnie jej metodę "NetworkInterface.GetIsNetworkAvailable()". Metoda ta zwraca wartość typu bool która informuje nas o tym czy połączenie do Internetu jest możliwe.
Dodatkowo możemy chcieć żeby aplikacja wykonała powyższe sprawdzenie w momencie gdy dostęp do Internetu się pojawia lub znika. W tym celu możemy wykorzystać event z klasy "NetworkChange.NetworkAddressChanged". Obie powyższe klasy są zadeklarowane w namespace "System.Net.NetworkInformation".
Spójrzmy na przykładowy kod który możemy umieścić np. w klasie MainPage.xaml.cs:
public MainPage()
{
InitializeComponent();
NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(OnNetworkChange);
}
void OnNetworkChange(object sender, EventArgs e)
{
if (NetworkInterface.GetIsNetworkAvailable())
{
// połączenie instnieje...
}
else
{
// brak połączenia
}
}
W konstruktorze dodajemy obsługę eventu zmiany połączenia, a w metodzie "OnNetworkChange" obsługujemy to zdarzenie. Aplikacja sprawdza czy istnieje połączenie i według tego podejmuje odpowiedni kroki.
Warto zwrócić tutaj uwagę na sytuację gdy mamy dwa dostępne połączenia. Gdy jedno "padnie" to w/w event zostanie wywołany ale metoda "NetworkInterface.GetIsNetworkAvailable()" wciąż zwróci true ze względu na to że istnieje wciąż inne połączenie. W związku z tym wszelkie przełączanie dostępności według np. flagi nie ma tutaj sensu i może powodować niepotrzebne błędy w działaniu programów.
Dodatkowo połączenie do sieci w której nie ma Internetu to także połączenie. Jest to ogromna wada całego tego rozwiązania ale może w kolejnych wersjach będzie to poprawione.
V. Automatyczne aktualizacje aplikacji
Pewnie część z Was zastanawia się już co z aktualizacją wersji aplikacji, w jaki sposób poradzić sobie z aktualizacją programów. Otóż OOB w Silverlight załatwia nam to z automatu, kiedy pojawia się nowsza wersja, zostaje ona pobrana i zainstalowana przy kolejnym uruchomieniu. Taki mechanizm jest bardzo wygodny i zapewnia spójność wersji programów zainstalowanych lokalnie oraz tych działających online. Dodatkowo możemy poinformować użytkownika o nowych wersjach poprzez skorzystanie z eventu
ExecutionStateChanged i App.Current.ExecutionState.
App.xaml.cs:
public App()
{
..
this.ExecutionStateChanged += new EventHandler(App_ExecutionStateChanged);
..
}
void App_ExecutionStateChanged(object sender, EventArgs e)
{
if (App.Current.ExecutionState == ExecutionStates.DetachedUpdatesAvailable)
{
MessageBox.Show("Ukazała się nowsza wersja programu. Proszę zrestartować aplikację.");
}
}
"ExecutionStateChanged" zostaje wywołany zawsze gdy stan aplikacji się zmienia. Warto zwrócić uwagę że "ExecutionStates" posiada także atrybuty takie jak "Detached", "DetachFailed", "Detaching" oraz "RunningOnline" które możemy sprawdzić gdy stan aplikacji się zmieni i wykonać odpowiednie operację. Np. gdy instalacja aplikacji lokalnie się nie powiedzie, metoda "ExecutionStateChanged" zostanie wywołana, a stan "ExecutionState" zostanie ustawiony na "DetachFailed". W tym momencie możemy wykonać dowolną operację która rozwiąże problem lub zasugeruje użytkownikowi inne rozwiązanie. To samo tyczy się pozostałych stanów.
Jak widzimy, taki typ obsługi daje nam skuteczny mechanizm zarządzania instalacją aplikacji i przełączania jej trybów działania.
Online Sample
Powyższą aplikację możemy zobaczyć pod adresem: (wymagany Silverlight 3.0 Beta 1) Live DEMO
Kod źródłowy dostępny jest pod adresem: link
Wnętrze
Od strony zaplecza, cały mechanizm działa na zasadzie zrzutu aplikacji Silverlight do przestrzenie użytkownika i nadaniu mu unikatowego numeru. Numer ten jest wykorzystywany do uruchamiania aplikacji. Sam proces uruchamiania odbywa się za pomocą pliku sllauncher.exe znajdującego się w plikach zainstalowanego plug-ina Silverlighta (zwykle jest to katalog: C:\Program Files\Microsoft Silverlight\3.0.40307.0\sllauncher.exe).
Jeśli przyjrzymy się na przykład skrótowi z pulpitu do aplikacji, zobaczymy coś w stylu:
C:\Program Files\Microsoft Silverlight\<wersja>\sllauncher.exe <adres.id>
Gdzie "wersja" to numer aktualnej wersji Silverlighta (w chwili pisania tego artykułu jest to 3.0.40307.0), a numer "adres.id" to adres strony i numer nadany dla aplikacji. Taki skrót może wyglądać np. tak:
"C:\Program Files\Microsoft Silverlight\3.0.40307.0\sllauncher.exe" localhost.4
lub
"C:\Program Files\Microsoft Silverlight\3.0.40307.0\sllauncher.exe" www.jacekciereszko.pl.2
W Windows Vista naszą zapisaną aplikację możemy znaleźć na przykład pod adresem
"C:\Users\<nazwa użytkownika>\AppData\LocalLow\Microsoft\Silverlight\Offline\<adres.id>"
gdzie mechanizmy Silverlighta przechowują pliki xap, html i jeszcze kilka plików. W innych systemach operacyjnych adres ten zapewne będzie inny, ale w żaden sposób nie będzie nam potrzebny do pracy z programem, a więc nie martwcie się jeśli nie dogrzebiecie się do swojego repozytorium.
Należy pamiętać że aplikacja przez cały czas pozostaje uruchomiona w sandbox-się, a więc po instalacji na komputerze nie otrzymuje żadnych dodatkowych uprawnień i jest traktowana tak samo jak ta uruchamiana w przeglądarce. Zaletą tego rozwiązania jest to, że użytkownik nie potrzebuje praw administratora do instalacji aplikacji.
Tak jak wspomniałem powyżej, zainstalowana aplikacja może mieć świadomość tego czy komputer jest podłączony do Internetu, działać gdy takiego połączenia nie ma oraz być powiadamiana o zmianie jego statusu. To ostatnie wydaje się szczególnie ważne, gdy tworzymy aplikację która będzie gromadzić dane i synchronizować je okazjonalnie (tzw. emisariusze). Mechanizm ten jest także wykorzystywany do update-ów aplikacji i obsługiwany automatycznie przez mechanizmy Silverlighta. Tak jak wspominałem powyżej, aplikacja która wykryła nowszą wersję, pobiera ją i instaluje przy kolejnym uruchomieniu aplikacji.
Wygląd
Aby wyjść naprzeciw oczekiwaniom użytkownika, Microsoft pozwoli nam customizować nasze aplikację w zależności od tego czy jest ona zainstalowana czy uruchamiana z przeglądarki. A więc na przykład w wersje uruchamianej w przeglądarce, umieścić tylko przycisk instalacji, a w wersji zainstalowanej całą aplikację, tak jak to widzieliśmy na przykładzie gry w szachy.
W tej wersji Silverlighta, okno uruchomieniowe programów zainstalowanych lokalnie pozwala tylko na ustawienie ikonki, tytułu oraz pozycji na ekranie. Jak podaje Microsoft, więcej opcji dostosowywania wyglądu okna pojawi się w kolejnych wersjach.
Debuger
Pierwszym poważnym problemem na który natknąłem się był brak debuggera. News o tym znalazłem na stronie transcriptu z jednej z sesji MIX09. Szybko jednak doinformowano mnie o zapomnianym "Attach Process" z VS który prawie idealnie rozwiązuje problem. Prawie, ponieważ nie jest to wygodne i trochę utrudnia pracę (np. podłączenie aplikacji do procesu).
Ograniczenia
Ponieważ w planie miałem stworzenie aplikacji która instaluje się lokalnie na komputerze klienta, oraz obsługuje Silverlight Navigation i kontrolkę Silverlight Virtual Earth Map Control, szybko przekonałem się że nie wszystko będzie działać. Należy pamiętać, że po instalacji aplikacji na komputerze lokalnym trochę rzeczy jednak się zmienia i np. komunikowanie się z mapą staje się niemożliwe ze względu na brak "współpracy" z HTML DOM. Sugerował bym najpierw upewnić czy to co chcemy zrobić zadziała (małe PoC) zanim zaplanujemy całe rozwiązanie.
Resources
- Wspaniały screencast Tim Heuera pokazujący krok po korku jak stworzyć aplikacje OOB – link,
- Strona z szachami - link,
- Szereg artykułów na temat OOB – link.
Live demo stworzonej aplikacji: link
Kod źródłowy dostępny jest pod adresem: link
Pozdrawiam
Jacek Ciereszko

















