BASIC! and Android Resources - RFO-BASIC/Basic GitHub Wiki
Android has things called resources. That may be an unfortunate term, because it can refer to memory space, screen size, sensors, or other physical resources. When you build an Android app, a "resource" is a data file - image, sound, text, anything you like - that gets compiled into the APK where the app can use the data directly.
BASIC! is an Android app. It uses these resources. But, BASIC!, the language, does not give users a way to define resources. So what does BASIC! use them for? It uses them two ways.
First, BASIC! uses resources to create the sample programs in "rfo-basic/source/Sample_Programs" on the Android device. It also uses resources to create the files in "rfo-basic/data", used by the sample programs.
When a new version of BASIC! is started for the first time, you see the message "Standby for initial file loading." What BASIC! is doing then is writing data from the compiled-in resources to the file system.
Second, BASIC! can be compiled with a program file built in. To the user, it looks like the included program is running as an app - the user does not see BASIC!. To build a standalone APK this way, you have to make some changes to the BASIC! Android source code. This process is described in Appendix D of De Re BASIC!, the BASIC! user's manual.
When BASIC! and an included program are compiled as a standalone APK, some BASIC! commands that can open files for reading can open resources instead. These commands:
- BYTE.OPEN
- TEXT.OPEN
- GR.BITMAP.LOAD
- AUDIO.LOAD
- SOUNDPOOL.LOAD look for a file. If the file does not exist, they look in the compiled-in resources.
This means that if you want to build an app that runs on BASIC!, and your app needs to load data from a file, you can compile the file into the app. To install your app, a user does not need to download the data file along with your APK file. The user can just install the APK and run.
You, as the developer of a standalone app using BASIC!, can use resources the same way BASIC! does. Which way you use them depends on whether or not you want BASIC! to create files.
If you do not want files, then your BASIC! program can load data from resources instead. All you have to do is put the files you want to use into the res/raw folder in Eclipse. Your BASIC! program will find the resources. If that description doesn't make sense to you, don't worry about it: Mougino's AppBuilder, also described in Appendix D of the manual, does it for you.
But some BASIC! commands that read files do not look for resources. For example, HTML.LOAD.URL can take a file name formatted as a URL, like "file:///sdcard/rfo-basic/data/htmlDemo.html". The command does not have a way to convert a name in this format to a resource name.
You could change your program so that it loads the HTML as text, using TEXT.OPEN and TEXT.READLN, and then read the HTML with HTML.LOAD.STRING. Or you could tell BASIC! to create the file at start-up. Where Appendix D tells you to remove all the file names from "LoadFileNames[]", put in your file name. Where it says to set apkCreateDataDir to false, leave it true. At start-up, your app will create your file.
If you are comfortable with the idea of putting a file into your app as a compiled-in resource, you may want to consider one more extension of this idea.
When you put a file into the res/raw folder, the Android build process puts the file's data into your app's installable APK. Internally, Android does not use your file's whole name. It drops the file's extension. (In fact, if your file name has a dot in it anywhere, Android drops that dot and everything after it.) So, for example, if your resource was a file named "dragon.png", Android sees it as "dragon". Its full name inside Android is "R.raw.dragon". If the file was named "dragon.flying.png", Android sees it as "R.raw.dragon". And if the file was named "dragon.wav", Android sees it as "R.raw.dragon".
You can't have more than one resource with the same full name inside Android. If you have files "dragon.png" and "dragon.wav" in res/raw, they are both "R.raw.dragon" to Android, so your build fails. In standard Android apps, Android lets you have resources with the same file name if you put them in different resource folders. If "dragon.png" is in "res/drawable", its Android internal name is "R.drawable.dragon". But a BASIC! program built into a standalone app is not the same as a standard Android app. BASIC! gives you access to "res/raw", but not to any other resource folder.
Instead, BASIC! gives you a way to put related resources into "res/raw". If you want files "dragon.png" and "dragon.wav" in "res/raw", you can put them there, but you have to change their names: replace the dot with an underscore. So, for example, you change "dragon.png" to "dragon_png" and "dragon.wav" to "dragon_wav". You do not change the BASIC! commands that open the files or resources. The BASIC! commands can find resources with their names changed this way. [NOTE: THIS DOES NOT WORK NOW. This is the way BASIC! was intended to work, but in versions through v01.72, it is broken. This page will be updated when the bug is fixed.]
WORKAROUND FOR VERSIONS v01.72 and earlier
You can put any resource into "res/raw" and access it from BASIC! commands, even in versions where the automatic name translation is broken, if you understand how BASIC!'s automatic name translation works.
In the broken versions, a file name is converted to a resource name just by dropping everything from the first dot to the end -- just like normal Android conversion. There is no substitution changing dots to underscores. If there is no dot in the file name, the conversion produces an empty string, which is never a valid resource, so your application closes with a runtime error.
If you don't change your file names when you make them into resources, there is no workaround needed -- everything works already. Don't change the resource names and don't change any BASIC! commands. If the file name was "my.file" and the BASIC! command is TEXT.OPEN r,f1,"my.file" then the resource name is actually "R.raw.my" and everything works.
If you have files that are named the same except for their extensions, you need to work around this bug. Here's how: you change your resource names, then change your BASIC! commands so the "file name" they look for is actually the name of the resource, but with a dot artificially added at the end.
If you have resource files named "x.y" and "x.z", the internal Android name of both would be "R.raw.x". Instead, change the resource names to "x_y" and "x_z".
Then, your original BASIC! commands may have been TEXT.OPEN r,f1,"x.y" BYTE.OPEN r,f2,"x.z" Instead, change them to TEXT.OPEN r,f1,"x_y." BYTE.OPEN r.f2,"x_z."
This will work with versions v01.69, 70, 71, and 72. I have not looked at versions earlier than that.