Linking a Channel to an Online Account

There are several different ways of associating a channel with an online account. In this tutorial, we will explore rendezvous style registration where a channel presents a code to the user and asks them to go to a computer and enter that code into a web site to complete the registration process. This linking method is documented in the Device Registration and Linking document in the Roku SDK.

Rendezvous style registration has the benefit of not requiring the user to type information directly into the channel using an on-screen keyboard. The downside is that the user may have to move to a different room to access the website and enter the code. In a future tutorial, we will look at the method where the user directly enters their username and password into the channel.

The first step in a rendezvous style registration is for the channel to request a linking code from your API. When your API receives that request, it should generate a new linking code and store it along with an expiration timestamp that is some reasonable amount of time in the future. Linking codes should be unique enough that no other device will be assigned the same code before the code has expired.

In the simplest case, the API can respond with the newly generated linking code and a timestamp indicating when the code expires. The API response to this request might look like this:

<apiResponse>
  <linkingCode expires="1310598793">ABC123</linkingCode>
</apiResponse>

To make the API request in BrighScript and extract the linking code, your channel would have a function similar to this one:

function GetLinkingCode()
  result = invalid

  xfer = CreateObject("roURLTransfer")
  xfer.SetURL("http://api.example.com/getLinkingCode")
  response = xfer.GetToString()
  xml = CreateObject("roXMLElement")
  if xml.Parse(response)
    result = {
      code: xml.linkingCode.GetText()
      expires: StrToI(xml.linkingCode@expires)
    }
  end if

  return result
end function

When the user validates their linking code, the API should generate a unique token for the device and store that token along with its association to the user’s account. This token will be stored by the channel in the Roku’s registry and used to identify the device to the API during future sessions.

While the registration screen is visible, the channel should periodically poll the API to find out whether the user has validated their linking code and to retrieve the associated token. A successful API response to this request might look like this:

<apiResponse>
  <status>success</status>
  <deviceToken>3F2504E0-4F89-11D3-9A0C-0305E82C3301</deviceToken>
</apiResponse>

The API may also respond to the polling request with a failure status if the user has not yet validated the linking code or the linking code has expired or some other error occurs. That response might look like this:

<apiResponse>
  <status>failure</status>
</apiResponse>

To make this API request in BrightScript and process the result, your channel might implement a function similar to the following. This function will poll the API to check whether the linking code has been validated. If the code has been validated, it saves the associated token in the registry for future use. The function returns a boolean value indicating whether the linking code has been validated.

function ValidateLinkingCode(linkingCode)
  result = false

  xfer = CreateObject("roURLTransfer")
  xfer.SetURL("http://api.example.com/validateLinkingCode?code=" + linkingCode)
  response = xfer.GetToString()
  xml = CreateObject("roXMLElement")
  if xml.Parse(response)
    if UCase(xml.status.GetText()) = "SUCCESS"
      sec = CreateObject("roRegistrySection", "mySection")      
      sec.Write("deviceToken", xml.deviceToken.GetText())
      sec.Flush()

      result = true
    end if
  end if

  return result
end function

With these two functions, you are ready to build your channel’s rendezvous linking experience. This chunk of BrightScript will get a linking code from the API, display it on a roCodeRegistrationScreen, and then start polling the API waiting for the linking code to be validated. Once the code has been validated, the screen will close.

