Windows Phone 72011.05.27 18:43

마지막이다.

 

이제 메세지를 보낼 UI를 만들어보자 관리자를 위한 프로그램이다

 

난 그냥 쉬운 WPF로 만들었다.

 

일단 버튼 하나 만들고

 

private void ToastButton_Click(object sender, RoutedEventArgs e)
      {
          string appId = "1";
          //string baseUri = string.Format("http://localhost:19976/Notifications/GetSubscribers?appId={0}", appId);
          string baseUri = string.Format("http://192.168.10.174:6060/Notifications/GetSubscribers?appId={0}", appId);
 
          GetSubscribers(baseUri);
          
      }

 

 

private void GetSubscribers(string baseUri)
     {
         WebClient webclient = new WebClient();
         webclient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(webclient_DownloadDataCompleted);
         webclient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webclient_DownloadStringCompleted);
         webclient.DownloadStringAsync(new Uri(baseUri));
     }

 

이렇게 WCF 를 호출해서 사용자 URI들을 받는다. (10명이 등록 되어 있으면 서버가 10개가 들어 있는 List를 보내줌)

 

void webclient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
       {                           
           MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(e.Result));
           DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Uri>));
           deserializedListUri = serializer.ReadObject(ms) as List<Uri>;
 
           SendToast();
       }

 

자 다운이 다 되면 List로  Deserialize 한후

 

private void SendToast()
       {
 
           HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(deserializedListUri[0]);
 
           // We will create a HTTPWebRequest that posts the toast notification to the Microsoft Push Notification Service.
           // HTTP POST is the only allowed method to send the notification.
           sendNotificationRequest.Method = "POST";
 
           // The optional custom header X-MessageID uniquely identifies a notification message. 
           // If it is present, the // same value is returned in the notification response. It must be a string that contains a UUID.
           // sendNotificationRequest.Headers.Add("X-MessageID", "<UUID>");
 
           var title = "test Title";
           var subtitle = "test SubTitle";
           // Create the toast message.
 
 
           string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
           "<wp:Notification xmlns:wp=\"WPNotification\">" +
              "<wp:Toast>" +
                   "<wp:Text1>" + title + "</wp:Text1>" +
                   "<wp:Text2>" + subtitle + "</wp:Text2>" +
              "</wp:Toast> " +
           "</wp:Notification>";
 
           // Sets the notification payload to send.
           byte[] notificationMessage = Encoding.Default.GetBytes(toastMessage);
 
           // Sets the web request content length.
           sendNotificationRequest.ContentLength = notificationMessage.Length;
           sendNotificationRequest.ContentType = "text/xml";
           sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "toast");
           sendNotificationRequest.Headers.Add("X-NotificationClass", "2");
 
           using (Stream requestStream = sendNotificationRequest.GetRequestStream())
           {
               requestStream.Write(notificationMessage, 0, notificationMessage.Length);
           }
 
           // Send the notification and get the response.
           HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
           string notificationStatus = response.Headers["X-NotificationStatus"];
           string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
           string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
 
           // Display the response from the Microsoft Push Notification Service.  
           // Normally, error handling code would be here.  In the real world, because data connections are not always available,
           // notifications may need to be throttled back if the device cannot be reached.
 
           resultTextBlock.Text = notificationStatus + " | " + deviceConnectionStatus + " | " + notificationChannelStatus;
       }
 
이렇게 보낸다 xml 형식으로 만들어서 보내면 되며
 
상태들도 header정보를 받아서 볼수 있다.

Posted by 동동(이재동)
Windows Phone 72011.05.27 18:37

자 이번에는 WCF Rest Service를 만들어 보자.

 

이것도 역시 WCF Rest Service 프로젝트 생성해서

 

