PhysicsFS on Android

Hey guys,

Is anyone using PhysicsFS and SDL 2.0 together on Android? I would really
like to read my Android assets through PhysFS, but I haven’t been able to
get PhysFS to see them. Normally I would use SDL_RWops to get the assets
transparently in the apk, but PhysFS does its own file locating, which
won’t work for apk assets. I can convert a PHYSFS_File into a SDL_RWops,
but not the other way around.

I’m hoping I don’t have to write JNI code for it. :frowning:

Jonny D

The way i did it is to not put my assets to the apk But download them to a
folder once the application starts.Then i used physfs to mount the folder
and read it.This is how applications with big assets are doing it.You want
to have your applications size minimal.Thats the reason you download on
init.On Sun, May 26, 2013 at 4:43 PM, Jonathan Dearborn wrote:

Hey guys,

Is anyone using PhysicsFS and SDL 2.0 together on Android? I would really
like to read my Android assets through PhysFS, but I haven’t been able to
get PhysFS to see them. Normally I would use SDL_RWops to get the assets
transparently in the apk, but PhysFS does its own file locating, which
won’t work for apk assets. I can convert a PHYSFS_File into a SDL_RWops,
but not the other way around.

I’m hoping I don’t have to write JNI code for it. :frowning:

Jonny D


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I could see that working decently, but not really great for small apks
(mine is less than 2 MB). It does take a lot of infrastructure both for
serving and downloading, and you end up with a worthless apk if the server
or the client connection is down temporarily or permanently.

Wouldn’t it be almost the same to copy the files from the apk to internal
storage and then mount it with PhysFS? Still not ideal…

Jonny DOn Sun, May 26, 2013 at 12:14 PM, Dimitris Zenios <dimitris.zenios at gmail.com wrote:

The way i did it is to not put my assets to the apk But download them to a
folder once the application starts.Then i used physfs to mount the folder
and read it.This is how applications with big assets are doing it.You want
to have your applications size minimal.Thats the reason you download on
init.

On Sun, May 26, 2013 at 4:43 PM, Jonathan Dearborn <@Jonathan_Dearborn>wrote:

Hey guys,

Is anyone using PhysicsFS and SDL 2.0 together on Android? I would
really like to read my Android assets through PhysFS, but I haven’t been
able to get PhysFS to see them. Normally I would use SDL_RWops to get the
assets transparently in the apk, but PhysFS does its own file locating,
which won’t work for apk assets. I can convert a PHYSFS_File into a
SDL_RWops, but not the other way around.

I’m hoping I don’t have to write JNI code for it. :frowning:

Jonny D


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

What I do is keep loose files on Android and use a zip data file everywhere
else. The loose files get put into a compressed asset archive anyway, so
it’s functionally equivalent. If I left the files in the zip, Android may
be uncompressing the zip from the asset archive at runtime to access a
file, which I wanted to avoid.

As other people mentioned, if you’re working with a large amount of data it
may be worth downloading it at runtime.

There are some Android specific functions in SDL_system.h that may be
useful for you:
SDL_AndroidGetInternalStoragePath()
SDL_AndroidGetExternalStorageState()
SDL_AndroidGetExternalStoragePath()

Here is my filesystem code, which you’re welcome to use under the zlib
license:

/*
Copyright © 2012-2013 Sam Lantinga <@slouken>

This software is provided ‘as-is’, without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
    claim that you wrote the original software. If you use this software
    in a product, an acknowledgment in the product documentation would be
    appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
    */

/* ----------------------------------------------------------------- /
/
– Initialize PHYSFS and mount the data archive */
bool
InitFilesystem(const char *argv0)
{
const char *prefspath;

if (!PHYSFS_init(argv0)) {
    error("Couldn't initialize PHYSFS: %s\n", PHYSFS_getLastError());
    return false;
}

// Set up the write directory for this platform

#ifdef ANDROID
prefspath = SDL_AndroidGetInternalStoragePath();
#else
prefspath = PHYSFS_getPrefDir(EQUATE_ORGANIZATION, EQUATE_NAME);
#endif
if (!prefspath) {
error(“Couldn’t get preferences path for this platform\n”);
return false;
}
if (!PHYSFS_setWriteDir(prefspath)) {
error(“Couldn’t set write directory to %s: %s\n”, prefspath,
PHYSFS_getLastError());
return false;
}

/* Put the write directory first in the search path */
PHYSFS_mount(prefspath, NULL, 0);

#ifdef ANDROID
// We’ll use SDL’s asset manager code path for Android
return true;

#else
/* Then add the base directory to the search path */
PHYSFS_mount(PHYSFS_getBaseDir(), NULL, 0);

/* Then add the data file, which could be appended to the executable */
if (PHYSFS_mount(argv0, "/", 1)) {
    return true;
}

/* ... or not */
char path[4096];
SDL_snprintf(path, SDL_arraysize(path), "%s%s", PHYSFS_getBaseDir(),

EQUATE_DATA);
if (PHYSFS_mount(path, “/”, 1)) {
return true;
}

SDL_snprintf(path, SDL_arraysize(path), "%sContents/Resources/%s",

PHYSFS_getBaseDir(), EQUATE_DATA);
if (PHYSFS_mount(path, “/”, 1)) {
return true;
}

error("Couldn't find %s", EQUATE_DATA);
return false;

#endif // ANDROID
}

