Fahr in München Version 3.9

Geschrieben am von leitning

Fahr in München Version 3.9

Es gibt jetzt end­lich eine neue Ver­sion der Fahr in Mün­chen App, wel­che mit den Ände­run­gen des jähr­li­chen Fahr­plan­wech­sels der MVG umge­hen kann.

Die Ände­run­gen im Ein­zel­nen sind:

  • Die App kann mit den seit dem Fahr­plan­wech­sel in die Fahr­plan­aus­kunft auf­ge­nom­me­nen Meri­dian Zügen umge­hen. Bis­her hat die App bei Ver­bin­dun­gen, in denen ein Meri­dian Zug vor­ge­schla­gen wurde, eine Feh­ler­mel­dung pro­du­ziert und über­haupt keine Ver­bin­dun­gen mehr angezeigt.
  • Alle Netz­pläne sind aktua­li­siert auf den Stand nach dem Fahr­plan­wech­sel im Dezem­ber 2013.
  • Ein paar wei­tere Klei­nig­kei­ten, ins­be­son­dere ein neues Hin­ter­grund­bild auf der Haupt­seite der App und ein beho­be­nes Dar­stel­lungs­pro­blem bei hel­ler Far­bein­stel­lung des Handys.

Viel Spaß mit der App! Ich freue mich natür­lich immer über Bewer­tun­gen im Win­dows Phone Store und Rück­mel­dun­gen hier.

30 Windows Phone 8 Samples auf einen Blick

Geschrieben am von leitning

Irgend­wie bin ich mit Twit­ter immer noch nicht so ganz warm gewor­den. Aber jedes Mal, wenn ich etwas her­um­stö­bere, finde ich etwas Inter­es­san­tes. Heute ist es eine coole und anschau­li­che Info­gra­fik zu Code­bei­spie­len für die Win­dows Phone 8 Entwicklung.

Windows Phone 8 Samples

(zum Ver­grö­ßern auf das Bild klicken)

Rich­tig nütz­lich wird die Info­gra­fik in ihrer inter­ak­ti­ven Ver­sion als Silverlight-Anwendung.

Es gibt natür­lich wesent­lich mehr Code­bei­spiele als die 30 in der Info­gra­fik dar­ge­stell­ten. Die 30 sind eine Aus­wahl von Mat­thias Shapiro, dem Erstel­ler der Info­gra­fik in sei­nem Arti­kel 10 Great Win­dows Phone 8 Code Sam­ples (No, Wait… 30).

Mat­thias stellt in sei­nem Arti­kel noch 10 sei­ner Mei­nung nach beson­ders bemer­kens­werte Code­bei­spiele vor. Da ich die meis­ten The­men bereits in der Serie 8 Tage Win­dows Phone 8 behan­delt habe, gebe ich diese hier nicht wieder.

The Munich Windows Phone App Creators #MUCWPDEV

Geschrieben am von leitning

mucwpdev-coverDas Foto stammt von Peter Juras, einem wei­te­ren Mit­glied der Gang und dem Ent­wick­ler von Locks­li­des.

Steve Beh­rendt von Ava­nade hat neu­lich nach einer Twitter-Konversation (siehe Bild unten) mit Derek, einem sehr akti­ven Mit­glied unse­rer Münch­ner App Mafia eine Münch­ner Win­dows Phone Deve­l­oper Group ins Leben gerufen.

mucwpdev-twitter

Ich selbst habe mich auch schon län­ger mit dem Gedan­ken getra­gen, den letz­ten Schritt aber nie gemacht. Umso mehr freue ich mich, dass so etwas plötz­lich „von selbst“ passiert.

Steve hat für die Orga­ni­sa­tion der #MUCWPDEV Tref­fen auf Meetup.com eine Gruppe ange­legt. Also flei­ßig anmel­den:

The Munich Win­dows Phone App Crea­tors #MUCWPDEV

Ich würde mich über eine rege Teil­nahme freuen und hoffe auf inter­es­sante und anre­gende Treffen!

8 Tage Windows Phone 8 | Tag #8: Brieftasche & In-App Käufe

Geschrieben am von leitning

Die­ser Arti­kel ist Tag #8 der Serie 8 Tage Win­dows Phone 8 von Geert van der Cruijsen.

Der Ori­gi­nal­ar­ti­kel befin­det sich hier: 8 days of Win­dows Phone 8 — Day 8: Wal­let and In-App Purcha­ses.

8 Tage Windows Phone 8

Will­kom­men zum letz­ten Arti­kel der Serie 8 Tage Win­dows Phone 8, wel­che sich mit den neuen Fea­tures der Win­dows Phone 8 Platt­form beschäf­tigt. Heute, am Tag 8, bespre­chen wir die Brief­ta­sche und In-App Käufe.

day8

Brief­ta­sche

Die Brieftaschen-Anwendung ist als Ort gedacht, in wel­chem alle mög­li­chen Anwen­dun­gen Dinge wie Deals, Kre­dit­kar­ten­in­for­ma­tio­nen, Bonus­punkte und der­glei­chen spei­chern kön­nen. Mit Hilfe der Wal­let API kön­nen Sie Ein­träge zur Brief­ta­sche hin­zu­fü­gen, diese lesen, ver­än­dern und löschen.

Als ers­tes wer­den wir in unse­rer Bei­spiel­an­wen­dung einen Deal zur Brief­ta­sche hin­zu­fü­gen. In die­sem Bei­spiel erstel­len wir einen Deal für ein Frei­bier, wel­chen der Benut­zer in sei­ner Lieb­lings­bar in Anspruch neh­men kann. Bevor wir mit Code anfan­gen, stat­ten wir unser WMAppManifest.xml mit der Wal­let Fähig­keit aus.

