AT&T U-verse® Enabled How to Write Your First AT&T U -verse Enabled iOS ® App Publication Date: November 1st, 2013 © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Legal Disclaimer This document and the information contained herein (collectively, the "Information") is provided to you (both the individual receiving this document and any legal entity on behalf of which such individual is acting) ("You" and "Your") by AT&T, on behalf of itself and its affiliates ("AT&T") for informational purposes only. AT&T is providing the Information to You because AT&T believes the Information may be useful to You. The Information is provided to You solely on the basis that You will be responsible for making Your own assessments of the Information and are advised to verify all representations, statements and information before using or relying upon any of the Information. Although AT&T has exercised reasonable care in providing the Information to You, AT&T does not warrant the accuracy of the Information and is not responsible for any damages arising from Your use of or reliance upon the Information. You further understand and agree that AT&T in no way represents, and You in no way rely on a belief, that AT&T is providing the Information in accordance with any standard or service (routine, customary or otherwise) related to the consulting, services, hardware or software industries. AT&T DOES NOT WARRANT THAT THE INFORMATION IS ERROR-FREE. AT&T IS PROVIDING THE INFORMATION TO YOU "AS IS" AND "WITH ALL FAULTS." AT&T DOES NOT WARRANT, BY VIRTUE OF THIS DOCUMENT, OR BY ANY COURSE OF PERFORMANCE, COURSE OF DEALING, USAGE OF TRADE OR ANY COLLATERAL DOCUMENT HEREUNDER OR OTHERWISE, AND HEREBY EXPRESSLY DISCLAIMS, ANY REPRESENTATION OR WARRANTY OF ANY KIND WITH RESPECT TO THE INFORMATION, INCLUDING, WITHOUT LIMITATION, ANY REPRESENTATION OR WARRANTY OF DESIGN, PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, OR ANY REPRESENTATION OR WARRANTY THAT THE INFORMATION IS APPLICABLE TO OR INTEROPERABLE WITH ANY SYSTEM, DATA, HARDWARE OR SOFTWARE OF ANY KIND. AT&T DISCLAIMS AND IN NO EVENT SHALL BE LIABLE FOR ANY LOSSES OR DAMAGES OF ANY KIND, WHETHER DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, SPECIAL OR EXEMPLARY, INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, LOSS OF GOODWILL, COVER, TORTIOUS CONDUCT OR OTHER PECUNIARY LOSS, ARISING OUT OF OR IN ANY WAY RELATED TO THE PROVISION, NON-PROVISION, USE OR NON-USE OF THE INFORMATION, EVEN IF AT&T HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSSES OR DAMAGES. IOS is a trademark or registered trademark of Cisco in the U.S. and other countries. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. i Table of Contents Contents 1 Introduction .......................................................................................................................................... 1 2 Overview ............................................................................................................................................... 2 3 Initial Setup ........................................................................................................................................... 4 4 RemoteControlViewController Design.................................................................................................. 5 5 4.1 Implementing the viewDidLoad Method ...................................................................................... 5 4.2 Implementing the UverseConnectedManagerDidChangeState Notification Callback Method ... 7 4.3 Implementing the connectToReceiver Method ............................................................................ 9 4.4 About the UverseConnectedManagerErrorOccurred Notification Callback Method ................. 10 4.5 Handling the RemoteKey and Button Commands on the RemoteControlViewController......... 10 SetTopBoxPickerTableViewController Design .................................................................................... 13 5.1 Implementing the viewDidLoad Method .................................................................................... 14 5.2 Implementing the registerForNotifications Method .................................................................. 14 5.3 Implementing the uveSetTopBoxEnagagementDidSucceed notification Callback Method ....... 15 5.4 Implementing the uveSetTopBoxEnagagementDidFail notification Callback Method............... 15 5.5 Implementing the UverseConnectedManagerSetTopBoxesUpdated Notification Callback Method ................................................................................................................................................... 17 6 5.6 Implementing the setupListOfstb Method ................................................................................. 17 5.7 Implementing the UITableView:cellForRowAtIndexPath Method ............................................. 18 5.8 Implementing the didSelectRowAtIndexPath Method ............................................................... 20 5.9 Implementing the PasswordViewController Delegate Method ................................................. 21 PasswordViewController Design ......................................................................................................... 22 6.1 Implementing the viewDidLoad Method .................................................................................... 22 © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. ii Table of Figures Figure 4-1: RemoteControlViewController Screen ....................................................................................... 5 Figure 5-1: SetTopBoxPickerTableViewController ...................................................................................... 13 Figure 6-1: PasswordViewController .......................................................................................................... 22 © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. iii Table of Examples Example 4-1: viewDidLoad method. ............................................................................................................. 7 Example 4-2: UverseConnectedManagerDidChangeState ........................................................................... 8 Example 4-3: associateToSTBAfterDiscovery Method .................................................................................. 9 Example 4-4: connectToReceiver................................................................................................................ 10 Example 4-5: stbCommandbuttonPressed ................................................................................................. 11 Example 4-6: commandSucceeded ............................................................................................................. 12 Example 5-1: viewDidLoad .......................................................................................................................... 14 Example 5-2: registerForNotifications ........................................................................................................ 15 Example 5-3: uveSetTopBoxEnagagementDidSucceed .............................................................................. 15 Example 5-4: uveSetTopBoxEnagagementDidFail notification................................................................... 17 Example 5-5: UverseConnectedManagerSetTopBoxesUpdated ................................................................ 17 Example 5-6: setupListOfstb ....................................................................................................................... 18 Example 5-7: UITableView:cellForRowAtIndexPath ................................................................................... 20 Example 5-8: didSelectRowAtIndexPath ..................................................................................................... 21 Example 5-9: PasswordViewController....................................................................................................... 21 Example 6-1: viewDidLoad .......................................................................................................................... 23 Example 6-2: passwordEntered .................................................................................................................. 23 © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. iv 1 Introduction This document takes you through the creation of the elements that must be included in a functional U-verse Enabled app. These elements include a discovery and authentication process like the one described in the AT&T U-verse ® Enabled User Device Design Guidelines which establishes the connection between your app and the U-verse receiver (SetTopBox), and a basic remote control that allows your app to invoke receiver commands. The code that is shown and discussed in this document is downloaded from the sample code page. The main body of the sample app described in this document primarily focuses on the authentication process. This portion of the sample app has been designed to be as reusable as possible. Some of the terminology that is used in the U-verse API, and in this document, is different from the terms on the U-verse receiver. These are the terms that a user will be familiar with, and you should not use the name used in the API in any user facing areas. The main differences are: The U-verse receiver is referred to as the SetTopBox in the API. Default mode is referred to as "Open" mode for the receiver engagement in the API. Custom mode is referred to as "Managed" mode for the receiver engagement in the API. To complete this tutorial and create your first U-verse Enabled iOS app, it is assumed that you have completed the following prerequisites: You have completed your app registration and have been issued an AAP for test purposes. The process for completing both of these tasks is described in the document How to Register and Start Developing AT&T U-verse Enabled Applications. You have set up your project as described in the document How to Set Up an AT&T U-verse-Enabled Project in Xcode®. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 1 of 25 2 Overview To implement the discovery, authentication, and remote control elements that are essential to a functional U-verse Enabled app, the project described in this tutorial uses these three objects in the U-verse Enabled SDK: The SetTopBox object contains state information, such as the current program that the user is watching. The object also contains methods for sending commands to the SetTopBox, querying for information about the current program or the user’s recording status, and for engaging with the SetTopBox. UverseConnectedManager Is a singleton object that is created by calling [UverseConnectedManager sharedManager], and it is kept alive for the lifetime of the app. This object is used to communicate between the U-verse Network Service and your application. The UverseConnectedManager object handles discovery of the SetTopBoxes on the network and has a number of helpful properties such as SetTopBoxes which returns an NSArray of SetTopBoxes on the current network after discovery has completed. The mostRecentlyEngagedSetTopBox property provides a reference to the SetTopBox that was most recently engaged by the user. There are two common uses for this property: o The app can check the value after discovery is complete and, if not nil, choose to engage with this SetTopBox automatically for the user. o The app can check this value to determine which SetTopBox was most recently engaged, as the UverseConnectedManager will keep this value up to date as the user engages with SetTopBoxes in a multi SetTopBox environment. The uveRemoteButtonCommand object is used to send RemoteKey commands to the SetTopBox. These commands are used to emulate buttons on the remote control (like channel up), or to send alphanumeric characters. To allow the user to interact with the functionality of these objects, the UI for this sample app uses these four different View Controllers: The RemoteControlViewController is used to create the main screen. This view controller is the root view controller for the app. It displays a simple remote controller using Apple’s® default buttons to demonstrate the functionality of the uveRemoteKeyCommand, and to handle the discovery of the SetTopBoxes. The SetTopBoxPickerTableViewController handles the selection and engagement of a SetTopBox on the U-verse Network. This is either done automatically, in the discovery phase, or as a user event, if the user wishes to change the setTopBox that they are engaged with. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 2 of 25 The LinkingInfoViewController is the simplest view controller in the project. Its role is to provide helpful information to the user about the steps needed to engage a SetTopBox with a U-verse Enabled application. The details of how to implement this view controller will not be explained in this tutorial, but the implementation is included in the accompanying sample code. The PasswordViewController is used to prompt the user for a PIN. The controller then passes the entered password to its delegate for verification. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 3 of 25 3 Initial Setup There are a few design choices you can make when creating a U-verse Enabled app. In this sample app, the AppDelegate selects whether the app is to be run in a test environment or the production environment and selects the correct AAP files and the url of the server for the environment. Most of the other interaction with the library is handled in the RemoteControlViewController. It is important to note that your app will be able to engage with a U-verse receiver until you have correctly setup the AAP in your app for the environment you are working in. The details of how to do this are covered in the document How to Setup an AT&T U-verse Enabled Project in Xcode, so they will not be repeated in this tutorial. The following sections of this tutorial describe in detail the implementation of the four view controllers. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 4 of 25 4 RemoteControlViewController Design The RemoteControlViewController is the root view controller and it is used to create the main screen of the app shown in the following figure. Note: The following View is designed to be replaced by a View in your own app, and as such, it is very basic. It’s not recommended that you present a similar design to users. Figure 4-1: RemoteControlViewController Screen 4.1 Implementing the viewDidLoad Method The code to implement the RemoteControlViewController begins with the viewDidLoad method which performs the following actions: Retrieving a reference to the sharedManager from the UverseConnectedManager object. Registering for the uveSetTopBoxCommandDidSucceed, uveSetTopBoxCommandDidFail, UverseConnectedManagerDidChangeState, and UverseConnectedManagerErrorOccurred notifications. This is the minimum set of notifications that you need to register in order to create a functional U-verse app. The UverseConnectedManagerDidChangeState notification is used for the © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 5 of 25 changes in discovery state, but it can also inform you of any state changes that occur after discovery. For example, it will notify you if the app loses the network connection to the SetTopBox. Checking the state of the UverseConnectedManager (using the reference uvcMgr in the code example). If the state is LibraryNotReady, you can use the startDiscovery method of the UverseConnectedManger to start discovery. Checking whether the discovery state is not LibraryReady. While this condition is similar to the last check, the subtle difference is that it is checking whether the state is LibraryNotReady, or DiscoveringNetwork. These are the states that the app can be in before it is ready to use. If it is in one of these states, the application displays an alert to the user indicating that the app is performing discovery. The final portion of the viewDidLoad method sets the title in the navigation bar and a button for the user to reconnect with a U-verse receiver. The following code shows the implementation of the viewDidLoad method. viewDidLoad Method 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | - (void)viewDidLoad | { | [super viewDidLoad]; | UverseConnectedManager *uvcMgr = [UverseConnectedManager sharedManager]; | [self registerForNotifications]; | if(uvcMgr.state == LibraryNotReady){ | [uvcMgr startDiscovery]; | } | if (uvcMgr.state != LibraryReady){ | ProgressIndictator *waitView = [[ProgressIndictator alloc] initWithTitleLabelText:@"Please Wait" andInfoLabelText:@"Discovering Network"]; | self.spinnerView = waitView; | [self.view addSubview:waitView]; | } | if (uvcMgr.mostRecentlyEngagedSetTopBox == nil){ | self.title = @"No Receiver"; | [self connectToReceiver]; | } | | UIBarButtonItem *connectButton = [[UIBarButtonItem alloc] initWithTitle:@"Connect" style:UIBarButtonItemStyleBordered target:self action:@selector(connectToReceiver)]; | self.navigationItem.rightBarButtonItem = connectButton; © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 6 of 25 21 22 23 24 | | UIBarButtonItem *sdkButton = [[UIBarButtonItem alloc] initWithTitle:@"SDK 2.0" style:UIBarButtonItemStyleBordered target:self action:@selector(uverse2sdkfeatures)]; | self.navigationItem.leftBarButtonItem = sdkButton; | } Example 4-1: viewDidLoad Method 4.2 Implementing the UverseConnectedManagerDidChangeState Notification Callback Method The next method for implementing the RemoteControlViewController is the callback for the UverseConnectedManagerDidChangeState notification. The three possible states that the UverseConnectManager can be in are LibraryNotReady: This is the initial state of the library. When the app starts, the library will be in the LibraryNotReady state. The library can be returned to LibraryNotReady after discovery if there is an error in Discovery. You can listen for the notification UverseConnectedManagerErrorOccurred to be notified of any errors that occur. DiscoveringNetwork: This is a transient state while the Library performs discovery. Discovery will search for the U-verse receivers on the same local WiFi network as the iOS Device. LibraryReady: The LibraryReady state indicates you are able to interact with the library. All the setup has completed and the next step is to engage with a U-verse receiver. After you engage with a U-verse receiver, you will then be able to interact with that U-verse receiver. The important case here is the LibraryReady state, in which the application code removes the alert from the screen and then calls the associateToSTBAfterDiscovery method. UverseConnectedManagerDidChangeState 1 2 3 4 5 6 7 8 | -(void)uveMgrDidChangeState:(NSNotification *)notification{ | | UverseConnectedManager *uvcMgr = [UverseConnectedManager sharedManager]; | | switch(uvcMgr.state) { | case LibraryReady:{ | NSLog(@"NOTIFICATION UverseConnectedManagerDidChangeState: LibraryReady"); | [self.spinnerView removeFromSuperview]; © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 7 of 25 9 10 11 12 13 14 15 16 17 18 | | | | | | | | | | 19 20 21 22 | | | | 23 24 25 26 27 28 | | | | | self.spinnerView = nil; [self associateToSTBAfterDiscovery]; break; } case LibraryNotReady:{ [self.spinnerView removeFromSuperview]; self.spinnerView = nil; NSLog(@"NOTIFICATION UverseConnectedManagerDidChangeState: LibraryNotReady"); break; } case DiscoveringNetwork:{ NSLog(@"NOTIFICATION UverseConnectedManagerDidChangeState: DiscoveringNetwork"); UILabel *infoLabel = self.spinnerView.infoLabel; infoLabel.text = @"Discovering Network"; break; } } } Example 4-2: UverseConnectedManagerDidChangeState The associateToSTBAfterDiscovery method is where the majority of the work will be done after discovery. The method performs the following actions: Checking whether the mostRecentlyEngagedSetTopBox property of the UverseConnectedManager singleton is set. If this property is not nil, the receiver is the one that the user most recently engaged with. Determining the connection mode of the receiver. The connection mode determines how the application can engage with the receiver. o The user can immediately engage with a receiver if the receiver is in Default mode OR in Custom mode and the user has previously entered the four digit passcode for this application and device. This would be the most common use case in a household that has only one receiver. When the app launches and goes through the discovery process, the user does not need to select the receiver that they wish to interact with. This can be done by either calling the engage method on a SetTopBox or by calling the associatedAndEngageWithOneTimeToken with an argument of nil. o If the receiver is in the Custom (Managed) mode and this is the first time that the user is using this U-verse Enabled app on the device, a four digit passcode will need to be entered by the user. For details, see the AT&T U-verse ® Enabled User Device Design Guidelines. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 8 of 25 The following code shows the implementation of the associateToSTBAfterDiscovery method. associateToSTBAfterDiscovery Method 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | -(void)associateToSTBAfterDiscovery{ | UverseConnectedManager *uvcMgr = [UverseConnectedManager sharedManager]; | SetTopBox *lastUsedSTB = uvcMgr.mostRecentlyEngagedSetTopBox; | if (lastUsedSTB != nil){ | if (lastUsedSTB.mode == UverseModeOpen || (lastUsedSTB.mode == UverseModeManaged && lastUsedSTB.isAssociated)){ | [lastUsedSTB associateAndEngageWithOneTimeToken:nil]; | self.title = uvcMgr.mostRecentlyEngagedSetTopBox.friendlyName; | }else { | [self connectToReceiver]; | } | } else { | [self connectToReceiver]; | } | } Example 4-3: associateToSTBAfterDiscovery Method 4.3 Implementing the connectToReceiver Method The following code example shows the connectToReceiver method, where a View Controller (the SettopBoxPickerTableViewController) is launched so the user can select the SetTopBox that they wish to connect to, and if necessary, launch the passcode entry screen. The View Controller is embedded in a UINavigationController for easier management of the UINavigationBar and so that it can be presented modally. connectToReceiver 1 2 3 4 5 6 | -(IBAction)connectToReceiver{ | UverseConnectedManager *uvcMgr = [UverseConnectedManager sharedManager]; | if (uvcMgr.state == LibraryReady && uvcMgr.SetTopBoxes != nil){ | SettopBoxPickerTableViewController *pickerController = [[SettopBoxPickerTableViewController alloc] initWithStyle:UITableViewStyleGrouped]; | UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:pickerController]; | [self presentModalViewController:navController © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 9 of 25 7 8 9 10 11 12 13 14 animated:YES]; | [navController release]; | [pickerController release]; | } else if (uvcMgr.state == LibraryNotReady) { | [uvcMgr startDiscovery]; | } else { | // if the middle of Discovery | } | } Example 4-4: connectToReceiver 4.4 About the UverseConnectedManagerErrorOccurred Notification Callback Method The callback method that handles the UverseConnectedManagerErrorOccurred notification covers any errors that may occur while the app is running. When you are first creating a U-verse Enabled project, the most common errors that you will receive are: uveInternalError(3000) - This normally occurs if there is a problem with the AAP bundle that you used, e.g., you are using the wrong AAP for the environment. uveNetworkError(3001) - This error occurs when your app has a problem communicating with the server. The most common cause of this error is a network error; it can also occur if you set the server to the wrong URL. uveApplicationBlocked(3002) - This occurs when either the app bundle identifier or the build number of the app have not been registered with AT&T. The code for this callback method is not described here, but the implementation is in the sample code of the project. 4.5 Handling the RemoteKey and Button Commands on the RemoteControlViewController The view of the RemoteControlViewController (shown in figure 1) displays a navigation bar with a bar button (labeled “Connect”) on the right, to start the authentication process. The remainder of the view controller contains the remote control buttons. The view controller is split into two sections, the top section, which contains the basic buttons necessary for navigation through any U-verse app and through the menu system on the SetTopBox, and the lower section which contains a number pad and a few extra buttons. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 10 of 25 Each of the RemoteKeys is exposed by the SDK in an enum contained in the file RemoteKey.h. The easiest way to send a command to the SetTopBox is to set the tag property of a button to the value of that button in the RemoteKey.h file. For example, the up button on the directional pad has the value of 24. By passing RemoteKey values to an action method, the same action method can be reused for each RemoteKey. The stbCommandbuttonPressed method, shown in the following code snippet, uses this technique. The method performs these actions: Casting the sender to a UIButton so that the compiler will not give a warning when the tag property of the object is accessed. Creating the command object which is of type uveRemoteButtonCommand. This is the object that is used anytime you are sending a remote Control Button to the receiver, i.e., any of the Remote keys declared in RemoteKey.h file. Sending the command to the receiver and releasing the command. stbCommandbuttonPressed 1 2 3 4 5 7 | - (IBAction)stbCommandbuttonPressed:(id)sender{ | UIButton *button = (UIButton *)sender; | uveRemoteButtonCommand *buttonCommand =[[uveRemoteButtonCommand alloc] initWithRemoteKey:button.tag]; | | [[[UverseConnectedManager sharedManager] mostRecentlyEngagedSetTopBox] sendSetTopBoxCommand:buttonCommand]; | } Example 4-5: stbCommandbuttonPressed As the command object will not contain any information that will be returned, it is safe to release the object after it has been sent. However, this is different for some of the other commands that inherit from uveBaseCommand. For example, the uveRecordingsCommand includes the array of recordings as a property called recordings on the uveRecordingCommand, so you must retain a reference to the command so that you can access the recordings property in the callback to the uveSetTopBoxCommandDidSucceed notification. All commands that are sent to the receiver are asynchronous, so you will need to listen for the uveSetTopBoxCommandDidSucceed and uveSetTopBoxCommandDidFail notifications to determine the success or failure of the command. As all commands that inherit from uveBaseCommand will send the same notification, the first step is to find out what type of command has sent the notification. This can be queried from the uveSetTopBoxCommandKey key that is passed as a parameter in the notification object. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 11 of 25 The following code shows the commandSucceeded method which is the callback for the uveSetTopBoxCommandDidSucceed notification. commandSucceeded 1 2 3 4 5 6 7 8 | -(void)commandSucceeded:(NSNotification *)notification { | uveBaseCommand *baseCommand = (uveBaseCommand *)[notification objectForKey:uveSetTopBoxCommandKey]; | if ([baseCommand isKindOfClass:[uveRecordingsCommand class]]){ | uveRecordingCommand *recordingsCommand = (uveRecording *)baseCommand; | // handle for uveRecordingCommand | } else if ([baseCommand isKindOfClass:[uveRemoteKeyCommand class]]){ | // handle for uveRemoteKeyCommand | } Example 4-6: commandSucceeded © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 12 of 25 5 SetTopBoxPickerTableViewController Design The purpose of the SetTopBoxPickerTableViewController, which inherits from UITableViewController, is to display a list of the SetTopBoxes that the user has on their local network. The list that is constructed includes any SetTopBoxes that are in Default mode (those that do not require a passcode to engage), or Custom mode (those that require the user to enter a passcode on first time engagement). If there are any SetTopBoxes in UverseModeUnknown, it means that the user has not yet enabled the U-verse Enabled features on those U-verse receivers. The user is also able to disable the U-verse Enabled functionality on a U-verse receiver. In this case the U-verse receiver will be in Closed Mode. To handle the case of receivers in Closed or Unknown mode, an extra row in the tableview is displayed called “Add New Receiver”, with instructions for the user on how to enable the U-verse Enabled features on their SetTopBox. If there are any receivers in UverseModeClosed or UverseModeUnknown, they should not be displayed in the list, and instead the “Add New Receiver” cell should be displayed. Figure 5-1: SetTopBoxPickerTableViewController © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 13 of 25 5.1 Implementing the viewDidLoad Method The viewDidLoad method performs the following actions: Setting up the UINavigationBar with a title (“Receivers”) and a button that allows the user to cancel out of the Model view and go back to the main viewController for the app (the RemoteControlViewController). Calling the registerForNotifications method which registers for the Notifications necessary to handle the engagement process. Calling the setupListOfstb method. This method prepares the model (a list of SetTopBoxes) that the tableview will use. The following code shows the implementation of the viewDidLoad method. viewDidLoad 1 2 3 4 5 6 7 8 9 10 11 | - (void)viewDidLoad | { | [super viewDidLoad]; | [self registerForNotifications]; | self.title = @"Receivers"; | UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStyleBordered target:self action:@selector(close:)]; | self.navigationItem.leftBarButtonItem = closeButton; | [closeButton release]; | | [self setupListOfstb]; | } Example 5-1: viewDidLoad 5.2 Implementing the registerForNotifications Method The following code shows the implementation of the registerForNotifications method that is called from viewDidLoad of the SetTopBoxPickerTableViewController. In the registerForNotifications method, the two notifications that you will need to observe are uveSetTopBoxEngagementDidFail and uveSetTopBoxEngagementDidSucceed. With the update to fast discovery caching with the 3.0 library, you should now also listen for the UverseConnectedManagerSetTopBoxUpdated notification, which will informed you that the property SetTopBoxes on the UverseConnectedManager has been updated. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 14 of 25 registerForNotifications 1 2 3 4 5 6 7 11 | -(void)registerForNotifications | { | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uvcSTBAssociationDidFail:) name: uveSetTopBoxEngagementDidFail object:nil]; | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uvcSTBAssociationDidSucceed:) name: uveSetTopBoxEngagementDidSucceed object:nil]; | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uvcSTBAssociationDidSucceed:) name:uveSetTopBoxCommandDidSucceed object:nil]; | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uvcSTBAssociationDidFail:) name:uveSetTopBoxCommandDidFail object:nil]; | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uveMgrSetTopBoxesUpdated:) name:UverseConnectedManagerSetTopBoxesUpdated object:nil]; | } Example 5-2: registerForNotifications 5.3 Implementing the uveSetTopBoxEnagagementDidSucceed notification Callback Method The callback for uveSetTopBoxEngagementDidSucceed (shown here) simply dismisses the SetTopBoxPicker and returns to the main view controller. uveSetTopBoxEnagagementDidSucceed 1 2 3 4 | -(void)uvcSTBAssociationDidSucceed:(NSNotification *)notification | { | [self.presentingViewController dismissModalViewControllerAnimated:YES]; | } Example 5-3: uveSetTopBoxEnagagementDidSucceed 5.4 Implementing the uveSetTopBoxEnagagementDidFail notification Callback Method The following code shows the cases from the uveSetTopBoxEngagementDidFail notification. For the two cases uveNotOnAUverseNetwork and uveNetworkError, an info view controller is displayed to the user to show details of the problem. This is a simple view controller that is in the sample code, but the details of it will not be discussed here. The uveNonceInvalid case occurs when the user enters the wrong passcode. In this case, the method checks to see if the © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 15 of 25 PasswordViewController is the currently displayed view controller, and if it is, the user is prompted to re-enter the passcode. uveSetTopBoxEnagagementDidFail notification 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | -(void)uvcSTBAssociationDidFail:(NSNotification *)notification{ | NSDictionary *userInfo = [notification userInfo]; | NSError *error = [userInfo objectForKey:UverseConnectedManagerErrorKey]; | switch (error.code) { | case uveNonceInvalid: | NSLog(@"NOTIFICATION uvcSetTopBoxAssociationDidFail:uveNonceInvalid"); | if ([self.navigationController.visibleViewController isKindOfClass:[PasswordViewController class]]){ | PasswordViewController *passwordController = (PasswordViewController *)self.navigationController.visibleViewController; | passwordController.bottomLabel.textColor = [UIColor redColor]; | passwordController.bottomLabel.text = @"Please retry Password"; | } | break; | | case uveNotOnAUverseNetwork: { | NSLog(@"NOTIFICATION uvcSetTopBoxAssociationDidFail:uvcNotOnAUverseNetwork"); | InfoViewController *noUverseViewController = [[InfoViewController alloc] initWithStyle:uvcNotOnAUverseNetworkStyle]; | UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:noUverseViewController]; | [self presentModalViewController:navController animated:YES]; | [noUverseViewController release]; | [navController release]; | break; | } | | case uveNetworkError:{ | NSLog(@"NOTIFICATION uvcSetTopBoxAssociationDidFail:uvcNetworkError"); | InfoViewController *networkViewController = [[InfoViewController alloc] initWithStyle:uvcNetworkErrorStyle]; UINavigationController *nav2Controller = [[UINavigationController alloc] initWithRootViewController:networkViewController]; [self presentModalViewController:nav2Controller animated:YES]; [networkViewController release]; © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 16 of 25 30 31 32 [nav2Controller release]; break; | } Example 5-4: uveSetTopBoxEnagagementDidFail notification 5.5 Implementing the UverseConnectedManagerSetTopBoxesUpdated Notification Callback Method The callback for UverseConnectedManagerSetTopBoxesUpdated (shown here) simply calls the setupListOfstb method (described in the next section). UverseConnectedManagerSetTopBoxesUpdated 1 2 3 4 | -(void)uveMgrSetTopBoxesUpdated:(NSNotification *)notification | { | [self setupListOfstb]; | } Example 5-5: UverseConnectedManagerSetTopBoxesUpdated 5.6 Implementing the setupListOfstb Method The setupListOfstb method performs the following actions: Sets the unknownSTBs flag to NO. Clears the list of SetTopBoxes. Enumerates through the NSArray of the UverseConnectedManager property SetTopBoxes, and adds any SetTopBoxes that are in the open (UverseModeOpen) or managed (UverseModeManaged ) modes to the list that will be displayed in the tableView. If any SetTopBoxes are in the UverseModeUnknowns state, the unknownSTBs flag will be set to YES. Sorts the list in alphabetical order. The following code shows the implementation of the setupListOfstb method. setupListOfstb 1 2 3 4 5 | -(void)setupListOfstb{ | unknownSTBs = NO; | UverseConnectedManager *uvcMgr = [UverseConnectedManager sharedManager]; | [self.list removeAllObjects]; | for (SetTopBox *stb in [uvcMgr SetTopBoxes]){ © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 17 of 25 6 7 8 | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | | | | | | | | | | | | | | 23 | 24 25 | | switch (stb.mode) { // if the mode is open or mananged, add the stb to the list of the stbs to display case UverseModeOpen: case UverseModeManaged: [self.list addObject:stb]; break; case UverseModeUnknown: unknownSTBs = YES; break; case UverseModeClosed: break; default: break; } } [self.list sortedArrayUsingComparator:^(SetTopBox *first, SetTopBox *second){ return [first.friendlyName localizedCaseInsensitiveCompare:second.friendlyName]; }]; } Example 5-6: setupListOfstb 5.7 Implementing the UITableView:cellForRowAtIndexPath Method The UITableView:cellForRowAtIndexPath: method, shown in the following code, begins by setting up a new cell. The method then contains the condition if ( indexPath.row < [self.list count]) which checks whether the row should be for an Open or managed SetTopBox on the local network, and if this condition fails, a row is displayed at the end of the tableview for “Add New Receiver”. If the condition is true, the cell is built by first getting a reference to the SetTopBox for the row and setting the name of the SetTopBox as the main text of the cell. If a row in the table for a SetTopBox is being created, there is a check to see whether the SetTopBox is in UverseModeManaged mode. If it is, the row’s image is set to be an open lock if the SetTopBox has previously been engaged or if it is currently engaged while using this app. This means that the user will not need to enter the four digit passcode when they engage with the receiver. The isAssociated property of the SetTopBox will return YES if the user has previously entered the four digit passcode for this U-verse Enabled app. If the U-verse receiver is in managed mode and the isAssociated property returns YES for the device and app, the user does not need to enter the four digit passcode again. If © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 18 of 25 the isAssociated property returns NO, the user will need to enter the four digit passcode before they can engage with the U-verse receiver, and the row’s image is set to be a closed lock to indicate that the user will need to enter the four digit passcode before being able to engage with this SetTopBox. The final check inside this condition checks to see whether the SetTopBox is currently engaged. If it is engaged, the accessoryType is set to be a checkmark, otherwise, it is left blank. UITableView:cellForRowAtIndexPath 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath | { | static NSString *CellIdentifier = @"stbCell"; | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; | if (cell == nil){ | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; | cell.textLabel.font = [UIFont systemFontOfSize:16]; | cell.textLabel.textColor = [UIColor blackColor]; | cell.imageView.image = nil; | cell.accessoryType = UITableViewCellAccessoryNone; | } | | if (indexPath.row < [self.list count] ){ | | // Configure the cell... | SetTopBox *listSTB = [self.list objectAtIndex:indexPath.row]; | // setup the name | cell.textLabel.text = listSTB.friendlyName; | | // check wether to display the lock | if (listSTB.mode = UverseModeManaged){ | if (listSTB.isAssociated || listSTB.isEngaged){ | cell.imageView.image = [UIImage imageNamed:@"PairingUnlock.png"]; | } else { | cell.imageView.image = [UIImage imageNamed:@"PairingLock.png"]; | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; | } | } | | if (listSTB.isEngaged && listSTB == © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 19 of 25 31 | 32 33 34 35 36 37 38 39 40 41 | | | | | | | | | | [UverseConnectedManager sharedManager].mostRecentlyEngagedSetTopBox){ cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryView = nil; cell.accessoryType = UITableViewCellAccessoryNone; } } else { cell.textLabel.textColor = [UIColor blueColor]; cell.textLabel.text = @"Add New Receiver..."; } return cell; } Example 5-7: UITableView:cellForRowAtIndexPath 5.8 Implementing the didSelectRowAtIndexPath Method The didSelectRowAtIndexPath method, shown in the following code, tests the mode of the selected SetTopBox to see whether it is open or engaged. The method contains a main test that checks whether the row is less than the size of the list. If this is true, it indicates that the item is a SetTopBox. If this condition fails, the flow for engaging a new SetTopBox is started by calling the displayLinkingInfoController method. Inside this branch, the mode of the SetTopBox is checked. If the SetTopBox is in the UverseModeOpen mode, it will be engaged and the app will return to the main view Controller. If the SetTopBox is in the UverseModeManaged mode, the method checks whether the SetTopBox has previously been engaged, by checking the isAssociated property of the SetTopBox. If it has been, it will engage again and the app will return to the main screen. If this condition fails, a new view controller will be displayed for the user to enter the passcode and connect with the SetTopBox. didSelectRowAtIndexPath 1 2 3 4 5 6 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath | { | [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; | if (indexPath.row < [self.list count]) { | self.currentSTB = [self.list objectAtIndex:indexPath.row]; | switch (self.currentSTB.mode) { © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 20 of 25 7 8 9 | | | 10 11 12 | | | 13 14 | | 15 16 17 18 19 20 21 22 23 24 25 26 | | | | | | | | | | | | case UverseModeOpen:{ [self.currentSTB engage]; [self.presentingViewController dismissModalViewControllerAnimated:YES]; break; case UverseModeManaged:{ if (YES == self.currentSTB.isAssociated || YES == self.currentSTB.isEngaged) { [self.currentSTB engage]; [self.presentingViewController dismissModalViewControllerAnimated:YES]; } else { [self displayPasswordController]; } break; } default: break; } // END switch }else { [self displayLinkingInfoController]; } } Example 5-8: didSelectRowAtIndexPath 5.9 Implementing the PasswordViewController Delegate Method The final method in the SetTopBoxPickerTableViewController is the PasswordViewController delegate method. The purpose of this method is to send the passcode to the setTopBox for processing and rely on the notification callbacks setup earlier for the failed or succeed states of this command. PasswordViewController 1 2 3 4 | - (void)passwordController:(PasswordViewController *)controller checkPassword:(NSString *)password { | NSLog(@"password: %@", password); | [self.currentSTB associateAndEngageWithOneTimeToken:password]; | } Example 5-9: PasswordViewController © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 21 of 25 6 PasswordViewController Design The purpose of the passwordViewController is to take a passcode entered by the user and send that passcode to its delegate to check whether the correct passcode was entered. This class was designed to be as reusable as possible, and for this reason, it does not perform any interaction with the U-verse Enabled subsystem. It simply passes the passcode to its delegate (the SetTopBoxPickerTableViewController in this code example), to be processed. The design of this viewController uses a hidden text field that stores the passcode and captures the input from the keyboard. It then sets the digits into the text fields that are displayed to the users. It’s important to note that the passwordHiddenField is not setup as a property, because this variable must not be exposed outside of the class. Figure 6-1: PasswordViewController 6.1 Implementing the viewDidLoad Method The viewDidLoad method, performs the following actions: Sets up the passwordHiddenField with a frame of CGRectZero, a zero sized rect. © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 22 of 25 Sets the delegate to be the PasswordViewController. Sets the keyboard type to be the number pad. Calls becomeFirstResponder so the keyboard will be displayed on load. Sets up the title and a label with the name of the SetTopBox. The following code shows the implementation of the viewDidLoad method. viewDidLoad 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | - (void)viewDidLoad { | [super viewDidLoad]; | | passwordHiddenField = [[UITextField alloc] initWithFrame:CGRectZero]; | passwordHiddenField.delegate = self; | passwordHiddenField.keyboardType = UIKeyboardTypeNumberPad; | passwordHiddenField.text = @""; | [passwordHiddenField becomeFirstResponder]; | [self.view addSubview:passwordHiddenField]; | | // Do any additional setup after loading the view from its nib. | self.navigationItem.title = @”Enter your Passcode"); | self.topLabel.text = [NSString stringWithFormat: @"Using your U-verse remote, tune to channel 9301 on receiver %@", self.delegate.currentSTB.friendlyName]; | } Example 6-1: viewDidLoad The passwordEntered method calls the checkPassword method of the delegate. passwordEntered is called when the user enters the four digit passcode. passwordEntered 1 2 3 4 5 6 7 | - (void)passwordEntered:(NSString *)password { | //self.waitView = [[ProgressIndictator alloc]initWithTitleLabelText:@"Please Wait" andInfoLabelText:@"Checking Passcode"]; | | if (self.delegate && [self.delegate respondsToSelector:@selector(passwordController:checkPassword:)]){ | [self.delegate passwordController:self checkPassword:password]; | } | } Example 6-2: passwordEntered © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 23 of 25 The UITextFieldDelegate method shouldChangeCharactersInRange:replacementString: is used to update the characters in the one character text fields on the screen. This method is the delegate for the UITextField called passwordHiddenField that was set in the viewDidLoad method. The shouldChangeCharactersInRange:replacementString: method uses the length of the characters in the passwordHiddenField, and then updates the four password test fields that are displayed to the user. After the user has entered four characters, the passwordEntered method is called. shouldChangeCharactersInRange:replacementString: Method 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { | NSString *password = [textField text]; | password = [password stringByReplacingCharactersInRange:range withString:string]; | | switch ([password length]) { | case 0: | self.passwordField0.text = nil; | self.passwordField1.text = nil; | self.passwordField2.text = nil; | self.passwordField3.text = nil; | break; | case 1: | self.passwordField0.text = [password substringWithRange:NSMakeRange(0, 1)]; | self.passwordField1.text = nil; | self.passwordField2.text = nil; | self.passwordField3.text = nil; | break; | case 2: | self.passwordField0.text = [password substringWithRange:NSMakeRange(0, 1)]; | self.passwordField1.text = [password substringWithRange:NSMakeRange(1, 1)]; | self.passwordField2.text = nil; | self.passwordField3.text = nil; | break; | case 3: | self.passwordField0.text = [password substringWithRange:NSMakeRange(0, 1)]; | self.passwordField1.text = [password substringWithRange:NSMakeRange(1, 1)]; | self.passwordField2.text = [password substringWithRange:NSMakeRange(2, 1)]; | self.passwordField3.text = nil; © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 24 of 25 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | | | break; case 4: self.passwordField0.text = [password substringWithRange:NSMakeRange(0, 1)]; | self.passwordField1.text = [password substringWithRange:NSMakeRange(1, 1)]; | self.passwordField2.text = [password substringWithRange:NSMakeRange(2, 1)]; | self.passwordField3.text = [password substringWithRange:NSMakeRange(3, 1)]; | | [self performSelector:@selector(passwordEntered:) withObject:password afterDelay:0]; | | return NO; | | break; | default: | return NO; | break; | } | | return YES; | | } Example 6-3: shouldChangeCharactersInRange:replacementString: Method © 2013 AT&T Intellectual Property. All rights reserved. AT&T and the AT&T logo are trademarks of AT&T Intellectual Property. Page 25 of 25
© Copyright 2024