wtorek, 3 kwietnia 2012

Notatki o Windows 8 Consumer Preview - odc. 6

Dzisiaj reszta ciekawostek na temat kafelków i notyfikacji.

O ile notyfikacje do kafelków secondary nie zaskakują, o tyle w przypadku notyfikacji toast można odnaleźć parę nowych szczegółów. Mamy wizualnie przedstawione wszystkie szablony z tekstem i mieszane (obrazek z tekstem). Można też odnaleźć informację o sposobie wskazania pliku obrazka także w przypadku notyfikacji dla aplikacji desktopowych! W przypadku kafelków na ekranie lock dowiadujemy się więcej - m.in jakie są rodzaje tasków w tle, które są z nimi powiązane. Notyfikacje wysyłane do kafelków square nie pojawiają się na ekranie lock, bo takie kafelki nie są tam używane. Planowane notyfikacje toast i tile wymagają identyfikatora, by można było je odwołać. Można użyć taski w tle/triggery do okresowego planowania. Dodatkowo mamy też notyfikacje periodyczne, które odpytują regularnie serwisy webowe o plik XML z zawartością kafelka. Odświeżanie pliku XML przez serwis powinno najlepiej odbywać się z taką samą częstotliwością jak odpytywanie. Przy tego rodzaju notyfikacji najlepiej nie używać kolejek (w tym przypadku brakuje obsługi identyfikatorów notyfikacji). Aby wysyłać notyfikacje push należy wykonać odpowiednie kroki na swoim koncie w Windows Store albo poprzez tymczasowy portal. Potrzebna jest autentykacja w WNS  (OAuth 2.0). Tego rodzaju notyfikacje mogą być z pewnymi ograniczeniami cachowane, jeśli urządzenie znajduje się w stanie off-line. Część rzeczy nadal nie jest udokumentowana np. notyfikacje raw. Nie zauważyłem znaczących różnic między JS a C#, z wyjątkiem tego że przy JS więcej tematów - także ogólnych, nie związanych z danym językiem - jest poruszonych, co zdaje się jest ogólną prawidłowością nie tylko przy notyfikacjach.

JS

Tiles & toast notifications

Secondary tile

var tileID = "SecondaryTile.01";var shortName = "A Secondary Tile"; var displayName = "An Example Secondary Tile"var tileOptions = Windows.UI.StartScreen.TileOptions.showName;var uriLogo = new Windows.Foundation.Uri("ms-appx:///images/SecondaryTileDefault-sdk.png");// As an example argument, we pass the time the secondary tile was pinned to the Start screen.var currentTime = new Date();var tileActivationArguments = "timeTileWasPinned=" + currentTime;

var tile = new Windows.UI.StartScreen.SecondaryTile(tileID, shortName, displayName, tileActivationArguments, tileOptions, uriLogo);

The example shown here specifies the foreground text color and overrides the default small logo, which is otherwise inherited from the parent app tile.

tile.foregroundText = Windows.UI.StartScreen.ForegroundText.dark;tile.smallLogo = new Windows.Foundation.Uri("ms-appx:///images/smallLogoSecondaryTile-sdk.png");

The user must confirm before a secondary tile is pinned. It is a best practice to display the Flyout that asks for this confirmation near the button, usually on the app bar, that invoked the pin request.

var element = document.getElementById("pinButton");var selectionRect = element.getBoundingClientRect();