walletcapability

Danach erstel­len wir einen But­ton in der MainPage.xaml, um den neuen Freibier-Deal zu erzeugen.

<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
   <Button x:Name="FreeBeerButton" Content="get 1 free beer deal!" Click="FreeBeerButton_Click_1"></Button>
</StackPanel>

In dem Click Event fügen wir den Code hinzu, um den neuen Deal in der Brief­ta­sche zu erstel­len. Wir begin­nen, indem wir ein neues Deal Objekt erstel­len und die­sem eine ein­deu­tige ID über­ge­ben. Auf dem Deal Objekt kön­nen Sie eine Reihe von Eigen­schaf­ten set­zen, wie z.B. Name, Bil­der und einen Bar­code. In unse­rem Bei­spiel habe ich einige der ein­fa­chen Eigen­schaf­ten mit Wer­ten belegt. Gerade die Bar­code Eigen­schaft kann aber sehr prak­tisch sein, etwa, wenn es daran geht, den Deal in einer Bar ein­zu­lö­sen. Nach­dem wir alle Eigen­schaf­ten gesetzt haben, kön­nen wir die Methode Save­Async auf­ru­fen und der Deal wird gespei­chert. Es ist gän­gige Pra­xis, danach die Brief­ta­sche zu öffnen, so dass der Benut­zer sehen kann, was dort gespei­chert wurde. Es gibt kei­nen spe­zi­el­len Laun­cher für die Brief­ta­sche. Statt­des­sen öffnen Sie eine spe­zi­elle URL — begin­nend mit wallet:// — um die Brief­ta­sche zu öffnen.

private async void FreeBeerButton_Click_1(object sender, RoutedEventArgs e)
{
   var beerDeal = new Deal("1FREEBEER");
   beerDeal.MerchantName = "MyBar";
   beerDeal.DisplayName = "1 free beer!"; 
   beerDeal.Description = "collect 1 free beer at your favorite bar";
   beerDeal.CustomerName = "Geert";
   beerDeal.ExpirationDate = DateTime.Now.AddDays(1);
   beerDeal.IssuerName = "Your Favorite Bar";
   beerDeal.NavigationUri = new Uri("/mainpage.xaml?deal=freebeer", UriKind.Relative);
   await beerDeal.SaveAsync(); 
   Launcher.LaunchUriAsync(new Uri("wallet://", UriKind.RelativeOrAbsolute));
}

Wenn wir die Anwen­dung aus­füh­ren und auf den Free Beer But­ton drü­cken, wird sich die Brief­ta­sche öffnen und unser Deal wird sicht­bar sein. Wenn wir auf die­sen kli­cken, sehen wir seine Details. Wenn Sie einen Bar­code hin­zu­fü­gen, wird die­ser eben­falls hier sicht­bar sein. Wei­ter­hin gibt es eine Mög­lich­keit, die zum Deal gehö­rige Anwen­dung zu öffnen. Dabei wird der Wert der Eigen­schaft Navi­ga­ti­onURI ver­wen­det, die wir auf dem Deal Objekt set­zen kön­nen. Sie kön­nen die Deals hier auch als ver­braucht mar­kie­ren oder diese aus Ihrer Brief­ta­sche löschen.

wallet1

wallet2

wallet3

wallet4

Neben Deals kön­nen Sie auch Zah­lungs­mit­tel hin­ter­le­gen. Diese Objekte sind Dinge wie z.B. Bonus­punkte, die man beim Ein­kau­fen sam­melt. Oft kann man diese Punkte ein­lö­sen gegen irgend­eine Beloh­nung. Die Erstel­lung eines Zah­lungs­mit­tels läuft fast genau so ab wie die Erstel­lung eines Deals. Wir ver­wen­den dies­mal nur ein Pay­men­tIn­stru­ment Objekt. Die Klasse Pay­men­tIn­stru­ment hat eine Eigen­schaft, mit wel­cher Sie den Betrag set­zen kön­nen. Die­sen kön­nen Sie auch nach­träg­lich noch erhö­hen oder verringern.

Um die Zah­lungs­mit­tel in der Brief­ta­sche zu ver­wen­den, müs­sen Sie dem WMAppManifest.xml eine wei­tere Fähig­keit mit dem Namen ID_CAP_WALLET_PAYMENTINSTRUMENTS hinzufügen.

Zu guter Letzt kön­nen Sie der Brief­ta­sche gene­ri­sche Objekte hin­zu­fü­gen. Das könnte etwa eine Kun­den­karte mit einem Bar­code oder einer Num­mer sein, wel­che Sie in einem Laden als Stamm­kun­den iden­ti­fi­ziert. Gene­ri­sche Ein­träge in der Brief­ta­sche kön­nen Sie mit Hilfe des Wal­let­T­ran­sac­tio­nI­tem erstellen.

In-App Käufe

Ein wirk­lich wich­ti­ges Fea­ture von Win­dows Phone 8 ist die Mög­lich­keit, In-App Käufe zu nut­zen. In Win­dows Phone 7 konn­ten Sie nur zwi­schen kos­ten­lo­sen und zah­lungs­pflich­ti­gen Apps (evtl. mit Test­ver­sion) wäh­len. In-App Käufe eröff­nen ganz neue Mög­lich­kei­ten, mit einer App Geld zu ver­die­nen. Sie könn­ten z.B. ein kos­ten­lo­ses Spiel ent­wi­ckeln, in wel­chem der Nut­zer neue Levels für einen gewis­sen Betrag kau­fen kann. Ein wei­te­res Bei­spiel wäre eine Sport-Anwendung, in wel­cher Ihre Benut­zer die Push-Benachrichtigungen für eine Sai­son abon­nie­ren kön­nen, anstatt diese für immer zu bekom­men. Wie also machen wir das?

