Prístroje pod taktovkou operačného systému Windows Phone 7 sú vybavené kompasom, akcelerometrom, gyroskopom a systémom pre určovanie polohy. Akceleromerer je povinná súčasť, kompas a gyroskop prístroje rôznych výrobcov môžu a nemusia obsahovať. Akcelerometer má v mobilnom telefóne veľmi dôležitú funkciu, umožňuje nielen zistenie aktuálnej orientácie prístroja (na výšku, či na šírku), ale nakoľko prístroj nemá žiadne kurzorové tlačidlá ani nijaký ekvivalent joysticku využíva sa naklápanie prístroja aj na ovládanie hier.
Ak zariadenia, alebo emulátor nepodporujú gyroskop, prípadne kompas, je potrebné v aplikácii túto skutočnosť ošetriť
if (compass == null)
{
compass = new Compass();
compass.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
compass.CurrentValueChanged
+= new EventHandler<SensorReadingEventArgs<CompassReading>>
(compass_CurrentValueChanged);
}
try
{
statusTextBlock.Text = “…inicializácia kompasu”;
compass.Start();
}
catch (InvalidOperationException)
{
statusTextBlock.Text = “Zariadenie nepodporuje kompas.”;
}
if (!Gyroscope.IsSupported)
{
statusTextBlock.Text = “Zariadenie nepodporuje gyroskop”;
startButton.IsEnabled = false;
stopButton.IsEnabled = false;
}
Ak zariadenia, alebo emulátor nepodporujú gyroskop, prípadne kompas, je potrebné v aplikácii túto skutočnosť ošetriť
Pre úplnosť uvádzame aj fragmenty kódu pre čítanie hodnôt kompasu
xTextBlock.Text = “X: ” + reading.MagnetometerReading.X.ToString(“0.00”);
yTextBlock.Text = “Y: ” + reading.MagnetometerReading.Y.ToString(“0.00”);
zTextBlock.Text = “Z: ” + reading.MagnetometerReading.Z.ToString(“0.00”);
a gyroskopu
Vector3 rotationRate = gyroscopeReading.RotationRate;
xTextBlock.Text = “X: ” + rotationRate.X.ToString(“0.00”);
yTextBlock.Text = “Y: ” + rotationRate.Y.ToString(“0.00”);
zTextBlock.Text = “Z: ” + rotationRate.Z.ToString(“0.00”);
Novinkou verzie “Mango” sú komplexné informácie o dynamických zmenách polohy telefónu. Existujú totiž fyzické obmedzenia jednotlivých senzorov pre ktoré môže byť ťažké určiť skutočnú orientáciu a pohyb zariadenia zo surových údajov z jednotlivých čidiel Windows Phone. Napríklad údaje z akcelerometra sú odvodené od zotrvačnosti vyplývajúcej z pohybu zariadenia. Gyroskop meria rýchlosť otáčania, no nie polohu. Preto sú v operačnom systéme implementované zložité geometrické výpočty, ktoré sú potrebné zistenie polohy orientácie a pohybu zo surových dát z jednotlivých senzorov. Takéto informácie sú dôležité pre aplikácie pracujúce s rozšírenou realitou (augmented reality), jedná sa hlavne o polohu, rotačné zrýchlenie, a lineárne zrýchlenie.
Akcelerometer
Senzor akcelerometru musí byť povolený (implicitné nastavenie) v súbore WMAppManifest.xml v sekcii <Capabilities>.
<Capabilities>
<Capability Name=”ID_CAP_GAMERSERVICES”/>
<Capability Name=”ID_CAP_IDENTITY_DEVICE”/>
<Capability Name=”ID_CAP_IDENTITY_USER”/>
<Capability Name=”ID_CAP_LOCATION”/>
<Capability Name=”ID_CAP_MEDIALIB”/>
<Capability Name=”ID_CAP_MICROPHONE”/>
<Capability Name=”ID_CAP_NETWORKING”/>
<Capability Name=”ID_CAP_PHONEDIALER”/>
<Capability Name=”ID_CAP_PUSH_NOTIFICATION”/>
<Capability Name=”ID_CAP_SENSORS”/>
<Capability Name=”ID_CAP_WEBBROWSERCOMPONENT”/>
</Capabilities>
Budeme monitorovať zabudovaný akcelerometer, pre lepšie pochopenie údajov, ktoré vracia ich budeme vypisovať v textovej podobe pomocou prvku TextBlock
<!–ContentPanel – place additional content here–>
<Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″>
<TextBlock Name=”tblVypis”
HorizontalAlignment=”Center” VerticalAlignment=”Center” />
</Grid>
Je potrebné vytvoriť referenciu na knižnicu Microsoft.Devices.Sensors.
Vytvorenie referencie na knižnicu Microsoft.Devices.Sensors
Do kódu v súbore MainPage.xaml.cs je potrebné pridať referenciu na namespace.
using Microsoft.Devices.Sensors;
V konštruktore vytvorte objekt Accelerometer. Následne vytvorte procedúru ktorá bude reagovať na udalosť ReadingChanged, ktorá nastane pri zmene polohy telefónu s akcelerometrom
// Constructor
public MainPage()
{
InitializeComponent();
Accelerometer aclr = new Accelerometer();
aclr.ReadingChanged += OnAclrReadingChanged;
try
{
aclr.Start();
}
catch (Exception exc)
{
tblVypis.Text = exc.Message;
}
}
V tele obslužnej procedúry pre výpis údajov z akcelerometra vypíšeme hodnotu posunov v jednotlivých osiach a komplexný parameter Magnitúda. Magnitúda sa vypočíta ako odmocnina so súčtu druhých mocnín vektorov X,Y a Y. V procedúre si dajte pozor, nakoľko sa vypisujú údaje z iného threadu.
void OnAclrReadingChanged(object sender, AccelerometerReadingEventArgs args)
{
string str = String.Format(“X = {0:F2}\n” +
“Y = {1:F2}\n” +
“Z = {2:F2}\n\n” +
“M = {3:F2}\n\n”,
args.X, args.Y, args.Z,
Math.Sqrt(args.X * args.X + args.Y * args.Y + args.Z *
args.Z));
if (tblVypis.CheckAccess())
{
SetTextBlockText(tblVypis, str);
}
else
{
tblVypis.Dispatcher.BeginInvoke(new
SetTextBlockTextDelegate(SetTextBlockText),
tblVypis, str);
}
}
delegate void SetTextBlockTextDelegate(TextBlock txtblk, string text);
void SetTextBlockText(TextBlock txtblk, string text)
{
txtblk.Text = text;
}
Aplikáciu využívajúcu akcelerometer môžete vo verzii SDK 7.1 otestovať aj v emulátore. Zmena polohy (náklon) prístroja sa simuluje posúvaním ružového bodu, pričom zmeny pozície je možné zaznamenať a následne ako sekvenciu činností prehrať, takže aplikáciu využívajúcu akcelerometer bude možné ladiť počas simulovania identických pohybov.
Text akcelerometra na emulátore
Geografická lokalizácia
Najpresnejšie je GPS, ale je pomalé a nadá sa použiť v budovách, alebo husto zastavaných oblastiach. Preto Win Phone 7 používa univerzálnu koncepcia zisťovania aktuálnej polohy cez GPS, WiFi a GSM
Univerzálna koncepcia lokalizácie
Ak chcete geografickú lokalizáciu využívať vo svojom projekte, Je potrebné vytvoriť referenciu na knižnicu System.Device.
using System.Device.Location;
Námetom jednoduchej aplikácie je výpis aktuálnych súradníc
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
GeoCoordinateWatcher gcw = new GeoCoordinateWatcher();
gcw.PositionChanged += OnGcwChanged;
try
{
gcw.Start();
}
catch (Exception exc)
{
tblVypis.Text = exc.Message;
}
}
void OnGcwChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> args)
{
string str = String.Format(“Zemep. dĺžka: {0:F3}\r\n” +
“Zemep. šírka: {1:F3}\r\n” +
“Výška: {2}”,
args.Position.Location.Longitude,
args.Position.Location.Latitude,
args.Position.Location.Altitude);
if (tblVypis.CheckAccess())
{
SetTextBlockText(tblVypis, str);
}
else
{
tblVypis.Dispatcher.BeginInvoke(new
SetTextBlockTextDelegate(SetTextBlockText),
tblVypis, str);
}
}
delegate void SetTextBlockTextDelegate(TextBlock txtblk, string text);
void SetTextBlockText(TextBlock txtblk, string text)
{
txtblk.Text = text;
}
}
Mapové služby
V príklade pre využitie mapových služieb budeme využívať mapovú službu Microsoft Research Maps http://msrmaps.com. Do projektu aplikácie pridajte referenciu na službu (položka kontextového menu Add Service Reference) http://msrmaps.com/TerraService2.asmx?WSDL
Referencia na mapovú službu
Službu pomenujte napríklad MsrMapsService
V XAML návrhu pridajte prvok typu text block navýpis
<!–ContentPanel – place additional content here–>
<Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″>
<TextBlock Name=”tblVypis” HorizontalAlignment=”Center”
VerticalAlignment=”Center” TextWrapping=”Wrap” />
</Grid>
Do kódu pridajte referencie na menné priestory
using System.Device.Location;
using System.IO;
using System.Windows.Media.Imaging;
using MapoveSlužby.MsrMapsService;
kód
namespace MapoveSlužby
{
public partial class MainPage : PhoneApplicationPage
{
GeoCoordinateWatcher gcw = new GeoCoordinateWatcher();
TerraServiceSoapClient proxy = new TerraServiceSoapClient();
// Constructor
public MainPage()
{
InitializeComponent();
Loaded += OnMainPageLoaded;
}
void OnMainPageLoaded(object sender, RoutedEventArgs args)
{
// udalosti pre TerraServiceSoapClient proxy
proxy.GetAreaFromPtCompleted += OnProxyGetAreaFromPtCompleted;
proxy.GetTileCompleted += OnProxyGetTileCompleted;
// Start gcw
tblVypis.Text = “Zisťovanie polohy…”;
gcw.PositionChanged += OngcwPositionChanged;
gcw.Start();
}
void OngcwPositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> args)
{
// zastav gcw
gcw.PositionChanged -= OngcwPositionChanged;
gcw.Stop();
// Výpis súradníc do záhlavia
GeoCoordinate coord = args.Position.Location;
ApplicationTitle.Text += “: ” + String.Format(“{0:F2}°{1} {2:F2}°{3}”,
Math.Abs(coord.Latitude),
coord.Latitude > 0 ? ‘N’ : ‘S’,
Math.Abs(coord.Longitude),
coord.Longitude > 0 ? ‘E’ : ‘W’);
// Dotaz na službu na aktuálnu oblasť
LonLatPt center = new LonLatPt();
center.Lon = args.Position.Location.Longitude;
center.Lat = args.Position.Location.Latitude;
tblVypis.Text = “Prístup k mapovej službe…”;
proxy.GetAreaFromPtAsync(center, 1, Scale.Scale16m, (int)ContentPanel.ActualWidth,
(int)ContentPanel.ActualHeight);
}
void OnProxyGetAreaFromPtCompleted(object sender, GetAreaFromPtCompletedEventArgs args)
{
if (args.Error != null)
{
tblVypis.Text = args.Error.Message;
return;
}
tblVypis.Text = “Načítanie mapy…”;
AreaBoundingBox box = args.Result;
int xBeg = box.NorthWest.TileMeta.Id.X;
int yBeg = box.NorthWest.TileMeta.Id.Y;
int xEnd = box.NorthEast.TileMeta.Id.X;
int yEnd = box.SouthWest.TileMeta.Id.Y;
// Loop through the tiles
for (int x = xBeg; x <= xEnd; x++)
for (int y = yBeg; y >= yEnd; y–)
{
// Create Image object to display tile
Image img = new Image();
img.Stretch = Stretch.None;
img.HorizontalAlignment = HorizontalAlignment.Left;
img.VerticalAlignment = VerticalAlignment.Top;
img.Margin = new Thickness((x – xBeg) * 200 –
box.NorthWest.Offset.XOffset,
(yBeg – y) * 200 – box.NorthWest.Offset.YOffset, 0, 0);
// Insert after TextBlock but before Image with logo
ContentPanel.Children.Insert(1, img);
// Define the tile ID
TileId tileId = box.NorthWest.TileMeta.Id;
tileId.X = x;
tileId.Y = y;
// Call proxy to get the tile (Notice that Image is user object)
proxy.GetTileAsync(tileId, img);
}
}
void OnProxyGetTileCompleted(object sender, GetTileCompletedEventArgs args)
{
if (args.Error != null)
{
return;
}
Image img = args.UserState as Image;
BitmapImage bmp = new BitmapImage();
bmp.SetSource(new MemoryStream(args.Result));
img.Source = bmp;
}
}
Test príkladu využívajúceho mapové služby