async Task<bool> RegisterWithCCTHelper(string serverUri) { bool result = false; socket = new StreamWebSocket(); // Specify the keepalive interval expected by the server for this app // in order of minutes. const int serverKeepAliveInterval = 30; // Specify the channelId string to differentiate this // channel instance from any other channel instance. // When background task fires, the channel object is provided // as context and the channel id can be used to adapt the behavior // of the app as required. const string channelId = "channelOne"; // IMPORTANT: Note that this is a websocket sample, therefore the // keepalive task class is provided by Windows for websockets. // For websockets, the system does the keepalive on behalf of the // app but the app still needs to specify this well known keepalive task. // This should be done here in the background registration as well // as in the package manifest. const string WebSocketKeepAliveTask = "Windows.Networking.Sockets.WebSocketKeepAlive"; // Try creating the controlchanneltrigger if this has not been already // created and stored in the property bag. Diag.DebugPrint("RegisterWithCCTHelper Starting..."); ControlChannelTriggerStatus status; Diag.DebugPrint("Create ControlChannelTrigger ..."); // Create the ControlChannelTrigger object and request a hardware slot for this app. // If the app is not on LockScreen, then the ControlChannelTrigger constructor will // fail right away. try { channel = new ControlChannelTrigger(channelId, serverKeepAliveInterval, ControlChannelTriggerResourceType.RequestHardwareSlot); } catch (UnauthorizedAccessException exp) { Diag.DebugPrint("Please add the app to the lock screen." + exp.Message); return result; } Uri serverUriInstance; try { serverUriInstance = new Uri(serverUri); } catch (Exception exp) { Diag.DebugPrint("Error creating URI: " + exp.Message); return result; } // Register the apps background task with the trigger for keepalive. var keepAliveBuilder = new BackgroundTaskBuilder(); keepAliveBuilder.Name = "KeepaliveTaskForChannelOne"; keepAliveBuilder.TaskEntryPoint = WebSocketKeepAliveTask; keepAliveBuilder.SetTrigger(channel.KeepAliveTrigger); keepAliveBuilder.Register(); // Register the apps background task with the trigger for push notification task. var pushNotifyBuilder = new BackgroundTaskBuilder(); pushNotifyBuilder.Name = "PushNotificationTaskForChannelOne"; pushNotifyBuilder.TaskEntryPoint = "BackgroundTaskHelper.PushNotifyTask"; pushNotifyBuilder.SetTrigger(channel.PushNotificationTrigger); pushNotifyBuilder.Register(); // Tie the transport method to the ControlChannelTrigger object to push enable it. // Note that if the transport's TCP connection is broken at a later point of time, // the ControlChannelTrigger object can be reused to plug in a new transport by // calling UsingTransport API again. Diag.DebugPrint("Calling UsingTransport() ..."); try { channel.UsingTransport(socket); // Connect the socket // // If connect fails or times out it will throw exception. await socket.ConnectAsync(serverUriInstance); Diag.DebugPrint("Connected"); // Call WaitForPushEnabled API to make sure the TCP connection has // been established, which will mean that the OS will have allocated // any hardware slot for this TCP connection. // // In this sample, the ControlChannelTrigger object was created by // explicitly requesting a hardware slot. // // On Non-AOAC systems, if app requests hardware slot as above, // the system will fallback to a software slot automatically. // // On AOAC systems, if no hardware slot is available, then app // can request a software slot [by re-creating the ControlChannelTrigger object]. status = channel.WaitForPushEnabled(); Diag.DebugPrint("WaitForPushEnabled() completed with status: " + status); if (status != ControlChannelTriggerStatus.HardwareSlotAllocated && status != ControlChannelTriggerStatus.SoftwareSlotAllocated) { throw new Exception(string.Format("Neither hardware nor software slot could be allocated. ChannelStatus is {0}", status.ToString())); } // Store the objects created in the property bag for later use. // NOTE: make sure these objects are free threaded. STA/Both objects can // cause deadlocks when foreground threads are suspended. CoreApplication.Properties.Remove(channel.ControlChannelTriggerId); var appContext = new AppContext(this, socket, channel, channel.ControlChannelTriggerId); ((IDictionary<string, object>)CoreApplication.Properties).Add(channel.ControlChannelTriggerId, appContext); result = true; Diag.DebugPrint("RegisterWithCCTHelper Completed."); // Almost done. Post a read since we are using streamwebsocket // to allow push notifications to be received. PostSocketRead(MAX_BUFFER_LENGTH); } catch (Exception exp) { Diag.DebugPrint("RegisterWithCCTHelper Task failed with: " + exp.Message); // Exceptions may be thrown for example if the application has not // registered the background task class id for using real time communications // broker in the package appx manifest. } return result; }
private bool RegisterControlChannel() { if (!UnregisterControlChannel()) return false; if (IsInternetAvailable) { _XMPP.Socket = new StreamSocket(); try { // Create controlchannel var slotType = _currentParameters.RequestConnectedStandby ? ControlChannelTriggerResourceType.RequestHardwareSlot : ControlChannelTriggerResourceType.RequestSoftwareSlot; _controlChannel = new ControlChannelTrigger("CT" + Id, 15, slotType); _controlChannel.UsingTransport(_XMPP.Socket); // Register package received event BackgroundTaskBuilder pushNotificationTrigger = new BackgroundTaskBuilder(); pushNotificationTrigger.Name = "PN" + Id; pushNotificationTrigger.TaskEntryPoint = "BackgroundTasks.PushNotificationTrigger"; pushNotificationTrigger.SetTrigger(_controlChannel.PushNotificationTrigger); pushNotificationTrigger.Register(); // Register keepalive event BackgroundTaskBuilder keepAliveTrigger = new BackgroundTaskBuilder(); keepAliveTrigger.Name = "KA" + Id; keepAliveTrigger.TaskEntryPoint = "BackgroundTasks.KeepAliveTrigger"; keepAliveTrigger.SetTrigger(_controlChannel.KeepAliveTrigger); keepAliveTrigger.Register(); } catch { PushEvent(ErrorType.RegisterControlChannel, ErrorPolicyType.Reconnect); return false; } #if DEBUG PushEvent(LogType.Info, "ControlChanel registered"); #endif return true; } else { return false; } }