diff --git a/jni/NativeFormats/JavaPluginCollection.cpp b/jni/NativeFormats/JavaPluginCollection.cpp index 8905aba6b..016c6ccc1 100644 --- a/jni/NativeFormats/JavaPluginCollection.cpp +++ b/jni/NativeFormats/JavaPluginCollection.cpp @@ -17,11 +17,10 @@ * 02110-1301, USA. */ -#include - #include #include +#include #include "fbreader/src/formats/FormatPlugin.h" @@ -29,18 +28,17 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_org_geometerplus_fbreader_formats_PluginCollection_nativePlugins(JNIEnv* env, jobject thiz) { const std::vector > plugins = PluginCollection::Instance().plugins(); const size_t size = plugins.size(); - jclass cls = env->FindClass(AndroidUtil::Class_NativeFormatPlugin); + jclass cls = AndroidUtil::Class_NativeFormatPlugin->j(); // TODO: memory leak? jobjectArray javaPlugins = env->NewObjectArray(size, cls, 0); for (size_t i = 0; i < size; ++i) { jstring fileType = AndroidUtil::createJavaString(env, plugins[i]->supportedFileType()); - jobject p = env->NewObject(cls, AndroidUtil::MID_NativeFormatPlugin_init, fileType); + jobject p = AndroidUtil::Constructor_NativeFormatPlugin->call(fileType); env->SetObjectArrayElement(javaPlugins, i, p); env->DeleteLocalRef(p); env->DeleteLocalRef(fileType); } - env->DeleteLocalRef(cls); return javaPlugins; } diff --git a/jni/NativeFormats/util/AndroidUtil.cpp b/jni/NativeFormats/util/AndroidUtil.cpp index b8ee0f5ab..0a46e41eb 100644 --- a/jni/NativeFormats/util/AndroidUtil.cpp +++ b/jni/NativeFormats/util/AndroidUtil.cpp @@ -30,14 +30,14 @@ const char * const AndroidUtil::Class_java_util_Collection = "java/util/Collecti const char * const AndroidUtil::Class_java_util_Locale = "java/util/Locale"; const char * const AndroidUtil::Class_java_io_InputStream = "java/io/InputStream"; const char * const AndroidUtil::Class_ZLibrary = "org/geometerplus/zlibrary/core/library/ZLibrary"; -const char * const AndroidUtil::Class_NativeFormatPlugin = "org/geometerplus/fbreader/formats/NativeFormatPlugin"; +shared_ptr AndroidUtil::Class_NativeFormatPlugin; const char * const AndroidUtil::Class_PluginCollection = "org/geometerplus/fbreader/formats/PluginCollection"; const char * const AndroidUtil::Class_Encoding = "org/geometerplus/zlibrary/core/encodings/Encoding"; const char * const AndroidUtil::Class_EncodingConverter = "org/geometerplus/zlibrary/core/encodings/EncodingConverter"; const char * const AndroidUtil::Class_JavaEncodingCollection = "org/geometerplus/zlibrary/core/encodings/JavaEncodingCollection"; const char * const AndroidUtil::Class_Paths = "org/geometerplus/fbreader/Paths"; const char * const AndroidUtil::Class_ZLFile = "org/geometerplus/zlibrary/core/filesystem/ZLFile"; -const char * const AndroidUtil::Class_ZLFileImage = "org/geometerplus/zlibrary/core/image/ZLFileImage"; +shared_ptr AndroidUtil::Class_ZLFileImage; const char * const AndroidUtil::Class_Book = "org/geometerplus/fbreader/library/Book"; const char * const AndroidUtil::Class_Tag = "org/geometerplus/fbreader/library/Tag"; const char * const AndroidUtil::Class_NativeBookModel = "org/geometerplus/fbreader/bookmodel/NativeBookModel"; @@ -58,7 +58,7 @@ shared_ptr AndroidUtil::Method_java_io_InputStream_skip; shared_ptr AndroidUtil::StaticMethod_ZLibrary_Instance; shared_ptr AndroidUtil::Method_ZLibrary_getVersionName; -jmethodID AndroidUtil::MID_NativeFormatPlugin_init; +shared_ptr AndroidUtil::Constructor_NativeFormatPlugin; shared_ptr AndroidUtil::Method_NativeFormatPlugin_supportedFileType; shared_ptr AndroidUtil::StaticMethod_PluginCollection_Instance; @@ -82,7 +82,7 @@ shared_ptr AndroidUtil::Method_ZLFile_getPath; shared_ptr AndroidUtil::Method_ZLFile_isDirectory; shared_ptr AndroidUtil::Method_ZLFile_size; -jmethodID AndroidUtil::MID_ZLFileImage_init; +shared_ptr AndroidUtil::Constructor_ZLFileImage; shared_ptr AndroidUtil::StaticMethod_Paths_cacheDirectory; @@ -149,10 +149,9 @@ bool AndroidUtil::init(JavaVM* jvm) { Method_ZLibrary_getVersionName = new StringMethod(env, cls, "getVersionName", "()"); env->DeleteLocalRef(cls); - CHECK_NULL( cls = env->FindClass(Class_NativeFormatPlugin) ); - CHECK_NULL( MID_NativeFormatPlugin_init = env->GetMethodID(cls, "", "(Ljava/lang/String;)V") ); - Method_NativeFormatPlugin_supportedFileType = new StringMethod(env, cls, "supportedFileType", "()"); - env->DeleteLocalRef(cls); + Class_NativeFormatPlugin = new JavaClass(env, "org/geometerplus/fbreader/formats/NativeFormatPlugin"); + Constructor_NativeFormatPlugin = new Constructor(*Class_NativeFormatPlugin, "(Ljava/lang/String;)V"); + Method_NativeFormatPlugin_supportedFileType = new StringMethod(*Class_NativeFormatPlugin, "supportedFileType", "()"); CHECK_NULL( cls = env->FindClass(Class_PluginCollection) ); StaticMethod_PluginCollection_Instance = new StaticObjectMethod(env, cls, "Instance", "org/geometerplus/fbreader/formats/PluginCollection", "()"); @@ -185,9 +184,8 @@ bool AndroidUtil::init(JavaVM* jvm) { Method_ZLFile_size = new LongMethod(env, cls, "size", "()"); env->DeleteLocalRef(cls); - CHECK_NULL( cls = env->FindClass(Class_ZLFileImage) ); - CHECK_NULL( MID_ZLFileImage_init = env->GetMethodID(cls, "", "(Ljava/lang/String;Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;Ljava/lang/String;II)V") ); - env->DeleteLocalRef(cls); + Class_ZLFileImage = new JavaClass(env, "org/geometerplus/zlibrary/core/image/ZLFileImage"); + Constructor_ZLFileImage = new Constructor(*Class_ZLFileImage, "(Ljava/lang/String;Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;Ljava/lang/String;II)V"); CHECK_NULL( cls = env->FindClass(Class_Paths) ); StaticMethod_Paths_cacheDirectory = new StaticObjectMethod(env, cls, "cacheDirectory", "java/lang/String", "()"); @@ -244,14 +242,11 @@ jobject AndroidUtil::createJavaImage(JNIEnv *env, const ZLFileImage &image) { jobject javaFile = createJavaFile(env, image.file().path()); jstring javaEncoding = createJavaString(env, image.encoding()); - jclass cls = env->FindClass(Class_ZLFileImage); - jobject javaImage = env->NewObject( - cls, MID_ZLFileImage_init, + jobject javaImage = Constructor_ZLFileImage->call( javaMimeType, javaFile, javaEncoding, image.offset(), image.size() ); - env->DeleteLocalRef(cls); env->DeleteLocalRef(javaEncoding); env->DeleteLocalRef(javaFile); env->DeleteLocalRef(javaMimeType); diff --git a/jni/NativeFormats/util/AndroidUtil.h b/jni/NativeFormats/util/AndroidUtil.h index 1d3bb20c9..7cbe7c467 100644 --- a/jni/NativeFormats/util/AndroidUtil.h +++ b/jni/NativeFormats/util/AndroidUtil.h @@ -28,6 +28,7 @@ #include class JavaClass; +class Constructor; class VoidMethod; class IntMethod; class LongMethod; @@ -51,8 +52,8 @@ public: static const char * const Class_java_io_InputStream; static const char * const Class_ZLibrary; static const char * const Class_ZLFile; - static const char * const Class_ZLFileImage; - static const char * const Class_NativeFormatPlugin; + static shared_ptr Class_ZLFileImage; + static shared_ptr Class_NativeFormatPlugin; static const char * const Class_PluginCollection; static const char * const Class_Encoding; static const char * const Class_EncodingConverter; @@ -86,9 +87,9 @@ public: static shared_ptr Method_ZLFile_isDirectory; static shared_ptr Method_ZLFile_size; - static jmethodID MID_ZLFileImage_init; + static shared_ptr Constructor_ZLFileImage; - static jmethodID MID_NativeFormatPlugin_init; + static shared_ptr Constructor_NativeFormatPlugin; static shared_ptr Method_NativeFormatPlugin_supportedFileType; static shared_ptr StaticMethod_PluginCollection_Instance; diff --git a/jni/NativeFormats/util/JniEnvelope.cpp b/jni/NativeFormats/util/JniEnvelope.cpp index 1d4e03320..2b2a029fa 100644 --- a/jni/NativeFormats/util/JniEnvelope.cpp +++ b/jni/NativeFormats/util/JniEnvelope.cpp @@ -33,6 +33,18 @@ JavaClass::~JavaClass() { myEnv->DeleteGlobalRef(myClass); } +Constructor::Constructor(const JavaClass &cls, const std::string &signature) : myClass(cls) { + myId = cls.myEnv->GetMethodID(cls.j(), "", signature.c_str()); +} + +jobject Constructor::call(...) { + va_list lst; + va_start(lst, this); + jobject obj = myClass.myEnv->NewObjectV(myClass.j(), myId, lst); + va_end(lst); + return obj; +} + Method::Method(JNIEnv *env, jclass cls, const std::string &name, const std::string &signature) : myName(name) { //ZLLogger::Instance().registerClass(JNI_LOGGER_CLASS); myEnv = env; diff --git a/jni/NativeFormats/util/JniEnvelope.h b/jni/NativeFormats/util/JniEnvelope.h index 16fbe0c5e..342f6f107 100644 --- a/jni/NativeFormats/util/JniEnvelope.h +++ b/jni/NativeFormats/util/JniEnvelope.h @@ -29,7 +29,7 @@ class JavaClass { public: JavaClass(JNIEnv *env, const std::string &name); ~JavaClass(); - jclass j(); + jclass j() const; private: JavaClass(const JavaClass&); @@ -42,6 +42,22 @@ private: friend class Method; friend class StaticMethod; +friend class Constructor; +}; + +class Constructor { + +public: + Constructor(const JavaClass &cls, const std::string &signature); + jobject call(...); + +private: + Constructor(const Constructor&); + const Constructor &operator = (const Constructor&); + +protected: + const JavaClass &myClass; + jmethodID myId; }; class Method { @@ -127,6 +143,6 @@ public: jobject call(jclass cls, ...); }; -inline jclass JavaClass::j() { return myClass; } +inline jclass JavaClass::j() const { return myClass; } #endif /* __JNIENVELOPE_H__ */