The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
[SOLVED] Android resource management
wilbefast


Joined: 19 Jul 2011
Posts: 115
Another slight hitch here: thus far I've been using "/data/" folder for resources, which is fine but means that the APK file and data files need to be uploaded separately from the app itself, a process which might seem trivial with the right script but which is beyond the layman and obviously incompatible with the appstore. My brief is that resources will need to be placed in a single APK archive, compressed, so impossible for me to get to file path to.

The only solution I can think of is to uncompress and export all the data to the file-system when the application is first loaded, but I'm not even sure if this is possible. It's possible to "prefer" external installation (on the sd card, so in /data/) but there's no way of forcing it if I understand correctly.

Ideas anyone?

Thanks,

William
Android resource management
gabomdq


Joined: 28 Jul 2011
Posts: 495
Location: Argentina
On Lun 07 Nov 2011 17:17:11 wilbefast escribió:
Quote:
Another slight hitch here: thus far I've been using "/data/" folder for
resources, which is fine but means that the APK file and data files need
to be uploaded separately from the app itself, a process which might seem
trivial with the right script but which is beyond the layman and obviously
incompatible with the appstore. My brief is that resources will need to be
placed in a single APK archive, compressed, so impossible for me to get to
file path to.

The only solution I can think of is to uncompress and export all the data
to the file-system when the application is first loaded, but I'm not even
sure if this is possible. It's possible to "prefer" external installation
(on the sd card, so in /data/) but there's no way of forcing it if I
understand correctly.

Ideas anyone?

I don't completely understand what you are asking, so apologies in advance if
I'm answering a question you didn't ask, but SDL supports asset reading in
Android, just place your files in "assets" in the root of your Android project,
and they'll be picked up by the Android build system when you build the
package. Accessing them (in read only mode at least) is trivial using IMG_Load
or any other function that works through RWops.
If you need to acces files somewhere else, I think you can just use fopen,
fread,etc.

Gabriel.
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Re: Android resource management
wilbefast


Joined: 19 Jul 2011
Posts: 115
gabomdq wrote:
On Lun 07 Nov 2011 17:17:11 wilbefast escribió:SDL supports asset reading in
Android, just place your files in "assets" in the root of your Android project,
and they'll be picked up by the Android build system when you build the
package. Accessing them (in read only mode at least) is trivial using IMG_Load
or any other function that works through RWops.

Gabriel.

Not sure I understand. I've always given IMG_Load a filename, which clearly isn't possible here as the file is compressed, inside an archive, somewhere in "/system/app" (I think). Yes, I know that since a .apk is just a .zip it should be theoretically possible to open it and read the contents with some library (zlib?). An yes, we can take this pointer and pass it to SDL (via RWops? Never heard of it up till now) or OpenGL directly.

But this seems like a rather dirty, round-about way of doing things, plus really dangerous to boot. I'd think it would be safest to send resources via the JNI, ie. open them in Java (Davlik has easy access to JNI contents) and pass them to the native code. What I'm wondering is whether the SDL port has anything like this implemented or whether it needs to be written from scratch. Is this what you meant?
Android resource management
gabomdq


Joined: 28 Jul 2011
Posts: 495
Location: Argentina
Quote:

But this seems like a rather dirty, round-about way of doing things, plus
really dangerous to boot. I'd think it would be safest to send resources
via the JNI, ie. open them in Java (Davlik has easy access to JNI
contents) and pass them to the native code. What I'm wondering is whether
the SDL port has anything like this implemented or whether it needs to be
written from scratch. Is this what you meant?

1) Put a image.png inside an "assets" directory in the Android project root
(that is where AndroidManifest.xml and build.xml live).
2) Call IMG_Load("image.png")
3) ndk-build, ant build, etc
3) ????
4) Profit.

SDL and Android work their magic behind the scenes, your image.png is going to
be placed inside the apk, and you don't have to worry about compression, where
it is decompressed or when, it just works. If you want to know the details,
I'm afraid you'll have to check for yourself in the source code.
This works for SDL_ttf as well if you want to load fonts for example using the
same technique (that's as far as I've tried, _image and _ttf, though I think
anything that uses RWOps should work in the same way).

Gabriel.

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Re: Android resource management
wilbefast


Joined: 19 Jul 2011
Posts: 115
gabomdq wrote:

1) Put a image.png inside an "assets" directory in the Android project root
(that is where AndroidManifest.xml and build.xml live).
2) Call IMG_Load("image.png")
3) ndk-build, ant build, etc

That's nice and simple - I'll give it a try...

Unfortunately it doesn't seem to be working: IMG_Load fails to find the file in the working directory. This despite it being in the apk under /assets. Perhaps I'm using an older version of the port which doesn't include this shortcut - is it a recent addition?

edit: found a good example of decompressing files in Java and passing them via the JNI: http://www.philhassey.com/blog/2010/07/22/android-day-3-packaging-assets-jni-and-opengl/ I'd rather get SDL's implementation working though...
Android resource management
gabomdq


Joined: 28 Jul 2011
Posts: 495
Location: Argentina
Quote:
Unfortunately it doesn't seem to be working: IMG_Load fails to find the
file in the working directory. This despite it being in the apk under
/assets. Perhaps I'm using an older version of the port which doesn't
include this shortcut - is it a recent addition?

I don't remember when these patches by Tim Angus where applied but I think it
was fairly recent, for more information you should check Bugzilla for the
"android" keyword, check the closed tickets, you'll see this patch I'm
refering to, the multitouch stuff, and some other changes (like OpenGL ES 2
support).

Gabriel.
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Re: Android resource management
wilbefast


Joined: 19 Jul 2011
Posts: 115
gabomdq wrote:
patches by Tim Angus

Found it:
http://bugzilla.libsdl.org/show_bug.cgi?id=1261

I guess it's time I got the new release of Mercurial, since I don't know whether the version I'm using is compatible with the patch. So: replaced the old SDL C code, plus the SDLActivity class with the new one.

Okay, so a little error:
Code:
11-08 23:54:53.890: ERROR/AndroidRuntime(23069): Caused by: java.lang.UnsatisfiedLinkError: Library main not found
11-08 23:54:53.890: ERROR/AndroidRuntime(23069):     at java.lang.Runtime.loadLibrary(Runtime.java:461)
11-08 23:54:53.890: ERROR/AndroidRuntime(23069):     at java.lang.System.loadLibrary(System.java:557)
11-08 23:54:53.890: ERROR/AndroidRuntime(23069):     at org.libsdl.app.SDLActivity.<clinit>(SDLActivity.java:43)


I replaced:
Code:
        System.loadLibrary("SDL");
        //System.loadLibrary("SDL_image");
        //System.loadLibrary("SDL_mixer");
        //System.loadLibrary("SDL_ttf");
        System.loadLibrary("main");


With what I had before:
Code:
      System.loadLibrary("SDL");
      System.loadLibrary("SDL_image");
      System.loadLibrary("mikmod");
      System.loadLibrary("SDL_mixer");
      System.loadLibrary("SDL_ttf");
      System.loadLibrary("main");


Working now, except I notices touches are no longer interpreted as mouse clicks so I'll need to modify my code to support the new multi-touch stuff... Still, thanks a lot gabomdq, I can now load images from the apk Very Happy
Re: Android resource management
wilbefast


Joined: 19 Jul 2011
Posts: 115
This works so well I forgot myself a moment and tried to use it for TinyXML - dang, looks like I'll still need to write something that extracts the XML files. Well, if you'll excuse me I'm off to cannibalise some code...
[SOLVED] Android resource management
Jonny D


Joined: 12 Sep 2009
Posts: 932
Did you look at TiXmlDocument::Parse()?  I don't know where the magic is happening on Android, but if something like SDL_RWFromFile() works by itself, then you might be able to pass the char data to Parse().

Jonny D


On Fri, Nov 11, 2011 at 4:54 PM, wilbefast wrote:
Quote:
This works so well I forgot myself a moment and tried to use it for TinyXML - dang, looks like I'll still need to write something that extracts the XML files. Well, if you'll excuse me I'm off to cannibalise some code...


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Re: [SOLVED] Android resource management
wilbefast


Joined: 19 Jul 2011
Posts: 115
Jonny D wrote:
Did you look at TiXmlDocument::Parse()?  I don't know where the magic is happening on Android, but if something like SDL_RWFromFile() works by itself, then you might be able to pass the char data to Parse().

Good idea Smile only one way to find out. Actually two ways: read the code or try it and see what happens. I'm too impatient to read code so I switched to loading using RWops to see what would happen. Here are my results:

Code:
int io::read_text(const char* source_file, char* destination)
{
    // Open the file
    SDL_RWops *file;
    file = SDL_RWFromFile(source_file, "r");
    ASSERT(file, "Opening file using SDL_RWops");

    // Read text from file
    int n_blocks = SDL_RWread(file, destination, BLOCK_SIZE, MAX_BLOCKS);
    // BLOCK_SIZE = 8, MAX_BLOCKS = 1024
    SDL_RWclose(file);

    // Make sure the operation was successful
    ASSERT(n_blocks >= 0, "Reading blocks of data from SDL_RWops");
    WARN_IF(n_blocks == MAX_BLOCKS, "Reading data from SDL_RWops",
                                    "Buffer full so may be too small for data");

    // Success!
    return EXIT_SUCCESS;
}


Used as follows:

Code:
    // Generate world XML file name based on number
    char file_name[32];
    WARN_IF((sprintf(file_name, "%sworld_%d.xml", ASSET_PATH, world_number) < 0),
            "Game::load_things", "buffer to small to create formatted string");

    /// ATTEMPT TO OPEN THE XML FILE
    // Open with SDL_RWops
    char file_contents[io::MAX_BLOCKS];
    ASSERT(io::read_text(file_name, file_contents) == EXIT_SUCCESS,
            "Reading XML World contents");

    // Pass string to the TinyXML document
    TiXmlDocument doc;
    doc.Parse(file_contents);
    ASSERT_AUX(doc.Parse(file_contents), "Opening world XML file",
               doc.ErrorDesc());


Works on both Linux and Android Very Happy

Assertions are warning are used to wrap stderr or __android_log_print depending on platform. Long story short, XML can now be loaded from the assets folder. Thanks for the pointer Very Happy
[SOLVED] Android resource management
Jonny D


Joined: 12 Sep 2009
Posts: 932
Sweet.

Jonny D


On Sat, Nov 12, 2011 at 7:41 AM, wilbefast wrote:
Quote:



Jonny D wrote:

Did you look at TiXmlDocument::Parse()?  I don't know where the magic is happening on Android, but if something like SDL_RWFromFile() works by itself, then you might be able to pass the char data to Parse().



Good idea only one way to find out. Actually two ways: read the code or try it and see what happens. I'm too impatient to read code so I switched to loading using RWops to see what would happen. Here are my results:




Code:

int io::read_text(const char* source_file, char* destination)
{
    // Open the file
    SDL_RWops *file;
    file = SDL_RWFromFile(source_file, "r");
    ASSERT(file, "Opening file using SDL_RWops");

    // Read text from file
    int n_blocks = SDL_RWread(file, destination, BLOCK_SIZE, MAX_BLOCKS);
    // BLOCK_SIZE = 8, MAX_BLOCKS = 1024
    SDL_RWclose(file);

    // Make sure the operation was successful
    ASSERT(n_blocks >= 0, "Reading blocks of data from SDL_RWops");
    WARN_IF(n_blocks == MAX_BLOCKS, "Reading data from SDL_RWops",
                                    "Buffer full so may be too small for data");

    // Success!
    return EXIT_SUCCESS;
}




Used as follows:




Code:

    // Generate world XML file name based on number
    char file_name[32];
    WARN_IF((sprintf(file_name, "%sworld_%d.xml", ASSET_PATH, world_number) < 0),
            "Game::load_things", "buffer to small to create formatted string");

    /// ATTEMPT TO OPEN THE XML FILE
    // Open with SDL_RWops
    char file_contents[io::MAX_BLOCKS];
    ASSERT(io::read_text(file_name, file_contents) == EXIT_SUCCESS,
            "Reading XML World contents");

    // Pass string to the TinyXML document
    TiXmlDocument doc;
    doc.Parse(file_contents);
    ASSERT_AUX(doc.Parse(file_contents), "Opening world XML file",
               doc.ErrorDesc());




Works on both Linux and Android

Assertions are warning are used to wrap stderr or __android_log_print depending on platform. Long story short, XML can now be loaded from the assets folder. Thanks for the pointer


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Re: [SOLVED] Android resource management
wilbefast


Joined: 19 Jul 2011
Posts: 115
Blog post explaining all this in detail Smile
http://wilbefast.com/2011/11/16/tinyxmlsdl-glue-code/