android: PhysicsFS now has actual Android support.
This compiled and worked on Android before, if you didn't care about PHYSFS_getBaseDir() and PHYSFS_getPrefDir() being useful. Now you can pass PHYSFS_init() some necessary Android objects to solve this. Passing NULL to PHYSFS_init is acceptable and will simply report "/" for the base dir and prefdir, under the assumption that the app queried the OS for these directly instead.
This commit is contained in:
parent
22297e7ea2
commit
55c3d9f9d8
|
@ -76,6 +76,7 @@ set(PHYSFS_SRCS
|
||||||
src/physfs_platform_windows.c
|
src/physfs_platform_windows.c
|
||||||
src/physfs_platform_os2.c
|
src/physfs_platform_os2.c
|
||||||
src/physfs_platform_qnx.c
|
src/physfs_platform_qnx.c
|
||||||
|
src/physfs_platform_android.c
|
||||||
src/physfs_archiver_dir.c
|
src/physfs_archiver_dir.c
|
||||||
src/physfs_archiver_unpacked.c
|
src/physfs_archiver_unpacked.c
|
||||||
src/physfs_archiver_grp.c
|
src/physfs_archiver_grp.c
|
||||||
|
|
|
@ -1233,7 +1233,9 @@ int PHYSFS_init(const char *argv0)
|
||||||
if (!userDir) goto initFailed;
|
if (!userDir) goto initFailed;
|
||||||
|
|
||||||
/* Platform layer is required to append a dirsep. */
|
/* Platform layer is required to append a dirsep. */
|
||||||
|
#ifndef __ANDROID__ /* it's an APK file, not a directory, on Android. */
|
||||||
assert(baseDir[strlen(baseDir) - 1] == __PHYSFS_platformDirSeparator);
|
assert(baseDir[strlen(baseDir) - 1] == __PHYSFS_platformDirSeparator);
|
||||||
|
#endif
|
||||||
assert(userDir[strlen(userDir) - 1] == __PHYSFS_platformDirSeparator);
|
assert(userDir[strlen(userDir) - 1] == __PHYSFS_platformDirSeparator);
|
||||||
|
|
||||||
if (!initStaticArchivers()) goto initFailed;
|
if (!initStaticArchivers()) goto initFailed;
|
||||||
|
|
32
src/physfs.h
32
src/physfs.h
|
@ -493,6 +493,14 @@ typedef struct PHYSFS_Version
|
||||||
PHYSFS_DECL void PHYSFS_getLinkedVersion(PHYSFS_Version *ver);
|
PHYSFS_DECL void PHYSFS_getLinkedVersion(PHYSFS_Version *ver);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
typedef struct PHYSFS_AndroidInit
|
||||||
|
{
|
||||||
|
void *jnienv;
|
||||||
|
void *context;
|
||||||
|
} PHYSFS_AndroidInit;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \fn int PHYSFS_init(const char *argv0)
|
* \fn int PHYSFS_init(const char *argv0)
|
||||||
* \brief Initialize the PhysicsFS library.
|
* \brief Initialize the PhysicsFS library.
|
||||||
|
@ -502,11 +510,22 @@ PHYSFS_DECL void PHYSFS_getLinkedVersion(PHYSFS_Version *ver);
|
||||||
* This should be called prior to any attempts to change your process's
|
* This should be called prior to any attempts to change your process's
|
||||||
* current working directory.
|
* current working directory.
|
||||||
*
|
*
|
||||||
|
* \warning On Android, argv0 should be a non-NULL pointer to a
|
||||||
|
* PHYSFS_AndroidInit struct. This struct must hold a valid JNIEnv *
|
||||||
|
* and a JNI jobject of a Context (either the application context or
|
||||||
|
* the current Activity is fine). Both are cast to a void * so we
|
||||||
|
* don't need jni.h included wherever physfs.h is. PhysicsFS
|
||||||
|
* uses these objects to query some system details. PhysicsFS does
|
||||||
|
* not hold a reference to the JNIEnv or Context past the call to
|
||||||
|
* PHYSFS_init(). If you pass a NULL here, PHYSFS_init can still
|
||||||
|
* succeed, but PHYSFS_getBaseDir() and PHYSFS_getPrefDir() will be
|
||||||
|
* incorrect.
|
||||||
|
*
|
||||||
* \param argv0 the argv[0] string passed to your program's mainline.
|
* \param argv0 the argv[0] string passed to your program's mainline.
|
||||||
* This may be NULL on most platforms (such as ones without a
|
* This may be NULL on most platforms (such as ones without a
|
||||||
* standard main() function), but you should always try to pass
|
* standard main() function), but you should always try to pass
|
||||||
* something in here. Unix-like systems such as Linux _need_ to
|
* something in here. Many Unix-like systems _need_ to pass argv[0]
|
||||||
* pass argv[0] from main() in here.
|
* from main() in here. See warning about Android, too!
|
||||||
* \return nonzero on success, zero on error. Specifics of the error can be
|
* \return nonzero on success, zero on error. Specifics of the error can be
|
||||||
* gleaned from PHYSFS_getLastError().
|
* gleaned from PHYSFS_getLastError().
|
||||||
*
|
*
|
||||||
|
@ -762,6 +781,15 @@ PHYSFS_DECL char **PHYSFS_getCdRomDirs(void);
|
||||||
*
|
*
|
||||||
* You should probably use the base dir in your search path.
|
* You should probably use the base dir in your search path.
|
||||||
*
|
*
|
||||||
|
* \warning On most platforms, this is a directory; on Android, this gives
|
||||||
|
* you the path to the app's package (APK) file. As APK files are
|
||||||
|
* just .zip files, you can mount them in PhysicsFS like regular
|
||||||
|
* directories. You'll probably want to call
|
||||||
|
* PHYSFS_setRoot(basedir, "/assets") after mounting to make your
|
||||||
|
* app's actual data available directly without all the Android
|
||||||
|
* metadata and directory offset. Note that if you passed a NULL to
|
||||||
|
* PHYSFS_init(), you will not get the APK file here.
|
||||||
|
*
|
||||||
* \return READ ONLY string of base dir in platform-dependent notation.
|
* \return READ ONLY string of base dir in platform-dependent notation.
|
||||||
*
|
*
|
||||||
* \sa PHYSFS_getPrefDir
|
* \sa PHYSFS_getPrefDir
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Android support routines for PhysicsFS.
|
||||||
|
*
|
||||||
|
* Please see the file LICENSE.txt in the source's root directory.
|
||||||
|
*
|
||||||
|
* This file written by Ryan C. Gordon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __PHYSICSFS_INTERNAL__
|
||||||
|
#include "physfs_platforms.h"
|
||||||
|
|
||||||
|
#ifdef PHYSFS_PLATFORM_ANDROID
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include "physfs_internal.h"
|
||||||
|
|
||||||
|
static char *prefpath = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
int __PHYSFS_platformInit(void)
|
||||||
|
{
|
||||||
|
return 1; /* always succeed. */
|
||||||
|
} /* __PHYSFS_platformInit */
|
||||||
|
|
||||||
|
|
||||||
|
void __PHYSFS_platformDeinit(void)
|
||||||
|
{
|
||||||
|
if (prefpath)
|
||||||
|
{
|
||||||
|
allocator.Free(prefpath);
|
||||||
|
prefpath = NULL;
|
||||||
|
} /* if */
|
||||||
|
} /* __PHYSFS_platformDeinit */
|
||||||
|
|
||||||
|
|
||||||
|
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||||
|
{
|
||||||
|
/* no-op. */
|
||||||
|
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||||
|
|
||||||
|
|
||||||
|
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||||
|
{
|
||||||
|
/* as a cheat, we expect argv0 to be a PHYSFS_AndroidInit* on Android. */
|
||||||
|
PHYSFS_AndroidInit *ainit = (PHYSFS_AndroidInit *) argv0;
|
||||||
|
char *retval = NULL;
|
||||||
|
JNIEnv *jenv = NULL;
|
||||||
|
jobject jcontext;
|
||||||
|
|
||||||
|
if (ainit == NULL)
|
||||||
|
return __PHYSFS_strdup("/"); /* oh well. */
|
||||||
|
|
||||||
|
jenv = (JNIEnv *) ainit->jnienv;
|
||||||
|
jcontext = (jobject) ainit->context;
|
||||||
|
|
||||||
|
if ((*jenv)->PushLocalFrame(jenv, 16) >= 0)
|
||||||
|
{
|
||||||
|
jobject jfileobj = 0;
|
||||||
|
jmethodID jmeth = 0;
|
||||||
|
jthrowable jexception = 0;
|
||||||
|
jstring jstr = 0;
|
||||||
|
|
||||||
|
jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jcontext), "getPackageResourcePath", "()Ljava/lang/String;");
|
||||||
|
jstr = (jstring)(*jenv)->CallObjectMethod(jenv, jcontext, jmeth);
|
||||||
|
jexception = (*jenv)->ExceptionOccurred(jenv); /* this can't throw an exception, right? Just in case. */
|
||||||
|
if (jexception != NULL)
|
||||||
|
(*jenv)->ExceptionClear(jenv);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *path = (*jenv)->GetStringUTFChars(jenv, jstr, NULL);
|
||||||
|
retval = __PHYSFS_strdup(path);
|
||||||
|
(*jenv)->ReleaseStringUTFChars(jenv, jstr, path);
|
||||||
|
} /* else */
|
||||||
|
|
||||||
|
/* We only can rely on the Activity being valid during this function call,
|
||||||
|
so go ahead and grab the prefpath too. */
|
||||||
|
jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jcontext), "getFilesDir", "()Ljava/io/File;");
|
||||||
|
jfileobj = (*jenv)->CallObjectMethod(jenv, jcontext, jmeth);
|
||||||
|
if (jfileobj)
|
||||||
|
{
|
||||||
|
jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jfileobj), "getCanonicalPath", "()Ljava/lang/String;");
|
||||||
|
jstr = (jstring)(*jenv)->CallObjectMethod(jenv, jfileobj, jmeth);
|
||||||
|
jexception = (*jenv)->ExceptionOccurred(jenv);
|
||||||
|
if (jexception != NULL)
|
||||||
|
(*jenv)->ExceptionClear(jenv);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *path = (*jenv)->GetStringUTFChars(jenv, jstr, NULL);
|
||||||
|
const size_t len = strlen(path) + 2;
|
||||||
|
prefpath = allocator.Malloc(len);
|
||||||
|
if (prefpath)
|
||||||
|
snprintf(prefpath, len, "%s/", path);
|
||||||
|
(*jenv)->ReleaseStringUTFChars(jenv, jstr, path);
|
||||||
|
} /* else */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
(*jenv)->PopLocalFrame(jenv, NULL);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
/* we can't return NULL because then PhysicsFS will treat argv0 as a string, but it's a non-NULL jobject! */
|
||||||
|
if (retval == NULL)
|
||||||
|
retval = __PHYSFS_strdup("/"); /* we pray this works. */
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
} /* __PHYSFS_platformCalcBaseDir */
|
||||||
|
|
||||||
|
|
||||||
|
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
|
||||||
|
{
|
||||||
|
return __PHYSFS_strdup(prefpath ? prefpath : "/");
|
||||||
|
} /* __PHYSFS_platformCalcPrefDir */
|
||||||
|
|
||||||
|
#endif /* PHYSFS_PLATFORM_ANDROID */
|
||||||
|
|
||||||
|
/* end of physfs_platform_android.c ... */
|
||||||
|
|
|
@ -40,11 +40,11 @@
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
# define PHYSFS_PLATFORM_POSIX 1
|
||||||
#elif defined(macintosh)
|
#elif defined(macintosh)
|
||||||
# error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X.
|
# error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X.
|
||||||
#elif defined(ANDROID)
|
#elif defined(__ANDROID__)
|
||||||
# define PHYSFS_PLATFORM_LINUX 1
|
# define PHYSFS_PLATFORM_LINUX 1
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
# define PHYSFS_PLATFORM_ANDROID 1
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
# define PHYSFS_PLATFORM_POSIX 1
|
||||||
# define PHYSFS_NO_CDROM_SUPPORT 1
|
# define PHYSFS_NO_CDROM_SUPPORT 1
|
||||||
#elif defined(__linux)
|
#elif defined(__linux)
|
||||||
# define PHYSFS_PLATFORM_LINUX 1
|
# define PHYSFS_PLATFORM_LINUX 1
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
# define PHYSFS_PLATFORM_UNIX 1
|
||||||
|
|
Loading…
Reference in New Issue