SDL_RWops *OpenRead(const char *fname)
{
#ifdef ANDROID
return SDL_RWFromFile(fname, “rb”);
#else
return PHYSFSRWOPS_openRead(fname);
#endif
}

SDL_RWops *OpenWrite(const char *fname)
{
#ifdef ANDROID
return SDL_RWFromFile(fname, “wb”);
#else
return PHYSFSRWOPS_openWrite(fname);
#endif
}On Sun, May 26, 2013 at 10:29 AM, Jonathan Dearborn wrote:

I could see that working decently, but not really great for small apks
(mine is less than 2 MB). It does take a lot of infrastructure both for
serving and downloading, and you end up with a worthless apk if the server
or the client connection is down temporarily or permanently.

Wouldn’t it be almost the same to copy the files from the apk to internal
storage and then mount it with PhysFS? Still not ideal…

Jonny D

On Sun, May 26, 2013 at 12:14 PM, Dimitris Zenios < dimitris.zenios at gmail.com> wrote:

The way i did it is to not put my assets to the apk But download them to
a folder once the application starts.Then i used physfs to mount the folder
and read it.This is how applications with big assets are doing it.You want
to have your applications size minimal.Thats the reason you download on
init.

On Sun, May 26, 2013 at 4:43 PM, Jonathan Dearborn wrote:

Hey guys,

Is anyone using PhysicsFS and SDL 2.0 together on Android? I would
really like to read my Android assets through PhysFS, but I haven’t been
able to get PhysFS to see them. Normally I would use SDL_RWops to get the
assets transparently in the apk, but PhysFS does its own file locating,
which won’t work for apk assets. I can convert a PHYSFS_File into a
SDL_RWops, but not the other way around.

I’m hoping I don’t have to write JNI code for it. :frowning:

Jonny D


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

It’s not a lot of data, ~100kB. What I’m working with is a modding system
that uses PhysicsFS to load the mods preferentially over the base assets.
There is a built-in mod (zip file) that provides the default levels and
such.

Thanks for the suggestions so far. I checked out the Maelstrom code for
how it uses PhysFS on Android and that is an option, but perhaps not for
this particular use-case.

Jonny DOn Sun, May 26, 2013 at 1:41 PM, Sam Lantinga wrote:

What I do is keep loose files on Android and use a zip data file
everywhere else. The loose files get put into a compressed asset archive
anyway, so it’s functionally equivalent. If I left the files in the zip,
Android may be uncompressing the zip from the asset archive at runtime to
access a file, which I wanted to avoid.

As other people mentioned, if you’re working with a large amount of data
it may be worth downloading it at runtime.

There are some Android specific functions in SDL_system.h that may be
useful for you:
SDL_AndroidGetInternalStoragePath()
SDL_AndroidGetExternalStorageState()
SDL_AndroidGetExternalStoragePath()

Here is my filesystem code, which you’re welcome to use under the zlib
license:

/*
Copyright © 2012-2013 Sam Lantinga

This software is provided ‘as-is’, without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
    claim that you wrote the original software. If you use this software
    in a product, an acknowledgment in the product documentation would be
    appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not
    be
    misrepresented as being the original software.
  3. This notice may not be removed or altered from any source
    distribution.
    */