In-App Käufe müs­sen im Ent­wick­ler­por­tal erstellt wer­den. Log­gen Sie sich mit Ihrem Ent­wick­ler­konto auf dev.windowsphone.com ein und laden Sie eine neue Anwen­dung hoch oder navi­gie­ren Sie zu den Details einer exis­tie­ren­den Anwendung.

inapp1

Kli­cken Sie auf den Rei­ter Pro­ducts und dann auf „Add in-app pro­duct“. Damit erstel­len Sie ein neues Pro­dukt, wel­ches aus Ihrer App her­aus erwor­ben wer­den kann.

inapp2

Zunächst müs­sen wir die Eigen­schaf­ten des In-App Pro­dukts aus­fül­len. Diese beste­hen aus einem Namen und einem Iden­ti­fi­ka­tor. Die­ser Iden­ti­fi­ka­tor ist wich­tig, da wir über die­sen das Pro­dukt in unse­rer App anspre­chen können.

Wei­ter­hin kön­nen Sie fest­le­gen, ob es sich um ein dau­er­haf­tes oder ein zu ver­brau­chen­des Pro­dukt han­delt. Dau­er­hafte Pro­dukte kön­nen ein­mal erwor­ben wer­den und ste­hen dem Nut­zer danach unein­ge­schränkt zur Ver­fü­gung. Zu ver­brau­chende Pro­dukte wer­den ein­mal gekauft und ver­fal­len nach Benutzung.

inapp3

Zum Schluss wäh­len wir einen Preis und drü­cken auf Save. Danach geben wir eine Beschrei­bung für unser Pro­dukt an.

inapp4

Bei der Beschrei­bung müs­sen Sie einen Titel, einen aus­führ­li­chen Beschrei­bungs­text und ein Bild ange­ben. Drü­cken Sie danach wie­der Save.

inapp5

inapp6

Jetzt sind wir bereit, das In-App Pro­dukt ein­zu­rei­chen. Wenn wir Sub­mit drü­cken, wird unser Pro­dukt gespei­chert und wir kön­nen es nach der Zer­ti­fi­zie­rung in unse­rer Anwen­dung verwenden.

inapp7

Da wir jetzt ein In-App Pro­dukt defi­niert haben, kön­nen wir ver­su­chen, die­ses aus unse­rer App her­aus zu kaufen.

Fügen wir einen But­ton hinzu, um unsere 30 neuen Levels zu kaufen.

<Button x:Name="BuyLevelsButton" Content="buy 30 more levels!" Click="BuyLevelsButton_Click_1" ></Button>

Im Click Event fügen wir den Code hinzu, um unser Pro­dukt zu kau­fen. Als ers­tes holen wir uns eine Liste aller ver­füg­ba­ren Pro­dukte. Diese bekom­men wir vom Cur­ren­tApp Objekt, indem wir die Methode Load­Lis­tin­gIn­for­ma­tionAsync auf­ru­fen. Da wir wis­sen, dass es nur ein Pro­dukt gibt, neh­men wir eine Abkür­zung und grei­fen gleich auf den ers­ten Ein­trag zu. Wenn es meh­rere Pro­dukte gäbe, könn­ten Sie das gewünschte Pro­dukt mit Hilfe der ID aus­wäh­len. Sobald wir eine Refe­renz auf das Pro­dukt haben, kön­nen wir die Methode Request­Pro­duct­Purchase­Async auf­ru­fen, um den Store zu öffnen. Dort hat der Nut­zer die Mög­lich­keit, zu ent­schei­den, ob er die­sen Extra­kauf täti­gen möchte. Nach­dem der Nut­zer seine Ent­schei­dung getrof­fen hat, kom­men wir zurück in unse­ren Code, wo wir über­prü­fen kön­nen, ob das Pro­dukt nun auf Active gesetzt ist. Wenn die­ser Wert true ist, müs­sen wir die Methode Report­Pro­duct­Ful­fill­ment rufen, um den Store wis­sen zu las­sen, dass die App den Kauf regis­triert hat. Anschlie­ßend kön­nen wir irgendwo eine Eigen­schaft spei­chern, wel­che anzeigt, dass das zum Pro­dukt gehö­rige Fea­ture in der Anwen­dung frei­ge­schal­tet wurde.

private async void BuyLevelsButton_Click_1(object sender, RoutedEventArgs e)
{
    var products = await CurrentApp.LoadListingInformationAsync();
    var product1 = products.ProductListings.FirstOrDefault();
    var boughtProduct  = await CurrentApp.RequestProductPurchaseAsync(product1.Value.ProductId, true);

   if (CurrentApp.LicenseInformation.ProductLicenses[product1.Value.ProductId].IsActive)    
   {                
      CurrentApp.ReportProductFulfillment(product1.Value.ProductId);
      var saveBoughtProductstate = true;
   }
}

Beach­ten Sie, dass wir in einem Pro­dukt kei­nen Extra-Code oder sons­ti­ges hin­zu­fü­gen. Es han­delt sich um nichts wei­ter als einen Boole’schen Wert, wel­cher auf true gesetzt wurde. In dem Bei­spiel, in dem der Nut­zer 30 Levels kau­fen kann, müs­sen diese bereits im Paket vor­han­den sein. Sie deak­ti­vie­ren ein­fach die ent­spre­chen­den Berei­che der Benut­zer­ober­flä­che, so lange der Wert durch den Kauf noch nicht auf true gesetzt wurde.

Ich mag die Mög­lich­kei­ten der In-App Käufe und glaube, dass dadurch mehr Fir­men, etwa Zei­tun­gen, dazu moti­viert wer­den, Apps für die Win­dows Phone Platt­form zu entwickeln.