tile.requestCreateAsync({ x: selectionRect.left, y: selectionRect.top }).then(function (isCreated) { if (isCreated) { // Secondary tile successfully pinned. } else { // Secondary tile not pinned. }});

Notifications to a secondary tile

We use the CreateTileUpdaterForSecondaryTile method, specific to secondary tiles. This step also requires the ID of the secondary tile that you're updating.

var updater = Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForSecondaryTile("SecondaryTile.01");

updater.update(tileNotification);

How to use the app bar to pin a secondary tile

When the user selects your button on the app bar, a Flyout appears asking for confirmation. To make sure that the app bar isn't dismissed while the Flyout is showing, set the app bar's WinJS.UI.sticky property.

Secondary tiles, like all tiles on the Start screen, are dynamic outlets that should be frequently updated with new content.

Sending toast notifications

var template = Windows.UI.Notifications.ToastTemplateType.toastImageAndText01;

var toastXml = Windows.UI.Notifications.ToastNotificationManager.getTemplateContent(template);

var toastTextElements = toastXml.getElementsByTagName("text"); toastTextElements[0].appendChild(toastXml.createTextNode("Hello World!")); var toastImageElements = toastXml.getElementsByTagName("image");toastImageElements[0].setAttribute("src", "ms-appx:///images/redWide.png"); toastImageElements[0].setAttribute("alt", "red graphic");

You can optionally set a display duration for your toast. There are two values: "short" and "long". Use "short" unless your notification is part of a scenario such as an incoming call or calendar reminder.

Note  The default duration is "short", so you normally would add this attribute only to set the duration to "long".

toastXml.setAttribute("duration", "long");

Specify toast audio

You can optionally specify audio that plays when your toast is displayed. If you do not specify an option, the default sound will be played. For more information, see Toast audio options.

var toastAudioElements = toastXml.getElementsByTagName("audio"); toastAudioElements[0].setAttribute("src", "ms-winsoundevent:Notification.IM"); toastAudioElements[0].setAttribute("loop", "false");

Specify app launch parameters

When the user clicks your toast notification, the expectation is that your app will be launched, with a view that relates to the content of the notification. To accomplish this, use the launch attribute of the toast element, which provides a string that is passed from the toast to the app when the app is launched through the toast. This string has no specific form and is app-defined. Your app must check for this string as an argument each time that it is activated adjust its view or operation accordingly.

toastXml.selectSingleNode("/toast").setAttribute("launch", '{"type":"toast","param1":"12345","param2":"67890"}');

Create the toast notification based on the XML content you've specified.

var toast = new Windows.UI.Notifications.ToastNotification(toastXml);

var toastNotifier = Windows.UI.Notifications.ToastNotificationManager.createToastNotifier(); toastNotifier.show(toast);

The background color applied to your toast notification is the background color declared for your app's tile in its app manifest.

The capability to raise toast notifications is declared in your app's package.appxmanifest file. If you use Microsoft Visual Studio 11 Express Beta for Windows 8, simply set the Toast Capable option to "Yes" in the Notifications section of the Application UI tab.

<VisualElements ... ToastCapable="true"></VisualElements>

Toast and tile notification background and text colors are always linked. If you use Visual Studio 11 Express Beta for Windows 8, select the Foreground Text option in the Tile section of the Application UI tab. Set the Background Color option with a W3DC color string (for example, "#FFFFFF").

The app's small logo image is displayed in the lower right corner of each toast notification, to identify to the user which app has raised it.

If you use Visual Studio 11 Express Beta for Windows 8, set the Small Logo image path in the Tile section of the Application UI tab. Preface the path with "images\", followed by the name of the file, such as "images\smallTile-sdk.png". The specified image must be included in the app's package.

Using toast templates

Text-only templates

ToastText01

ToastText01 example
ToastText02

ToastText02 example
ToastText03

ToastText03 example
ToastText04

ToastText04 example

Image-and-text templates

In this set of templates, the image element is expressed using one of these protocols:

  • http:// or https://

    A web-based image.

  • ms-appx:///

    An image included in the app package.

  • ms-appdata:///local/

    An image saved to local storage.

  • file:///

    A local image. (Only supported for desktop apps.)

ToastImageAndText01

ToastImageAndText01 example
ToastImageAndText02

ToastImageAndText02 example
ToastImageAndText03

ToastImageAndText03 example
ToastImageAndText04

ToastImageAndText04 example

The toast audio options catalog

When you specify one of these sounds in the audio element of the toast notification's XML payload, you must add the "ms-winsoundevent:" prefix.

<audio src="ms-winsoundevent:Notification.Mail" loop="false"/>

Only the system sounds listed in this topic can be used in a toast notification; the selections are not extensible.

Non-looping sounds

  • Notification.Default

    The sound that plays in the following situations:

    • When it is explicitly specified
    • When no other audio option is specified
    • When the specified audio option is invalid
    • When no other audio option fits your scenario
  • Notification.IM

    Scenario: A new instant messenger notification has arrived.

  • Notification.Mail

    Scenario: A new e-mail has arrived.

  • Notification.Reminder

    Scenario: An calendar item is due.

  • Notification.SMS

    Scenario: A new text message has arrived.

Looping sounds

The following sounds can optionally be looped until the notification is addressed.

Note  Looping audio requires that you set the duration attribute in the audio element's parent toast element to "long".

  • Notification.Looping.Alarm

    Scenario: A countdown stopwatch has reached 0.

  • Notification.Looping.Alarm2

    Scenario: A countdown stopwatch has reached 0.

  • Notification.Looping.Call

    Scenario: An incoming phone call.

  • Notification.Looping.Call2

    Scenario: An incoming phone call.

If looping audio is specified in the toast template but the source is invalid or not specified, the Notification.Looping.Call sound will be used.

To send a toast notification that does not play a sound upon arrival, you must set the silent attribute in the audio element to "true" as shown here. The audio element is required and cannot be simply omitted.

<audio silent="true"/>

var template = Windows.UI.Notifications.ToastTemplateType.toastText02var toastXml = Windows.UI.Notifications.ToastNotificationManager.getTemplateContent(template); var toastNode = toastXml.selectSingleNode("/toast");toastNode.setAttribute("duration", "long");var audio = toastXml.createElement("audio");audio.setAttribute("src", "ms-winsoundevent:Notification.Looping.Call"); audio.setAttribute("loop", "true"); toastNode.appendChild(audio);

Check the user settings

Possible cause: The user or administrator has disabled notifications through settings. Check the global notification on/off switch and the per-application on/off switches in the PC Settings -> Notifications page. As for the administrator, there are several group policies which can disable notifications.

http:// and https://
Images stored online

These images might be cached locally, so your image server might not receive a request for the image.

Displaying tiles on the lock screen

Lock screen capabilities are declared in your app's package.appxmanifest file. If you use Microsoft Visual Studio 11 Express Beta for Windows 8, simply choose the appropriate Lock Screen Notifications option in the Application UI tab.

The following example shows the XML that is inserted in the package.appxmanifest file as a result of the option choice. The LockScreen element is added as a child node of the manifest's VisualElements element.

<VisualElements ... <LockScreen Notification="badge" BadgeLogo="images\logo-lockscreen.png"/> ...</VisualElements>

An app with a lock screen presence must declare one of the following types of background tasks:

  • Control Channel
  • Timer
  • Push Notification

In Visual Studio 11 Express Beta for Windows 8, this value is set in the Declarations page of the manifest editor.

  1. Choose "Background Tasks" from the Available Declarations drop-down list.
  2. Click the Add button.
  3. Select the appropriate items from the Properties list and add any additional information required by your choices.

In the manifest's XML, this value is declared in the BackgroundTasks element.

If you chose the badgeAndTileText value in Step 1, you must specify a wide logo image as part of the app's default tile. If the user has set your tile on the lock screen and chosen it to display detailed status, a wide tile is used. Square tiles are not used on the lock screen, so tile notifications sent as square tiles are not seen on the lock screen.

After you complete the steps above, your tile is a candidate to be shown on the lock screen, should the user choose to show it. After the procedure detailed in this topic, your app is listed as a lock screen app in the Personalize category of PC settings. The user has the final choice of which of those apps to show on the lock screen, and which single one of them will show detailed status through text.

Delivering notifications

Scheduling notifications

How to schedule a toast notification

var currentTime = new Date();var startTime = new Date(currentTime.getTime() + 3 * 1000);

var scheduledToast = new Windows.UI.Notifications.ScheduledToastNotification(toastXml, startTime);

Give the scheduled toast notification an ID

This ID must be 16 characters or less, plus the terminating null character. It can be used later if you want to cancel the notification.

scheduledToast.id = "Future_Toast";

var toastNotifier = Windows.UI.Notifications.ToastNotificationManager.createToastNotifier(); toastNotifier.addToSchedule(scheduledToast);

Adding a toast notification that repeats at a specific interval

var template = Windows.UI.Notifications.ToastTemplateType.toastText02; var toastXml = notifications.ToastNotificationManager.getTemplateContent(template); // TODO: Fill in the template with your notification content. var currentTime = new Date(); var startTime = new Date(currentTime.getTime() + 1000); var recurringToast = new Windows.UI.Notifications.ScheduledToastNotification(toastXml, startTime, 60 * 1000, 5); recurringToast.id = "Recurring_Toast"; var toastNotifier = notifications.ToastNotificationManager.createToastNotifier(); toastNotifier.addToSchedule(recurringToast);

Consider using background tasks to update the schedule periodically using the MaintenanceTrigger class. For example, your app can initially schedule notifications a week in advance and then use the MaintenanceTrigger class to continue to schedule successive weeks on an ongoing basis, even without the user launching your app during any given week.

Consider using a timeZoneChange system trigger to respond to changes to the system clock, such as Daylight Savings Time. By default, scheduled notifications are triggered in coordinated universal time (UTC) and are not updated automatically in response to system clock changes. For example, a reminder app would need to change the scheduled time of the reminders when the system time changes. To do so, your app can use a background task that responds to the timeZoneChange trigger, adjusting its timing appropriately.

Both TileUpdater.addToSchedule and ToastNotifier.addToSchedule will fail if you attempt to schedule more than 4096 notifications.

Periodic notifications

How to set up periodic notifications for tiles

Step 1: Create or identify a web service to host the tile's XML content

At a specified interval, Windows will poll the specified web service for updated tile content for your app. The web service must support HTTP. For testing, you can also set up a web service, such as Microsoft Internet Information Services (IIS) on your local machine to test the XML.

Step 2: Place your tile content's XML file in a web-accessible location

Your web service will host the tile XML content. To get started, host the tile XML shown here on your web site. Save this content as a file named Tile.xml and place the file on the server in a web-accessible location (for example, http://www.fabrikam.com/tile.xml). The contents of the XML document must use a UTF-8 encoding and conform to the tile schema. You should update this XML at least as frequently as the specified polling recurrence interval.

Step 3: Begin the periodic updates

This example shows how to start polling the URL for new content once an hour. This code uses a previously defined variable called "polledUrl", which is a string that specifies the URL to be polled.

var notifications = Windows.UI.Notifications;var recurrence = notifications.PeriodicUpdateRecurrence.hour;var url = new System.Uri(polledUrl); notifications.TileUpdateManager.createTileUpdaterForApplication().startPeriodicUpdate(url, recurrence);

Call TileUpdater.startPeriodicUpdate each time the app is launched or switched to. This will cause the URL to be polled immediately and the tile to be updated at each app launch.

Periodic tile updates do not support the tile notification tag used with the notification queue. We recommended that tiles that use periodic notifications to update their content do not enable the notification queue.

Windows can delay the polling of your URL by up to 15 minutes if necessary to optimize power and performance.

Push notifications

Sending a tile/toast push notification

The accessToken parameter is the access token (stored on the server) that was received from WNS when the cloud server authenticated. Without the access token, you cannot send a notification.

protected string PostToCloud(string uri, string xml, string type = "wns/tile") { try { byte[] contentInBytes = Encoding.UTF8.GetBytes(xml); WebRequest webRequest = HttpWebRequest.Create(uri); HttpWebRequest request = webRequest as HttpWebRequest; webRequest.Method = "POST"; webRequest.Headers.Add("X-WNS-Type", type); webRequest.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken)); Stream requestStream = webRequest.GetRequestStream(); requestStream.Write(contentInBytes, 0, contentInBytes.Length); requestStream.Close(); HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); LogResponse(webResponse); return webResponse.StatusCode.ToString(); } catch (WebException webException) { string exceptionDetails = webException.Response.Headers["WWW-Authenticate"]; if (exceptionDetails.Contains("Token expired")) { getAccessToken(); OutPutInfo("Updated access token"); return PostToCloud(uri, xml, type); } else { LogResponse(webException.Response); return "EXCEPTION: " + webException.Message; } } catch (Exception ex) { return "EXCEPTION: " + ex.Message; }

How to request, create, and save a notification channel

Notification channels expire after 30 days.

var channel; var channelOperation = Windows.Networking.PushNotifications.PushNotificationChannelManager.createPushNotificationChannelForApplicationAsync(); return channelOperation.then(function (newChannel) { channel = newChannel; // Success. The channel URI is found in newChannel.uri. }, function (error) { // Could not create a channel. Retrieve the error through error.number. });

How to authenticate with the Windows Push Notification Service

Step 1: Register your app with the Dashboard

Before you can send notifications through WNS, you must register your app with the Dashboard, the developer portal that supports the end-to-end process for submitting, certifying, and managing applications for sale in the Windows Store. When you register your app with the Dashboard, you are given credentials—a Package security identifier (SID) and a secret key—which your cloud service will use to authenticate itself with WNS.

Step 2: Obtain the identity values for your app

When you reserved a name for your app, the Windows Store created your associated credentials. It also assigned identity values that must be present in your app's manifest file (package.appxmanifest): name and publisher. If you have already uploaded your app to the Windows Store, these values will have automatically been added to your manifest. If you have not uploaded your app, you will need to add the identity values to your manifest manually.

Step 3: Obtain the credentials for your app

Step 4: Send the cloud server's credentials to WNS

[DataContract] public class OAuthToken { [DataMember(Name = "access_token")] public string AccessToken { get; set; } [DataMember(Name = "token_type")] public string TokenType { get; set; } } OAuthToken GetOAuthTokenFromJson(string jsonString) { using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString))) { var ser = new DataContractJsonSerializer(typeof(OAuthToken)); var oAuthToken = (OAuthToken)ser.ReadObject(ms); return oAuthToken; } } protected void getAccessToken() { var urlEncodedSid = HttpUtility.UrlEncode(String.Format("{0}", this.sid)); var urlEncodedSecret = HttpUtility.UrlEncode(this.secret); var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com", urlEncodedSid, urlEncodedSecret); var client = new WebClient(); client.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); string response = client.UploadString("https://login.live.com/accesstoken.srf", body); var oAuthToken = GetOAuthTokenFromJson(response); this.accessToken = oAuthToken.AccessToken; }

Important: Testing with WNS if you do not have Windows Store access

If you have a Windows Store developer account, follow the instructions given above to register your app and retrieve WNS credentials. If you do not have a Windows Store developer account, the following instructions outline a temporary process that you can use to develop and test against WNS until the Windows Store becomes widely available.

The credentials generated through this temporary portal are for development purposes only and cannot be used to upload your app to the Windows Store.

Registering your app through the temporary portal

The temporary portal that you will use to register you app and receive your credentials is the Windows Live Application Management site. To access this site, you will need a Microsoft account.

Push notification service request and response headers

The authorization header is used to specify the credentials of the calling party, following the OAuth 2.0 authorization method for bearer tokens.

When the notification target device is offline, WNS will cache one badge and one tile notification per app. If notification cycling is enabled for the app, WNS will cache up to five tile notifications. Items are not held in the cache indefinitely and will be dropped after a reasonable period of time. Otherwise, the cached content is delivered when the device next comes online.

Your users can receive notifications at any time, even when their device is in a low power state.

Channel URLs can expire and are not guaranteed to remain the same each time you request one.

Your access token can be used to send multiple notifications. Therefore, your server should cache the access token so that it does not need to reauthenticate each time it wants to send a notification. If the token has expired, your app server will receive an error and you should authenticate your app server and retry the notification.

Raw notifications

C#

Secondary tiles

Rect pinButtonRect = GetElementRect((FrameworkElement)pinButton);// GetElementRect returns a Rect object that we can use to pin the tile.Rect GetElementRect(FrameworkElement element){ GeneralTransform buttonTransform = element.TransformToVisual(null); Point point = buttonTransform.TransformPoint(new Point()); return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));}

Brak komentarzy: