Configurar e usar notificações por push em aplicativos do SharePoint para Windows Phone

Crie uma solução no SharePoint Server para enviar notificações por push e desenvolva um aplicativo Windows Phone para receber as notificações.

Usando o serviço de notificação por Push (MPNS) da Microsoft, Windows Phone apps podem receber notificações via Internet dos eventos acionados em Microsoft SharePoint Server. O aplicativo de telefone não deve sondar o servidor para que as alterações, por exemplo, os itens em uma lista na qual o aplicativo de telefone se baseia. O aplicativo pode ser registrado para receber notificações de servidor e um receptor de evento pode iniciar uma notificação e enviá-la para o aplicativo receptor para o tratamento. A notificação por push é retransmitida para dispositivos Windows Phone por MPNS.

Windows Phone 7 não tem suporte para a execução simultânea de vários aplicativos. Que não seja os componentes do sistema operacional (SO) próprio Windows Phone, apenas um aplicativo pode ser executado no telefone por vez. Um evento relevante para um aplicativo de telefone determinado pode ocorrer (como, por exemplo, um item de lista que está sendo adicionado a uma lista) quando o aplicativo não está em execução em primeiro plano do telefone (ou seja, quando o aplicativo é marcado para exclusão ou fechado). Você pode desenvolver um serviço em segundo plano no telefone com uma tarefa periódica que pode verificar se há alterações feitas na lista no servidor, mas essa abordagem seria consomem recursos (por exemplo, a alimentação de bateria e largura de banda de rede) no telefone. Com MPNS e os componentes que oferecem suporte a notificações incorporadas ao sistema operacional Windows 7 telefone, o telefone em si pode receber uma notificação relevante para o contexto de um determinado aplicativo — mesmo quando esse aplicativo não está em execução — e o usuário pode ser fornecido a oportunidade para iniciar o aplicativo relevante em resposta à notificação. (Para obter mais informações sobre notificações por push, consulte Visão geral de notificações por push para Windows Phone no Biblioteca MSDN.)

Neste tópico, você cria uma solução do lado do servidor para enviar notificações por push para um aplicativo de telefone com base em uma alteração na lista na qual o aplicativo se baseia. Em seguida, você irá criar o aplicativo de telefone para receber essas notificações.

Criar uma solução do lado do servidor para enviar notificações de push com base em um evento de item de lista

A solução do lado do servidor pode ser um aplicativo do SharePoint implantado em um objeto SPWeb isolado ou uma solução farm do SharePoint empacotada como um pacote de solução do SharePoint (ou seja, um arquivo .wsp) que contém um Recurso com escopo da Web. Nos procedimentos desta seção, você desenvolverá uma solução simples do SharePoint que cria uma lista de destino a ser usada por um aplicativo Windows Phone e que ativa o mecanismo de notificação por push no servidor. Na seção subsequente, você desenvolverá o aplicativo Windows Phone para receber notificações da solução do lado do servidor.

Para criar o projeto do servidor

  1. Inicie o Visual Studio 2012 usando a opção Executar como administrador.

  2. Escolha arquivo, novoprojeto.

    Será exibida a caixa de diálogo Novo projeto.

  3. Na caixa de diálogo Novo projeto, expanda o nó do SharePoint em Visual c# e, em seguida, escolha o nó de 15.

  4. No painel Modelos , selecione Projeto do SharePoint e especifique um nome para o projeto, comoPushNotificationsList.

  5. Escolha o botão OK. O Assistente de personalização do SharePoint é exibida. Este assistente permite que você selecione o site de destino para desenvolver e depurar o projeto e o nível de confiança da solução.

  6. Especifique a URL de um site SharePoint Server. Selecione um site que você será capaz de usar mais tarde no desenvolvimento de aplicativo de lista do SharePoint para Windows Phone.

  7. Selecione implantar como uma solução de farm e clique em Concluir para criar o projeto.

Em seguida, adicione um arquivo de classe ao projeto e criar algumas classes para encapsular e gerenciar notificações de push.

Para criar as classes de gerenciamento de notificações por push

  1. No Solution Explorer, escolha o nó que representa o projeto (chamado PushNotificationsList se você seguir a convenção de nomenclatura usada nesses procedimentos).

  2. No menu projeto, escolha Adicionar classe. A caixa de diálogo Adicionar Novo Item aparece com o modelo de c# classe que já está selecionado.

  3. Especifique PushNotification.cs como o nome do arquivo e clique em Adicionar. O arquivo de classe é adicionado à solução e aberto para edição.

  4. Substitua o conteúdo do arquivo com o código a seguir.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Text;
    using Microsoft.SharePoint;
    
    namespace PushNotificationsList
    {
        internal static class WP7Constants
        {
            internal static readonly string[] WP_RESPONSE_HEADERS =
                {
                    "X-MessageID",
                    "X-DeviceConnectionStatus",
                    "X-SubscriptionStatus",
                    "X-NotificationStatus"
                };
        }
    
        public enum TileIntervalValuesEnum
        {
            ImmediateTile = 1,
            Delay450SecondsTile = 11,
            Delay900SecondsTile = 21,
        }
    
        public enum ToastIntervalValuesEnum
        {
            ImmediateToast = 2,
            Delay450SecondsToast = 12,
            Delay900SecondsToast = 22,
        }
    
        public enum RawIntervalValuesEnum
        {
            ImmediateRaw = 3,
            Delay450SecondsRaw = 13,
            Delay900SecondsRaw = 23
        }
    
        public enum NotificationTypeEnum
        {
            Tile = 1,
            Toast = 2,
            Raw = 3
        }
    
        class PushNotification
        {
            public PushNotificationResponse PushToast(SPPushNotificationSubscriber subscriber, string toastTitle, string toastMessage, string toastParam, ToastIntervalValuesEnum intervalValue)
            {
                // Construct toast notification message from parameter values.
                string toastNotification = "<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>" +
                "<wp:Notification xmlns:wp=\\"WPNotification\\">" +
                   "<wp:Toast>" +
                        "<wp:Text1>" + toastTitle + "</wp:Text1>" +
                        "<wp:Text2>" + toastMessage + "</wp:Text2>" +
                        "<wp:Param>" + toastParam + "</wp:Param>" +
                   "</wp:Toast> " +
                "</wp:Notification>";
    
                return SendPushNotification(NotificationTypeEnum.Toast, subscriber, toastNotification, (int)intervalValue);
            }
    
            public PushNotificationResponse PushRaw(SPPushNotificationSubscriber subscriber, string rawMessage, RawIntervalValuesEnum intervalValue)
            {
                return SendPushNotification(NotificationTypeEnum.Raw, subscriber, rawMessage, (int)intervalValue);
            }
    
            private PushNotificationResponse SendPushNotification(NotificationTypeEnum notificationType, SPPushNotificationSubscriber subscriber, string message, int intervalValue)
            {
                // Create HTTP Web Request object.
                string subscriptionUri = subscriber.ServiceToken;
                HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(subscriptionUri);
    
                // MPNS expects a byte array, so convert message accordingly.
                byte[] notificationMessage = Encoding.Default.GetBytes(message);
    
                // Set the notification request properties.
                sendNotificationRequest.Method = WebRequestMethods.Http.Post;
                sendNotificationRequest.ContentLength = notificationMessage.Length;
                sendNotificationRequest.ContentType = "text/xml";
                sendNotificationRequest.Headers.Add("X-MessageID", Guid.NewGuid().ToString());
    
                switch (notificationType)
                {
                    case NotificationTypeEnum.Tile:
                        sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "token");
                        break;
                    case NotificationTypeEnum.Toast:
                        sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "toast");
                        break;
                    case NotificationTypeEnum.Raw:
                        // A value for the X-WindowsPhone-Target header is not specified for raw notifications.
                        break;
                }
    
                sendNotificationRequest.Headers.Add("X-NotificationClass", intervalValue.ToString());
    
                // Merge byte array payload with headers.
                using (Stream requestStream = sendNotificationRequest.GetRequestStream())
                {
                    requestStream.Write(notificationMessage, 0, notificationMessage.Length);
                }
    
                string statCode = string.Empty;
                PushNotificationResponse notificationResponse;
    
                try
                {
                    // Send the notification and get the response.
                    HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
                    statCode = Enum.GetName(typeof(HttpStatusCode), response.StatusCode);
    
                    // Create PushNotificationResponse object.
                    notificationResponse = new PushNotificationResponse((int)intervalValue, subscriber.ServiceToken);
                    notificationResponse.StatusCode = statCode;
                    foreach (string header in WP7Constants.WP_RESPONSE_HEADERS)
                    {
                        notificationResponse.Properties[header] = response.Headers[header];
                    }
                }
                catch (Exception ex)
                {
                    statCode = ex.Message;
                    notificationResponse = new PushNotificationResponse((int)intervalValue, subscriber.ServiceToken);
                    notificationResponse.StatusCode = statCode;
                }
    
                return notificationResponse;
            }
        }
    
        /// <summary>
        /// Object used for returning notification request results.
        /// </summary>
        class PushNotificationResponse
        {
            private DateTime timestamp;
            private int notificationIntervalValue;
            private string statusCode = string.Empty;
            private string serviceToken;
            private Dictionary<string, string> properties;
    
            public PushNotificationResponse(int numericalIntervalValue, string srvcToken)
            {
                timestamp = DateTime.UtcNow;
                notificationIntervalValue = numericalIntervalValue;
                serviceToken = srvcToken;
                properties = new Dictionary<string, string>();
            }
    
            public DateTime TimeStamp
            {
                get { return timestamp; }
            }
    
            public int NotificationIntervalValue
            {
                get { return notificationIntervalValue; }
            }
    
            public string StatusCode
            {
                get { return statusCode; }
                set { statusCode = value; }
            }
    
            public string ServiceToken
            {
                get { return serviceToken; }
            }
    
            public Dictionary<string, string> Properties
            {
                get { return properties; }
            }
        }
    }
    
  5. Salve o arquivo.

Nesse código, os métodos PushToast e PushRaw levam argumentos de parâmetro apropriados para o tipo de dado de notificação para enviar, processar desses argumentos e então chamar o método SendPushNotification, que faz o trabalho de envio da notificação usando o serviço de notificação por Push da Microsoft. (Nesse código de exemplo, um método de envio de notificações de blocos não foi implementado.) A classe PushNotificationResponse é simplesmente um mecanismo para encapsular o resultado recebido da solicitação de notificação. Aqui, a classe adiciona algumas informações ao objeto (cast como um objeto HttpWebResponse ) retornadas pelo método GetResponse do objeto HttpWebRequest. O receptor de evento que você criar no procedimento a seguir usa esta classe PushNotificationResponse para atualizar uma lista de resultados de notificações no servidor.

Agora, crie uma classe de receptor de evento que enviará as notificações por push para dispositivos que foram registrados para recebê-las. (Você irá acoplar esse receptor de evento para a lista de trabalhos que é criada em um procedimento posterior).

Para criar a classe do receptor de evento para obter uma lista

  1. No Solution Explorer, escolha o nó que representa o projeto.

  2. No menu projeto, clique em Add Class. A caixa de diálogo Adicionar Novo Item aparece com o modelo de c# classe que já está selecionado.

  3. Especifique ListItemEventReceiver.cs como o nome do arquivo e clique em Adicionar. O arquivo de classe é adicionado à solução e aberto para edição.

  4. Substitua o conteúdo do arquivo com o código a seguir.

    using System;
    using System.Security.Permissions;
    using System.Text;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Utilities;
    
    namespace PushNotificationsList
    {
        /// <summary>
        /// List Item Events
        /// </summary>
        public class ListItemEventReceiver : SPItemEventReceiver
        {
            internal static string ResultsList = "Push Notification Results";
    
            /// <summary>
            /// An item was added.
            /// </summary>
            public override void ItemAdded(SPItemEventProperties properties)
            {
                SPWeb spWeb = properties.Web;
                SPPushNotificationSubscriberCollection pushSubscribers = spWeb.PushNotificationSubscribers;
                PushNotification pushNotification = new PushNotification();
    
                SPListItem listItem = properties.ListItem;
    
                string jobAssignment = "[Unassigned]";
    
                // This event receiver is intended to be associated with a specific list,
                // but the list may not have an "AssignedTo" field, so using try/catch here.
                try
                {
                    jobAssignment = listItem["AssignedTo"].ToString();
                }
                catch { }
    
                PushNotificationResponse pushResponse = null;
    
                foreach (SPPushNotificationSubscriber ps in pushSubscribers)
                {
                    // Send a toast notification to be displayed on subscribed phones on which the app is not running.
                    pushResponse = pushNotification.PushToast(ps, "New job for:", jobAssignment, string.Empty, ToastIntervalValuesEnum.ImmediateToast);
                    UpdateNotificationResultsList(spWeb, ps.User.Name, pushResponse);
    
                    // Also send a raw notification to be displayed on subscribed phones on which the app is running when the item is added.
                    pushResponse = pushNotification.PushRaw(ps, string.Format("New job for: {0}", jobAssignment), RawIntervalValuesEnum.ImmediateRaw);
                    UpdateNotificationResultsList(spWeb, ps.User.Name, pushResponse);
                }
    
                base.ItemAdded(properties);
            }
    
            private void UpdateNotificationResultsList(SPWeb spWeb, string subscriberName, PushNotificationResponse pushResponse)
            {
                SPList resultsList = spWeb.Lists.TryGetList(ResultsList);
    
                if (resultsList == null)
                    return;
    
                try
                {
                    SPListItem resultItem = resultsList.Items.Add();
                    resultItem["Title"] = subscriberName;
                    resultItem["Notification Time"] = pushResponse.TimeStamp;
                    resultItem["Status Code"] = pushResponse.StatusCode;
                    resultItem["Service Token"] = pushResponse.ServiceToken;
    
                    StringBuilder builder = new StringBuilder();
                    foreach (string key in pushResponse.Properties.Keys)
                    {
                        builder.AppendFormat("{0}: {1}; ", key, pushResponse.Properties[key]);
                    }
                    resultItem["Headers"] = builder.ToString();
    
                    resultItem["Interval Value"] = pushResponse.NotificationIntervalValue;
                    resultItem.Update();
                }
                catch
                {
                    // Could log to ULS here if adding list item fails.
                }
            }
        }
    }
    
  5. Salve o arquivo.

