| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- using System;
- using System.Net;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Documents;
- using System.Windows.Ink;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Animation;
- using System.Windows.Shapes;
- using Microsoft.Phone.Notification;
- using System.Windows.Threading;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.IO.IsolatedStorage;
- using System.ComponentModel;
- namespace WindowsPhone.Recipes.Push.Client
- {
- public sealed class PushContext : INotifyPropertyChanged
- {
- #region Fields
- private readonly IsolatedStorageSettings Settings = IsolatedStorageSettings.ApplicationSettings;
- private static PushContext _current;
- private bool _isConnected;
- #endregion
- #region Properties
- private Dispatcher Dispatcher { get; set; }
- public string ChannelName { get; private set; }
- public string ServiceName { get; private set; }
- public IList<Uri> AllowedDomains { get; private set; }
- public HttpNotificationChannel NotificationChannel { get; private set; }
- public static PushContext Current
- {
- get { return _current; }
- }
- public bool IsConnected
- {
- get { return _isConnected; }
- set
- {
- if (_isConnected != value)
- {
- _isConnected = value;
- NotifyPropertyChanged("IsConnected");
- }
- }
- }
- public bool IsPushEnabled
- {
- get { return GetOrCreate<bool>("PushContext.IsPushEnabled", false); }
- set
- {
- SetOrCreate("PushContext.IsPushEnabled", value);
- UpdateNotificationBindings();
- NotifyPropertyChanged("IsPushEnabled");
- }
- }
- public bool IsTileEnabled
- {
- get { return GetOrCreate<bool>("PushContext.IsTileEnabled", true); }
- set
- {
- SetOrCreate("PushContext.IsTileEnabled", value);
- UpdateNotificationBindings();
- NotifyPropertyChanged("IsTileEnabled");
- }
- }
- public bool IsToastEnabled
- {
- get { return GetOrCreate<bool>("PushContext.IsToastEnabled", true); }
- set
- {
- SetOrCreate("PushContext.IsToastEnabled", value);
- UpdateNotificationBindings();
- NotifyPropertyChanged("IsToastEnabled");
- }
- }
- public bool IsRawEnabled
- {
- get { return GetOrCreate<bool>("PushContext.IsRawEnabled", true); }
- set
- {
- SetOrCreate("PushContext.IsRawEnabled", value);
- NotifyPropertyChanged("IsRawEnabled");
- }
- }
- #endregion
- #region Events
- public event EventHandler<PushContextErrorEventArgs> Error;
- public event EventHandler<PushContextEventArgs> ChannelPrepared;
- public event EventHandler<HttpNotificationEventArgs> RawNotification;
- public event PropertyChangedEventHandler PropertyChanged = delegate { };
- #endregion
- #region Ctor
- public PushContext(string channelName, string serviceName, IList<Uri> allowedDomains, Dispatcher dispatcher)
- {
- if (_current != null)
- {
- throw new InvalidOperationException("There should be no more than one push context.");
- }
- ChannelName = channelName;
- ServiceName = serviceName;
- AllowedDomains = allowedDomains;
- Dispatcher = dispatcher;
- _current = this;
- }
- #endregion
- #region Public Methods
- public void Connect(Action<HttpNotificationChannel> prepared)
- {
- if (IsConnected)
- {
- prepared(NotificationChannel);
- return;
- }
- try
- {
- // First, try to pick up an existing channel.
- NotificationChannel = HttpNotificationChannel.Find(ChannelName);
- if (NotificationChannel == null)
- {
- // Create new channel and subscribe events.
- CreateChannel(prepared);
- }
- else
- {
- // Channel exists, no need to create a new one.
- SubscribeToNotificationEvents();
- PrepareChannel(prepared);
- }
- IsConnected = true;
- }
- catch (Exception ex)
- {
- OnError(ex);
- }
- }
- public void Disconnect()
- {
- if (!IsConnected)
- {
- return;
- }
- try
- {
- if (NotificationChannel != null)
- {
- UnbindFromTileNotifications();
- UnbindFromToastNotifications();
- NotificationChannel.Close();
- }
- }
- catch (Exception ex)
- {
- OnError(ex);
- }
- finally
- {
- NotificationChannel = null;
- IsConnected = false;
- }
- }
- #endregion
- #region Privates
- /// <summary>
- /// Create channel, subscribe to channel events and open the channel.
- /// </summary>
- private void CreateChannel(Action<HttpNotificationChannel> prepared)
- {
- // Create a new channel.
- NotificationChannel = new HttpNotificationChannel(ChannelName, ServiceName);
- // Register to UriUpdated event. This occurs when channel successfully opens.
- NotificationChannel.ChannelUriUpdated += (s, e) => Dispatcher.BeginInvoke(() => PrepareChannel(prepared));
- SubscribeToNotificationEvents();
- // Trying to Open the channel.
- NotificationChannel.Open();
- }
- private void SubscribeToNotificationEvents()
- {
- // Register to raw notifications.
- NotificationChannel.HttpNotificationReceived += (s, e) =>
- {
- if (IsPushEnabled & IsRawEnabled)
- {
- Dispatcher.BeginInvoke(() => OnRawNotification(e));
- }
- };
- }
- private void OnRawNotification(HttpNotificationEventArgs e)
- {
- if (RawNotification != null)
- {
- RawNotification(this, e);
- }
- }
- private void PrepareChannel(Action<HttpNotificationChannel> prepared)
- {
- try
- {
- // OnChannelPrepared(new PushContextEventArgs(NotificationChannel));
- prepared(NotificationChannel);
- UpdateNotificationBindings();
- }
- catch (Exception ex)
- {
- OnError(ex);
- }
- }
- private void OnError(Exception exception)
- {
- if (Error != null)
- {
- Error(this, new PushContextErrorEventArgs(exception));
- }
- }
- private void OnChannelPrepared(PushContextEventArgs args)
- {
- if (ChannelPrepared != null)
- {
- ChannelPrepared(this, args);
- }
- }
- private void BindToTileNotifications()
- {
- try
- {
- if (NotificationChannel != null && !NotificationChannel.IsShellTileBound)
- {
- var listOfAllowedDomains = new Collection<Uri>(AllowedDomains);
- NotificationChannel.BindToShellTile(listOfAllowedDomains);
- }
- }
- catch (Exception ex)
- {
- OnError(ex);
- }
- }
- private void BindToToastNotifications()
- {
- try
- {
- if (NotificationChannel != null && !NotificationChannel.IsShellToastBound)
- {
- NotificationChannel.BindToShellToast();
- }
- }
- catch (Exception ex)
- {
- OnError(ex);
- }
- }
- private void UnbindFromTileNotifications()
- {
- try
- {
- if (NotificationChannel.IsShellTileBound)
- {
- NotificationChannel.UnbindToShellTile();
- }
- }
- catch (Exception ex)
- {
- OnError(ex);
- }
- }
- private void UnbindFromToastNotifications()
- {
- try
- {
- if (NotificationChannel.IsShellToastBound)
- {
- NotificationChannel.UnbindToShellToast();
- }
- }
- catch (Exception ex)
- {
- OnError(ex);
- }
- }
- private void UpdateNotificationBindings()
- {
- if (IsPushEnabled && IsTileEnabled)
- {
- BindToTileNotifications();
- }
- else
- {
- UnbindFromTileNotifications();
- }
- if (IsPushEnabled && IsToastEnabled)
- {
- BindToToastNotifications();
- }
- else
- {
- UnbindFromToastNotifications();
- }
- }
- private T GetOrCreate<T>(string key, T defaultValue = default(T))
- {
- T value;
- if (Settings.TryGetValue(key, out value))
- {
- return value;
- }
- return defaultValue;
- }
- private void SetOrCreate<T>(string key, T value)
- {
- Settings[key] = value;
- }
- private void NotifyPropertyChanged(string propertyName)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- #endregion
- }
- }
|