msdevcon.ru #msdevcon Windows Phone 8 Networking Survival Kit Andy Wigley Microsoft UK Http Programming with async and await C# 5.0 includes the async and await keywords to ease writing of asynchronous code In Windows Store Apps, new Task-based methods exclusively used for networking, not supported on Windows Phone 8 Workarounds are available: API WP7.1 WP8 W8 System.Net.WebClient System.Net.HttpWebRequest ( NuGet) ( NuGet) Windows.Web.Syndication.SyndicationClient Windows.Web.AtomPub.AtomPubClient ASMX Web Services WCF Services OData Services System.Net.Http.HttpClient using System.Net; ... WebClient client; public MainPage() { ... client = new WebClient(); client.DownloadStringCompleted += client_DownloadStringCompleted; } void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { this.downloadedText = e.Result; } private void loadButton_Click(object sender, RoutedEventArgs e) { client.DownloadStringAsync(new Uri("http://MyServer/ServicesApplication/rssdump.xml")); } using System.Net; using System.Threading.Tasks; ... private async void LoadWithWebClient() { var client = new WebClient(); string response = await client.DownloadStringTaskAsync( new Uri("http://MyServer/ServicesApplication/rssdump.xml")); this.downloadedText = response; } private async void LoadWithHttpWebRequest() { HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://services.odata.org/Northwind/Northwind.svc/Suppliers"); request.Method = HttpMethod.Get; HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); ... } // Following requires HttpClient.Compression NuGet package var handler = new AdvancedREI.Net.Http.Compression.CompressedHttpClientHandler(); // Create the HttpClient HttpClient httpClient = new HttpClient(handler); // To use without compression support (but why do that?), use default HttpClient constructor // without the compression handler: HttpClient httpClient = new HttpClient(); // Optionally, define HTTP headers httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); // Make the call HttpResponseMessage response = await httpClient.GetAsync( "http://services.odata.org/Northwind/Northwind.svc/Suppliers"); response.EnsureSuccessStatusCode(); // Throws exception if bad HTTP status code string responseBodyAsText = await response.Content.ReadAsStringAsync(); DEMO HTTP Networking using Async Andy Wigley Make Smart Decisions About Data Transfer Making Decisions based on Data Connections Use the NetworkInterfaceType object to detect network type and speed Subscribe to the NetworkChange event to detect when the network state changes 12 private const int IANA_INTERFACE_TYPE_OTHER = 1; private const int IANA_INTERFACE_TYPE_ETHERNET = 6; private const int IANA_INTERFACE_TYPE_PPP = 23; private const int IANA_INTERFACE_TYPE_WIFI = 71; ... string network = string.Empty; // Get current Internet Connection Profile. ConnectionProfile internetConnectionProfile = Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile(); if (internetConnectionProfile != null) // if ‘null’, we are offline. { switch (internetConnectionProfile.NetworkAdapter.IanaInterfaceType) { case IANA_INTERFACE_TYPE_OTHER: cost += "Network: Other"; break; case IANA_INTERFACE_TYPE_ETHERNET: cost += "Network: Ethernet"; break; case IANA_INTERFACE_TYPE_WIFI: cost += "Network: Wifi\r\n"; break; default: cost += "Network: Unknown\r\n"; break; } } Mobile devices are often connected to poor quality network connections Best chance of success in network data transfers achieved by: Avoid transferring redundant data Design your protocol to only transfer precisely the data you need and no more DEMO Wire Serialization Andy Wigley Wire Serialization Format Size in Bytes ODATA XML 73786 ODATA JSON ATOM 34030 JSON ‘Lite’ 15540 JSON ‘Lite’ GZip 8680 Implementing Compression http://sharpziplib.com/ http://sharpcompress.codeplex.com/ var request = HttpWebRequest.Create("http://yourPC:15500/NorthwindDataService.svc/Suppliers") as HttpWebRequest; request.Accept = "application/json"; request.Method = HttpMethod.Get; request.Headers["Accept-Encoding"] = "gzip"; HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); // Read the response into a Stream object. System.IO.Stream responseStream = response.GetResponseStream(); string data; var stream = new GZipInputStream(response.GetResponseStream()); using (var reader = new System.IO.StreamReader(stream)) { data = reader.ReadToEnd(); } responseStream.Close(); private void EnableGZipResponses(DataServiceContext ctx) { ctx.WritingRequest += new EventHandler<ReadingWritingHttpMessageEventArgs>( (_, args) => { args.Headers["Accept-Encoding"] = "gzip"; } ); ctx.ReadingResponse += new EventHandler<ReadingWritingHttpMessageEventArgs>( (_, args) => { if (args.Headers.ContainsKey("Content-Encoding") && args.Headers["Content-Encoding"].Contains("gzip")) { args.Content = new GZipStream(args.Content); } } ); } Reference: http://blogs.msdn.com/b/astoriateam/archive/2011/10/04/odata-compression-in-windows-phone-7-5-mango.aspx if (oSession.host.toLowerCase() == "yourpc:8888") oSession.host = "yourpc:80"; http://yourPC:8888/ DEMO Compression Andy Wigley Accessing Local Services from the Emulator http://localhost http://localhost C:\Users\yourUsername\Documents\IISExpress\config\applicationhost.config <sites> <binding protocol="http" bindingInformation="*:18009:localhost" /> <binding protocol="http" bindingInformation="*:18009:YourPCName" /> YourPCName:18009 netsh advfirewall firewall add rule name="IIS Express (non-SSL)" action=allow protocol=TCP dir=in localport=8080 yourPC 8080 http://msdn.microsoft.com/en-us/library/ms178109(v=VS.100).aspx DEMO Accessing local services from the emulator Andy Wigley Bluetooth Bluetooth Near Field Communication (NFC) App to device App to app try { PeerFinder.AlternateIdentities["Bluetooth:Paired"] = ""; var peers = await PeerFinder.FindAllPeersAsync(); } catch (Exception ex) { if ((uint)ex.HResult == 0x8007048F) MessageBox.Show("Bluetooth is switched off"); } // Register for incoming connection requests PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested; // Start advertising ourselves so that our peers can find us PeerFinder.DisplayName = "TicTacToe BT"; PeerFinder.Start(); // Register for incoming connection requests PeerFinder.ConnectionRequested += PeerFinder_ConnectionRequested; // Start advertising ourselves so that our peers can find us PeerFinder.DisplayName = "TicTacToe BT"; PeerFinder.Start(); StreamSocket socket; async void PeerFinder_ConnectionRequested(object sender, ConnectionRequestedEventArgs args) { if ( args.PeerInformation.DisplayName == "RobsPhone" ) { socket = await PeerFinder.ConnectAsync(args.PeerInformation); PeerFinder.Stop(); } } DEMO Bluetooth communication Andy Wigley NFC Connect devices Acquire content Exchange digital objects ProximityDevice device = ProximityDevice.GetDefault(); // Make sure NFC is supported if (device != null) { PeerFinder.TriggeredConnectionStateChanged += OnTriggeredConnectionStateChanged; // Start finding peer apps, while making this app discoverable by peers PeerFinder.Start(); } ProximityDevice device = ProximityDevice.GetDefault(); // Make sure NFC is supported if (device != null) { PeerFinder.TriggeredConnectionStateChanged += OnTriggeredConnStateChanged; // Include the Windows 8 version of our app as possible peer PeerFinder.AlternateIdentities.Add("Windows", "my Win8 appID"); // Start finding peer apps, while making this app discoverable by peers PeerFinder.Start(); } void OnTriggeredConnStateChanged(object sender, TriggeredConnectionStateChangedEventArgs args) { switch (args.State) { case TriggeredConnectState.Listening: // Connecting as host break; case TriggeredConnectState.PeerFound: // Proximity gesture is complete – setting up link break; case TriggeredConnectState.Connecting: // Connecting as a client break; case TriggeredConnectState.Completed: // Connection completed, get the socket streamSocket = args.Socket; break; case TriggeredConnectState.Canceled: // ongoing connection cancelled break; case TriggeredConnectState.Failed: // Connection was unsuccessful break; } } PeerFinder.AllowBluetooth = true; PeerFinder.AllowInfrastructure = true; DEMO NFC ‘Tap to Connect’ and ‘Tap to Share’ Andy Wigley Windows.Networking.Proximity.ProximityDevice proximityDevice; long publishedMessageId = -1; private void PublishUriButton_Click(object sender, RoutedEventArgs e) { if (proximityDevice == null) proximityDevice = ProximityDevice.GetDefault(); // Make sure NFC is supported if (proximityDevice != null) { // Stop publishing the current message. if (publishedMessageId != -1) { proximityDevice.StopPublishingMessage(publishedMessageId); } // Publish the new one publishedMessageId = proximityDevice.PublishUriMessage( new Uri("zune:navigate?appid=351decc7-ea2f-e011-854c-00237de2db9e")); } } Контакты Andy Wigley Microsoft andy.wigley@microsoft.com & @andy_wigley andywigley.com © 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.