Nesse código, depois que um item é adicionado à lista à qual o receptor de evento estiver ligado, as notificações por push são enviadas para os assinantes que foram registrados para receber notificações. O valor do campo AssignedTo do item da lista adicionado é incluído na mensagem de notificação enviada aos assinantes. Para a notificação de proposta, os valores do parâmetro toastTitle (para o método de PushToast definido no procedimento anterior) e o parâmetro toastMessage são definidos. Esses valores correspondem às propriedades Text1 e Text2 no esquema XML que define as notificações de proposta.

Uma sequência vazia simplesmente está sendo passada como o valor do parâmetro toastParam, que corresponde à propriedade Param no esquema XML para notificações de proposta. Você poderia usar esse parâmetro para especificar, por exemplo, uma página do aplicativo telefone para abrir quando o usuário clica a notificação no telefone. No aplicativo de telefone de exemplo desenvolvido neste tópico para receber essas notificações do servidor, a propriedade Param não é usada. O formulário de lista (List.xaml) no aplicativo simplesmente é aberto quando o usuário clicar na notificação.

Observação

[!OBSERVAçãO] A propriedade Param para notificações de proposta é suportada somente no sistema operacional do Windows Phone 7.1 ou maior de versão.

Para a notificação bruta neste exemplo, uma cadeia de caracteres será passada que contém o valor do campo AssignedTo do item da lista adicionado.

Observe que a notificação de proposta será exibida se inscreveu telefones (se o aplicativo de telefone para o qual destina-se a notificação não está sendo executado) e a mensagem exibida será truncada se ela for maior que aproximadamente 41 caracteres. Notificações de brutas em MPNS estão limitadas a 1024 bytes (1 quilobyte). (O número exato de caracteres que pode ser enviado depende do tipo de codificação usado, como UTF-8). Notificações de blocos também estão sujeitos a limitações de tamanho. Grandes quantidades de dados não podem ser enviadas usando qualquer um dos tipos de notificações. O melhor uso dessas notificações não é como um mecanismo para transferência de dados, mas como uma maneira de enviar mensagens curtas para inscrito telefones para que certas ações podem ser realizadas no telefone. Essas ações, como atualização de uma lista no telefone com dados do servidor, podem envolver os maiores volumes de dados, dependendo do design do aplicativo do Windows Phone.

O objeto de PushNotificationResponse que é retornado por uma solicitação de notificação é passado para o método UpdateNotificationResultsList. Este método adiciona informações sobre a solicitação para uma lista do SharePoint denominada resultados de notificação de Push (se a lista existe). Isso é simplesmente uma demonstração de uma forma de usar o objeto retornado. Você pode colocar o objeto retornado para usos mais sofisticados em uma solução de produção. Por exemplo, você pode examinar o objeto retornado para códigos de status específico quando uma notificação é enviada para um determinado usuário (por exemplo, o usuário designado para a atribuição no campo AssignedTo) e executar a ação apropriada. Em um aplicativo de produção, você provavelmente não seria armazenar todas estas informações em uma lista no servidor. As informações estão sendo armazenadas aqui para ajudá-lo a entender as propriedades associadas ao notificações MPNS.

Em seguida, você pode criar uma simple lista do SharePoint, denominada trabalhos, que contém uma categoria de trabalho, uma descrição de um trabalho e a pessoa a quem o trabalho está atribuído. Além disso, você criar uma lista de auxiliar, denominada resultados de notificação de Push, para armazenar informações relacionadas a solicitações de notificação enviadas ao inscrevendo telefones.

O procedimento a seguir, você cria uma classe, ListCreator, que inclui um método CreateJobsList para criar e configurar a lista de trabalhos quando a solução é ativada no servidor. A classe também adiciona o receptor de evento ItemAdded (criado anteriormente na classe ListItemEventReceiver ) à coleção EventReceivers associada à lista. A classe ListCreator também inclui um método para criar a lista do SharePoint de resultados de notificação por Push.

