physfs_platform_android.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * Android support routines for PhysicsFS.
  3. *
  4. * Please see the file LICENSE.txt in the source's root directory.
  5. *
  6. * This file written by Ryan C. Gordon.
  7. */
  8. #define __PHYSICSFS_INTERNAL__
  9. #include "physfs_platforms.h"
  10. #ifdef PHYSFS_PLATFORM_ANDROID
  11. #include <jni.h>
  12. #include <android/log.h>
  13. #include "physfs_internal.h"
  14. static char *prefpath = NULL;
  15. int __PHYSFS_platformInit(const char *argv0)
  16. {
  17. return 1; /* always succeed. */
  18. } /* __PHYSFS_platformInit */
  19. void __PHYSFS_platformDeinit(void)
  20. {
  21. if (prefpath)
  22. {
  23. allocator.Free(prefpath);
  24. prefpath = NULL;
  25. } /* if */
  26. } /* __PHYSFS_platformDeinit */
  27. void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
  28. {
  29. /* no-op. */
  30. } /* __PHYSFS_platformDetectAvailableCDs */
  31. char *__PHYSFS_platformCalcBaseDir(const char *argv0)
  32. {
  33. /* as a cheat, we expect argv0 to be a PHYSFS_AndroidInit* on Android. */
  34. PHYSFS_AndroidInit *ainit = (PHYSFS_AndroidInit *) argv0;
  35. char *retval = NULL;
  36. JNIEnv *jenv = NULL;
  37. jobject jcontext;
  38. if (ainit == NULL)
  39. return __PHYSFS_strdup("/"); /* oh well. */
  40. jenv = (JNIEnv *) ainit->jnienv;
  41. jcontext = (jobject) ainit->context;
  42. if ((*jenv)->PushLocalFrame(jenv, 16) >= 0)
  43. {
  44. jobject jfileobj = 0;
  45. jmethodID jmeth = 0;
  46. jthrowable jexception = 0;
  47. jstring jstr = 0;
  48. jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jcontext), "getPackageResourcePath", "()Ljava/lang/String;");
  49. jstr = (jstring)(*jenv)->CallObjectMethod(jenv, jcontext, jmeth);
  50. jexception = (*jenv)->ExceptionOccurred(jenv); /* this can't throw an exception, right? Just in case. */
  51. if (jexception != NULL)
  52. (*jenv)->ExceptionClear(jenv);
  53. else
  54. {
  55. const char *path = (*jenv)->GetStringUTFChars(jenv, jstr, NULL);
  56. retval = __PHYSFS_strdup(path);
  57. (*jenv)->ReleaseStringUTFChars(jenv, jstr, path);
  58. } /* else */
  59. /* We only can rely on the Activity being valid during this function call,
  60. so go ahead and grab the prefpath too. */
  61. jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jcontext), "getFilesDir", "()Ljava/io/File;");
  62. jfileobj = (*jenv)->CallObjectMethod(jenv, jcontext, jmeth);
  63. if (jfileobj)
  64. {
  65. jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jfileobj), "getCanonicalPath", "()Ljava/lang/String;");
  66. jstr = (jstring)(*jenv)->CallObjectMethod(jenv, jfileobj, jmeth);
  67. jexception = (*jenv)->ExceptionOccurred(jenv);
  68. if (jexception != NULL)
  69. (*jenv)->ExceptionClear(jenv);
  70. else
  71. {
  72. const char *path = (*jenv)->GetStringUTFChars(jenv, jstr, NULL);
  73. const size_t len = strlen(path) + 2;
  74. prefpath = allocator.Malloc(len);
  75. if (prefpath)
  76. snprintf(prefpath, len, "%s/", path);
  77. (*jenv)->ReleaseStringUTFChars(jenv, jstr, path);
  78. } /* else */
  79. } /* if */
  80. (*jenv)->PopLocalFrame(jenv, NULL);
  81. } /* if */
  82. /* we can't return NULL because then PhysicsFS will treat argv0 as a string, but it's a non-NULL jobject! */
  83. if (retval == NULL)
  84. retval = __PHYSFS_strdup("/"); /* we pray this works. */
  85. return retval;
  86. } /* __PHYSFS_platformCalcBaseDir */
  87. char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
  88. {
  89. return __PHYSFS_strdup(prefpath ? prefpath : "/");
  90. } /* __PHYSFS_platformCalcPrefDir */
  91. #endif /* PHYSFS_PLATFORM_ANDROID */
  92. /* end of physfs_platform_android.c ... */