sobota, 31 grudnia 2011

Notatki o Windows 8 - odc. 17

Aplikacje Metro - JavaScript: search, przekazywanie danych z jednej aplikacji do drugiej, strumieniowanie multimediów do urządzeń za pomocą PlayTo, komunikacja dwóch komputerów poprzez zbliżenie ich na odległość 3-4 cm lub dotyk.

The Charms bar presents a standard set of connection points to users. Users swipe the Charms bar open, and then select an action:

  • Search: to search for content from your app, other participating apps, or the file system.
  • Share: to share content from your app with other users, web services, or other apps.
  • Start: to return to the Start screen.
  • Connect: to connect to other apps or devices.
    • Play to: to stream media files to DLNA devices.
    • Print: to print content from your app to connected printers.
  • Settings: to configure your app and the system to suit users' preferences.

Each charm is associated with an action that is governed by an app contract, and applications need to declare the contracts they support in the package manifest at install time. Do not duplicate charms functionality elsewhere in your app. That will just confuse your users.

Search

Participating in the Search contract allows users to search with your app by selecting your app from the list in the Search charm. Your app can present search results to users in a view that you control and can customize to fit your users' needs.

  1. Bring up the Add a New Item dialog for your project in Visual Studio.
  2. Add the Search contract by selecting Search Contract from the center pane of the Add a New Item dialog and click the Add button. When you add the Search contract, Visual Studio automatically updates your "package.appmanifest" manifest file and adds the following files to your project:
    1. "search.js" contains the JavaScript code for search in your app.
    2. "search.html" is the landing page for your app's custom view of search results.
    3. "search.css" contains the styles used to render the landing page for your app's search results.

       Your manifest file is updated with markup for the Search contract.

When users search using your app, the system fires an activated event to load your app for search.
JavaScript code that listens for and handles this activated event is automatically included in the "search.js" file.

Appropriate use of search

  • Use the Search charm as the primary way to initiate search in your application and eliminate the need for additional chrome within your application for search controls. Avoid showing search boxes or search buttons within your Application’s UI.
  • Use query suggestions as a way to autocomplete terms for which the user will see results within your Application. Query suggestions are displayed just below the search box while they user is typing in their query. They are a great way to help users quickly complete their search by reducing the amount of typing they have to do. Limit the number of query suggestions supplied to the search pane to no more than 5.
  • Use Result suggestions when you want to suggest exact or strong matches from your application data while the user is typing. This reduces the intermediate step of seeing a search results view and then selecting the result users want to look at. Result suggestions differ from query suggestion because they contain
    • A thumbnail or appropriate image representing the result
    • A title or label for the suggested result
    • A description for the suggested result

When a result suggestion is selected, Applications should navigate to the view that shows the details of the selected item. If you are supplying result suggestions in your app, limit the number to no more than 5.

  • Limit the number of result suggestion when showing both query and result suggestions together. When using both query suggestions and result suggestions in the search pane, show only one result suggestion to indicate the best match. This allows for more query suggestions to be shown in case the result suggestion is not what the user is looking for.
  • Use separators when showing both rich suggestions and query suggestions. Separators can be added to the list of suggestions that the Application provides to the Search pane. Separators visually distinguish result suggestions from query suggestions. If the result suggestion is shown below query suggestions, use the separator label to provide additional context for what the result suggestion supplied is.
  • The search results are designed by the applications themselves and shown in their App UI , not in the search pane . Best practices for search results design include:
    • Provide filters to help the user refine their query
    • Provide scopes or views in the application to help the user re-direct their query appropriately
    • Show the search term for which the user is seeing results
  • When searching, users are often going to be looking at several results as they gather information. Looking at a specific result and get back to the search results view should be easy
  • The power of the search contract allows users to invoke an application for search from anywhere in the system via the search charm. The application must be able to respond to a search activation event at any time. Applications should save their state and provide users with a mechanism to get back to that previous state where appropriate.