Para criar uma classe para adicionar e configurar as listas

  1. No Solution Explorer, escolha o nó que representa o projeto (novamente, nomeado PushNotificationsList se você seguir a convenção de nomenclatura usada nesses procedimentos).

  2. No menu projeto, clique em Add Class. A caixa de diálogo Adicionar Novo Item aparece com o modelo de c# classe que já está selecionado.

  3. Especifique ListCreator.cs como o nome do arquivo e clique em Adicionar. O arquivo de classe é adicionado à solução e aberto para edição.

  4. Substitua o conteúdo do arquivo com o código a seguir.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using Microsoft.SharePoint;
    
    namespace PushNotificationsList
    {
        class ListCreator
        {
            internal void CreateJobsList(SPWeb spWeb)
            {
                string listTitle = "Jobs";
                string listDescription = "List of jobs and assignments.";
                Dictionary<string, SPFieldType> columns = new Dictionary<string, SPFieldType>();
    
                // The "Title" column will be added based on the GenericList template. That field
                // will be used as the category name for the job (e.g., Shopping), so only need to add
                // the remaining fields.
                columns.Add("Description", SPFieldType.Text);
                columns.Add("AssignedTo", SPFieldType.Text);
    
                // Creating list (or retrieving GUID for list if it already exists).
                Guid listId = CreateCustomList(spWeb, listTitle, listDescription, columns, false);
                if (listId.Equals(Guid.Empty))
                    return;
    
                SPList list = spWeb.Lists[listId];
    
                // Add event receiver (if the current Jobs list is not already associated with the receiver).
                bool ReceiverExists = false;
                string receiverClassName = "PushNotificationsList.ListItemEventReceiver";
    
                for (int i = 0; i < list.EventReceivers.Count; i++)
                {
                    SPEventReceiverDefinition rd = list.EventReceivers[i];
                    if (rd.Class == receiverClassName &amp;&amp; rd.Type == SPEventReceiverType.ItemAdded)
                    {
                        ReceiverExists = true;
                        break;
                    }
                }
    
                if (ReceiverExists == false)
                {
                    SPEventReceiverDefinition eventReceiver = list.EventReceivers.Add();
                    // Must specify information here for this specific assembly.
                    eventReceiver.Assembly = "PushNotificationsList,
                        Version=1.0.0.0, Culture=Neutral,
                        PublicKeyToken=[YOUR TOKEN VALUE HERE]";
                    eventReceiver.Class = receiverClassName;
                    eventReceiver.Name = "ItemAdded Event";
                    eventReceiver.Type = SPEventReceiverType.ItemAdded;
                    eventReceiver.SequenceNumber = 10000;
                    eventReceiver.Synchronization = SPEventReceiverSynchronization.Synchronous;
                    eventReceiver.Update();
                }
            }
    
            internal void CreateNotificationResultsList(SPWeb spWeb)
            {
                string listTitle = "Push Notification Results";
                string listDescription = "List for results from push notification operations.";
    
                Dictionary<string, SPFieldType> columns = new Dictionary<string, SPFieldType>();
                columns.Add("Notification Time", SPFieldType.Text);
                columns.Add("Status Code", SPFieldType.Text);
                columns.Add("Service Token", SPFieldType.Text);
                columns.Add("Headers", SPFieldType.Text);
                columns.Add("Interval Value", SPFieldType.Integer);
    
                // Creating the list for storing notification results.
                CreateCustomList(spWeb, listTitle, listDescription, columns, true);
            }
    
            /// <summary>
            /// Creates a SharePoint list (based on the Generic List template).
            /// </summary>
            /// <param name="spWeb">The target website for the list.</param>
            /// <param name="listTitle">The title of the list.</param>
            /// <param name="listDescription">A description for the list.</param>
            /// <param name="columns">A Dictionary object containing field names and types.</param>
            /// <param name="replaceExistingList">Indicates whether to overwrite an existing list of the same name on the site.</param>
            /// <returns>A GUID for the created (or existing) list.</returns>
            internal Guid CreateCustomList(SPWeb spWeb, string listTitle, string listDescription, Dictionary<string, SPFieldType> columns, bool replaceExistingList)
            {
                SPList list = spWeb.Lists.TryGetList(listTitle);
    
                if (list != null)
                {
                    if (replaceExistingList == true)
                    {
                        try
                        {
                            list.Delete();
                        }
                        catch
                        {
                            return Guid.Empty;
                        }
                    }
                    else
                    {
                        return list.ID;
                    }
                }
    
                try
                {
                    Guid listId = spWeb.Lists.Add(listTitle, listDescription, SPListTemplateType.GenericList);
                    list = spWeb.Lists[listId];
                    SPView view = list.DefaultView;
    
                    foreach (string key in columns.Keys)
                    {
                        list.Fields.Add(key, columns[key], false);
                        view.ViewFields.Add(key);
                    }
    
                    list.Update();
                    view.Update();
    
                    return listId;
                }
                catch
                {
                    return Guid.Empty;
                }
            }
        }
    }
    

    Certifique-se de especificar o valor apropriado de Token de chave pública para determinado seu assembly. Para adicionar uma ferramenta ao Visual Studio para obter o valor do Token de Chave Pública para seu assembly, consulte Como criar uma ferramenta para obter a chave pública de um assembly no Biblioteca MSDN. Observe que você terá que compilar o seu projeto pelo menos uma vez para poder obter o valor de Token de chave pública para o seu assembly de saída.

  5. Salve o arquivo.

Nesse código, o método CreateJobsList da classe ListCreator cria a lista (ou obtém a lista se ela existir no servidor) e vincula o receptor de evento criado em um procedimento anterior à lista por adicioná-lo à classe EventReceivers associada à lista. O método CreateNotificationResultsList cria a lista de resultados de notificação de Push.

Em seguida, adicionar um recurso ao seu projeto para executar operações de inicialização no servidor quando sua solução está implantada e ativada. Você pode adicionar uma classe de receptor de evento para o recurso de lidar com os eventos FeatureActivated e FeatureDeactivating.

Para adicionar um recurso ao seu projeto

  1. Em Visual Studio 2012, no menu Exibir, aponte para Other Windows e clique em Gerenciador de empacotamento.

  2. No Gerenciador de empacotamento, com o botão direito no nó que representa seu projeto e clique em Adicionar recursos. Um novo recurso (chamado "Feature1" por padrão) é adicionado ao seu projeto, sob um nó de recursos (no Solution Explorer ).

  3. Agora, no Solution Explorer, sob o nó de recursos, clique com o botão o recurso recém-adicionado (ou seja, Feature1 ) e clique em Adicionar receptor de evento. Um arquivo de classe do receptor de evento (Feature1.EventReceiver.cs) é adicionado ao recurso e aberto para edição.

  4. Dentro da implementação (delimitada por chaves de abertura e fechamento) da classe Feature1EventReceiver, adicione o código a seguir.

    internal const string PushNotificationFeatureId = "41E1D4BF-B1A2-47F7-AB80-D5D6CBBA3092";
    

    Essa variável de cadeia de caracteres armazena o identificador para o recurso de notificação de Push no servidor.

    Dica

    Você pode obter uma lista de identificadores exclusivos para os Recursos em um SharePoint Server executando o seguinte cmdlet Windows PowerShell: >Get-SPFeature | Sort -Property DisplayName> o recurso de notificação por push aparece como "PhonePNSubscriber" nos resultados retornados por este cmdlet.

  5. O arquivo de classe do receptor de eventos é criado com algumas declarações de método padrão para lidar com eventos de recurso. As declarações de método no arquivo são inicialmente comentadas. Substitua o método FeatureActivated no arquivo pelo código a seguir.

    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        base.FeatureActivated(properties);
        SPWeb spWeb = (SPWeb)properties.Feature.Parent;
    
        ListCreator listCreator = new ListCreator();
        listCreator.CreateJobsList(spWeb);
        listCreator.CreateNotificationResultsList(spWeb);
    
        // Then activate the Push Notification Feature on the server.
        // The Push Notification Feature is not activated by default in a SharePoint Server installation.
        spWeb.Features.Add(new Guid(PushNotificationFeatureId), false);
    }
    
  6. Substitua o método FeatureDeactivating no arquivo de código a seguir.

    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
        base.FeatureDeactivating(properties);
        SPWeb spWeb = (SPWeb)properties.Feature.Parent;
    
        // Deactivate the Push Notification Feature on the server
        // when the PushNotificationsList Feature is deactivated.
        spWeb.Features.Remove(new Guid(PushNotificationFeatureId), false);
    }
    
  7. Salve o arquivo.

Na implementação do manipulador de eventos FeatureActivated aqui, uma instância da classe ListCreator for instanciada e seus métodos CreateJobsList e CreateNotificationResultsList são chamados, usando o SPWeb onde o recurso é implantado e ativado como o local em que as listas serão criadas. Além disso, porque a funcionalidade de notificação de push não está habilitada por padrão em uma instalação padrão do SharePoint Server, o manipulador de eventos ativa o recurso de notificação de Push no servidor. No manipulador de eventos FeatureDeactivating, a funcionalidade de notificação de push é desativada quando o aplicativo foi desativado. Não é necessário lidar com esse evento. Você pode ou não deseja desativar as notificações por push no servidor quando o aplicativo é desativado, dependendo das circunstâncias da sua instalação e se outros aplicativos de destino site fazer uso das notificações por push.