Sie kön­nen das Bei­spiel­pro­jekt hier her­un­ter­la­den: http://sdrv.ms/QSJ2yx.

Das war’s Leute. Die Serie 8 Tage Win­dows Phone 8 ist zum Ende gekom­men. Hof­fent­lich hat Ihnen das Lesen die­ser Serie etwas Spaß gemacht und Sie haben dabei etwas gelernt.

Wenn Sie neue Fea­tures ver­misst haben soll­ten, las­sen Sie es mich wis­sen. Wenn mög­lich, kann ich noch einige wei­tere Arti­kel schreiben.

8 Tage Windows Phone 8 | Tag #7: NFC & Bluetooth

Geschrieben am von leitning

Die­ser Arti­kel ist Tag #7 der Serie 8 Tage Win­dows Phone 8 von Geert van der Cruijsen.

Der Ori­gi­nal­ar­ti­kel befin­det sich hier: 8 days of Win­dows Phone 8 — Day 7: Pro­xi­mity Capa­bi­li­ties.

8 Tage Windows Phone 8

Will­kom­men zurück zu mei­ner Blog-Serie 8 Tage Win­dows Phone 8. Heute, im vor­letz­ten Arti­kel, befas­sen wir uns mit den Nah­feld­sen­so­ren, nament­lich Blue­tooth und NFC. Wich­tig bei die­sem Arti­kel ist, dass ich den Code mit dem Emu­la­tor nicht tes­ten konnte, da Blue­tooth und NFC nur mit einem rich­ti­gen Gerät getes­tet wer­den kön­nen. Da ich beim Schrei­ben die­ser Arti­kel kein Gerät zur Ver­fü­gung hatte, kann es sein, dass die Bei­spiele nicht hun­dert­pro­zen­tig funktionieren.

day7

Blue­tooth

Um Blue­tooth oder NFC zu nut­zen, müs­sen Sie als ers­tes eine ent­spre­chende Fähig­keit im WMAppManifest.xml hinzufügen.

proximitycapability

Nach­dem wir das getan haben, sind wir bereit, eine Anwen­dung zu bauen, wel­che mit einem ande­ren Gerät über Blue­tooth kom­mu­ni­ziert. Die Kom­mu­ni­ka­tion über Blue­tooth funk­tio­niert durch eine Art Client/Server Ver­bin­dung. Ein Tele­fon wird der Ser­ver, zu wel­chem sich das andere Tele­fon ver­bin­den kann. Damit kön­nen beide Tele­fone kommunizieren.

Um den Ser­ver und den Cli­ent auf­zu­set­zen, fügen wir zwei But­tons hinzu — einem zum Start des Ser­vers und einen für den Client.

<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
   <Button x:Name="ServerButton" Click="ServerButton_Click_1" Content="server"></Button>
   <Button x:Name="ClientButton" Click="ClientButton_Click_1" Content="client"></Button>
</StackPanel>

Im Click Event des But­tons für den Ser­ver fügen wir den fol­gen­den Code hinzu, um ein Peer­Fin­der Objekt zu erstel­len, wel­ches auf ein­ge­hende Ver­bin­dungs­ver­su­che hört. Wenn sich ein ande­res Gerät mit unse­rem Tele­fon ver­bin­det, wird ein Con­nec­tionRe­ques­ted Event gefeu­ert. Im Event­Hand­ler zei­gen wir ein­fach eine Mes­sa­ge­Box, um zu bestä­ti­gen, dass sich das andere Gerät ver­bun­den hat.

private void ServerButton_Click_1(object sender, RoutedEventArgs e)
{
   PeerFinder.Start();
   PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested;
}
 
async void PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args)
{
   MessageBox.Show("Connected");
   _ss = await PeerFinder.ConnectAsync(args.PeerInformation);
}

Um die Ver­bin­dung mit dem Ser­ver her­zu­stel­len, müs­sen wir die Client-Seite imple­men­tie­ren. Im ent­spre­chen­den Click Event fügen wir den fol­gen­den Code hinzu, um nach Server-Telefonen zu suchen und uns zu ver­bin­den, wenn wir eins gefun­den haben. Wir ver­wen­den wie­der den Peer­Fin­der, um nach Ver­bin­dungs­part­nern zu suchen. Wenn die Methode Fin­dAll­Peers zurück kommt, prü­fen wir, ob es einen akti­ven Ser­ver gibt, indem wir mit der Eigen­schaft Count die Anzahl der Ergeb­nisse abfra­gen. Wenn Count grö­ßer 0 ist, ver­bin­den wir uns mit die­sem Part­ner und prü­fen sei­nen DisplayName.

protected async void ClientButton_Click_1(object sender, RoutedEventArgs e)
{
   PeerFinder.Start(); 
   var p = await PeerFinder.FindAllPeersAsync(); 
   if (p.Count > 0) 
   { 
      _ss = await PeerFinder.ConnectAsync(p[0]);
      string phoneName = p[0].DisplayName;
   }
}

Nun, da wir zwei Tele­fone ver­bun­den haben, kön­nen wir eine Nach­richt von einem Tele­fon zum ande­ren schi­cken. Wir fügen der Main­Page einen wei­te­ren But­ton und den fol­gen­den Code im Click Event hinzu. Damit schi­cken wir eine Nach­richt von einem Tele­fon zum anderen.

private async void SendMessageButton_Click_1(object sender, RoutedEventArgs e)
{
   if (_ss == null)
      throw new Exception("Socket not initialized");

   DataWriter dw = new DataWriter(ss.OutputStream);
   dw.WriteString("Hello Windows Phone 8");
   await dw.StoreAsync();
}