sub ShowLinkScreen()
  dt = CreateObject("roDateTime")

  ' create a roCodeRegistrationScreen and assign it a roMessagePort
  port = CreateObject("roMessagePort")
  screen = CreateObject("roCodeRegistrationScreen")
  screen.SetMessagePort(port)

  ' add some header text
  screen.AddHeaderText("Link Your Account")
  ' add some buttons
  screen.AddButton(1, "Get new code")
  screen.AddButton(2, "Back")
  ' Add a short narrative explaining what this screen is
  screen.AddParagraph("Before you can use this channel, you must link the channel to your account.")
  ' Focal text should give specific instructions to the user
  screen.AddFocalText("Go to http://www.example.com/roku, log into your account, and enter the following code.", "spacing-normal")

  ' display a retrieving message until we get a linking code
  screen.SetRegistrationCode("Retrieving...")
  screen.Show()

  ' get a new code
  linkingCode = GetLinkingCode()
  if linkingCode <> invalid
    screen.SetRegistrationCode(linkingCode.code)
  else
    screen.SetRegistrationCode("Failed to get code...")
  end if
 
  screen.Show()

  while true
    ' we want to poll the API every 15 seconds for validation,
    ' so set a 15000 millisecond timeout on the Wait()
    msg = Wait(15000, screen.GetMessagePort())
   
    if msg = invalid
      ' poll the API for validation
      if ValidateLinkingCode(linkingCode.code)
        ' if validation succeeded, close the screen
        exit while
      end if

      dt.Mark()
      if dt.AsSeconds() > linkingCode.expires
        ' the code expired. display a message, then get a new one
        d = CreateObject("roMessageDialog")
        dPort = CreateObject("roMessagePort")
        d.SetMessagePort(dPort)
        d.SetTitle("Code Expired")
        d.SetText("This code has expired. Press OK to get a new one")
        d.AddButton(1, "OK")
        d.Show()

        Wait(0, dPort)
        d.Close()
        screen.SetRegistrationCode("Retrieving...")
        screen.Show()

        linkingCode = GetLinkingCode()
        if linkingCode <> invalid
          screen.SetRegistrationCode(linkingCode.code)
        else
          screen.SetRegistrationCode("Failed to get code...")
        end if
        screen.Show()
      end if
    else if type(msg) = "roCodeRegistrationScreenEvent"
      if msg.isScreenClosed()
        exit while
      else if msg.isButtonPressed()
        if msg.GetIndex() = 1
          ' the user wants a new code
          code = GetLinkingCode()
          linkingCode = GetLinkingCode()
          if linkingCode <> invalid
            screen.SetRegistrationCode(linkingCode.code)
          else
            screen.SetRegistrationCode("Failed to get code...")
          end if
          screen.Show()
        else if msg.GetIndex() = 2
          ' the user wants to close the screen
          exit while
        end if
      end if
    end if
  end while
 
  screen.Close()
end sub

Once the channel is successfully linked with your API, the device token will be stored in the Roku’s registry. By including the device token in subsequent API requests, your API will be able to associate the channel with the user’s account and provide the channel with appropriate data.

This entry was posted in sdk. Bookmark the permalink.
  • Pingback: Logging Into an Online Account | Developer Blog

  • Marku_sth

    how to get roku box serial number using php code so that i can control user to visit my iptv channels

    • Paras Nath Chaudhary

      In your roku script you can get your roku device id using CreateObject(“roDeviceInfo”).GetDeviceUniqueId() and then you can pass this value to your php script. An example thus would be as follows ( for me the response is json data ):

      uniqueDeviceId=CreateObject(“roDeviceInfo”).GetDeviceUniqueId()
      statusRequest=CreateObject(“roUrlTransfer”)
      statusRequest.SetURL(“http://example.com/index.php?deviceid=”+uniqueDeviceId)
      response=ParseJson(statusRequest.GetToString())

  • Biju

    where to use this code

  • Biju

    where to call these functions. should it be in new .brs file or apphome.brs file

  • http://www.milesplit.com/ Jason B

    It would be awesome if Roku could display a QR code on the screen with the URL. And they could scan it with their phone and not have to go to another room or type in a URL at all. :-)

    • http://www.roku.com/developer Patrick Ellis

      You could certainly use a web service to generate the QR code and then show it to the user.

  • Emmanueljx
  • http://profile.yahoo.com/QZJTOOUNUFEJB4W7SAP4JMW5TU Ionatan

    Isn’t easier instead of storing a unique token in device registry to store device id (using GetDeviceUniqueId function) in website database and then every time when a request is sent from channel to server to include also device id as parameter?!

    Isn’t deleted unique token stored on registry if user reset his device?

    • Paras Nath Chaudhary

      I prefer storing the device id in website database along with the unique token (in website database and device registry) .

      Data in registry is stored even if the device boots and for every reset, all registry data you have stored will be deleted.