Criar um aplicativo de lista do SharePoint do Windows Phone para receber notificações de push

Nesta seção, você cria um aplicativo do Windows Phone do modelo de aplicativo para Windows Phone SharePoint lista, especificando a lista do SharePoint criada na seção anterior, como a lista de destino para o aplicativo. Em seguida, desenvolver uma classe Notifications para se inscrever para notificações de push, a implementação de manipuladores de eventos de notificação e armazenar informações relacionadas às notificações no telefone. Você também pode adicionar uma página XAML para seu aplicativo com controles para permitir que usuários registrar ou cancelar o registro para notificações de push.

Para seguir os procedimentos nesta seção, primeiro execute as etapas no procedimento descrito em Como: Criar um aplicativo de lista Windows Phone SharePoint para criar um projeto do Visual Studio a partir do modelo Windows Phone Aplicativo de Lista do SharePoint, usando a lista de trabalhos criada na seção anterior como a lista de destino do SharePoint para o projeto. Para os fins dos procedimentos desta seção, presume-se o nome especificado para o projeto éSPListAppForNotifications.

Para criar a classe de gerenciamento de assinaturas e recebidas notificações

  1. No Solution Explorer, escolha o nó que representa o projeto (chamado SPListAppForNotifications).

  2. No menu projeto, clique em Add Class. A caixa de diálogo Adicionar Novo Item aparece com o modelo de c# classe que já está selecionado.

  3. Especifique "Notifications.cs" como o nome do arquivo e clique em Adicionar. O arquivo de classe é adicionado à solução e aberto para edição.

  4. Substitua o conteúdo do arquivo com o código a seguir.

    using System;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using Microsoft.Phone.Notification;
    using Microsoft.SharePoint.Client;
    using System.Diagnostics;
    using System.Collections.Generic;
    using Microsoft.Phone.Shell;
    using System.IO;
    using System.IO.IsolatedStorage;
    
    namespace SPListAppForNotifications
    {
        public class Notifications
        {
            static HttpNotificationChannel httpChannel;
            private const string RegStatusKey = "RegistrationStatus";
            public static string DeviceAppIdKey = "DeviceAppInstanceId";
            public static string ChannelName = "JobsListNotificationChannel";
            public static ClientContext Context { get; set; }
    
            public static void OpenNotificationChannel(bool isInitialRegistration)
            {
                try
                {
                    // Get channel if it was created in a previous session of the app.
                    httpChannel = HttpNotificationChannel.Find(ChannelName);
    
                    // If channel is not found, create one.
                    if (httpChannel == null)
                    {
                        httpChannel = new HttpNotificationChannel(ChannelName);
    
                        // Add event handlers. When the Open method is called, the ChannelUriUpdated event will fire.
                        // A call is made to the SubscribeToService method in the ChannelUriUpdated event handler.
                        AddChannelEventHandlers();
                        httpChannel.Open();
                    }
                    else
                    {
                        // The channel exists and is already open. Add handlers for channel events.
                        // The ChannelUriUpdated event won't fire in this case.
                        AddChannelEventHandlers();
    
                        // If app instance is registering for first time
                        // (instead of just starting up again), then call SubscribeToService.
                        if (isInitialRegistration)
                        {
                            SubscribeToService();
                        }
                    }
                }
                catch (Exception ex)
                {
                    ShowMessage(ex.Message, "Error Opening Channel");
                    CloseChannel();
                }
            }
    
            private static void AddChannelEventHandlers()
            {
                httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);
                httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ExceptionOccurred);
                httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);
                httpChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(httpChannel_HttpNotificationReceived);
            }
    
            private static void httpChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
            {
                UpdateChannelUriOnServer();
                SubscribeToService();
            }
    
            private static void httpChannel_ExceptionOccurred(object sender, NotificationChannelErrorEventArgs e)
            {
                // Simply showing the exception error.
                ShowMessage(e.Message, "Channel Event Error");
            }
    
            static void httpChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
            {
                if (e.Collection != null)
                {
                    Dictionary<string, string> collection = (Dictionary<string, string>)e.Collection;
                    ShellToast toast = new ShellToast();
                    toast.Title = collection["wp:Text1"];
                    toast.Content = collection["wp:Text2"];
    
                    // Note that the Show method for a toast notification won't
                    // display the notification in the UI of the phone when the app
                    // that calls the method is running (as the foreground app on the phone).
                    // toast.Show();
                   //Toast and Raw notification will be displayed if user is running the app. Be default only Toast notification
                   // will be displayed when the app is tombstoned
    
                    // Showing the toast notification with the ShowMessage method.
                    ShowMessage(string.Format("Title: {0}\\r\\nContent: {1}", toast.Title, toast.Content), "Toast Notification");
                }
            }
    
            static void httpChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
            {
                Stream messageStream = e.Notification.Body;
                string message = string.Empty;
    
                // Replacing NULL characters in stream.
                using (var reader = new StreamReader(messageStream))
                {
                    message = reader.ReadToEnd().Replace('\\0', ' ');
                }
    
                // Simply displaying the raw notification.
                ShowMessage(message, "Raw Notification");
            }
    
            private static void SubscribeToService()
            {
                Guid deviceAppInstanceId = GetSettingValue<Guid>(DeviceAppIdKey, false);
    
                Context.Load(Context.Web, w => w.Title, w => w.Description);
    
                PushNotificationSubscriber pushSubscriber = Context.Web.RegisterPushNotificationSubscriber(deviceAppInstanceId, httpChannel.ChannelUri.AbsoluteUri);
    
                Context.Load(pushSubscriber);
    
                Context.ExecuteQueryAsync
                    (
                        (object sender, ClientRequestSucceededEventArgs args) =>
                            {
                                SetRegistrationStatus(true);
    
                                // Indicate that tile and toast notifications can be
                                // received by phone shell when phone app is not running.
                                if (!httpChannel.IsShellTileBound)
                                    httpChannel.BindToShellTile();
    
                                if (!httpChannel.IsShellToastBound)
                                    httpChannel.BindToShellToast();
    
                                ShowMessage(
                                    string.Format("Subscriber successfully registered: {0}", pushSubscriber.User.LoginName),
                                    "Success");
                            },
                        (object sender, ClientRequestFailedEventArgs args) =>
                            {
                                ShowMessage(args.Exception.Message, "Error Subscribing");
                            });
            }
    
            private static void UpdateChannelUriOnServer()
            {
                Guid deviceAppInstanceId = GetSettingValue<Guid>(DeviceAppIdKey, false);
    
                Context.Load(Context.Web, w => w.Title, w => w.Description);
    
                PushNotificationSubscriber subscriber = Context.Web.GetPushNotificationSubscriber(deviceAppInstanceId);
    
                Context.Load(subscriber);
    
                Context.ExecuteQueryAsync(
                        (object sender1, ClientRequestSucceededEventArgs args1) =>
                        {
                            subscriber.ServiceToken = httpChannel.ChannelUri.AbsolutePath;
                            subscriber.Update();
                            Context.ExecuteQueryAsync(
                                (object sender2, ClientRequestSucceededEventArgs args2) =>
                                    {
                                        ShowMessage("Channel URI updated on server.", "Success");
                                    },
                                (object sender2, ClientRequestFailedEventArgs args2) =>
                                    {
                                        ShowMessage(args2.Exception.Message, "Error Upating Channel URI");
                                    });
                        },
                       (object sender1, ClientRequestFailedEventArgs args1) =>
                       {
                           // This condition can be ignored. Getting to this point means the subscriber
                           // doesn't yet exist on the server, so updating the Channel URI is unnecessary.
                           //ShowMessage("Subscriber doesn't exist on server.", "DEBUG");
                       });
            }
    
            public static void UnSubscribe()
            {
                Context.Load(Context.Web, w => w.Title, w => w.Description);
                Guid deviceAppInstanceId = GetSettingValue<Guid>(DeviceAppIdKey, false);
    
                Context.Web.UnregisterPushNotificationSubscriber(deviceAppInstanceId);
    
                Context.ExecuteQueryAsync
                    (
                        (object sender, ClientRequestSucceededEventArgs args) =>
                        {
                            CloseChannel();
                            SetRegistrationStatus(false);
                            //SetInitializationStatus(false);
                            ShowMessage("Subscriber successfully unregistered.", "Success");
                        },
                        (object sender, ClientRequestFailedEventArgs args) =>
                        {
                            ShowMessage(args.Exception.Message, "Error Unsubscribing");
                        });
            }
    
            public static void ClearSubscriptionStore()
            {
                Context.Load(Context.Web, w => w.Title, w => w.Description);
                List subscriptionStore = Context.Web.Lists.GetByTitle("Push Notification Subscription Store");
                Context.Load(subscriptionStore);
                ListItemCollection listItems = subscriptionStore.GetItems(new CamlQuery());
                Context.Load(listItems);
    
                Context.ExecuteQueryAsync
                    (
                        (object sender1, ClientRequestSucceededEventArgs args1) =>
                        {
                            foreach (ListItem listItem in listItems.ToList())
                            {
                                listItem.DeleteObject();
                            }
                            Context.ExecuteQueryAsync(
                                    (object sender2, ClientRequestSucceededEventArgs args2) =>
                                    {
                                        // Close channel if open and set registration status for current app instance.
                                        CloseChannel();
                                        SetRegistrationStatus(false);
    
                                        ShowMessage("Subscriber store cleared.", "Success");
                                    },
                                    (object sender2, ClientRequestFailedEventArgs args2) =>
                                    {
                                        ShowMessage(args2.Exception.Message, "Error Deleting Subscribers");
                                    });
                        },
                        (object sender1, ClientRequestFailedEventArgs args1) =>
                        {
                            ShowMessage(args1.Exception.Message, "Error Loading Subscribers List");
                        });
            }
    
            private static void CloseChannel()
            {
                if (httpChannel == null) return;
                try
                {
                    httpChannel.UnbindToShellTile();
                    httpChannel.UnbindToShellToast();
                    httpChannel.Close();
                }
                catch (Exception ex)
                {
                    ShowMessage(ex.Message, "Error Closing Channel");
                }
            }
    
            public static void SaveDeviceAppIdToStorage()
            {
                if (!IsolatedStorageSettings.ApplicationSettings.Contains(DeviceAppIdKey))
                {
                    Guid DeviceAppId = Guid.NewGuid();
                    SetSettingValue<Guid>(DeviceAppIdKey, DeviceAppId, false);
                }
            }
    
            public static bool GetRegistrationStatus()
            {
                bool status = GetSettingValue<bool>(RegStatusKey, false);
                return status;
            }
    
            private static void SetRegistrationStatus(bool isRegistered)
            {
                SetSettingValue<bool>(RegStatusKey, isRegistered, false);
            }
    
            private static T GetSettingValue<T>(string key, bool fromTransientStorage)
            {
                if (fromTransientStorage == false)
                {
                    if (IsolatedStorageSettings.ApplicationSettings.Contains(key))
                        return (T)IsolatedStorageSettings.ApplicationSettings[key];
                    return default(T);
                }
    
                if (PhoneApplicationService.Current.State.ContainsKey(key))
                    return (T)PhoneApplicationService.Current.State[key];
                return default(T);
            }
    
            private static void SetSettingValue<T>(string key, T value, bool toTransientStorage)
            {
                if (toTransientStorage == false)
                {
                    if (IsolatedStorageSettings.ApplicationSettings.Contains(key))
                        IsolatedStorageSettings.ApplicationSettings[key] = value;
                    else
                        IsolatedStorageSettings.ApplicationSettings.Add(key, value);
    
                    IsolatedStorageSettings.ApplicationSettings.Save();
                }
                else
                {
                    if (PhoneApplicationService.Current.State.ContainsKey(key))
                        PhoneApplicationService.Current.State[key] = value;
                    else
                        PhoneApplicationService.Current.State.Add(key, value);
                }
            }
    
            // Method for showing messages on UI thread coming from a different originating thread.
            private static void ShowMessage(string message, string caption)
            {
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show(message, caption, MessageBoxButton.OK);
                });
            }
        }
    }
    
  5. Salve o arquivo.

Nesse código, o OpenNotificationChannel cria um canal de notificação para receber notificações de MPNS. Manipuladores de eventos estão anexados ao objeto canal para lidar com eventos de notificação e, em seguida, o canal for aberto. Neste exemplo, o evento HttpNotificationReceived (para receber notificações brutas) é implementado. Notificações brutas podem ser recebidas somente quando o aplicativo de telefone está sendo executado. O manipulador do evento ShellToastNotificationReceived (para receber notificações de proposta) também é implementado aqui para demonstrar o seu uso. Notificações de blocos podem ser recebidas somente quando o aplicativo de telefone inscritos não estiver funcionando, portanto não é necessário para implementar um manipulador de eventos do aplicativo para receber notificações de blocos em.

O método SubscribeToService executa o método RegisterPushNotificationSubscriber do objeto SPWeb de forma assíncrona (passando um valor para identificar o aplicativo de telefone e um valor URI associado com o canal de notificação) para registrar com o SharePoint Server para receber notificações por push. Se o registro for bem-sucedida, o Windows Phone shell estiver definida como receber (e exibir) brindar e notificações sobre o canal de notificação específico registrado com o SharePoint Server quando o próprio aplicativo de telefone não está sendo executado lado a lado.

O método UnSubscribe nesse código chama o método UnregisterPushNotificationSubscriber do objeto SPWeb. As diretrizes de desenvolvimento para aplicativos do Windows Phone recomendam que os usuários poderá optar se deseja inscrever-se para notificações de push ou não. Em um procedimento posterior, você adicionará um mecanismo para o usuário registrar ou cancelar o registro para notificações e esse estado do registro é preservado entre sessões do aplicativo, tornando desnecessárias pedir registrar toda vez que o aplicativo é iniciado. O método GetRegistrationStatus é disponibilizado para que o aplicativo de telefone possa determinar se o usuário foi registrado (em uma sessão anterior) para receber notificações por push e o canal de notificação subsequentemente é aberto. O SaveDeviceAppIdToStorage salva o identificador (representado como um GUID) para a instância do aplicativo em um determinado Windows Phone para armazenamento isolado.

O método ClearSubscriptionStore está incluído aqui como uma demonstração de uma das maneiras de desmarcar os assinantes do repositório de inscrição no SharePoint Server. Os assinantes de notificações por push são armazenados em uma lista do SharePoint denominada "Repositório de inscrições de notificação de Push". Um botão para chamar esse método da classe Notifications é adicionado à página de configurações do notificações adicionada para o aplicativo em um procedimento posterior.

Observe que as operações que envolvem acessando o SharePoint Server para definir as configurações ou preparar para notificações (por exemplo, o método RegisterPushNotificationSubscriber ) podem levar tempo para ser concluída, dependendo das condições da rede e a acessibilidade do servidor. Essas operações, portanto, são executadas de forma assíncrona (especificamente, usando o método ExecuteQueryAsync de um objeto ClientContext ) para permitir que o aplicativo para continuar a outros processos e manter a interface do usuário respondendo de forma ao usuário.

Em seguida, adicione uma página para o aplicativo com controles que permitem que um usuário registrar para ou cancelar o registro de notificações de envio do servidor.

Para adicionar uma página de configurações de notificação para o aplicativo

  1. No Solution Explorer, escolha o nó que representa o projeto (chamado SPListAppForNotifications se você seguir a convenção de nomenclatura destes procedimentos).

  2. No menu projeto, clique em Adicionar Novo Item. Será exibida a caixa de diálogo Adicionar Novo Item.

  3. No painel de modelos, escolha o modelo de Página do Windows Phone retrato. Especifique Settings.xaml como o nome do arquivo para a página e clique em Adicionar. A página é adicionada ao projeto e aberta para edição.

  4. No modo de exibição XAML para a página, substitua o conteúdo entre o colchete de fechamento da marca XML que define o elemento PhoneApplicationPage e a marca de fechamento do elemento ( </phone:PhoneApplicationPage>), a seguinte marcação.

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="JOBS LIST" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Settings" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
    
        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel Margin="0,5,0,5">
                <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                    <TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Style="{StaticResource PhoneTextTitle2Style}">Notification Registration</TextBlock>
                    <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                        <TextBlock x:Name="txtRegistrationStatus" TextWrapping="Wrap" HorizontalAlignment="Center" Text="Registered: No" Style="{StaticResource PhoneTextAccentStyle}" Foreground="{StaticResource PhoneAccentBrush}" />
                        <Button x:Name="btnRegister" Content="Register" Height="71" Width="260" Click="OnRegisterButtonClick" />
                        <Button x:Name="btnUnregister" Content="Unregister" Height="71" Width="260" Click="OnUnregisterButtonClick" />
                    </StackPanel>
                </StackPanel>
                <StackPanel Orientation="Vertical" Margin="0,5,0,5">
                    <TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Style="{StaticResource PhoneTextTitle2Style}">Subscriber Management</TextBlock>
                    <Button x:Name="btnDeleteSubscribers" Content="Delete Subscribers" Height="71" Width="260" Click="OnDeleteSubscribersButtonClick" />
                </StackPanel>
            </StackPanel>
        </Grid>
    </Grid>
    
    <!--Sample code showing usage of ApplicationBar-->
    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <shell:ApplicationBarIconButton x:Name="btnOK" IconUri="/Images/appbar.check.rest.png" Text="OK" Click="OnOKButtonClick" />
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
    
  5. Com o arquivo de Settings.xaml selecionado no Solution Explorer, pressioneF7Para abrir o seu arquivo code-behind associado, Settings.xaml.cs, para edição.

  6. Substitua o conteúdo do arquivo code-behind o código a seguir.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using Microsoft.Phone.Controls;
    using Microsoft.SharePoint.Client;
    
    namespace SPListAppForNotifications
    {
        public partial class Settings : PhoneApplicationPage
        {
            private const string RegisteredYesText = "Registered: Yes";
            private const string RegisteredNoText = "Registered: No";
    
            public Settings()
            {
                InitializeComponent();
            }
    
            protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
                this.txtRegistrationStatus.Text = (Notifications.GetRegistrationStatus()) ? RegisteredYesText : RegisteredNoText;
            }
    
            private void OnOKButtonClick(object sender, EventArgs e)
            {
                NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative));
            }
    
            private void OnRegisterButtonClick(object sender, RoutedEventArgs e)
            {
                Notifications.OpenNotificationChannel(true);
                // Navigating back to List form. User will be notified when process is complete.
                NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative));
            }
    
            private void OnUnregisterButtonClick(object sender, RoutedEventArgs e)
            {
                Notifications.UnSubscribe();
                // Navigating back to List form. User will be notified when process is complete.
                NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative));
            }
    
            private void OnDeleteSubscribersButtonClick(object sender, RoutedEventArgs e)
            {
                Notifications.ClearSubscriptionStore();
                // Navigating back to List form. User will be notified when process is complete.
                NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative));
            }
        }
    }
    
  7. Salve o arquivo.

  8. Para adicionar o arquivo de imagem (appbar.check.rest.png) para o botão ApplicationBar (btnOK) declarado no arquivo Settings.xaml ao seu projeto, escolha o nó da pasta de imagens no Solution Explorer.

  9. No menu projeto, clique em Adicionar Item existente. Uma janela do Navegador de arquivo é aberto.

  10. Navegue até a pasta na qual as imagens de ícone padrão do Windows Phone foram instaladas pelo SDK do Windows Phone 7.1.

    Observação

    As imagens com um primeiro plano claro e um plano de fundo escuro estão em %PROGRAMFILES%(x86)\Microsoft SDKs\Windows Phone\v7.1\Icons\dark em uma instalação padrão do SDK.

  11. Escolha o arquivo de imagem denominado appbar.check.rest.png e clique em Adicionar. A imagem está adicionada é adicionado ao projeto sob o nó de imagens.

  12. No Solution Explorer, escolha o arquivo de imagem apenas adicionado e na Janela Propriedades do arquivo, defina a propriedade Build Action para o arquivo de imagem para "Content" e defina a propriedade de cópia para o diretório de saída para "Copiar se mais recente".