Wir ver­wen­den den Stream­So­cket, wel­chen wir bei Her­stel­lung der Ver­bin­dung initia­li­siert hat­ten, um die Nach­richt zu schi­cken. Wenn der Stream­So­cket nicht initia­li­siert ist, feu­ern wir eine Excep­tion. Andern­falls kön­nen wir wei­ter­ma­chen. Wir erstel­len einen Data­Wri­ter basie­rend auf dem Out­putStream des Stream­So­cket und ver­wen­den die Methode Wri­teString, um die Nach­richt über den Data­Wri­ter zu schi­cken. Jetzt kön­nen wir die Methode StoreAsync auf­ru­fen, um die Daten tat­säch­lich an das ver­bun­dene Tele­fon zu senden.

Als letz­tes müs­sen wir die Nach­richt auf dem Tele­fon noch emp­fan­gen. Wir ver­bin­den den Stream­So­cket des Peer­Fin­der und rufen eine neue pri­vate Methode WaitForMessage.

In die­ser asyn­chro­nen Methode öffnen wir einen DataRe­a­der basie­rend auf dem InputStream des Stream­So­cket. Aus dem DataRe­a­der kön­nen wir zunächst die Länge der zu emp­fan­gen­den Nach­richt abfra­gen und anschlie­ßend die Nach­richt selbst aus­le­sen. Damit sind wir fer­tig mit der Über­tra­gung einer Nach­richt über Bluetooth.

async void PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args)
{
   MessageBox.Show("Connected");
   _ss = await PeerFinder.ConnectAsync(args.PeerInformation);
   string message = await WaitForMessage(); 
}

private async Task<string> WaitForMessage()
{
   DataReader dr = null;

   while (true)
   {
      if (dr == null)
         dr = new DataReader(_ss.InputStream);

      await dr.LoadAsync(4);
      uint messageLen = (uint)dr.ReadInt32();
      await dr.LoadAsync(messageLen);
      return dr.ReadString(messageLen);
   }
}

NFC

Der zweite Nah­feld­sen­sor in Win­dows Phone ist NFC. Mit NFC ist es mög­lich, NFC Tags zu lesen oder zwi­schen Tele­fo­nen zu kom­mu­ni­zie­ren. In fol­gen­den Abschnitt wol­len wir uns näher damit befas­sen, wie man per NFC zwi­schen Tele­fo­nen kom­mu­ni­zie­ren kann. Um Nach­rich­ten per NFC zu sen­den und zu emp­fan­gen, fügen wir wie­der mal zwei But­tons zu unse­rer MainPage.xaml hinzu.

<Button x:Name="NfcSendButton" Click="NfcSendButton_Click_1" Content="nfc send"></Button>
<Button x:Name="NfcReceiveButton" Click="NfcReceiveButton_Click_1" Content="nfc receive"></Button>

Im Click Event des Send But­tons fügen wir den fol­gen­den Code hinzu. Wir erstel­len eine Instanz der Klasse Pro­xi­mi­t­y­De­vice. Dann müs­sen wir nur noch die Methode PublishMes­sage auf die­sem Objekt auf­ru­fen. Im Bei­spiel sen­den wir einen String. Es ist aber auch mög­lich, binäre Daten zu übertragen.

private void NfcSendButton_Click_1(object sender, RoutedEventArgs e)
{
   ProximityDevice pd = ProximityDevice.GetDefault();

   if (pd != null) 
   { 
      pd.PublishMessage("8days", "Hello World!");
   }
}

Nach­dem wir die Nach­richt gesen­det haben, müs­sen wir als letz­tes für heute nur noch die Nach­richt emp­fan­gen. Fügen Sie den fol­gen­den Code zum Click Event des Receive But­tons hinzu. Wir erstel­len wie­der eine Instanz der Klasse Pro­xi­mi­t­y­De­vice und regis­trie­ren uns für ein­ge­hende Nach­rich­ten. Das war’s. Wenn jetzt eine Nach­richt ein­trifft, wird die Methode NfcReceive auf­ge­ru­fen und wir kön­nen die Nach­richt auslesen.

private void NfcReceiveButton_Click_1(object sender, RoutedEventArgs e)
{
   ProximityDevice pd = ProximityDevice.GetDefault();
   if (pd != null)
   {
      long Id = pd.SubscribeForMessage("8days", NfcReceive);
   }
}
 
private void NfcReceive(ProximityDevice sender, ProximityMessage message)
{
   var m = message.DataAsString;
}

Wie Sie sehen, ist die Umset­zung von NFC in Win­dows Phone 8 wirk­lich ein­fach. Ich kann es nicht erwar­ten, bis Ent­wick­ler anfan­gen, diese Fea­tures in ihren Anwen­dun­gen zu nut­zen. Alle momen­tan ange­kün­dig­ten Win­dows Phone 8 Geräte haben NFC Fähig­kei­ten — die Vor­aus­set­zun­gen sind also gelegt.

proximity

Mor­gen, am letz­ten Tag der Serie, wer­den wir uns mit den Fea­tures zur Brief­ta­sche beschäf­ti­gen und wie man In-App Käufe realisiert.

Das Bei­spiel­pro­jekt zum heu­ti­gen Arti­kel kön­nen Sie hier her­un­ter­la­den: http://sdrv.ms/QSJ2yx.

8 Tage Windows Phone 8 | Tag #6: Die API zur Sprachsteuerung

Geschrieben am von leitning

Die­ser Arti­kel ist Tag #6 der Serie 8 Tage Win­dows Phone 8 von Geert van der Cruijsen.

Der Ori­gi­nal­ar­ti­kel befin­det sich hier: 8 days of Win­dows Phone 8 — Day 6: Speech API.

