openMSX
AndroidApiWrapper.cc
Go to the documentation of this file.
1 /*
2  * Android API wrapper
3  *
4  * It makes a few Android functions available for the android flavour of openMSX
5  *
6  */
7 
8 #include "build-info.hh"
9 #include "AndroidApiWrapper.hh"
10 
11 #if PLATFORM_ANDROID
12 
13 #include "openmsx.hh"
14 #include <cstdlib>
15 #include <cstring>
16 #include <jni.h>
17 
18 // The jniVM parameter gets set by the JNI mechanism directly after loading the
19 // shared lib containing openMSX by invoking a method with following
20 // signature if it exists in the shared lib:
21 // JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
22 // This method is defined at the end of this source file and must be able to
23 // initialize this jniVM parameter, hence it must exist outside the openmsx
24 // namespace
25 static JavaVM* jniVM = nullptr;
26 
27 namespace openmsx {
28 
29 std::string AndroidApiWrapper::getStorageDirectory()
30 {
31  JNIEnv* jniEnv = nullptr;
32  jniVM->AttachCurrentThread(&jniEnv, nullptr);
33  if (!jniEnv) {
34  throw JniException("Java VM AttachCurrentThread() failed");
35  }
36  jclass cls = jniEnv->FindClass("android/os/Environment");
37  if (cls == 0) {
38  throw JniException("Cant find class android/os/Environment");
39  }
40  jmethodID mid = jniEnv->GetStaticMethodID(cls, "getExternalStorageDirectory", "()Ljava/io/File;");
41  if (mid == 0) {
42  throw JniException("Cant find getExternalStorageDirectory method");
43  }
44  jobject storageDirectory = jniEnv->CallStaticObjectMethod(cls, mid);
45  if (storageDirectory == 0) {
46  throw JniException("Cant get storageDirectory");
47  }
48  cls = jniEnv->GetObjectClass(storageDirectory);
49  if (cls == 0) {
50  throw JniException("Cant find class for storageDirectory object");
51  }
52  mid = jniEnv->GetMethodID(cls, "getAbsolutePath", "()Ljava/lang/String;");
53  if (mid == 0) {
54  throw JniException("Cant find getAbsolutePath method");
55  }
56  jstring storageDirectoryName = static_cast<jstring>(jniEnv->CallObjectMethod(storageDirectory, mid));
57  if (storageDirectoryName == 0) {
58  throw JniException("Cant get storageDirectoryName");
59  }
60  const char* str = jniEnv->GetStringUTFChars(storageDirectoryName, nullptr);
61  if (str == nullptr) {
62  throw JniException("Cant convert storageDirectoryName to C format");
63  }
64  std::string rslt(str);
65  jniEnv->ReleaseStringUTFChars(storageDirectoryName, str);
66  return rslt;
67 }
68 
69 } // namespace openmsx
70 
71 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
72 {
73  // Store the reference to the JVM so that the JNI calls can use it
74  jniVM = vm;
75  return JNI_VERSION_1_2;
76 }
77 
78 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* /*vm*/, void* /*reserved*/)
79 {
80  // Nothing to do
81 }
82 
83 #endif
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5