Em seguida, adicione um botão para o formulário de lista (List.xaml) no projeto e implementar o manipulador de eventos de Click do botão para navegar até a página de configurações criada nas etapas anteriores. Também modifica o manipulador de eventos OnViewModelInitialization para abrir um canal de notificação (se o usuário ter optado assinar notificações por push).

Para modificar o formulário de lista

  1. No Solution Explorer, sob o nó exibições, clique duas vezes no arquivo List.xaml. O arquivo é aberto para edição.

  2. Adicione marcação para declarar um botão adicional no elemento ApplicationBar do arquivo, como no exemplo a seguir.

    ...
    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
            <shell:ApplicationBarIconButton x:Name="btnNew"
                   IconUri="/Images/appbar.new.rest.png" Text="New"
                    Click="OnNewButtonClick" />
            <shell:ApplicationBarIconButton x:Name="btnRefresh"
                    IconUri="/Images/appbar.refresh.rest.png" Text="Refresh" IsEnabled="True"
                    Click="OnRefreshButtonClick" />
            <shell:ApplicationBarIconButton x:Name="btnSettings" IconUri="/Images/appbar.feature.settings.rest.png" Text="Settings" IsEnabled="True" Click="OnSettingsButtonClick" />
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
    ...
    
  3. Com o arquivo de List.xaml selecionado no Solution Explorer, pressioneF7Para abrir o seu arquivo code-behind associado, List.xaml.cs, para edição.

  4. Dentro do bloco de código (delimitado abrindo e fechando chaves) que implementa a classe parcial ListForm, adicione o manipulador de eventos a seguir ao arquivo.

    private void OnSettingsButtonClick(object sender, EventArgs e)
    {
        NavigationService.Navigate(new Uri("/Settings.xaml", UriKind.Relative));
    }
    
  5. Localize o OnViewModelInitialization no arquivo List.xaml.cs e adicione uma chamada para o método OpenNotificationChannel da classe Notifications criada anteriormente. A implementação de modificação do manipulador deve se parecer com o código a seguir.

    private void OnViewModelInitialization(object sender, InitializationCompletedEventArgs e)
    {
        this.Dispatcher.BeginInvoke(() =>
        {
            //If initialization has failed, show error message and return
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message, e.Error.GetType().Name, MessageBoxButton.OK);
                return;
            }
    
            App.MainViewModel.LoadData(((PivotItem)Views.SelectedItem).Name);
            this.DataContext = (sender as ListViewModel);
        });
    
        // Open notification channel here if user has chosen to subscribe to notifications.
        if (Notifications.GetRegistrationStatus() == true)
            Notifications.OpenNotificationChannel(false);
    }
    
  6. Salve o arquivo.

  7. Para adicionar o arquivo de imagem (appbar.feature.settings.rest.png) para o botão ApplicationBar (btnSettings) declarado no arquivo List.xaml ao seu projeto, escolha o nó da pasta de imagens no Solution Explorer.

  8. No menu projeto, clique em Adicionar Item existente. Uma janela do Navegador de arquivo é aberto.

  9. Navegue até a pasta na qual as imagens de ícone padrão do Windows Phone foram instaladas pelo SDK do Windows Phone 7.1. (Consulte a observação no procedimento anterior para o local dos arquivos de imagem em uma instalação padrão do SDK).

  10. Escolha o arquivo de imagem denominado appbar.feature.settings.rest.png e clique em Adicionar. A imagem está adicionada é adicionado ao projeto sob o nó de imagens.

    1. No Solution Explorer, escolha o arquivo de imagem apenas adicionado e na Janela Propriedades do arquivo, defina a propriedade Build Action para o arquivo de imagem para "Content" e defina a propriedade de cópia para o diretório de saída para "Copiar se mais recente".

Finalmente, adicione o código para o manipulador de eventos Application_Launching no arquivo App.xaml.cs para preparar o aplicativo para receber notificações de push, usando as propriedades e métodos da classe Notifications criada anteriormente.

Para adicionar código para o arquivo App.xaml.cs

  1. No Solution Explorer, sob o nó que representa o projeto, escolha o arquivo de App.

  2. PressioneF7Para abrir o seu arquivo code-behind associado, App.xaml.cs, para edição.

  3. Localize o manipulador de eventos Application_Launching no arquivo. (Para novos projetos criados usando o modelo de aplicativo para Windows Phone SharePoint lista, a assinatura para o método que manipula o evento Application_Launching é incluída mas nenhuma lógica é implementada no método).

  4. Substitua o manipulador de eventos Application_Launching o código a seguir.

    private void Application_Launching(object sender, LaunchingEventArgs e)
    {
        // Get set up for notifications.
        Notifications.Context = App.DataProvider.Context;
        Notifications.SaveDeviceAppIdToStorage();
    }
    
  5. Salve o arquivo.

Se você compile o projeto e implantar o aplicativo para o emulador do Windows Phone para executá-lo, você pode clique no botão configurações da Barra do aplicativo para exibir uma página a partir do qual você pode registrar para notificações de push (Figura 1).

Figura 1. Settings page for notification registration

Settings page for notification registration

Se você tiver implantado e ativado a solução PushNotificationsList (desenvolvida na seção Criar uma solução do lado do servidor para enviar notificações de push com base em um evento de item de lista anteriormente neste tópico) para seu destino SharePoint Server e se o registro do telefone para notificações for bem-sucedida, você pode adicionar um item à lista de trabalhos no servidor e você deverá receber ambas uma notificação de proposta (Figura 2) e , se o aplicativo estiver em execução no telefone quando o item é adicionado à lista, uma notificação bruta (Figura 3).

Figura 2. Toast notification (app running)

Toast notification (app running)

A mensagem exibida quando o seu aplicativo recebeu uma notificação de proposta enquanto ele é executado depende de como você implementou o manipulador de eventos ShellToastNotificationReceived no seu aplicativo. Na classe Notifications para este exemplo, o título e o conteúdo da mensagem simplesmente são exibidos ao usuário.

Figura 3. Raw notification

Raw notification

Se o aplicativo não estiver em execução quando o item é adicionado à lista, o telefone ainda deve exibir uma notificação de proposta (Figura 4).

Figura 4. Toast notification (app not running)

Toast notification (app not running)

Quando você adiciona um item à lista do SharePoint de trabalhos, o código no caso de receptor associada à lista tenta enviar notificações usando MPNS para inscreveu telefones, mas, dependendo das condições de rede e outros fatores, uma notificação de determinado não pode ser recebida por um telefone. Você pode consultar a lista de resultados de notificação de Push no servidor, especialmente os valores nas colunas cabeçalhos e código de Status, para determinar o status e os resultados relacionados às notificações individuais.

Confira também