8 Tage Windows Phone 8

Herz­lich will­kom­men zu einer wei­te­ren Aus­gabe mei­ner Serie 8 Tage Win­dows Phone 8. Heute, im sechs­ten Arti­kel, wid­men wir uns den APIs zur Sprach­steue­rung. Spra­che auf Win­dows Phone 8 besteht aus drei wesent­li­chen Bau­stei­nen: Text To Speech (Syn­these), Speech To Text (Sprach­ver­ständ­nis) und Voice Com­mands (Sprach­kom­man­dos). In die­sem Arti­kel wol­len wir uns mit allen drei Aspek­ten auseinandersetzen.

day6

Text To Speech

Als erste der drei APIs zur Sprach­steue­rung dis­ku­tie­ren wir die Text to Speech API zur Sprach­syn­these. In Win­dows Phone 7 muss­ten Sie die Bing Speech API ver­wen­den, wenn Sie einen geschrie­be­nen Satz in Ton über­set­zen woll­ten. In Win­dows Phone 8 ist diese API Teil der Win­dows Phone API. Unter der Haube ver­wen­det diese höchst­wahr­schein­lich auch wei­ter­hin die Bing Server.

Erstel­len wir ein neues Pro­jekt. Als ers­tes müs­sen wir die Capa­bi­lity zur Sprach­er­ken­nung im WMAppManifest.xml hin­zu­fü­gen. Mit Visual Stu­dio 2012 kön­nen wir das direkt im Capa­bi­li­ties Tab machen.

ID_CAP_SPEECH_RECOGNITION

Als nächs­tes plat­zie­ren wir einen But­ton auf der Main­Page und schrei­ben die fol­gen­den zwei Zei­len in den Click Event Hand­ler zu die­sem Button.

private void SayHelloButton_Click(object sender, RoutedEventArgs e)
{
   SpeechSynthesizer ss = new SpeechSynthesizer(); 
   ss.SpeakTextAsync("8 days of windows phone 8, day 6");
}

Wenn Sie die App aus­füh­ren, wer­den Sie mer­ken, dass Sie wirk­lich nur diese zwei Zei­len brau­chen, um geschrie­be­nen Text in Spra­che zu ver­wan­deln. Groß­ar­tig! Beach­ten Sie, dass die Methode SpeakTex­tAsync der Klasse Speech­Syn­the­si­zer eine async Methode ist. Sie kön­nen auch die Spra­che und die Stimme des gespro­che­nen Schnip­sels ver­än­dern. Fügen wir etwas mehr Code hinzu, um eine deut­sche Aus­gabe, gespro­chen von einer männ­li­chen Stimme zu bekommen:

private void SayGermanButton_Click_(object sender, RoutedEventArgs e)
{
   SpeechSynthesizer ss = new SpeechSynthesizer();
   VoiceInformation vi = InstalledVoices.All.Where(v => v.Language == "de-DE" && v.Gender == VoiceGender.Male).FirstOrDefault();
   ss.SetVoice(vi);
   ss.SpeakTextAsync("8 Tage von Windows Phone 8, Tag 6");
}

Es sind nur zwei Zei­len erfor­der­lich, um die Spra­che und das Geschlecht zu set­zen (ja, es würde sogar auch mit einer gehen). Der Rest bleibt unver­än­dert. Wenn wir den But­ton jetzt noch mal drü­cken (im Bei­spiel­pro­jekt habe ich einen zwei­ten But­ton hin­zu­ge­fügt, um beide Fälle tes­ten zu kön­nen), hören wir eine männ­li­che deut­sche Stimme. Kom­men wir zum nächs­ten Thema, der Über­set­zung von gespro­che­ner Spra­che in Text — Speech To Text.

Speech To Text

Die im vor­he­ri­gen Abschnitt dis­ku­tierte Sprach­syn­these ist schon sehr prak­tisch. Die Kon­ver­tie­rung von gespro­che­ner Spra­che in Text ist noch ein­drucks­vol­ler und nicht viel schwe­rer zu imple­men­tie­ren. Bevor wir anfan­gen, müs­sen wir der App die Fähig­keit zur Nut­zung des Mikro­fons ver­lei­hen. Machen Sie einen Haken bei der ent­spre­chen­den Box im Capa­bi­li­ties Rei­ter der Datei WMAppManifest.xml.

capabilitiesmicrophone

Nun, da wir die Fähig­keit zur Nut­zung des Mikro­fons haben, begin­nen wir mit etwas Code zur Sprach­er­ken­nung. Wir fügen einen But­ton hinzu, mit dem wir den Benut­zer fra­gen, wie er sich gerade fühlt.

<Button x:Name="AskStatusButton" Content="how are you doing?" Click="AskStatusButton_Click"></Button>
<TextBlock x:Name="StatusText"></TextBlock>
<TextBlock x:Name="ConfidenceText"></TextBlock>

Im Code Behind fügen wir im Click Event zu die­sem But­ton etwas Code zur Sprach­er­ken­nung hinzu und geben das Ergeb­nis der Erken­nung im Sta­tus­Text Text­Block aus. Wir ver­wen­den zudem einen wei­te­ren Text­Block, um das Con­fi­dence Level (also die Angabe, wie sicher der Text der gespro­che­nen Spra­che ent­spricht) der Sprach­er­ken­nung auszugeben.

