How is it possible to save some basic, small amount of data to the registry. I wish to store a zip code to be retrieved when the app is loaded. Since you can’t write to a file and retain it after the app closes, the only way to save it is in the registry, but how?
Thanks
I have looked at the sdk and see what it says on creating a section in the registry to save info to and also the example on reading it. But how do you assign the info back to say a variable to work with it. For example, I used the following to save the info to the registry, the result comes from user input thru the on screen keyboard.
in the SDK -
'******************************************************
'Registry Helper Functions
'******************************************************
Function RegRead(key,section=invalid)
If section=invalid section=“Default”
sec=CreateObject(“roRegistrySection”,section)
If sec.Exists(key) Return sec.Read(key)
Return invalid
End Function
Function RegWrite(key,val,section=invalid)
If section=invalid section=“Default”
sec=CreateObject(“roRegistrySection”,section)
sec.Write(key,val)
sec.Flush() 'commit it
End Function
Function RegDelete(key,section=invalid)
If section=invalid section=“Default”
sec=CreateObject(“roRegistrySection”,section)
sec.Delete(key)
sec.Flush()
End Function
so to read and store in a variable you would use variablename=regread(“keyname”,“registrysectionname”)
to write the variable back you would use regwrite(“keyname”,data to write,“registrysectionname”)
to delete the value from the registry is regdelete(“keyname”,“registrysectionname”)
AFAIK the roku registry saves/reads all data as a string. So if your zipcode is numeric, you might need to change it to a string first before writing - but definitely after reading it will be in string form and you’ll need to convert it back to an integer if you are using it as an integer.
In addition to storing the data to the roku registry (limited to 16KB), you could fairly easily send the data to your server and have the server store it in a database or text file or something on the server. This way if your client has 4 or 5 rokus, the value of this data will persist between physical devices instead of being limited to the roku they used to save to the registry - it’s how NetFlix and Amazon do it - saving data to their servers.
I’m just now trying to learn using registry, so this is helpful. But I don’t understand the section=invalid
bits, that just seems odd to me, how does that literally work?
It also seems odd to me to always be creating the registry sections with the same name each time the function are run - wouldn’t you want to just create each section once?
The section=invalid sets a default value if it’s not specified when calling the function.
It’s also not ‘creating the section’ - it’s specifying the section, which is required if you use more than one section.
I’d think of it this way - suppose you use the registry for saving bookmarks for video, saving user data like email address, name, and user number.
I’d use one section for the bookmarks for the channel (independent of channel within the same devid) and a second section for the user data (shared between channels on the same devid)
This way I could sort the bookmarks, limit the number of bookmarks, etc, through the registry without modifying the user data using for each based on the section instead of having to track each key, date, video position, etc.
Sure, you could do it all in the same section, just it makes it a little more complicated as you eliminate stuff you don’t want to mess with.
I think you could improve this code easily by setting the sec createobject line as an AA - but really in practice it’s not much slower to create it as needed for the relatively slow operation of writing or reading or deleting a value from the registry.
Any clues on how this is really taken up?
For instance, is one character 1 byte?
Does each key/value pair take up some set amount of space?
Can we use keys/values of very long length, like big sentences or paragraphs?
Do I just have to test all this myself and see what works?
Well, it’s a little complicated. Each registry entry stores the name and value, with a two byte header in front of each (so 4 extra bytes per entry). In addition there is a small header for each registry section (2 bytes plus the section name I think), and another header for the whole registry (about 30 bytes). However, the whole thing is zlib compressed before storing it, and it’s the compressed file that is limited to 16K. This makes it rather difficult to predict exactly how much space you will be using. I’m not sure how knowing the exact size would be helpful, unless you’re caching things in the registry that can be obtained elsewhere.
I appreciate the detailed insight into space usage with the extra bytes here and there. Basically I’m implementing a save game file using the registry, with quite a bit of info, so I’m trying to get a feel for how much practical room I really have.
Any idea how much the zlib compression helps? 50%? Varies?
You can probably get a rough idea by creating a text file containing all your keys and values and run it through gzip. The actual amount of compression is highly dependent on the data, so if you store different values at different times (as you certainly would for a game), the size will vary. A very safe approach would be to limit your uncompressed data to 16K.
“RokuMarkn” wrote:
Well, it’s a little complicated. […] the whole thing is zlib compressed before storing it, and it’s the compressed file that is limited to 16K. This makes it rather difficult to predict exactly how much space you will be using …
RokuMarkn - Is this also the case with persist?
In my tests seems any persist_quota < 68 is ignored (“ask and you shall receive… default quota”) - but which is worse, any change (increase or decrease) in larger values causes the storage content to be lost.
Which behavior is a horrible thing because how do you explain to a user that their saved game levels were be lost during app update? Moreover, there is no way to warn them not to update (channel updates are automatic). And can’t take evasive action because by the time the new version is running, the old persist is gone
6000 keys of all the same 8 characters compresses from about 96KB down to under 16KB, but 8000 doesn’t. This is silly though as they are all the same, easy targets for compression, and unrealistic.
3000 keys of all different 4 characters compresses from about 34KB down to under 16KB, but 4000 doesn’t. This is closer to reality with the different keys, but still might be quite a ways off since they were all written and flushed at the same time and were sequential and are the same length.
Interestingly, I tested 20,000 keys of 8 characters and it works between sessions (user can exit channel to Home, load another channel, exit that channel, and restart my channel, and all the keys load up just fine. But a power cycle of the Roku box loses all the info, as though it was never flushed.
RokuMarkn - Is this also the case with persist?
In my tests seems any persist_quota < 68 is ignored (“ask and you shall receive… default quota”) - but which is worse, any change (increase or decrease) in larger values causes the storage content to be lost.
Yes, 64K is the smallest possible persist filesystem, so smaller numbers are taken to mean 64K.
But it’s not supposed to lose content if you change the persist size. It’s supposed to create a new filesystem of the requested size, copy the files from the old one to the new one, and delete the old one. I haven’t tested it but that’s what the code says.
“RokuMarkn” wrote:
Yes, 64K is the smallest possible persist filesystem, so smaller numbers are taken to mean 64K.
Per my tests, the actual cut-off is persist_quota=67 vs 68 for some odd reason and the maximum file size under the default quota is 35840 bytes but that’s small beer -
But it’s not supposed to lose content if you change the persist size. It’s supposed to create a new filesystem of the requested size, copy the files from the old one to the new one, and delete the old one. I haven’t tested it but that’s what the code says.
Unfortunately it does not do what it’s supposed to. ANY change in the filesystem allocation leads to content loss; be it from default to custom (>67) quota or back, be it increase or decrease in the custom quota. I would have expected at least increase in the quota to preserve the content and decrease to preserve it if the actual content fit in the smaller quota but no - the contents gets lost. Boom! - and your save levels are toast and the app thinks this is brand new install. I am very sure of it, i did a meticulous, exhaustive testing (over 50 tests, will PM spreadsheet of the results).
I ran into this “feature” first couple of months ago, when i decided to be modest and decrease the persist_quota=16384 which Marmalade plants by default*. The reason i asked above if persist gets zlib compressed like the registry - the reason being that if it doesn’t get squeezed somehow, a Roku is losing 16MB flash per Marmalade game. Which given the total of 256MB flash means some horrible things will start happening when a dozen (possibly half a dozen) Marmaladen games are installed. I can’t know what things exactly but know when memory is low, things don’t go well…
So if I have a half dozen registry sections, each with a single key whole value is a large string, can I simply check the length of my strings, add them up, add in a few more bytes for the various registry headers, and know pretty close how many bytes I’m using (before compression)?
Assuming you’re using ASCII characters, one char equals one byte. Strings are stored as UTF-8, so if you’re using non-ASCII chars it’s more complicated.