[ServiceContract]
   [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
   public class Notifications
   {
       private static Dictionary<string,List<Uri>> subscribers = new Dictionary<string,List<Uri>>();
       private static object obj = new object();
 
       [WebInvoke(UriTemplate = "register?uri={uri}&appId={appId}", ResponseFormat = WebMessageFormat.Xml, Method = "GET")]
       public void Register(string uri,string appId)
       {            
           Uri channelUri = new Uri(uri, UriKind.Absolute);
           Subscribe(channelUri,appId);
       }
 
       private void Subscribe(Uri channelUri,string appId )
       {
           lock (obj)
           {
               if (subscribers.ContainsKey(appId) == false)
               {
                   subscribers.Add(appId, new List<Uri>());
               }
 
 
               if (!subscribers[appId].Exists((u) => u == channelUri))
               {
                   subscribers[appId].Add(channelUri);
               }
           }
           //OnSubscribed(channelUri, true);
       }
 
       [WebInvoke(UriTemplate = "GetSubscribers?appId={appId}", ResponseFormat = WebMessageFormat.Json, Method = "GET")]
       public List<Uri> GetSubscribers(string AppId)
       {
           return subscribers[AppId];
       }

 

귀찮아서 소스만 썻다 보면 알듯이

클라이언트가 Register 메소드를 호출하여 URI와 AppID(구분을 위해)

를 주면 그걸 그냥 List에 저장하는 형식이다.

나중에 이걸 DB로 저장하게 바꾸기만 하면 된다.



 

 

Posted by 동동(이재동)
Windows Phone 72011.05.27 18:31

그냥 여러개로 나누어서 적어보았다.. ㅋㅋ 웬지 그게 더 멋있어 보여서 (헐…)

 

요즘엔 다 이렇게 하더라 ㅋㅋ

자 이제 윈폰 클라이언트 프로그램을 만들어보자..

 

일단 윈폰 프로젝트를 열고

 

private HttpNotificationChannel httpChannel;
  const string channelName = "TestAppUpdatesChannel";
  // Constructor
  public MainPage()
  {
      InitializeComponent();
 
      //Create the channel
 
      //만약 채널이 이미 있으면 
      httpChannel = HttpNotificationChannel.Find(channelName);
 
      //이벤트 등록
      if (httpChannel == null)
      {
          httpChannel = new HttpNotificationChannel(channelName, "HugeFlowAppTestService");
          httpChannel.Open();
          httpChannel.BindToShellToast();
      }           
 
      SubscribeToChannelEvents();
      SubscribeToService();
      
  }

 

채널을 등록하고 open하고 bind 한다.

bindToshellToast()는 망고버전에 나온 좋은 기능이다 더 편리해졌다 ㅋ

 

만약 이미 등록되어있다면

그냥 이벤트만 연결하고 클라이언트 URI를 서버에 전달한다.

 

private void SubscribeToChannelEvents()
       {
           httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);
           httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);
       }

 

이렇게 이벤트 연결하고

void httpChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
       {
           StringBuilder message = new StringBuilder();
           string relativeUri = string.Empty;
 
           message.AppendFormat("Received Toast {0}:\n", DateTime.Now.ToShortTimeString());
 
           // Parse out the information that was part of the message.
           foreach (string key in e.Collection.Keys)
           {
               message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);
 
               if (string.Compare(
                   key,
                   "wp:Param",
                   System.Globalization.CultureInfo.InvariantCulture,
                   System.Globalization.CompareOptions.IgnoreCase) == 0)
               {
                   relativeUri = e.Collection[key];
               }
           }
 
           // Display a dialog of all the fields in the toast.
           Dispatcher.BeginInvoke(() => MessageBox.Show(message.ToString()));
       }
       

 

이건 이제 메세지를 받았을때 프로그램에 보여주기 위한 이벤트이다. 메세지를 받았을때 메세지 박스로 띄워준다.

 

 

/// <summary>
 /// MS에서 받아온 url을 서버(WCF Service)에 보낸다.
 /// </summary>
 private void SubscribeToService()
 {
     string appid = "1";
     
     //string baseUri = "http://localhost:19976/Notifications/Register?uri={0}&appId={1}";
     string baseUri = "http://192.168.10.174:6060/Notifications/Register?uri={0}&appId={1}";        
 
     string theUri = String.Format(baseUri, httpChannel.ChannelUri.ToString(),appid);
 
     WebClient client = new WebClient();
     client.DownloadStringCompleted += (s, e) =>
         {
              if (e.Error == null)
              {
                  Dispatcher.BeginInvoke(() => UpdateStatus("Registration Success"));
              }
              else 
              {
                  Dispatcher.BeginInvoke(() => UpdateStatus(e.Error.Message));
              }
 
         };
     
     client.DownloadStringAsync(new Uri(theUri));
 }

 

이렇게 서버에게 URI를 보내 준다. WCF Rest 서비스니 웹처럼 파라미터를 넣어서 전달

 

이렇게 해서 클라이언트 완성


NotificationToastClient.zip

Posted by 동동(이재동)