Im Click Event begin­nen wir, indem wir ein Speech­Re­co­gnize­rUI Objekt erstel­len. Auf die­sem Speech­Re­co­gnize­rUI Objekt set­zen wir einige Eigen­schaf­ten: die Eigen­schaft Lis­ten­Text ist der Text, wel­cher als Titel im Sprach­dia­log ange­zeigt wird (siehe das Bild unten). Die nächste Eigen­schaft ist der Exam­ple­Text. Mit die­ser Eigen­schaft kön­nen Sie ein ein­fa­ches Bei­spiel für die Ant­wort des Benut­zers ange­ben. Danach set­zen wir die Eigen­schaft Rea­dou­tEn­ab­led auf true, damit das Tele­fon den Text an den Benut­zer zurück spricht. Als letzte Eigen­schaft set­zen wir Show­Con­fir­ma­tion, damit der gespro­chene Text dem Benut­zer schrift­lich auf dem Bild­schirm ange­zeigt wird.

private async void AskStatusButton_Click(object sender, RoutedEventArgs e)
{
   SpeechRecognizerUI sr = new SpeechRecognizerUI();
   sr.Settings.ListenText = "How are you doing?";
   sr.Settings.ExampleText = "I'm doing fine"; 
   sr.Settings.ReadoutEnabled = true; 
   sr.Settings.ShowConfirmation = true; 
   SpeechRecognitionUIResult result = await sr.RecognizeWithUIAsync();

   if (result.ResultStatus == SpeechRecognitionUIStatus.Succeeded) 
   {
      StatusText.Text = result.RecognitionResult.Text;
      ConfidenceText.Text = result.RecognitionResult.TextConfidence.ToString();
   }
}

Nach­dem wir alle diese Eigen­schaf­ten gesetzt haben, kön­nen wir die Methode Reco­gnize­Wi­t­hUI­Async auf­ru­fen, um die Sprach­er­ken­nung zu star­ten. Beach­ten Sie, dass beim ers­ten Auf­ruf die­ser Methode der Benut­zer gefragt wird, ob er zustimmt, dass die Sprach­auf­nahme zur Ver­ar­bei­tung an die Ser­ver von Micro­soft gesen­det wird. Wenn der Benut­zer zustimmt, wird die Sprach­er­ken­nung gestartet.

speech1

speech2

speech3

speech4

Nach­dem die Sprach­er­ken­nung abschlos­sen ist, kön­nen Sie das Ergeb­nis im Code abfra­gen. Das Ergeb­nis, wel­ches von Reco­gnize­Wi­t­hUI­Async zurück kommt, ent­hält eine Text Eigen­schaft und ein Con­fi­dence Level. Mit dem Con­fi­dence Level bekom­men wir einen Hin­weis, ob das Ergeb­nis brauch­bar ist. Im Bei­spiel­pro­jekt zei­gen wir beide Werte in den bei­den Text­Bo­xes auf der Main­Page an.

In man­chen Fäl­len wol­len Sie den Benut­zer nur zwi­schen eini­gen vor­ge­ge­be­nen Optio­nen aus­wäh­len las­sen. Das ist eben­falls sehr ein­fach mit der Speech­Re­co­gnize­rUI Klasse umzu­set­zen. Wir fügen einen wei­te­ren But­ton und zwei wei­tere Text­Bo­xes zur Main­Page hinzu um den Benut­zer zu fra­gen, wel­cher Wochen­tag heute ist.

<Button x:Name="AskDayButton" Content="which day is it?" Click="AskDayButton_Click"></Button>
<TextBlock x:Name="DayText"></TextBlock>
<TextBlock x:Name="DayConfidenceText"></TextBlock>

Danach fügen wir den Code zum Click Event des But­tons hinzu. Die­ser ist, bis auf einige Erwei­te­run­gen, fast der selbe wie vorher.