/* ----------------------------------------------------------------- /
/
– Initialize PHYSFS and mount the data archive */
bool
InitFilesystem(const char *argv0)
{
const char *prefspath;

if (!PHYSFS_init(argv0)) {
    error("Couldn't initialize PHYSFS: %s\n", PHYSFS_getLastError());
    return false;
}

// Set up the write directory for this platform

#ifdef ANDROID
prefspath = SDL_AndroidGetInternalStoragePath();
#else
prefspath = PHYSFS_getPrefDir(EQUATE_ORGANIZATION, EQUATE_NAME);
#endif
if (!prefspath) {
error(“Couldn’t get preferences path for this platform\n”);
return false;
}
if (!PHYSFS_setWriteDir(prefspath)) {
error(“Couldn’t set write directory to %s: %s\n”, prefspath,
PHYSFS_getLastError());
return false;
}

/* Put the write directory first in the search path */
PHYSFS_mount(prefspath, NULL, 0);

#ifdef ANDROID
// We’ll use SDL’s asset manager code path for Android
return true;

#else
/* Then add the base directory to the search path */
PHYSFS_mount(PHYSFS_getBaseDir(), NULL, 0);

/* Then add the data file, which could be appended to the executable */
if (PHYSFS_mount(argv0, "/", 1)) {
    return true;
}

/* ... or not */
char path[4096];
SDL_snprintf(path, SDL_arraysize(path), "%s%s", PHYSFS_getBaseDir(),

EQUATE_DATA);
if (PHYSFS_mount(path, “/”, 1)) {
return true;
}

SDL_snprintf(path, SDL_arraysize(path), "%sContents/Resources/%s",

PHYSFS_getBaseDir(), EQUATE_DATA);
if (PHYSFS_mount(path, “/”, 1)) {
return true;
}

error("Couldn't find %s", EQUATE_DATA);
return false;

#endif // ANDROID
}

SDL_RWops *OpenRead(const char *fname)
{
#ifdef ANDROID
return SDL_RWFromFile(fname, “rb”);
#else
return PHYSFSRWOPS_openRead(fname);
#endif
}

SDL_RWops *OpenWrite(const char *fname)
{
#ifdef ANDROID
return SDL_RWFromFile(fname, “wb”);
#else
return PHYSFSRWOPS_openWrite(fname);
#endif
}

On Sun, May 26, 2013 at 10:29 AM, Jonathan Dearborn <@Jonathan_Dearborn>wrote:

I could see that working decently, but not really great for small apks
(mine is less than 2 MB). It does take a lot of infrastructure both for
serving and downloading, and you end up with a worthless apk if the server
or the client connection is down temporarily or permanently.

Wouldn’t it be almost the same to copy the files from the apk to internal
storage and then mount it with PhysFS? Still not ideal…

Jonny D

On Sun, May 26, 2013 at 12:14 PM, Dimitris Zenios < dimitris.zenios at gmail.com> wrote:

The way i did it is to not put my assets to the apk But download them to
a folder once the application starts.Then i used physfs to mount the folder
and read it.This is how applications with big assets are doing it.You want
to have your applications size minimal.Thats the reason you download on
init.

On Sun, May 26, 2013 at 4:43 PM, Jonathan Dearborn <@Jonathan_Dearborn>wrote:

Hey guys,

Is anyone using PhysicsFS and SDL 2.0 together on Android? I would
really like to read my Android assets through PhysFS, but I haven’t been
able to get PhysFS to see them. Normally I would use SDL_RWops to get the
assets transparently in the apk, but PhysFS does its own file locating,
which won’t work for apk assets. I can convert a PHYSFS_File into a
SDL_RWops, but not the other way around.

I’m hoping I don’t have to write JNI code for it. :frowning:

Jonny D


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Yeah, to do that you’ll probably have to write a backend for PhysFS that
uses SDL_rwops which in turn uses JNI to load assets.

If you end up doing this, please let Ryan know so other people can use it!
(icculus a t icculus.org)On Sun, May 26, 2013 at 11:44 AM, Jonathan Dearborn wrote:

It’s not a lot of data, ~100kB. What I’m working with is a modding system
that uses PhysicsFS to load the mods preferentially over the base assets.
There is a built-in mod (zip file) that provides the default levels and
such.

Thanks for the suggestions so far. I checked out the Maelstrom code for
how it uses PhysFS on Android and that is an option, but perhaps not for
this particular use-case.

Jonny D

On Sun, May 26, 2013 at 1:41 PM, Sam Lantinga <@slouken> wrote:

What I do is keep loose files on Android and use a zip data file
everywhere else. The loose files get put into a compressed asset archive
anyway, so it’s functionally equivalent. If I left the files in the zip,
Android may be uncompressing the zip from the asset archive at runtime to
access a file, which I wanted to avoid.

As other people mentioned, if you’re working with a large amount of data
it may be worth downloading it at runtime.

There are some Android specific functions in SDL_system.h that may be
useful for you:
SDL_AndroidGetInternalStoragePath()
SDL_AndroidGetExternalStorageState()
SDL_AndroidGetExternalStoragePath()

Here is my filesystem code, which you’re welcome to use under the zlib
license:

/*
Copyright © 2012-2013 Sam Lantinga <@slouken>

This software is provided ‘as-is’, without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
    claim that you wrote the original software. If you use this software
    in a product, an acknowledgment in the product documentation would be
    appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not
    be
    misrepresented as being the original software.
  3. This notice may not be removed or altered from any source
    distribution.
    */

/* ----------------------------------------------------------------- /
/
– Initialize PHYSFS and mount the data archive */
bool
InitFilesystem(const char *argv0)
{
const char *prefspath;

if (!PHYSFS_init(argv0)) {
    error("Couldn't initialize PHYSFS: %s\n", PHYSFS_getLastError());
    return false;
}

// Set up the write directory for this platform

#ifdef ANDROID
prefspath = SDL_AndroidGetInternalStoragePath();
#else
prefspath = PHYSFS_getPrefDir(EQUATE_ORGANIZATION, EQUATE_NAME);
#endif
if (!prefspath) {
error(“Couldn’t get preferences path for this platform\n”);
return false;
}
if (!PHYSFS_setWriteDir(prefspath)) {
error(“Couldn’t set write directory to %s: %s\n”, prefspath,
PHYSFS_getLastError());
return false;
}

/* Put the write directory first in the search path */
PHYSFS_mount(prefspath, NULL, 0);

#ifdef ANDROID
// We’ll use SDL’s asset manager code path for Android
return true;

#else
/* Then add the base directory to the search path */
PHYSFS_mount(PHYSFS_getBaseDir(), NULL, 0);

/* Then add the data file, which could be appended to the executable

*/
if (PHYSFS_mount(argv0, “/”, 1)) {
return true;
}

/* ... or not */
char path[4096];
SDL_snprintf(path, SDL_arraysize(path), "%s%s", PHYSFS_getBaseDir(),

EQUATE_DATA);
if (PHYSFS_mount(path, “/”, 1)) {
return true;
}

SDL_snprintf(path, SDL_arraysize(path), "%sContents/Resources/%s",

PHYSFS_getBaseDir(), EQUATE_DATA);
if (PHYSFS_mount(path, “/”, 1)) {
return true;
}

error("Couldn't find %s", EQUATE_DATA);
return false;

#endif // ANDROID
}

SDL_RWops *OpenRead(const char *fname)
{
#ifdef ANDROID
return SDL_RWFromFile(fname, “rb”);
#else
return PHYSFSRWOPS_openRead(fname);
#endif
}

SDL_RWops *OpenWrite(const char *fname)
{
#ifdef ANDROID
return SDL_RWFromFile(fname, “wb”);
#else
return PHYSFSRWOPS_openWrite(fname);
#endif
}

On Sun, May 26, 2013 at 10:29 AM, Jonathan Dearborn wrote:

I could see that working decently, but not really great for small apks
(mine is less than 2 MB). It does take a lot of infrastructure both for
serving and downloading, and you end up with a worthless apk if the server
or the client connection is down temporarily or permanently.

Wouldn’t it be almost the same to copy the files from the apk to
internal storage and then mount it with PhysFS? Still not ideal…

Jonny D

On Sun, May 26, 2013 at 12:14 PM, Dimitris Zenios < dimitris.zenios at gmail.com> wrote:

The way i did it is to not put my assets to the apk But download them
to a folder once the application starts.Then i used physfs to mount the
folder and read it.This is how applications with big assets are doing
it.You want to have your applications size minimal.Thats the reason you
download on init.

On Sun, May 26, 2013 at 4:43 PM, Jonathan Dearborn <grimfang4 at gmail.com wrote:

Hey guys,

Is anyone using PhysicsFS and SDL 2.0 together on Android? I would
really like to read my Android assets through PhysFS, but I haven’t been
able to get PhysFS to see them. Normally I would use SDL_RWops to get the
assets transparently in the apk, but PhysFS does its own file locating,
which won’t work for apk assets. I can convert a PHYSFS_File into a
SDL_RWops, but not the other way around.

I’m hoping I don’t have to write JNI code for it. :frowning:

Jonny D


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

The development branch has PHYSFS_Io, which lets you assign callbacks
much like a RWops, so you can talk to things that can look roughly like
files.

You can mount an archive from a PHYSFS_Io instead of a real filename, too.

https://hg.icculus.org/icculus/physfs/file/e0dbcd5e50b9/src/physfs.h#l2776

–ryan.On 5/26/13 3:16 PM, Sam Lantinga wrote:

Yeah, to do that you’ll probably have to write a backend for PhysFS that
uses SDL_rwops which in turn uses JNI to load assets.