CounterPushPatternViewModel.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.ComponentModel.Composition;
  6. using System.Xml.Linq;
  7. using WindowsPhone.Recipes.Push.Messasges;
  8. using WindowsPhone.Recipes.Push.Server.Services;
  9. using WindowsPhone.Recipes.Push.Server.Models;
  10. namespace WindowsPhone.Recipes.Push.Server.ViewModels
  11. {
  12. /// <summary>
  13. /// Represents the Counter push notification pattern.
  14. /// </summary>
  15. /// <remarks>
  16. /// Send a tile push notification message with a counter value.
  17. /// Each time a push notification message is sent the counter value
  18. /// increases by one, unless user is running the application and notifies
  19. /// the server.
  20. /// </remarks>
  21. [Export(typeof(PushPatternViewModel)), PartCreationPolicy(CreationPolicy.Shared)]
  22. internal sealed class CounterPushPatternViewModel : PushPatternViewModel
  23. {
  24. #region Fields
  25. /// <value>A dictionary for tracking tile message count while phone-application is not running.</value>
  26. private readonly Dictionary<string, int> _messageCounter = new Dictionary<string, int>();
  27. /// <value>Synchronizes access to the message counter collection.</value>
  28. private readonly object MessageCounterSync = new object();
  29. #endregion
  30. #region Ctor
  31. /// <summary>
  32. /// Initialize new instance of this type with defaults.
  33. /// </summary>
  34. public CounterPushPatternViewModel()
  35. {
  36. InitializeDefaults();
  37. }
  38. #endregion
  39. #region Overrides
  40. /// <summary>
  41. /// Send raw message to all subscribers. In case that the phone-application
  42. /// is not running, send tile update and increase tile counter.
  43. /// </summary>
  44. protected override void OnSend()
  45. {
  46. // Notify phone for having waiting messages.
  47. var rawMsg = new RawPushNotificationMessage(MessageSendPriority.High)
  48. {
  49. RawData = Encoding.ASCII.GetBytes(RawMessage)
  50. };
  51. foreach (var subscriber in PushService.Subscribers)
  52. {
  53. rawMsg.SendAsync(
  54. subscriber.ChannelUri,
  55. result =>
  56. {
  57. Log(result);
  58. OnRawSent(subscriber.UserName, result);
  59. },
  60. Log);
  61. }
  62. }
  63. /// <summary>
  64. /// On subscription change, reset the subscriber tile counter if exist.
  65. /// </summary>
  66. protected override void OnSubscribed(SubscriptionEventArgs e)
  67. {
  68. // Create a tile message to reset tile count.
  69. var tileMsg = new TilePushNotificationMessage(MessageSendPriority.High)
  70. {
  71. Count = 0,
  72. BackgroundImageUri = BackgroundImageUri,
  73. Title = Title
  74. };
  75. tileMsg.SendAsync(e.Subscription.ChannelUri, Log, Log);
  76. ResetCounter(e.Subscription.UserName);
  77. }
  78. #endregion
  79. #region Privates
  80. private void OnRawSent(string userName, MessageSendResult result)
  81. {
  82. // In case that the device is disconnected, no need to send a tile message.
  83. if (result.DeviceConnectionStatus == DeviceConnectionStatus.TempDisconnected)
  84. {
  85. return;
  86. }
  87. // Checking these three flags we can know what's the state of both the device and apllication.
  88. bool isApplicationRunning =
  89. result.SubscriptionStatus == SubscriptionStatus.Active &&
  90. result.NotificationStatus == NotificationStatus.Received &&
  91. result.DeviceConnectionStatus == DeviceConnectionStatus.Connected;
  92. // In case that the application is not running, send a tile update with counter increase.
  93. if (!isApplicationRunning)
  94. {
  95. var tileMsg = new TilePushNotificationMessage(MessageSendPriority.High)
  96. {
  97. Count = IncreaseCounter(userName),
  98. BackgroundImageUri = BackgroundImageUri,
  99. Title = Title
  100. };
  101. tileMsg.SendAsync(result.ChannelUri, Log, Log);
  102. }
  103. }
  104. private void ResetCounter(string userName)
  105. {
  106. lock (MessageCounterSync)
  107. {
  108. _messageCounter.Remove(userName);
  109. }
  110. }
  111. private int IncreaseCounter(string userName)
  112. {
  113. lock (MessageCounterSync)
  114. {
  115. int counter;
  116. if (_messageCounter.TryGetValue(userName, out counter))
  117. {
  118. ++counter;
  119. }
  120. else
  121. {
  122. counter = 1;
  123. }
  124. _messageCounter[userName] = counter;
  125. return counter;
  126. }
  127. }
  128. private void InitializeDefaults()
  129. {
  130. DisplayName = "Counter";
  131. Description = "Send push notification message of Tile type, with a counter value. Each time a push notification message is sent, the counter value increases by one, unless user is running the application and notifies the server.";
  132. BackgroundImageUri = TileImages.Length > 1 ? TileImages[1] : TileImages.FirstOrDefault();
  133. RawMessage = "Game Update";
  134. Count = 0;
  135. Title = "Updates";
  136. }
  137. #endregion
  138. }
  139. }