Hello, I am new to Roku development. I took the course on youtube, saw the repository on GitHub, ran the code, and made some minor tweaks (like changing the rest API URL). But despite being on it for a month, when I am asked to do something new in it, I am totally blank! I don't know my way around the code and can't seem to get hold of the basics. The docs are not much help as there is a lot of theoretical discussion in there with little or no code snippets with specific use cases.
Can anyone tell me the basics that I need to know so that I don't get lost when I come to work on it?
Recently I was working on an app where I am supposed to display the data from the registry to a rowlist. I implemented it but it was only showing the registry value in the console, not in the rowlist. Turns out there was something to do with a field, but the docs don't provide enough info.
Please help, I am completely lost!
I agree, there aren't many resources for this type of learning. Something like step-by-step interactive tutorials would be an incredible learning tool, but they just don't exist.
Not sure if it helps, but here's a small sample project that loads posts from reddit and displays them in a vertical list. Perhaps that can give you some insights into how to write your app?
https://github.com/rokucommunity/sample-projects/tree/master/standard-with-task
Another thing to check out would be the open-source jellyfin-roku project. It's a fully-functional roku app written to support the Jellyfin media server. There are tons of good examples of real-world code in there: https://github.com/jellyfin/jellyfin-roku
I agree, there aren't many resources for this type of learning. Something like step-by-step interactive tutorials would be an incredible learning tool, but they just don't exist.
Not sure if it helps, but here's a small sample project that loads posts from reddit and displays them in a vertical list. Perhaps that can give you some insights into how to write your app?
https://github.com/rokucommunity/sample-projects/tree/master/standard-with-task
Another thing to check out would be the open-source jellyfin-roku project. It's a fully-functional roku app written to support the Jellyfin media server. There are tons of good examples of real-world code in there: https://github.com/jellyfin/jellyfin-roku
It's really tricky, and coming from other languages/environments you will stumble across a ton of "WTF"s.
Assuming this is for work, not personal projects, one thing you should try to do is manage expectations - this is a weird niche thing to be doing, there's little in the way of resources available and some of Roku's decisions about how appschannels should be developed are, uh, let's say "unique". (No closures & no classes was one of my big "???"s) You should initially be trying to build something fairly simple rather than trying to replicate an existing complex TVOS/Android/Tizen/etc app. Push features back to "version 2" as much as you possibly can, give yourself a chance to succeed!
To learn, I mostly just bashed my head against the official docs and experimented, initially. As I came across some 3rd-party libraries with source available, that gave me some ideas (good and bad) about how people do things in real life.
RowLists are exceedingly useful, I end up doing almost everything with a RowList. Definitely worth getting a good handle on those.
If you break a built in component the quickest way to figure out what you've done is just strip it back to the most basic configuration (even with dummy data, if necessary), check it works, then slowly re-add your previous settings until it doesn't any more. There's going to be no error if you misconfigure something, most of the time.
Take this example for example, I am stuck on it for a whole week and it is not budging:
XML:
Just a labelList that I shall be appending dynamically to:
<LabelList translation="[643,450]" id="queryList" itemSize="[150,48]">
<ContentNode id="queries_labels" role="content">
(here <ContentNode title='some text' /> is supposed to com dynamically)
</ContentNode>
</LabelList>
queries = ParseJson(RegRead("queries"))
print "Init registry: " queries
if queries <> invalid
content = m.queryList.content
print "Some: " content
for each regQuery in queries
print regQuery.query
queryNode = CreateObject("roSGNode", "ContentNode") ' create new node for query
child = content.createChild(queryNode) ' add node to rowlist content
child = regQuery.query
content.title = regQuery.query
print "queries: " regQuery
end for
end if
This may not be a complete answer, but...
Looks like you're creating a ContentNode, "queryNode" fine.
Then you should try "appendChild" instead of "createChild" - you only want to add the node you created.
"child = regQuery.query" can be removed, that smells of some desperate "let's just try anything" debugging 🙂
You probably want "child.title = reqQuery.query" if that "query" property is your item title.
I haven't tested it, but you might need to reassign "m.queryList.content = content" at the end to get it to update.
As it stands, this will append new items every time this code runs - if you want to run it repeatedly you'll probably want to create a new parent node each time, and add the children to that.
In the XML:
<LabelList translation="[643,450]" id="queryList" itemSize="[150,48]"/>
Just have a self-closing labellist. No need to add content.
In the BRS:
queries = ParseJson(RegRead("queries"))
print "Init registry: " queries
if queries <> invalid
if m.queryList.content <> invalid
content = m.queryList.content ' keep old content
else
content = CreateObject("roSGNode", "ContentNode") ' start new content
end if
for each regQuery in queries
print regQuery.query
queryNode = CreateObject("roSGNode", "ContentNode") ' create new node for query
queryNode.title = regQuery.query
queryNode.id = "?"
content.appendChild(queryNode) ' add node to content
print "queries: " regQuery
end for
if content <> invalid m.queryList.content = content ' update labellist with new content
end if
You have to "nest" the content nodes. The main content node is just the parent. It only has children. Then each child inside the parent node has a title and id. You need to figure out if you even need the id of the children. Maybe you do not. I have included it to show you can add one if you'd like.
I have no idea the json you are parsing if it even constructs a type you can iterate with a for each. You just check type(queries) and make sure it is. Then once you know the data you are parsing is accurate you can see in the code how this works.
You check the original list to make sure it isn't missing. If it is not missing you add the parent and its children to content. If it is missing you create the parent list content.
Then you iterate the queries. Inside you must again create a content node for the child. Then add the title and id to this child you just created. Then append this child to the main parent content.
Once all of the queries are iterated you can add the main parent content back to the labellist. It will update.
Yeah I did that, now the update is that the content shows up in the console, but not on the Roku UI.
Here's the updated code:
if queries <> invalid
if m.queryList.content <> invalid
content = m.queryList.content ' keep old content
else
content = CreateObject("roSGNode", "ContentNode") ' start new content
end if
print "Some: " content
for each regQuery in queries
content = regQuery.query
print "Content: " content
'queryNode = CreateObject("roSGNode", "ContentNode")
'contentNode = CreateObject("roSGNode", "ContentNode") ' create new node for query
'contentNode.title = regQuery.query
'queryNode.appendChild(contentNode)
'queryNode = regQuery.query
'content.appendChild(queryNode) ' add node to rowlist content
'print "QueryNode: " queryNode
print "queries: " regQuery.query
end for
end if
The commented part and the printing content directly both print the same content in the console, but not displaying the field, Is there something wrong with the XML?
We don't know what your regQuery objects look like, but this works:
m.queryList = m.top.findNode("queryList")
' queries = ParseJson(RegRead("queries"))
queries = [
{query: "Item 1"},
{query: "Item 2"},
{query: "Item 3"}
]
if queries <> invalid
content = CreateObject("roSGNode", "ContentNode")
for each regQuery in queries
child = CreateObject("roSGNode", "ContentNode")
child.title = regQuery.query
content.appendChild(child)
end for
m.queryList.content = content
end if
Maybe compare the structure of the JSON you're getting to that, and it'll provide some clues.
Great! Thanks a bunch! This worked finally! I am getting the labels now dynamically.
However, I will keep this thread open so that people can keep posting more and more learning resources related to Roku Development for future developers.
Cheers!!!