private async void AskDayButton_Click(object sender, RoutedEventArgs e)
{
   SpeechRecognizerUI sr = new SpeechRecognizerUI();
   sr.Settings.ListenText = "Which day is it today?";
   sr.Settings.ExampleText = "Friday";
   sr.Settings.ReadoutEnabled = true;
   sr.Settings.ShowConfirmation = true;
   
   sr.Recognizer.Grammars.AddGrammarFromList("answer", new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" });
   
   SpeechRecognitionUIResult result = await sr.RecognizeWithUIAsync();
   if (result.ResultStatus == SpeechRecognitionUIStatus.Succeeded)
   {
      DayText.Text = result.RecognitionResult.Text;
      DayConfidenceText.Text = result.RecognitionResult.TextConfidence.ToString();
   }
}

In der ein­zi­gen neuen Zeile geben wir die Liste der mög­li­chen Ant­wor­ten an. Die Sprach­er­ken­nung wird die gespro­chene Spra­che nun nur noch gegen diese Wör­ter prü­fen. In unse­rem Bei­spiel habe ich die Wochen­tage als mög­li­che Ant­wor­ten angegeben.

speech5

speech6

speech7

Wenn Sie die Anwen­dung aus­füh­ren, wer­den Sie mer­ken, dass nur noch die Wör­ter in der Liste als Ant­wort akzep­tiert werden.

Voice Com­mands

Das letzte Thema für heute sind die Sprach­kom­man­dos. Mit Sprach­kom­man­dos kann der Benut­zer Ihre App mit einer bestimm­ten Auf­gabe star­ten oder eine Auf­gabe inner­halb der App aus­füh­ren, wenn diese bereits läuft. Sprach­kom­man­dos beste­hen immer aus 3 Tei­len: Dem Namen der App, damit das Betriebs­sys­tem weiß, an wel­che App das Kom­mando zu rich­ten ist, dem Namen des Kom­man­dos und einem Satz, wel­cher eine Art Para­me­ter für Ihr Kom­mando darstellt.

Um Sprach­kom­man­dos zu rea­li­sie­ren, müs­sen Sie eine XML Datei hin­zu­fü­gen, wel­che die Defi­ni­tion der Sprach­kom­man­dos beinhal­tet. Um diese VCD Datei hin­zu­zu­fü­gen, kli­cken Sie mit Rechts auf Ihr Pro­jekt im Visual Stu­dio und wäh­len sie Add New Item. Dann wäh­len Sie Voice Com­mand Defi­ni­tion aus der Liste.

vcdfile

Stan­dard­mä­ßig erhal­ten Sie eine VCD Datei, wel­che bereits einige Bei­spiel­kom­man­dos und –Sätze beinhal­tet. Wir wer­den diese ändern, um ein Kom­mando zu defi­nie­ren, wel­ches die App star­tet, indem es den Benut­zer fragt, wel­cher Tag heute, ges­tern oder mor­gen ist.

Als ers­tes müs­sen Sie in der VCD Datei das Com­mandPre­fix defi­nie­ren. Das ist das Wort, wel­ches das Betriebs­sys­tem ver­wen­det, um Ihre App zu fin­den. Danach fügen wir das Kom­mando hinzu. Die­ses braucht ein Ele­ment Lis­ten­For, womit dem Betriebs­sys­tem ange­ge­ben wird, auf wel­chen Text es hören soll. Zu dem Kom­mando kön­nen Sie wei­ter­hin einen Satz ange­ben, wie ich es im Bei­spiel mit dem {day} gemacht habe. Die­ser Satz, zusam­men mit sei­nen Vari­an­ten, muss eben­falls Teil der VCD Datei sein.

<?xml version="1.0" encoding="utf-8"?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
   <CommandSet xml:lang="en-US">
      <CommandPrefix>8 days</CommandPrefix>
      <Example>what day is it today?</Example>
      <Command Name="DayToday">
         <Example>What day is it?</Example>
         <ListenFor>What day is it {day}</ListenFor>
         <Feedback>Checking the day</Feedback>
         <Navigate Target="/MainPage.xaml"/>
      </Command>
      <PhraseList Label="day">
         <Item> today </Item>
         <Item> tomorrow </Item>
         <Item> yesterday </Item>
      </PhraseList>
   </CommandSet>
</VoiceCommands>

Wenn die Defi­ni­tion der Kom­man­dos in unse­rer VCD Datei abge­schlos­sen ist, kön­nen wir diese beim Betriebs­sys­tem regis­trie­ren. Sie müs­sen dies nur ein­mal machen, wenn Ihre Anwen­dung zum ers­ten Mal aus­ge­führt wird. Der Ein­fach­heit hal­ber fügen wir die Regis­trie­rung in unse­rem Bei­spiel ein­fach dem Kon­struk­tor der Main­Page hinzu.

public MainPage()
{
   InitializeComponent();
   InitializeVoiceCommands();
} 

private async System.Threading.Tasks.Task InitializeVoiceCommands()
{
   await VoiceCommandService.InstallCommandSetsFromFileAsync(new Uri("ms-appx:///VoiceCommandDefinition1.xml"));
}

Das ist alles, was wir tun müs­sen, um unsere Anwen­dung per Spra­che zu star­ten. Sie kön­nen die Sprach­er­ken­nung aus­lö­sen, indem Sie den Win­dows But­ton etwas län­ger gedrückt hal­ten. Sie sehen dann ein klei­nes „Ich höre zu …“ Fens­ter. Wenn Sie fra­gen „Was kann ich sagen?“ oder das Fra­ge­zei­chen drü­cken, kom­men Sie auf eine neue Seite mit der Erklä­rung, wel­che Kom­man­dos ver­füg­bar sind. Die erste Seite beinhal­tet die Kom­man­dos, die in das Sys­tem ein­ge­baut sind. Wenn Sie nach rechts wischen, sehen Sie eine Über­sicht über die Apps, die Sprach­kom­man­dos anbie­ten. Unsere App ist hier auf­ge­führt. Wenn Sie auf die App kli­cken, sehen Sie die Liste der Kom­man­dos, die von die­ser App unter­stützt werden.

speech8

speech9

speech10

speech11

Wenn wir jetzt den Win­dows But­ton gedrückt hal­ten und sagen „8 days, What day is it tomor­row?“, wird unsere Anwen­dung star­ten und die Main­Page anzeigen.

speech12

Das Sprach­kom­mando wird der Main­Page in Form des Que­rys­tring über­ge­ben. In dem wir den Hand­ler OnNa­vi­ga­tedTo über­schrei­ben, kön­nen wir prü­fen, wel­ches Sprach­kom­mando ver­wen­det wurde und wel­cher Satz vom Benut­zer gespro­chen wurde.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
   base.OnNavigatedTo(e);
   if (e.NavigationMode == System.Windows.Navigation.NavigationMode.New)
   {
      if (NavigationContext.QueryString.ContainsKey("voiceCommandName"))
      {
         string command = NavigationContext.QueryString["voiceCommandName"];
      }
   }
}

Das Kom­mando und der Satz wer­den als sepa­rate Para­me­ter über­ge­ben. Wenn wir die App also star­ten und sie über das Sprach­kom­mando akti­vie­ren, sehen wir im Debug­ger das folgende:

onnavigatedto

Wie Sie sehen, gibt es einen Para­me­ter „day“, wel­chen Sie bei­spiels­weise in einem Switch State­ment nut­zen kön­nen, um eine geeig­nete Methode aufzurufen.

Sie kön­nen das Bei­spiel­pro­jekt hier her­un­ter­la­den: http://sdrv.ms/QSJ2yx.

Das ist alles für heute zu den APIs zur Sprach­steue­rung. Hof­fent­lich kom­men Sie mor­gen wie­der, um mehr über die APIs zu NFC und Blue­thooth zu erfahren.