From 766b64dddc734963fae003fc1bf8d6ab3286abb1 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Wed, 5 Jul 2017 11:36:34 +0200 Subject: [PATCH 1/4] Update gen_kiwix.sh to not be dependent of the number of arguments. --- src/android/gen_kiwix.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/android/gen_kiwix.sh b/src/android/gen_kiwix.sh index c6fb46b5c..9966b7b27 100755 --- a/src/android/gen_kiwix.sh +++ b/src/android/gen_kiwix.sh @@ -4,8 +4,11 @@ set -e BUILD_PATH=$(pwd) -javac -d $BUILD_PATH/src/android $1 $2 $3 $4 +echo "javac -d $BUILD_PATH/src/android $@" +javac -d $BUILD_PATH/src/android "$@" + cd $BUILD_PATH/src/android +echo "javah -jni org.kiwix.kiwixlib.JNIKiwix" javah -jni org.kiwix.kiwixlib.JNIKiwix cd $BUILD_PATH From 7a59779b7786fa73789b24d3dadefc8a0585cf5d Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Wed, 5 Jul 2017 15:36:59 +0200 Subject: [PATCH 2/4] =?UTF-8?q?Change=20JNI=C2=A0API=20of=20kiwix-lib=20(m?= =?UTF-8?q?ainly=20to=20support=20multi-zims=20search)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a major API break. User code will have to be rewritten. Before this commit, API was a unique object wrapping the library and handle a global state with one `Reader` and one `Writer` at the time. Now, the API is axed around three main objects : - The `JNIKiwixReader`, a wrapper around a `kiwix::Reader` (who allow to read one zim) - The `JNIKiwixSearcher`, a wrapper around a `kiwix::Searcher` (who allow to search through one or more reader(s)) - The `JNIKiwixSearcher.Result` a result of a search. Allowing to get all information about a result (title, url, content, snippet, ...) --- src/android/kiwix.cpp | 523 +----------------- src/android/kiwixreader.cpp | 350 ++++++++++++ src/android/kiwixsearcher.cpp | 120 ++++ src/android/meson.build | 8 +- src/android/org/kiwix/kiwixlib/JNIKiwix.java | 47 +- .../org/kiwix/kiwixlib/JNIKiwixReader.java | 87 +++ .../org/kiwix/kiwixlib/JNIKiwixSearcher.java | 66 +++ src/android/utils.h | 140 +++++ 8 files changed, 776 insertions(+), 565 deletions(-) create mode 100644 src/android/kiwixreader.cpp create mode 100644 src/android/kiwixsearcher.cpp create mode 100644 src/android/org/kiwix/kiwixlib/JNIKiwixReader.java create mode 100644 src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java create mode 100644 src/android/utils.h diff --git a/src/android/kiwix.cpp b/src/android/kiwix.cpp index 10c9bd484..1dfef6903 100644 --- a/src/android/kiwix.cpp +++ b/src/android/kiwix.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 Emmanuel Engelhart + * Copyright (C) 2017 Matthieu Gautier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,540 +21,24 @@ #include #include "org_kiwix_kiwixlib_JNIKiwix.h" -#include -#include - #include #include -#include "common/base64.h" -#include "reader.h" -#include "searcher.h" #include "unicode/putil.h" -#include -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "kiwix", __VA_ARGS__) +#include "utils.h" -#include -#include -#include -#include -#include - -/* global variables */ -kiwix::Reader* reader = NULL; -kiwix::Searcher* searcher = NULL; - -static pthread_mutex_t readerLock = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t searcherLock = PTHREAD_MUTEX_INITIALIZER; - -/* c2jni type conversion functions */ -jboolean c2jni(const bool& val) -{ - return val ? JNI_TRUE : JNI_FALSE; -} -jstring c2jni(const std::string& val, JNIEnv* env) -{ - return env->NewStringUTF(val.c_str()); -} - -jint c2jni(const int val) -{ - return (jint)val; -} -jint c2jni(const unsigned val) -{ - return (unsigned)val; -} -/* jni2c type conversion functions */ -bool jni2c(const jboolean& val) -{ - return val == JNI_TRUE; -} -std::string jni2c(const jstring& val, JNIEnv* env) -{ - return std::string(env->GetStringUTFChars(val, 0)); -} - -int jni2c(const jint val) -{ - return (int)val; -} -/* Method to deal with variable passed by reference */ -void setStringObjValue(const std::string& value, const jobject obj, JNIEnv* env) -{ - jclass objClass = env->GetObjectClass(obj); - jfieldID objFid = env->GetFieldID(objClass, "value", "Ljava/lang/String;"); - env->SetObjectField(obj, objFid, c2jni(value, env)); -} - -void setIntObjValue(const int value, const jobject obj, JNIEnv* env) -{ - jclass objClass = env->GetObjectClass(obj); - jfieldID objFid = env->GetFieldID(objClass, "value", "I"); - env->SetIntField(obj, objFid, value); -} - -void setBoolObjValue(const bool value, const jobject obj, JNIEnv* env) -{ - jclass objClass = env->GetObjectClass(obj); - jfieldID objFid = env->GetFieldID(objClass, "value", "Z"); - env->SetIntField(obj, objFid, c2jni(value)); -} - -/* Kiwix library functions */ -JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwix_getMainPage(JNIEnv* env, jobject obj) -{ - jstring url; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cUrl = reader->getMainPageUrl(); - url = c2jni(cUrl, env); - } catch (...) { - std::cerr << "Unable to get ZIM main page" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return url; -} - -JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getId(JNIEnv* env, - jobject obj) -{ - jstring id; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cId = reader->getId(); - id = c2jni(cId, env); - } catch (...) { - std::cerr << "Unable to get ZIM id" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return id; -} - -JNIEXPORT jint JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getFileSize(JNIEnv* env, - jobject obj) -{ - jint size; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - int cSize = reader->getFileSize(); - size = c2jni(cSize); - } catch (...) { - std::cerr << "Unable to get ZIM file size" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return size; -} - -JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwix_getCreator(JNIEnv* env, jobject obj) -{ - jstring creator; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cCreator = reader->getCreator(); - creator = c2jni(cCreator, env); - } catch (...) { - std::cerr << "Unable to get ZIM creator" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return creator; -} - -JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwix_getPublisher(JNIEnv* env, jobject obj) -{ - jstring publisher; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cPublisher = reader->getPublisher(); - publisher = c2jni(cPublisher, env); - } catch (...) { - std::cerr << "Unable to get ZIM creator" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return publisher; -} - -JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getName(JNIEnv* env, - jobject obj) -{ - jstring name; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cName = reader->getName(); - name = c2jni(cName, env); - } catch (...) { - std::cerr << "Unable to get ZIM name" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return name; -} - -JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwix_getFavicon(JNIEnv* env, jobject obj) -{ - jstring favicon; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cContent; - std::string cMime; - reader->getFavicon(cContent, cMime); - favicon - = c2jni(base64_encode( - reinterpret_cast(cContent.c_str()), - cContent.length()), - env); - } catch (...) { - std::cerr << "Unable to get ZIM favicon" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return favicon; -} - -JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getDate(JNIEnv* env, - jobject obj) -{ - jstring date; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cDate = reader->getDate(); - date = c2jni(cDate, env); - } catch (...) { - std::cerr << "Unable to get ZIM date" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return date; -} - -JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwix_getLanguage(JNIEnv* env, jobject obj) -{ - jstring language; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cLanguage = reader->getLanguage(); - language = c2jni(cLanguage, env); - } catch (...) { - std::cerr << "Unable to get ZIM language" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return language; -} - -JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getMimeType( - JNIEnv* env, jobject obj, jstring url) -{ - jstring mimeType; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - std::string cUrl = jni2c(url, env); - try { - std::string cMimeType; - reader->getMimeTypeByUrl(cUrl, cMimeType); - mimeType = c2jni(cMimeType, env); - } catch (...) { - std::cerr << "Unable to get mime-type for url " << cUrl << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return mimeType; -} - -JNIEXPORT jboolean JNICALL -Java_org_kiwix_kiwixlib_JNIKiwix_loadZIM(JNIEnv* env, jobject obj, jstring path) -{ - jboolean retVal = JNI_TRUE; - std::string cPath = jni2c(path, env); - - pthread_mutex_lock(&readerLock); - try { - if (reader != NULL) { - delete reader; - } - reader = new kiwix::Reader(cPath); - } catch (...) { - std::cerr << "Unable to load ZIM " << cPath << std::endl; - reader = NULL; - retVal = JNI_FALSE; - } - pthread_mutex_unlock(&readerLock); - - return retVal; -} - -JNIEXPORT jbyteArray JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getContent( - JNIEnv* env, jobject obj, jstring url, jobject titleObj, jobject mimeTypeObj, jobject sizeObj) -{ - /* Default values */ - setStringObjValue("", titleObj, env); - setStringObjValue("", mimeTypeObj, env); - setIntObjValue(0, sizeObj, env); - jbyteArray data = env->NewByteArray(0); - - /* Retrieve the content */ - if (reader != NULL) { - std::string cUrl = jni2c(url, env); - std::string cData; - std::string cTitle; - std::string cMimeType; - unsigned int cSize = 0; - - pthread_mutex_lock(&readerLock); - try { - if (reader->getContentByUrl(cUrl, cData, cTitle, cSize, cMimeType)) { - data = env->NewByteArray(cSize); - env->SetByteArrayRegion( - data, 0, cSize, reinterpret_cast(cData.c_str())); - setStringObjValue(cMimeType, mimeTypeObj, env); - setStringObjValue(cTitle, titleObj, env); - setIntObjValue(cSize, sizeObj, env); - } - } catch (...) { - std::cerr << "Unable to get content for url " << cUrl << std::endl; - } - pthread_mutex_unlock(&readerLock); - } - - return data; -} - -JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_searchSuggestions( - JNIEnv* env, jobject obj, jstring prefix, jint count) -{ - jboolean retVal = JNI_FALSE; - std::string cPrefix = jni2c(prefix, env); - unsigned int cCount = jni2c(count); - - pthread_mutex_lock(&readerLock); - try { - if (reader != NULL) { - if (reader->searchSuggestionsSmart(cPrefix, cCount)) { - retVal = JNI_TRUE; - } - } - } catch (...) { - std::cerr << "Unable to search suggestions for pattern " << cPrefix - << std::endl; - } - pthread_mutex_unlock(&readerLock); - - return retVal; -} - -JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getNextSuggestion( - JNIEnv* env, jobject obj, jobject titleObj) -{ - jboolean retVal = JNI_FALSE; - std::string cTitle; - - pthread_mutex_lock(&readerLock); - try { - if (reader != NULL) { - if (reader->getNextSuggestion(cTitle)) { - setStringObjValue(cTitle, titleObj, env); - retVal = JNI_TRUE; - } - } - } catch (...) { - std::cerr << "Unable to get next suggestion" << std::endl; - } - pthread_mutex_unlock(&readerLock); - - return retVal; -} - -JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getPageUrlFromTitle( - JNIEnv* env, jobject obj, jstring title, jobject urlObj) -{ - jboolean retVal = JNI_FALSE; - std::string cTitle = jni2c(title, env); - std::string cUrl; - - pthread_mutex_lock(&readerLock); - try { - if (reader != NULL) { - if (reader->getPageUrlFromTitle(cTitle, cUrl)) { - setStringObjValue(cUrl, urlObj, env); - retVal = JNI_TRUE; - } - } - } catch (...) { - std::cerr << "Unable to get URL for title " << cTitle << std::endl; - } - pthread_mutex_unlock(&readerLock); - - return retVal; -} - -JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getTitle( - JNIEnv* env, jobject obj, jobject titleObj) -{ - jboolean retVal = JNI_FALSE; - std::string cTitle; - - pthread_mutex_lock(&readerLock); - try { - if (reader != NULL) { - std::string cTitle = reader->getTitle(); - setStringObjValue(cTitle, titleObj, env); - retVal = JNI_TRUE; - } - } catch (...) { - std::cerr << "Unable to get ZIM title" << std::endl; - } - pthread_mutex_unlock(&readerLock); - - return retVal; -} - -JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwix_getDescription(JNIEnv* env, jobject obj) -{ - jstring description; - - pthread_mutex_lock(&readerLock); - if (reader != NULL) { - try { - std::string cDescription = reader->getDescription(); - description = c2jni(cDescription, env); - } catch (...) { - std::cerr << "Unable to get ZIM description" << std::endl; - } - } - pthread_mutex_unlock(&readerLock); - - return description; -} - -JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_getRandomPage( - JNIEnv* env, jobject obj, jobject urlObj) -{ - jboolean retVal = JNI_FALSE; - std::string cUrl; - - pthread_mutex_lock(&readerLock); - try { - if (reader != NULL) { - std::string cUrl = reader->getRandomPageUrl(); - setStringObjValue(cUrl, urlObj, env); - retVal = JNI_TRUE; - } - } catch (...) { - std::cerr << "Unable to get random page" << std::endl; - } - pthread_mutex_unlock(&readerLock); - - return retVal; -} +pthread_mutex_t globalLock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_setDataDirectory( JNIEnv* env, jobject obj, jstring dirStr) { std::string cPath = jni2c(dirStr, env); - pthread_mutex_lock(&readerLock); + Lock l; try { u_setDataDirectory(cPath.c_str()); } catch (...) { std::cerr << "Unable to set data directory " << cPath << std::endl; } - pthread_mutex_unlock(&readerLock); -} - -JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_loadFulltextIndex( - JNIEnv* env, jobject obj, jstring path) -{ - jboolean retVal = JNI_TRUE; - std::string cPath = jni2c(path, env); - - pthread_mutex_lock(&searcherLock); - try { - if (searcher != NULL) { - delete searcher; - } - if (!reader || !reader->hasFulltextIndex()) { - // Use old API (no embedded full text index). - searcher = new kiwix::Searcher(cPath, reader, ""); - } else { - // Use the new API. We don't care about the human readable name as - // we don't use it (in android). - searcher = new kiwix::Searcher(); - searcher->add_reader(reader, ""); - } - } catch (...) { - searcher = NULL; - retVal = JNI_FALSE; - std::cerr << "Unable to load full text index " << cPath << std::endl; - } - pthread_mutex_unlock(&searcherLock); - - return retVal; -} - -JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwix_indexedQuery( - JNIEnv* env, jclass obj, jstring query, jint count) -{ - std::string cQuery = jni2c(query, env); - unsigned int cCount = jni2c(count); - kiwix::Result* p_result; - std::string result; - - pthread_mutex_lock(&searcherLock); - try { - if (searcher != NULL) { - searcher->search(cQuery, 0, count); - while ((p_result = searcher->getNextResult()) - && !(p_result->get_title().empty()) - && !(p_result->get_url().empty())) { - result += p_result->get_title() + "\n"; - delete p_result; - } - } - } catch (...) { - std::cerr << "Unable to make indexed query " << cQuery << std::endl; - } - pthread_mutex_unlock(&searcherLock); - - return env->NewStringUTF(result.c_str()); } diff --git a/src/android/kiwixreader.cpp b/src/android/kiwixreader.cpp new file mode 100644 index 000000000..5f15d3b2e --- /dev/null +++ b/src/android/kiwixreader.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2013 Emmanuel Engelhart + * Copyright (C) 2017 Matthieu Gautier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + + +#include +#include +#include "org_kiwix_kiwixlib_JNIKiwix.h" + +#include "common/base64.h" +#include "reader.h" +#include "utils.h" + +/* Kiwix Reader JNI functions */ +JNIEXPORT jlong JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_get_nativeReader( + JNIEnv* env, jobject obj, jstring filename) +{ + std::string cPath = jni2c(filename, env); + + Lock l; + kiwix::Reader* reader = nullptr; + try { + reader = new kiwix::Reader(cPath); + } catch (...) { + std::cerr << "Unable to load ZIM " << cPath << std::endl; + reader = NULL; + } + + return reinterpret_cast(new Handle(reader)); +} + +JNIEXPORT void JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_dispose(JNIEnv* env, jobject obj) +{ + Handle::dispose(env, obj); +} + +#define READER (Handle::getHandle(env, obj)) + +/* Kiwix library functions */ +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getMainPage(JNIEnv* env, jobject obj) +{ + jstring url; + + try { + std::string cUrl = READER->getMainPageUrl(); + url = c2jni(cUrl, env); + } catch (...) { + std::cerr << "Unable to get ZIM main page" << std::endl; + } + return url; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getId(JNIEnv* env, jobject obj) +{ + jstring id; + + try { + std::string cId = READER->getId(); + id = c2jni(cId, env); + } catch (...) { + std::cerr << "Unable to get ZIM id" << std::endl; + } + + return id; +} + +JNIEXPORT jint JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getFileSize(JNIEnv* env, jobject obj) +{ + jint size; + + try { + int cSize = READER->getFileSize(); + size = c2jni(cSize); + } catch (...) { + std::cerr << "Unable to get ZIM file size" << std::endl; + } + + return size; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getCreator(JNIEnv* env, jobject obj) +{ + jstring creator; + + try { + std::string cCreator = READER->getCreator(); + creator = c2jni(cCreator, env); + } catch (...) { + std::cerr << "Unable to get ZIM creator" << std::endl; + } + + return creator; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getPublisher(JNIEnv* env, jobject obj) +{ + jstring publisher; + + try { + std::string cPublisher = READER->getPublisher(); + publisher = c2jni(cPublisher, env); + } catch (...) { + std::cerr << "Unable to get ZIM creator" << std::endl; + } + return publisher; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getName(JNIEnv* env, jobject obj) +{ + jstring name; + + try { + std::string cName = READER->getName(); + name = c2jni(cName, env); + } catch (...) { + std::cerr << "Unable to get ZIM name" << std::endl; + } + return name; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getFavicon(JNIEnv* env, jobject obj) +{ + jstring favicon; + + try { + std::string cContent; + std::string cMime; + READER->getFavicon(cContent, cMime); + favicon = c2jni( + base64_encode(reinterpret_cast(cContent.c_str()), + cContent.length()), + env); + } catch (...) { + std::cerr << "Unable to get ZIM favicon" << std::endl; + } + return favicon; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getDate(JNIEnv* env, jobject obj) +{ + jstring date; + + try { + std::string cDate = READER->getDate(); + date = c2jni(cDate, env); + } catch (...) { + std::cerr << "Unable to get ZIM date" << std::endl; + } + return date; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getLanguage(JNIEnv* env, jobject obj) +{ + jstring language; + + try { + std::string cLanguage = READER->getLanguage(); + language = c2jni(cLanguage, env); + } catch (...) { + std::cerr << "Unable to get ZIM language" << std::endl; + } + + return language; +} + +JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getMimeType( + JNIEnv* env, jobject obj, jstring url) +{ + jstring mimeType; + + std::string cUrl = jni2c(url, env); + try { + std::string cMimeType; + READER->getMimeTypeByUrl(cUrl, cMimeType); + mimeType = c2jni(cMimeType, env); + } catch (...) { + std::cerr << "Unable to get mime-type for url " << cUrl << std::endl; + } + return mimeType; +} + +JNIEXPORT jbyteArray JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getContent( + JNIEnv* env, jobject obj, jstring url, jobject titleObj, jobject mimeTypeObj, jobject sizeObj) +{ + /* Default values */ + setStringObjValue("", titleObj, env); + setStringObjValue("", mimeTypeObj, env); + setIntObjValue(0, sizeObj, env); + jbyteArray data = env->NewByteArray(0); + + /* Retrieve the content */ + std::string cUrl = jni2c(url, env); + std::string cData; + std::string cTitle; + std::string cMimeType; + unsigned int cSize = 0; + + try { + if (READER->getContentByUrl(cUrl, cData, cTitle, cSize, cMimeType)) { + data = env->NewByteArray(cSize); + env->SetByteArrayRegion( + data, 0, cSize, reinterpret_cast(cData.c_str())); + setStringObjValue(cMimeType, mimeTypeObj, env); + setStringObjValue(cTitle, titleObj, env); + setIntObjValue(cSize, sizeObj, env); + } + } catch (...) { + std::cerr << "Unable to get content for url " << cUrl << std::endl; + } + + return data; +} + +JNIEXPORT jboolean JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_searchSuggestions(JNIEnv* env, + jobject obj, + jstring prefix, + jint count) +{ + jboolean retVal = JNI_FALSE; + std::string cPrefix = jni2c(prefix, env); + unsigned int cCount = jni2c(count); + + try { + if (READER->searchSuggestionsSmart(cPrefix, cCount)) { + retVal = JNI_TRUE; + } + } catch (...) { + std::cerr << "Unable to search suggestions for pattern " << cPrefix + << std::endl; + } + + return retVal; +} + +JNIEXPORT jboolean JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getNextSuggestion(JNIEnv* env, + jobject obj, + jobject titleObj) +{ + jboolean retVal = JNI_FALSE; + std::string cTitle; + + try { + if (READER->getNextSuggestion(cTitle)) { + setStringObjValue(cTitle, titleObj, env); + retVal = JNI_TRUE; + } + } catch (...) { + std::cerr << "Unable to get next suggestion" << std::endl; + } + + return retVal; +} + +JNIEXPORT jboolean JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getPageUrlFromTitle(JNIEnv* env, + jobject obj, + jstring title, + jobject urlObj) +{ + jboolean retVal = JNI_FALSE; + std::string cTitle = jni2c(title, env); + std::string cUrl; + + try { + if (READER->getPageUrlFromTitle(cTitle, cUrl)) { + setStringObjValue(cUrl, urlObj, env); + retVal = JNI_TRUE; + } + } catch (...) { + std::cerr << "Unable to get URL for title " << cTitle << std::endl; + } + + return retVal; +} + +JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getTitle( + JNIEnv* env, jobject obj, jobject titleObj) +{ + jboolean retVal = JNI_FALSE; + std::string cTitle; + + try { + std::string cTitle = READER->getTitle(); + setStringObjValue(cTitle, titleObj, env); + retVal = JNI_TRUE; + } catch (...) { + std::cerr << "Unable to get ZIM title" << std::endl; + } + + return retVal; +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixReader_getDescription(JNIEnv* env, jobject obj) +{ + jstring description; + + try { + std::string cDescription = READER->getDescription(); + description = c2jni(cDescription, env); + } catch (...) { + std::cerr << "Unable to get ZIM description" << std::endl; + } + return description; +} + +JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getRandomPage( + JNIEnv* env, jobject obj, jobject urlObj) +{ + jboolean retVal = JNI_FALSE; + std::string cUrl; + + try { + std::string cUrl = READER->getRandomPageUrl(); + setStringObjValue(cUrl, urlObj, env); + retVal = JNI_TRUE; + } catch (...) { + std::cerr << "Unable to get random page" << std::endl; + } + + return retVal; +} diff --git a/src/android/kiwixsearcher.cpp b/src/android/kiwixsearcher.cpp new file mode 100644 index 000000000..64d2bafcd --- /dev/null +++ b/src/android/kiwixsearcher.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2013 Emmanuel Engelhart + * Copyright (C) 2017 Matthieu Gautier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + + +#include + +#include "reader.h" +#include "searcher.h" +#include "utils.h" + +#define SEARCHER (Handle::getHandle(env, obj)) +#define RESULT (Handle::getHandle(env, obj)) + +JNIEXPORT void JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_dispose(JNIEnv* env, jobject obj) +{ + Handle::dispose(env, obj); +} + +/* Kiwix Reader JNI functions */ +JNIEXPORT jlong JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_get_nativeHandle(JNIEnv* env, + jobject obj) +{ + kiwix::Searcher* searcher = new kiwix::Searcher("", nullptr); + return reinterpret_cast(new Handle(searcher)); +} + +/* Kiwix library functions */ +JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher__add_reader( + JNIEnv* env, jobject obj, jobject reader) +{ + auto searcher = SEARCHER; + searcher->add_reader(*(Handle::getHandle(env, reader)), ""); +} + +JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_search( + JNIEnv* env, jobject obj, jstring query, jint count) +{ + std::string cquery = jni2c(query, env); + unsigned int ccount = jni2c(count); + + SEARCHER->search(cquery, 0, ccount); +} + +JNIEXPORT jobject JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_get_next_result(JNIEnv* env, + jobject obj) +{ + jobject result = nullptr; + + kiwix::Result* cresult = SEARCHER->getNextResult(); + if (cresult != nullptr) { + jclass resultclass + = env->FindClass("org/kiwix/kiwixlib/JNIKiwixSearcher/Result"); + jmethodID ctor = env->GetMethodID( + resultclass, "", "(JLorg/kiwix/kiwixlib/JNIKiwixSearcher;)V"); + result = env->NewObject(resultclass, ctor, cresult, obj); + } + return result; +} + +JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_dispose( + JNIEnv* env, jobject obj) +{ + Handle::dispose(env, obj); +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_url(JNIEnv* env, + jobject obj) +{ + try { + return c2jni(RESULT->get_url(), env); + } catch (...) { + return nullptr; + } +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_title(JNIEnv* env, + jobject obj) +{ + try { + return c2jni(RESULT->get_title(), env); + } catch (...) { + return nullptr; + } +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_snippet(JNIEnv* env, + jobject obj) +{ + return c2jni(RESULT->get_snippet(), env); +} + +JNIEXPORT jstring JNICALL +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_content(JNIEnv* env, + jobject obj) +{ + return c2jni(RESULT->get_content(), env); +} diff --git a/src/android/meson.build b/src/android/meson.build index bb9bc8861..aa2a4d37d 100644 --- a/src/android/meson.build +++ b/src/android/meson.build @@ -3,6 +3,8 @@ jni_generator = find_program('gen_kiwix.sh') kiwix_jni = custom_target('jni', input: ['org/kiwix/kiwixlib/JNIKiwix.java', + 'org/kiwix/kiwixlib/JNIKiwixReader.java', + 'org/kiwix/kiwixlib/JNIKiwixSearcher.java', 'org/kiwix/kiwixlib/JNIKiwixInt.java', 'org/kiwix/kiwixlib/JNIKiwixString.java', 'org/kiwix/kiwixlib/JNIKiwixBool.java'], @@ -10,7 +12,11 @@ kiwix_jni = custom_target('jni', command:[jni_generator, '@INPUT@'] ) -kiwix_sources += ['android/kiwix.cpp', kiwix_jni] +kiwix_sources += [ + 'android/kiwix.cpp', + 'android/kiwixreader.cpp', + 'android/kiwixsearcher.cpp', + kiwix_jni] install_subdir('org', install_dir: 'kiwix-lib/java') install_subdir('res', install_dir: 'kiwix-lib') diff --git a/src/android/org/kiwix/kiwixlib/JNIKiwix.java b/src/android/org/kiwix/kiwixlib/JNIKiwix.java index 0c87396ab..0d79db697 100644 --- a/src/android/org/kiwix/kiwixlib/JNIKiwix.java +++ b/src/android/org/kiwix/kiwixlib/JNIKiwix.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 Emmanuel Engelhart + * Copyright (C) 2017 Matthieu Gautier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,56 +20,12 @@ package org.kiwix.kiwixlib; +import org.kiwix.kiwixlib.JNIKiwixReader; import org.kiwix.kiwixlib.JNIKiwixString; -import org.kiwix.kiwixlib.JNIKiwixBool; -import org.kiwix.kiwixlib.JNIKiwixInt; public class JNIKiwix { static { System.loadLibrary("kiwix"); } - public native String getMainPage(); - - public native String getId(); - - public native String getLanguage(); - - public native String getMimeType(String url); - - public native boolean loadZIM(String path); - - public native boolean loadFulltextIndex(String path); - - public native byte[] getContent(String url, JNIKiwixString title, JNIKiwixString mimeType, JNIKiwixInt size); - - public native boolean searchSuggestions(String prefix, int count); - - public native boolean getNextSuggestion(JNIKiwixString title); - - public native boolean getPageUrlFromTitle(String title, JNIKiwixString url); - - public native boolean getTitle(JNIKiwixString title); - - public native String getDescription(); - - public native String getDate(); - - public native String getFavicon(); - - public native String getCreator(); - - public native String getPublisher(); - - public native String getName(); - - public native int getFileSize(); - - public native int getArticleCount(); - - public native int getMediaCount(); - - public native boolean getRandomPage(JNIKiwixString url); public native void setDataDirectory(String icuDataDir); - - public static native String indexedQuery(String db, int count); } diff --git a/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java b/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java new file mode 100644 index 000000000..e805317f0 --- /dev/null +++ b/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2013 Emmanuel Engelhart + * Copyright (C) 2017 Matthieu Gautier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +package org.kiwix.kiwixlib; + +import org.kiwix.kiwixlib.JNIKiwixString; +import org.kiwix.kiwixlib.JNIKiwixInt; +import org.kiwix.kiwixlib.JNIKiwixSearcher; + +public class JNIKiwixReader +{ + public native String getMainPage(); + + public native String getTitle(); + + public native String getId(); + + public native String getLanguage(); + + public native String getMimeType(String url); + + public native byte[] getContent(String url, + JNIKiwixString title, + JNIKiwixString mimeType, + JNIKiwixInt size); + + public native boolean searchSuggestions(String prefix, int count); + + public native boolean getNextSuggestion(JNIKiwixString title); + + public native boolean getPageUrlFromTitle(String title, JNIKiwixString url); + + public native String getDescription(); + + public native String getDate(); + + public native String getFavicon(); + + public native String getCreator(); + + public native String getPublisher(); + + public native String getName(); + + public native int getFileSize(); + + public native int getArticleCount(); + + public native int getMediaCount(); + + public native boolean getRandomPage(JNIKiwixString url); + + public JNIKiwixSearcher search(String query, int count) + { + JNIKiwixSearcher searcher = new JNIKiwixSearcher(); + searcher.add_reader(this); + searcher.search(query, count); + return searcher; + } + + public JNIKiwixReader(String filename) + { + nativeHandle = get_nativeReader(filename); + } + + public native void dispose(); + + private native long get_nativeReader(String filename); + private long nativeHandle; +} diff --git a/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java b/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java new file mode 100644 index 000000000..035ff0542 --- /dev/null +++ b/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2013 Emmanuel Engelhart + * Copyright (C) 2017 Matthieu Gautier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + + +package org.kiwix.kiwixlib; + +import org.kiwix.kiwixlib.JNIKiwixReader; +import java.util.Vector; + +public class JNIKiwixSearcher +{ + public class Result + { + private long nativeHandle; + private JNIKiwixSearcher searcher; + public Result(long handle, JNIKiwixSearcher _searcher) + { + nativeHandle = handle; + searcher = _searcher; + } + public native String get_url(); + public native String get_title(); + public native String get_content(); + public native void dispose(); + } + + public JNIKiwixSearcher() + { + nativeHandle = get_nativeHandle(); + usedReaders = new Vector(); + } + public native void dispose(); + + private native long get_nativeHandle(); + private long nativeHandle; + private Vector usedReaders; + + public native void _add_reader(JNIKiwixReader reader); + public void add_reader(JNIKiwixReader reader) + { + _add_reader(reader); + usedReaders.addElement(reader); + }; + + public native Result search(String query, int count); + + public native Result get_next_result(); + public native boolean has_more_result(); +} diff --git a/src/android/utils.h b/src/android/utils.h new file mode 100644 index 000000000..f61114730 --- /dev/null +++ b/src/android/utils.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2013 Emmanuel Engelhart + * Copyright (C) 2017 Matthieu Gautier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + + +#ifndef _ANDROID_JNI_UTILS_H +#define _ANDROID_JNI_UTILS_H + +#include + +#include +#include + +extern pthread_mutex_t globalLock; + +inline jfieldID getHandleField(JNIEnv* env, jobject obj) +{ + jclass c = env->GetObjectClass(obj); + // J is the type signature for long: + return env->GetFieldID(c, "nativeHandle", "J"); +} + +class Lock +{ + protected: + pthread_mutex_t* lock; + + public: + Lock() : lock(&globalLock) { pthread_mutex_lock(lock); } + Lock(const Lock&) = delete; + Lock& operator=(const Lock&) = delete; + Lock(Lock&& other) : lock(&globalLock) { other.lock = nullptr; } + virtual ~Lock() + { + if (lock) { + pthread_mutex_unlock(lock); + } + } +}; + +template +class LockedHandle; + +template +class Handle +{ + protected: + T* h; + + public: + Handle(T* h) : h(h){}; + + // No destructor. This must and will be handled by dispose method. + + static LockedHandle getHandle(JNIEnv* env, jobject obj) + { + jlong handle = env->GetLongField(obj, getHandleField(env, obj)); + return LockedHandle(reinterpret_cast*>(handle)); + } + + static void dispose(JNIEnv* env, jobject obj) + { + auto lHandle = getHandle(env, obj); + auto handle = lHandle.h; + delete handle->h; + delete handle; + } + friend class LockedHandle; +}; + +template +struct LockedHandle : public Lock { + Handle* h; + LockedHandle(Handle* h) : h(h) {} + T* operator->() { return h->h; } + T* operator*() { return h->h; } + operator bool() const { return (h->h != nullptr); } +}; + +/* c2jni type conversion functions */ +inline jboolean c2jni(const bool& val) { return val ? JNI_TRUE : JNI_FALSE; } +inline jstring c2jni(const std::string& val, JNIEnv* env) +{ + return env->NewStringUTF(val.c_str()); +} + +inline jint c2jni(const int val) { return (jint)val; } +inline jint c2jni(const unsigned val) { return (unsigned)val; } +/* jni2c type conversion functions */ +inline bool jni2c(const jboolean& val) { return val == JNI_TRUE; } +inline std::string jni2c(const jstring& val, JNIEnv* env) +{ + const char* chars = env->GetStringUTFChars(val, 0); + std::string ret(chars); + env->ReleaseStringUTFChars(val, chars); + return ret; +} + +inline int jni2c(const jint val) { return (int)val; } +/* Method to deal with variable passed by reference */ +inline void setStringObjValue(const std::string& value, + const jobject obj, + JNIEnv* env) +{ + jclass objClass = env->GetObjectClass(obj); + jfieldID objFid = env->GetFieldID(objClass, "value", "Ljava/lang/String;"); + env->SetObjectField(obj, objFid, c2jni(value, env)); +} + +inline void setIntObjValue(const int value, const jobject obj, JNIEnv* env) +{ + jclass objClass = env->GetObjectClass(obj); + jfieldID objFid = env->GetFieldID(objClass, "value", "I"); + env->SetIntField(obj, objFid, value); +} + +inline void setBoolObjValue(const bool value, const jobject obj, JNIEnv* env) +{ + jclass objClass = env->GetObjectClass(obj); + jfieldID objFid = env->GetFieldID(objClass, "value", "Z"); + env->SetIntField(obj, objFid, c2jni(value)); +} + +#endif // _ANDROID_JNI_UTILS_H From d2f7503cfade7a60c516771ce8b35cf1bf98d715 Mon Sep 17 00:00:00 2001 From: mhutti1 Date: Fri, 11 Aug 2017 14:50:22 -0400 Subject: [PATCH 3/4] Fix JNI for android integration --- src/android/gen_kiwix.sh | 6 ++++-- src/android/kiwixreader.cpp | 17 +++++++---------- src/android/kiwixsearcher.cpp | 1 + src/android/meson.build | 4 +++- .../org/kiwix/kiwixlib/JNIKiwixReader.java | 6 ++++-- .../org/kiwix/kiwixlib/JNIKiwixSearcher.java | 2 +- 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/android/gen_kiwix.sh b/src/android/gen_kiwix.sh index 9966b7b27..9140ae010 100755 --- a/src/android/gen_kiwix.sh +++ b/src/android/gen_kiwix.sh @@ -5,10 +5,12 @@ set -e BUILD_PATH=$(pwd) echo "javac -d $BUILD_PATH/src/android $@" -javac -d $BUILD_PATH/src/android "$@" +javac -d $BUILD_PATH/src/android/ "$@" cd $BUILD_PATH/src/android -echo "javah -jni org.kiwix.kiwixlib.JNIKiwix" +echo "javah -jni org.kiwix.kiwixlib" javah -jni org.kiwix.kiwixlib.JNIKiwix +javah -jni org.kiwix.kiwixlib.JNIKiwixReader +javah -jni org.kiwix.kiwixlib.JNIKiwixSearcher cd $BUILD_PATH diff --git a/src/android/kiwixreader.cpp b/src/android/kiwixreader.cpp index 5f15d3b2e..e50e100ca 100644 --- a/src/android/kiwixreader.cpp +++ b/src/android/kiwixreader.cpp @@ -21,14 +21,14 @@ #include #include -#include "org_kiwix_kiwixlib_JNIKiwix.h" +#include "org_kiwix_kiwixlib_JNIKiwixReader.h" #include "common/base64.h" #include "reader.h" #include "utils.h" /* Kiwix Reader JNI functions */ -JNIEXPORT jlong JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_get_nativeReader( +JNIEXPORT jlong JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getNativeReader( JNIEnv* env, jobject obj, jstring filename) { std::string cPath = jni2c(filename, env); @@ -301,21 +301,18 @@ Java_org_kiwix_kiwixlib_JNIKiwixReader_getPageUrlFromTitle(JNIEnv* env, return retVal; } -JNIEXPORT jboolean JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getTitle( - JNIEnv* env, jobject obj, jobject titleObj) +JNIEXPORT jstring JNICALL Java_org_kiwix_kiwixlib_JNIKiwixReader_getTitle( + JNIEnv* env, jobject obj) { - jboolean retVal = JNI_FALSE; - std::string cTitle; + jstring title; try { std::string cTitle = READER->getTitle(); - setStringObjValue(cTitle, titleObj, env); - retVal = JNI_TRUE; + title = c2jni(cTitle, env); } catch (...) { std::cerr << "Unable to get ZIM title" << std::endl; } - - return retVal; + return title; } JNIEXPORT jstring JNICALL diff --git a/src/android/kiwixsearcher.cpp b/src/android/kiwixsearcher.cpp index 64d2bafcd..410b54bb6 100644 --- a/src/android/kiwixsearcher.cpp +++ b/src/android/kiwixsearcher.cpp @@ -20,6 +20,7 @@ #include +#include "org_kiwix_kiwixlib_JNIKiwixSearcher.h" #include "reader.h" #include "searcher.h" diff --git a/src/android/meson.build b/src/android/meson.build index aa2a4d37d..2ee81d957 100644 --- a/src/android/meson.build +++ b/src/android/meson.build @@ -8,7 +8,9 @@ kiwix_jni = custom_target('jni', 'org/kiwix/kiwixlib/JNIKiwixInt.java', 'org/kiwix/kiwixlib/JNIKiwixString.java', 'org/kiwix/kiwixlib/JNIKiwixBool.java'], - output: ['org_kiwix_kiwixlib_JNIKiwix.h'], + output: ['org_kiwix_kiwixlib_JNIKiwix.h', + 'org_kiwix_kiwixlib_JNIKiwixReader.h', + 'org_kiwix_kiwixlib_JNIKiwixSearcher.h'], command:[jni_generator, '@INPUT@'] ) diff --git a/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java b/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java index e805317f0..ee4dfa68e 100644 --- a/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java +++ b/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java @@ -77,11 +77,13 @@ public class JNIKiwixReader public JNIKiwixReader(String filename) { - nativeHandle = get_nativeReader(filename); + nativeHandle = getNativeReader(filename); } + public JNIKiwixReader() { + } public native void dispose(); - private native long get_nativeReader(String filename); + private native long getNativeReader(String filename); private long nativeHandle; } diff --git a/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java b/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java index 035ff0542..72508391e 100644 --- a/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java +++ b/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java @@ -59,7 +59,7 @@ public class JNIKiwixSearcher usedReaders.addElement(reader); }; - public native Result search(String query, int count); + public native void search(String query, int count); public native Result get_next_result(); public native boolean has_more_result(); From 520c1edf3147f8084cad835b53fcf6bef877402e Mon Sep 17 00:00:00 2001 From: mhutti1 Date: Sun, 1 Oct 2017 21:03:50 +0100 Subject: [PATCH 4/4] Fix JNI android integration --- src/android/kiwixsearcher.cpp | 27 ++++++++++--------- src/android/meson.build | 3 ++- .../org/kiwix/kiwixlib/JNIKiwixReader.java | 2 +- .../org/kiwix/kiwixlib/JNIKiwixSearcher.java | 20 +++++++------- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/android/kiwixsearcher.cpp b/src/android/kiwixsearcher.cpp index 410b54bb6..317c50e8a 100644 --- a/src/android/kiwixsearcher.cpp +++ b/src/android/kiwixsearcher.cpp @@ -21,6 +21,7 @@ #include #include "org_kiwix_kiwixlib_JNIKiwixSearcher.h" +#include "org_kiwix_kiwixlib_JNIKiwixSearcher_Result.h" #include "reader.h" #include "searcher.h" @@ -29,6 +30,7 @@ #define SEARCHER (Handle::getHandle(env, obj)) #define RESULT (Handle::getHandle(env, obj)) + JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_dispose(JNIEnv* env, jobject obj) { @@ -37,18 +39,19 @@ Java_org_kiwix_kiwixlib_JNIKiwixSearcher_dispose(JNIEnv* env, jobject obj) /* Kiwix Reader JNI functions */ JNIEXPORT jlong JNICALL -Java_org_kiwix_kiwixlib_JNIKiwixSearcher_get_nativeHandle(JNIEnv* env, +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_getNativeHandle(JNIEnv* env, jobject obj) { - kiwix::Searcher* searcher = new kiwix::Searcher("", nullptr); + kiwix::Searcher* searcher = new kiwix::Searcher(); return reinterpret_cast(new Handle(searcher)); } /* Kiwix library functions */ -JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher__add_reader( +JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_addReader( JNIEnv* env, jobject obj, jobject reader) { auto searcher = SEARCHER; + searcher->add_reader(*(Handle::getHandle(env, reader)), ""); } @@ -62,7 +65,7 @@ JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_search( } JNIEXPORT jobject JNICALL -Java_org_kiwix_kiwixlib_JNIKiwixSearcher_get_next_result(JNIEnv* env, +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_getNextResult(JNIEnv* env, jobject obj) { jobject result = nullptr; @@ -70,22 +73,22 @@ Java_org_kiwix_kiwixlib_JNIKiwixSearcher_get_next_result(JNIEnv* env, kiwix::Result* cresult = SEARCHER->getNextResult(); if (cresult != nullptr) { jclass resultclass - = env->FindClass("org/kiwix/kiwixlib/JNIKiwixSearcher/Result"); + = env->FindClass("org/kiwix/kiwixlib/JNIKiwixSearcher$Result"); jmethodID ctor = env->GetMethodID( - resultclass, "", "(JLorg/kiwix/kiwixlib/JNIKiwixSearcher;)V"); - result = env->NewObject(resultclass, ctor, cresult, obj); + resultclass, "", "(Lorg/kiwix/kiwixlib/JNIKiwixSearcher;JLorg/kiwix/kiwixlib/JNIKiwixSearcher;)V"); + result = env->NewObject(resultclass, ctor, obj, reinterpret_cast(new Handle(cresult)), obj); } return result; } -JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_dispose( +JNIEXPORT void JNICALL Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_dispose( JNIEnv* env, jobject obj) { Handle::dispose(env, obj); } JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_url(JNIEnv* env, +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_getUrl(JNIEnv* env, jobject obj) { try { @@ -96,7 +99,7 @@ Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_url(JNIEnv* env, } JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_title(JNIEnv* env, +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_getTitle(JNIEnv* env, jobject obj) { try { @@ -107,14 +110,14 @@ Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_title(JNIEnv* env, } JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_snippet(JNIEnv* env, +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_getSnippet(JNIEnv* env, jobject obj) { return c2jni(RESULT->get_snippet(), env); } JNIEXPORT jstring JNICALL -Java_org_kiwix_kiwixlib_JNIKiwixSearcher_Result_get_content(JNIEnv* env, +Java_org_kiwix_kiwixlib_JNIKiwixSearcher_00024Result_getContent(JNIEnv* env, jobject obj) { return c2jni(RESULT->get_content(), env); diff --git a/src/android/meson.build b/src/android/meson.build index 2ee81d957..be6aeab24 100644 --- a/src/android/meson.build +++ b/src/android/meson.build @@ -10,7 +10,8 @@ kiwix_jni = custom_target('jni', 'org/kiwix/kiwixlib/JNIKiwixBool.java'], output: ['org_kiwix_kiwixlib_JNIKiwix.h', 'org_kiwix_kiwixlib_JNIKiwixReader.h', - 'org_kiwix_kiwixlib_JNIKiwixSearcher.h'], + 'org_kiwix_kiwixlib_JNIKiwixSearcher.h', + 'org_kiwix_kiwixlib_JNIKiwixSearcher_Result.h'], command:[jni_generator, '@INPUT@'] ) diff --git a/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java b/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java index ee4dfa68e..db416d4bc 100644 --- a/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java +++ b/src/android/org/kiwix/kiwixlib/JNIKiwixReader.java @@ -70,7 +70,7 @@ public class JNIKiwixReader public JNIKiwixSearcher search(String query, int count) { JNIKiwixSearcher searcher = new JNIKiwixSearcher(); - searcher.add_reader(this); + searcher.addKiwixReader(this); searcher.search(query, count); return searcher; } diff --git a/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java b/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java index 72508391e..ea21d8fe3 100644 --- a/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java +++ b/src/android/org/kiwix/kiwixlib/JNIKiwixSearcher.java @@ -35,32 +35,32 @@ public class JNIKiwixSearcher nativeHandle = handle; searcher = _searcher; } - public native String get_url(); - public native String get_title(); - public native String get_content(); + public native String getUrl(); + public native String getTitle(); + public native String getContent(); public native void dispose(); } public JNIKiwixSearcher() { - nativeHandle = get_nativeHandle(); + nativeHandle = getNativeHandle(); usedReaders = new Vector(); } public native void dispose(); - private native long get_nativeHandle(); + private native long getNativeHandle(); private long nativeHandle; private Vector usedReaders; - public native void _add_reader(JNIKiwixReader reader); - public void add_reader(JNIKiwixReader reader) + public native void addReader(JNIKiwixReader reader); + public void addKiwixReader(JNIKiwixReader reader) { - _add_reader(reader); + addReader(reader); usedReaders.addElement(reader); }; public native void search(String query, int count); - public native Result get_next_result(); - public native boolean has_more_result(); + public native Result getNextResult(); + public native boolean hasMoreResult(); }