Switch to full style
Build your BASIC! programs into an APK, right from your Android device!
Post a reply

resources in inside subdirectories

Mon Aug 29, 2016 3:10 am

Hi Nicolas-- I am still having problems getting my resources to be included in the BASIC! compiler.
I have everything under the rfo-basic/data directory in internal memory and the main directories show up but I am pretty sure it isn't including them in my apks. Are subdirectories allowed ?

I tried my voice food diary for example and it didn't include any of of the html icons or sampledb file.

I will try it on my old LG Transpyre. The phone I am having problems with is a Samsung J3 running Android 6.0.1

Re: resources in inside subdirectories

Mon Aug 29, 2016 4:18 am

Hi Chris, yes subdirectories are allowed. When you select a folder to be included as a resource in the Compiler, all its data is recursively added in the APK (files, subfolders with or w/fo files...)
If you open your apk as a zip file and look inside it, you should see everything is correctly present in assets/<app_folder>/data

Now there's a limitation in the Compiler for 2 things: the html mode and databases (you are not lucky, you use both :oops: )
Both HTML and SQL commands need the files on sdcard, they cannot render (in the case of HTML) or operate (in the case of SQL) files inside the APK.

As you may have noticed, the BASIC! Compiler doesn't have an option to copy resources to SD at startup. This is an intentional choice on my side, to keep the options small in number and to simplify the user's actions.

So for now you need to deal with these resources and copy them to SD yourself, directly in your code...

The GW lib has been modified a few versions back to do that (read the last bullet point from this post). You can adapt the dedicated GW function to your needs and call it for each of your resources.

Just add this routine at the top of your program (you may have to adapt the resource list after "IF isApk()", I only had an old version of the Voice Calorie Counter to get the resource list from):
FN.DEF IsApk() % return true (1) if we are in apk mode, false (0) otherwise
  FILE.EXISTS Editor, "../source/Sample_Programs\f01_commands.bas"
  FN.RTN (!Editor)

FN.DEF PutResOnSd(f$) % make sure the file f$ is on sd-card, else try to copy it from asset
  FILE.EXISTS onSd, f$        % This function is to be used after testing: IF IsApk() THEN ...
  IF !onSd
    BYTE.OPEN r, fid, f$      % open from assets
    IF fid<0 THEN FN.RTN 0    % file does not exist
    PRINT "Unpacking " + f$
    j = IS_IN("/", f$)
    WHILE j % create subfolder hierarchy for this file, if any
      FILE.MKDIR LEFT$(f$, j)
      j = IS_IN("/", f$, j+1)
    BYTE.COPY fid, f$

IF IsApk()
  h$ = "html/images/"
  ARRAY.LOAD htmlRes$[], "autoc.png", "graphs.png", "green.png", ~
     "red.png", "remind.png", "scale.png", "star.gif", "yellow.png"
  ARRAY.LENGTH nres, htmlRes$[]
  FOR i=1 TO nres
    PutResOnSd(h$ + htmlRes$[i])


Re: resources in inside subdirectories

Mon Aug 29, 2016 5:40 am

Chris, if the workaround above is too much trouble, should I add an additional (super advanced) option "Dump APK resources to SD-Card" ?
(and autoset it to true in case of HTML and/or SQL commands ?)


Re: resources in inside subdirectories

Tue Aug 30, 2016 2:42 pm

Thanks Nicolas!

I tried your solution and it seems to work really well.. In fact I think my app launches faster since
it takes less time copying the resources over on subsequent runs.

I'm for anything that makes apps launch quicker... I don't think I need the "copy to SD" option at this point but
thanks for offering.

I am pretty sure that the apks are indeed smaller from the rfo-compiler. My voice food diary apk is only 385Kb from the rfo compiler whereas it came out to 586Kb on QuickAPK on my PC (I did not assign an icon yet for the compiler version but I don't think it's that significant). Not sure why there is such a big discrepancy but I would even hazard to say that the rfo-compiler's apks seem to run faster than the PC generated ones.

Re: resources in inside subdirectories

Tue Sep 13, 2016 3:36 pm

Hmm... the only problem with the code is that if I alter an original resource file, I don't think it will
automatically get updated when installing a new apk.

I can check the timestamps and also replace it if the file is newer.

Re: resources in inside subdirectories

Tue Sep 13, 2016 5:12 pm

That's right, you need to deal with the updated html resources yourself, a little tedious.

AFAIK there is no timestamp in Android file system, so you would need to check content of file, or use a hash of the file.

...which makes me think we don't have an MD5() command in BASIC! and it would be very useful!

Another new command in my todo list ;)


Re: resources in inside subdirectories

Tue Sep 13, 2016 6:27 pm

Hmm but hash wouldn't work, because when you try to access a file for read in an APK the precedence is always to check in assets first, then if it doesn't exist, on sd.
It means that if you have a file both on sd and in assets, with same name, it is impossible to access the one on sd (and to calculate its hash).

So I think the preferred method in this case would be to keep a version file somewhere on sd (and *not* in assets) to tell what version of your resources is on sd.
If you don't want the user to interfere with this version file (modify or delete it) I would suggest to store it in the protected space.

Does it make sense somehow? :?


Re: resources in inside subdirectories

Tue Sep 13, 2016 11:00 pm

Other way around. The file commands always look on the sd first, then assets. If you copy an asset (or resource) to the file system, you can no longer access the asset.

Files in the file system do have timestamps. We don't have a BASIC! command to get at them, but you can use a System command. However, assets and resources do not have timestamps.

We really do need an easier way to access the app-private protected file space.

- Marc

Re: resources in inside subdirectories

Mon Mar 20, 2017 9:00 am

Look also at:



Re: resources in inside subdirectories

Tue Apr 18, 2017 11:51 am

The code sample that mougino shared works, but I modified it as follows:

Function to see if running from an APK.
Return 1 if APK, 0 otherwise.
fn.def IsApk()

   program.info ProgBundle
   bundle.get ProgBundle, "UserApk", APK

% if APK then Msg$="APK" else Msg$="Interpreter"
% dialog.message "Running from",Msg$,i

   fn.rtn (APK)


This way it does not matter if the sample_programs folder is there or not.

By the way, the compiler to generate APKs works great!

Post a reply