Inappropriate use of search

  • Don’t place search entry points in the App command bar
  • Don’t use the Search Charm as way to implement Find in functionality for your app. Find In page functionality should be implemented within the App command bar and not in the search pane. Find In page helps the user locate exact instances in the current view, which is different from search.
  • Don’t use query suggestions or result suggestions as a way to filter or scope the search for your application. All interactions that refine or manipulate the results set of results should be placed near the search results in the App UI.

Sharing content between apps

There are two types of apps that participate in sharing:

  • Source applications provide shareable content, potentially in multiple formats.
  • Target applications receive shareable content.

Sharing content

At the core of any sharing operation is the DataPackage object. The types of content that a DataPackage can contain include:

  • Plain text
  • URIs
  • HTML
  • Formatted text
  • Bitmaps
  • Files
  • Developer-defined data

A DataPackage object can contain one or more of these formats, in any combination. In addition, a DataPackage can contain a delegate - a function that is called when the receiving app requests data. We recommend using a delegate any time that the data a user wants to share is resource-intensive, as a delegate can help your app share data more efficiently.

var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();

The DataTransferManager class supports a datarequested event, which is fired when a user presses the Share or Connect charm.

dataTransferManager.addEventListener("datarequested" function (e) {

    var request = e.request;

    shareDataEventHandler(request);

}

Sharing text

Any content that you share must contain two properties: a title and the content itself. (We recommend that you include a description, too.)

function shareDataEventHandler(request) {

    request.data.properties.title = "My sharing example";

    request.data.properties.description = "Content from my app";

    request.data.setText("Hello World!");

}

Sharing HTML

function shareDataEventHandler(request) {

    request.data.properties.title = "My sharing example";

    request.data.properties.description = "Content from my app";

    request.data.setHtml("<p>Here is some <b>HTML content</b>.</p>");

}

Sharing links

As with text, you need to set the title.

function shareDataEventHandler(request) {

    request.data.properties.title = "My sharing example";

    request.data.properties.description = "A URL to my site."

    request.data.setUri(http://www.contoso.com);

}

Sharing files

var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();

var fileToShare;

 

dataTransferManager.addEventListener("datarequested" function (e){

    var request = e.request;

    shareFileEventHandler(request);

}

 

function shareFileEventHandler() {

    request.data.properties.title = fileToShare.name;

    request.data.properties.description = "Sharing a file from my app!";

    request.data.setStorageItems([fileToShare]);

}

If your app supports sharing images, we recommend that you set a thumbnail to go with each image.

We also recommend that you use both setBitmap and setStorageItems when sharing a single image—just in case the target app supports only one or the other. Because it might take some time to create a bitmap of the image, you need to set up an asynchronous way of adding it to the DataPackage object. You do this by creating a DataProviderDeferral object, which informs the target app that this is an asynchronous share.

Your app must call the complete method within 200 milliseconds. If you need more time, you should use a delegate.

function shareImageEventHandler() {

    request.data.properties.title = fileToShare.name;

    request.data.properties.description = "Sharing a images from my app!";

    request.data.properties.fileTypes = [".jpg", ".bmp", ".gif", ".png"];

   

    var streamReference = Windows.Storage.Streams.StreamReference.createFromFile(imageToShare);

    request.data.properties.thumbnail = streamReference;

 

    var deferral = request.getDeferral();

    imageToShare.openAsync(Windows.Storage.FileAccessMode.read).then(function (randomAccessStream) {

        request.data.setBitmap(randomAccessStream);

        deferral.complete();   

    });

}

Sharing and delegates

Sometimes, it might not make sense to prepare the data the user wants to share right away. For example, if your app supports several different data formats, it is inefficient to create those formats immediately. The better solution is to wait until the target app specifies the format that it wants, and then generate the data. To accomplish this, you configure the DataPackage object to call a function any time a target app requests a specific format.

mydataPackage.setDataProvider(StandardDataFormats.Bitmap, function (sender, args) {

    var deferral = args.deferral;

    imageToShare.openAsync(Windows.Storage.FileAccessMode.read).then(function (randomAccessStream) {

        sender.setBitmap(randomAccessStream);

        deferral.complete();

    });

});

The previous example works if the format in question is one of the following standard data formats:

  • Bitmap
  • Html
  • Rtf
  • StorageItems
  • Text
  • Uri

If you want to support other format types, that's pretty easy to do.

var myArray = new Array(1,2,3,4);

mydataPackage.setDataProvider("csv", function (sender, args) {

    sender.setText("csv", myArray.join(","));

});

mydataPackage.getDataAsync(".csv");

The important thing to remember is that both your app and the target app have to agree on the format name. If the names don't match, your function won't be called.

Programmatically invoking the share UI

For those situations in which using the charm isn't ideal—such as to share a high score on a game—you can also launch the Share charm programmatically.

function showShareUI() {

    Windows.ApplicationModel.DataTransfer.DataTransferManager.showShareUI();

}

Receiving shared content

Before your app can receive shared content, you have to declare that it supports the share target contract. This contract essentially lets the system know that your app is available to receive content. Open the Declarations tab. Choose Share Target from the Available Declarations list.

To specify the file types you support: In the Supported File Types section, click Add New. Type the file name extension that you want to support. For example, .docx. You need to include the period (.). If you want to support all file types, check the SupportsAnyFileType box.

To specify the data formats you support: In the Data Formats section, click Add New. Type the name of the data format you support. For example, "text".

When a user selects your app (usually by selecting it from a list of available target apps in the share UI), an application activated event is fired.

Windows.UI.WebUIApplication.addEventListener("activated", activatedHandler);

function activatedHandler(eventArgs) {

    if (eventArgs.kind === Windows.ApplicationModel.Activation.ActivationKind.shareTarget) {

        shareOperation = eventArgs.shareOperation;

        if (shareOperation.data.contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.text) {

            document.write("The title for this share is: " + shareOperation.data.properties.title);

            document.write("The description for this share is: " + shareOperation.data.properties.description);

            document.write("The text being shared is: " + shareOperation.data.getText());

        }

    }

}

Report extended share status (for lengthy operations)

In some cases, it can take time for your app to process the data wants to share. We call these situations extended shares. Examples of extended shares include users sharing collections of files or images.

As a target app, your app should not force the user to stay in the share UI just because your app needs more time to handle data. Instead, you should use the ShareOperation object to let the system know that your app is still working. That way, the user can dismiss the share UI and return to what they were doing. Meanwhile, your app continues to process the data in the background.

shareOperation.reportStarted();

With an extended share, it's possible that the user might dismiss the source app before your app has all the data from the DataPackage object. As a result, we recommend that you let the system know when your app has acquired the data it needs. This way, the system can suspend or terminate the source app as necessary.

shareOperation.reportDataRetreived();

It's also a good idea to let the system know if you're using the Upload APIs to upload your content. You can do this with the reportSubmittedBackgroundTask method.

shareOperation.reportSubmittedBackgroundTask();

If something goes wrong, you can also send an error message to the system. The user will see the message when they check on the status of the share.

shareOperation.reportError("Could not reach the server! Try again later.");

Report that sharing has been completed

shareOperation.reportCompleted();

Return a Quicklink object if sharing was successful

When a user selects your app to receive shared content, we highly recommend that you create a QuickLink. A QuickLink is like a shortcut that makes it easier for users to share information with your app. For example, your app could create a QuickLink that opens a new mail message pre-configured with a friend's email address.

A QuickLink must have a title, an icon, and an ID. The title (like "Email Mom") and icon appear when the user taps the Share charm. The ID is what your app uses to access any custom information, such as an email address or login credentials. When your app creates a QuickLink, the app returns the QuickLink to the system by calling the ShareOperation object's reportCompleted method.

function reportCompleted() {

    var quickLink = new Windows.ApplicationModel.DataTransfer.ShareTarget.QuickLink();

    quickLink.title = "Email Mom";

    quickLink.id = "ABC123";

    Windows.ApplicationMoel.Package.current.installedLocation.getFileAsync("images\\myQuickLinkImage.jpg").then(function (image) {

        quickLink.thumbnail = Windows.Storage.Streams.StreamReference.createFromFile(image);

        shareOperation.reportCompleted(quickLink);

    });

}

Remember that your app is responsible for storing the ID of the QuickLink and the corresponding user data. When the user taps the QuickLink, you can get its ID through the ShareOperation object.

function activatedHandler(eventArgs) {

    if (eventArgs.kind === Windows.ApplicationModel.Activation.ActivationKind.shareTarget) {

        shareOperation = eventArgs.shareOperation;

        if (shareOperation.data.contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.text) {

            if (shareOperation.quickLinkId !== "") {

                document.write("Thanks for using a QuickLink!");

            }

        }

    }

}

User experience

The user swipes from the side of the screen to display the charms, presses the share charm and the share window is displayed, as shown. The source application provides the requested content, and the metadata is displayed in the content preview. Quicklinks are deep links into target applications. Quicklinks and applications are displayed if they are relevant to the content provided by the source application.

image

The user launches a target application from the application list in the share window. The target application reads the content shared by the source application and displays a user interface that the user interacts with.

When the target application reports that the sharing operation has completed, it can return a quicklink that will be displayed in the share window.

User experience with lengthy operations

The user can switch to another application after sharing a large amount of content, and check on the progress of the sharing operation by opening the share window. The user selects the progress notification, which displays the progress window. The user chooses an operation from the list in the progress window, which displays the target application again.

imageimage

If a sharing operation fails to complete, the user receives an informative message from the application with steps to correct the problem when possible. This message is displayed by Windows.

Best practises

Source applications

  • When possible, include links to online versions of local content.If an application supports downloading content that is also available to everyone on the web, it could share links to the online content rather than copies of the downloaded content (f.e news app with articles). If you do not provide a website that enables everyone to view content, your application must share a copy of the content.
  • If your application supports sharing but a particular sharing operation cannot be completed for some reason, provide a message to be displayed in the share window that describes the steps that the user must take to correct the problem.
  • Don’t provide alternate ways to invoke sharing. Rely on the share charm and share window. Do not create a Share command on your app bar, or create a Share button in your application window or context menus.
  • Preseve user selections. Your app should preserve the user's selection even after the share flyout closes. This can help users if they want modify their selection, or share the same content to multiple targets.
  • You should provide a string that indicates what the user what they're sharing. For example, if the user is sharing a web page, include a string that has the URL of the page

Target applications

  • Keep the look and feel the same between your target app and your primary app. Align your target app with the design for your primary app, including elements like fonts, colors, and controls.
  • Avoid time-consuming or complex interactions in your target app. In most cases, actions like text formatting and tagging people in photos are best handled outside of the Share charm.
  • Avoid making your users navigate back and forth between multiple pages in your target app.
  • The Share UI already uses light dismiss. Including another light dismiss element in your target app can cause confusion with your users.
  • When a user taps the Share charm or invokes the Share UI, let them know that the system is responding to their action—for example, through an inline message—before closing the share pane. This helps give the user confidence that their share started successfully.
  • Put share buttons where users can reach them easily. We recommend putting share buttons on the right side of the screen, so users can reach them with their right thumbs.
  • Disable links that lead users away from the sharing experience. When a user is sharing content, you should take steps to ensure they remain in the sharing context. For example, if your app has links that lead to other areas of your app (such as to a home page), you should disable them so the user doesn't leave the sharing experience accidentally.
  • If your app includes a preview of what the user is sharing, that preview should match what will actually be shared as much as possible.

Streaming media to devices using PlayTo

You can use PlayTo to enable users to easily stream audio, video, or images from their computer to devices in their home network. For example, a user who is watching a video in your application can stream that video to their TV for everyone in the room to view. PlayTo streams audio, video, or images to DLNA compatible devices. PlayTo is part of the Connect charm. For applications that contain audio, video, or images, the user opens the Connect charm and is presented with devices from their home network that they can stream the media content to.

When a user selects a PlayTo target from the Connect charm, PlayTo raises the SourceRequested event. If PlayTo is streaming media from your application to a target device, PlayTo will continue to stream the media from your application to the target device even if your application is moved to the background while another application is active.

If your application enables users to view video or images, or to listen to audio, be sure to include PlayTo functionality in your application to also enable the user to stream the media to a remote device. Ensure that you enable the Connect charm in your application wherever you have audio, video, or image content available to the user.

Ensure that users can continue to navigate through your application once they have begun streaming media to a remote device by using PlayTo. To keep media streaming, you must ensure that the media element in your application remains within scope.

Because PlayTo is part of the Windows UI, do not require users to navigate to a specific page or screen of your application in order to use PlayTo.

// Save a reference to the current media element for PlayTo.

var mediaElement;

 

function id(tagName) {

    return document.getElementById(tagName);

}

 

function showDiv(divName) {

    id("audioDiv").style.display = "none";

    id("aplayer").src = null;

    id("imageDiv").style.display = "none";

    id("videoDiv").style.display = "none";

    id("vplayer").src = null;

 

    id(divName).style.display = "block";

 

    switch (divName) {

        case "audioDiv":

            mediaElement = id("aplayer");

            break;

        case "videoDiv":

            mediaElement = id("vplayer");

            break;

        case "imageDiv":

            mediaElement = id("iplayer");

            break;

    }

}

 

function videoButtonClick() {

    showDiv("videoDiv");

    getVideoFile(0);

}

 

function audioButtonClick() {

    showDiv("audioDiv");

    getAudioFile(0);

}

 

function imageButtonClick() {

    showDiv("imageDiv");

    getImageFile(0);

}

 

function stopButtonClick() {

    clearConnections();

}

 

function closeButtonClick() {

    WinJS.Application.stop;

    window.close();

}

 

function getVideoFile(fileIndex) {

    try {

        var videosLibrary = Windows.Storage.KnownFolders.videosLibrary;

        videosLibrary.getFilesAsync().then(function (resultLibrary) {

            if (resultLibrary.length > 0) {

                id("messageDiv").innerHTML +=

        "Play video: " + resultLibrary[fileIndex].fileName + "<br/>";

                id("vplayer").src = URL.createObjectURL(resultLibrary[fileIndex]);

                id("vplayer").play();

            }

        });

    } catch (ex) {

        id("messageDiv").innerHTML +=

    "Exception encountered: " + ex.message + "<br/>";

    }

}

 

function getAudioFile(fileIndex) {

    try {

        var musicLibrary = Windows.Storage.KnownFolders.musicLibrary;

        musicLibrary.getFilesAsync().then(function (resultLibrary) {

            if (resultLibrary.length > 0) {

                id("messageDiv").innerHTML +=

        "Play audio: " + resultLibrary[fileIndex].fileName + "<br/>";

                id("aplayer").src = URL.createObjectURL(resultLibrary[fileIndex]);

                id("aplayer").play();

            }

        });

    } catch (ex) {

        id("messageDiv").innerHTML +=

    "Exception encountered: " + ex.message + "<br/>";

    }

}

 

function getImageFile(fileIndex) {

    try {

        var picturesLibrary = Windows.Storage.KnownFolders.picturesLibrary;

        picturesLibrary.getFilesAsync().then(function (resultLibrary) {

            if (resultLibrary.length > 0) {

                id("messageDiv").innerHTML +=

        "Show image: " + resultLibrary[fileIndex].fileName + "<br/>";

                id("iplayer").src = URL.createObjectURL(resultLibrary[fileIndex]);

            }

        });

    } catch (ex) {

        id("messageDiv").innerHTML +=

    "Exception encountered: " + ex.message + "<br/>";

    }

} 

If media is already streaming when the user selects a different media source, then the connection is disconnected.

var ptm = Windows.Media.PlayTo.PlayToManager.getForCurrentView();

ptm.addEventListener("sourcerequested", sourceRequestHandler, false);

 

function sourceRequestHandler(e) {

    try {

        clearConnections();

 

        var sr = e.sourceRequest;

        var deferral = sr.getDeferral();

        var controller;

 

        try {

            controller = mediaElement.msPlayToSource;

        } catch (ex) {

            id("messageDiv").innerHTML +=

        "msPlaytoSource failed: " + ex.message + "<br/>";

        }

 

        sr.setSource(controller);

        deferral.complete();

 

    } catch (ex) {

 

        id("messageDiv").innerHTML +=

    "Exception encountered: " + ex.message + "<br/>";

    }

}

 

function clearConnections() {

    id("vplayer").msPlayToSource.connection.disconnect();

    id("aplayer").msPlayToSource.connection.disconnect();

    id("iplayer").msPlayToSource.connection.disconnect();

}

To run the application, you will need a target device to which PlayTo can stream media. If you do not have a DLNA compatible device to use as a PlayTo target, you can use Windows Media Player as a target device. In order to use Windows Media Player as a target device your computer must be connected to a private network, or a network with a domain.

  1. Start Windows Media Player.
  2. Expand the Stream menu and enable the Allow remote control of my Player... option. Leave Windows Media Player open; it must be running to be available as a PlayTo target.
  3. Open the Devices and Printers control panel. Click Add devices and printers. In the Add devices and printers wizard, in the Choose a device or printer to add to this PC window, locate the Digital media renderer for your PC. This is the Windows Media Player for your PC. Select it and click Next. When the wizard finishes, you will see your instance of Windows Media Player in the list of Multimedia Devices.

Proximity and tapping

Proximity enables you to connect computers with a simple tap gesture. If two computers come within 3-4 centimeters of each other, or are tapped together, the operating system of each computer becomes aware of the other computer. You can then connect the two computers together to share content such as photos or links, create a multi-player experience, or publish and subscribe to messages.

A computer must have a proximity device, for example a Near Field Communication (NFC) radio device, installed for proximity to be enabled.

For example, these applications might include a multi-player game where two users tap their computers together to establish a shared game session, or an application where customers can tap a computer and receive a link to a location where they can get more information or make a purchase.

You can use proximity to enable a quick exchange of data during a tap gesture, or you can use the tap to set up a long-term communication channel using TCP/IP, Wifi-Direct, or Bluetooth.

Proximity is supported by the classes in the Windows Runtime that are in the Windows.Networking.Proximity namespace. You can use the ProximityDevice class to communicate with other computers within a range of 3-4 centimeters and exchange a small payload of data during the tap. You can use the PeerFinder class to communicate with peer applications and set up a long-term socket connection. A peer application is another instance of an application running on a separate computer.

If a peer application is not running on a target computer, then proximity will launch the application on the target computer. If a peer application is not installed on a target computer, then proximity will direct the target computer to the application store to install the application.

function id(elementId) {

    return document.getElementById(elementId);

}

 

WinJS.Application.onmainwindowactivated = function (e) {

    if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {

        try {

            var proximityDevice = Windows.Networking.Proximity.ProximityDevice.getDefault();

            proximityDevice.addEventListener("ondevicearrived", proximityDeviceArrived, false);

            proximityDevice.addEventListener("ondevicedeparted", proximityDeviceDeparted, false);

        }

        catch (ex) {

            id("MessageBlock").innerHTML += "Failed to initialized proximity device.<br/>";

        }

    }

}

 

function proximityDeviceArrived() {

    id("MessageBlock").innerHTML += "Proximate device arrived.<br/>";

}

 

function proximityDeviceDeparted() {

    id("MessageBlock").innerHTML += "Proximate device departed.<br/>";

}

To support tapping in your application, you must enable the Proximity capability. If your application creates a connection as a result of a tap gesture, you must enable the Home/work Networking capability.

   function peerFinderButton_click() {

        try

        {

            Windows.Networking.Proximity.PeerFinder.onpeerconnectprogress = peerFinderConnectProgress;

            Windows.Networking.Proximity.PeerFinder.start();

            id("MessageBlock").innerHTML += "Start finding peers. Enter proximity to connect to a peer.<br/>";

        }

        catch (ex)

        {

            id("MessageBlock").innerHTML += "Failed to start finding peers.<br/>" + ex.toString() + "<br/>";

        }

    }

 

        function peerFinderConnectProgress(e) {

        try

        {

            var peerConnectProgressEventArgs = e.detail[0];

 

            if (peerConnectProgressEventArgs.connectState ==

                Windows.Networking.Proximity.PeerConnectState.connectComplete) {

 

                var proximitySocket = peerConnectProgressEventArgs.proximityStreamSocket;

                id("MessageBlock").innerHTML += "Connected To: " + proximitySocket.Information.RemoteHostName.DisplayName + "<br/>";

       

        // Created socket connection between peers.

                // See the Windows.Networking.Sockets.StreamSocket for more info on reading and writing to a StreamSocket

                // Always call close() when you are finished with the socket.

 

                proximitySocket.close();

            }

 

            if (peerConnectProgressEventArgs.connectState ==

                Windows.Networking.Proximity.PeerConnectState.connectFailed) {

 

                id("MessageBlock").innerHTML += "Failed to create a socket connection.<br/>";

            }

        }

        catch (ex)

        {

          id("MessageBlock").innerHTML += "Failed to start finding peers.<br/>";

        }

    }

Publishing and subscribing to tapping

Select the NearFieldProximity capability to enable proximity.

var proximityDevice = null;

 

function initializeProximityDevice() {

    try {

        if (proximityDevice === null) {

            proximityDevice = Windows.Networking.Proximity.ProximityDevice.getDefault();

        }

    } catch (e) {

        id("MessageBlock").innerHTML += "Failed to get default proximity device.<br/>";

 

        return false;

    }

 

    return true;

}

Always use the Windows prefix for proximity message types.

var publishedMessageId = -1;

var receivedMessageId = -1;

 

function publishMessageButton_click() {

    if (publishedMessageId != -1 )

        proximityDevice.stopPublishingMessage(publishedMessageId);

 

    publishedMessageId = proximityDevice.publishMessage("Windows.SampleMessageType", id("PublishMessageBlock").textContent);

    id("MessageBlock").innerHTML += "Proximity message published, enter proximity to transmit.<br/>";

}

 

function subscribeForMessageButton_click() {

    if (receivedMessageId != -1)

        proximityDevice.stopSubscribingForMessage(receivedMessageId);

 

    receivedMessageId = proximityDevice.subscribeForMessage("Windows.SampleMessageType", messageReceived);

    id("MessageBlock").innerHTML += "Subscribed for proximity message, enter proximity to receive.<br/>";

}

 

function messageReceived(proximityDevice, message) {

    id("ReceivedMessageBlock").innerHTML += "Message received: " + message.dataAsString;

}

Note that both the publish and subscribe functions stop publishing and subscribing before they start a new publication or subscription. This ensures that only one message is published or subscribed to at a time.

To see the application in action, run it on two computers that have proximity enabled.

Guidelines

Proximity is intended for an app that just wants a connection with another instance of itself, without being concerned about the details of the connection. If an app needs to get constant updates about the connection (for example: bandwidth usage, speed), then do not use proximity.

Always ask for user consent to start a connected proximity experience, that is, putting an app in multi-user mode. While users are running an application, asking for consent should be forward and dismissible. For example: two people playing a game are given a chance to provide consent before they decide to play together. In cases where a tap occurs as the app launches, users should be given a chance to provide consent in the start menu or lobby of the app.

When a user puts an app in multi-user mode, you should reflect one of three states in the UI:

  • Waiting for a tap
  • Connecting devices (show progress)
  • Devices now connected or connection failed

If a connection breaks or fails to establish, you should convey this information to users by putting the app back into single user mode and displaying a message to indicate that the connection has failed.

Ensure that users can easily navigate out of a proximity experience.

Don't use proximity if your app requires detail about the out-of-band connection.

c.d.n