ANDROID: Try to sync Android backend

This commit is contained in:
Pawel Kolodziejski 2020-09-03 02:50:39 +02:00
parent d5304e2568
commit 1884ccaa3a
7 changed files with 154 additions and 74 deletions

View file

@ -152,7 +152,18 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
OSystem_Android::~OSystem_Android() { OSystem_Android::~OSystem_Android() {
ENTER(); ENTER();
// _audiocdManager should be deleted before _mixer!
// It is normally deleted in proper order in the OSystem destructor.
// However, currently _mixer is deleted here (OSystem_Android)
// and in the ModularBackend destructor,
// hence unless _audiocdManager is deleted here first,
// it will cause a crash for the Android app (arm64 v8a) upon exit
// -- when the audio cd manager was actually used eg. audio cd test of the testbed
// FIXME: A more proper fix would probably be to:
// - delete _mixer in the base class (OSystem) after _audiocdManager (this is already the current behavior)
// - remove its deletion from OSystem_Android and ModularBackend (this is what needs to be fixed).
delete _audiocdManager;
_audiocdManager = 0;
delete _mixer; delete _mixer;
_mixer = 0; _mixer = 0;
delete _fsFactory; delete _fsFactory;
@ -326,11 +337,11 @@ void OSystem_Android::initBackend() {
_main_thread = pthread_self(); _main_thread = pthread_self();
ConfMan.set("fullscreen", "true"); ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", true); ConfMan.registerDefault("aspect_ratio", true);
ConfMan.registerDefault("touchpad_mouse_mode", true); ConfMan.registerDefault("touchpad_mouse_mode", true);
ConfMan.setInt("autosave_period", 0); ConfMan.registerDefault("autosave_period", 0);
ConfMan.setBool("FM_high_quality", false); ConfMan.setBool("FM_high_quality", false);
ConfMan.setBool("FM_medium_quality", true); ConfMan.setBool("FM_medium_quality", true);
ConfMan.set("browser_lastpath", ConfMan.get("path")); ConfMan.set("browser_lastpath", ConfMan.get("path"));
@ -348,10 +359,13 @@ void OSystem_Android::initBackend() {
// screen. Passing the savepath in this way makes it stick // screen. Passing the savepath in this way makes it stick
// (via ConfMan.registerDefault) // (via ConfMan.registerDefault)
_savefileManager = new DefaultSaveFileManager(ConfMan.get("savepath")); _savefileManager = new DefaultSaveFileManager(ConfMan.get("savepath"));
// TODO remove the debug message eventually
LOGD("Setting DefaultSaveFileManager path to: %s", ConfMan.get("savepath").c_str());
_mutexManager = new PthreadMutexManager(); _mutexManager = new PthreadMutexManager();
_timerManager = new DefaultTimerManager(); _timerManager = new DefaultTimerManager();
_event_queue_lock = createMutex(); _event_queue_lock = new Common::Mutex();
gettimeofday(&_startTime, 0); gettimeofday(&_startTime, 0);
@ -374,6 +388,9 @@ void OSystem_Android::initBackend() {
JNI::setReadyForEvents(true); JNI::setReadyForEvents(true);
_eventManager = new DefaultEventManager(this);
_audiocdManager = new DefaultAudioCDManager();
BaseBackend::initBackend(); BaseBackend::initBackend();
} }
@ -388,7 +405,7 @@ bool OSystem_Android::hasFeature(Feature f) {
f == kFeatureClipboardSupport) { f == kFeatureClipboardSupport) {
return true; return true;
} }
return ModularBackend::hasFeature(f); return ModularGraphicsBackend::hasFeature(f);
} }
void OSystem_Android::setFeatureState(Feature f, bool enable) { void OSystem_Android::setFeatureState(Feature f, bool enable) {
@ -408,7 +425,7 @@ void OSystem_Android::setFeatureState(Feature f, bool enable) {
JNI::showKeyboardControl(enable); JNI::showKeyboardControl(enable);
break; break;
default: default:
ModularBackend::setFeatureState(f, enable); ModularGraphicsBackend::setFeatureState(f, enable);
break; break;
} }
} }
@ -422,10 +439,30 @@ bool OSystem_Android::getFeatureState(Feature f) {
case kFeatureOnScreenControl: case kFeatureOnScreenControl:
return ConfMan.getBool("onscreen_control"); return ConfMan.getBool("onscreen_control");
default: default:
return ModularBackend::getFeatureState(f); return ModularGraphicsBackend::getFeatureState(f);
} }
} }
Common::KeymapperDefaultBindings *OSystem_Android::getKeymapperDefaultBindings() {
Common::KeymapperDefaultBindings *keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
// The swap_menu_and_back is a legacy configuration key
// It is only checked here for compatibility with old config files
// where it may have been set as "true"
// TODO Why not just ignore it entirely anyway?
if (ConfMan.hasKey("swap_menu_and_back") && ConfMan.getBool("swap_menu_and_back")) {
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "MENU", "AC_BACK");
keymapperDefaultBindings->setDefaultBinding("engine-default", Common::kStandardActionSkip, "MENU");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "CLOS", "MENU");
} else {
keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "MENU", "MENU");
keymapperDefaultBindings->setDefaultBinding("engine-default", Common::kStandardActionSkip, "AC_BACK");
keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "CLOS", "AC_BACK");
}
return keymapperDefaultBindings;
}
// ResidualVM specific method // ResidualVM specific method
void OSystem_Android::launcherInitSize(uint w, uint h) { void OSystem_Android::launcherInitSize(uint w, uint h) {
dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->setupScreen(w, h, true, true, false); dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->setupScreen(w, h, true, true, false);
@ -464,7 +501,6 @@ void OSystem_Android::setWindowCaption(const char *caption) {
JNI::setWindowCaption(caption); JNI::setWindowCaption(caption);
} }
void OSystem_Android::showVirtualKeyboard(bool enable) { void OSystem_Android::showVirtualKeyboard(bool enable) {
ENTER("%d", enable); ENTER("%d", enable);
@ -523,18 +559,18 @@ Common::String OSystem_Android::getSystemLanguage() const {
} }
bool OSystem_Android::openUrl(const Common::String &url) { bool OSystem_Android::openUrl(const Common::String &url) {
return JNI::openUrl(url.c_str()); return JNI::openUrl(url);
} }
bool OSystem_Android::hasTextInClipboard() { bool OSystem_Android::hasTextInClipboard() {
return JNI::hasTextInClipboard(); return JNI::hasTextInClipboard();
} }
Common::String OSystem_Android::getTextFromClipboard() { Common::U32String OSystem_Android::getTextFromClipboard() {
return JNI::getTextFromClipboard(); return JNI::getTextFromClipboard();
} }
bool OSystem_Android::setTextInClipboard(const Common::String &text) { bool OSystem_Android::setTextInClipboard(const Common::U32String &text) {
return JNI::setTextInClipboard(text); return JNI::setTextInClipboard(text);
} }
@ -550,4 +586,8 @@ Common::String OSystem_Android::getSystemProperty(const char *name) const {
return Common::String(value, len); return Common::String(value, len);
} }
char *OSystem_Android::convertEncoding(const char *to, const char *from, const char *string, size_t length) {
return JNI::convertEncoding(to, from, string, length);
}
#endif #endif

View file

@ -28,6 +28,8 @@
#include "backends/platform/android/portdefs.h" #include "backends/platform/android/portdefs.h"
#include "common/fs.h" #include "common/fs.h"
#include "common/archive.h" #include "common/archive.h"
#include "common/mutex.h"
#include "common/ustr.h"
#include "audio/mixer_intern.h" #include "audio/mixer_intern.h"
#include "graphics/palette.h" #include "graphics/palette.h"
#include "graphics/surface.h" #include "graphics/surface.h"
@ -100,7 +102,7 @@ extern void checkGlError(const char *expr, const char *file, int line);
#define GLTHREADCHECK do { } while (false) #define GLTHREADCHECK do { } while (false)
#endif #endif
class OSystem_Android : public ModularBackend, Common::EventSource { class OSystem_Android : public ModularMutexBackend, public ModularGraphicsBackend, Common::EventSource {
private: private:
// passed from the dark side // passed from the dark side
int _audio_sample_rate; int _audio_sample_rate;
@ -127,9 +129,6 @@ private:
void setupKeymapper(); void setupKeymapper();
protected:
virtual Common::EventSource *getDefaultEventSource() { return this; }
public: public:
OSystem_Android(int audio_sample_rate, int audio_buffer_size); OSystem_Android(int audio_sample_rate, int audio_buffer_size);
virtual ~OSystem_Android(); virtual ~OSystem_Android();
@ -140,10 +139,6 @@ public:
virtual void setFeatureState(OSystem::Feature f, bool enable); virtual void setFeatureState(OSystem::Feature f, bool enable);
virtual bool getFeatureState(OSystem::Feature f); virtual bool getFeatureState(OSystem::Feature f);
virtual PaletteManager *getPaletteManager() override {
return dynamic_cast<AndroidGraphicsManager *>(_graphicsManager);
}
public: public:
void pushEvent(int type, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); void pushEvent(int type, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
bool shouldGenerateMouseEvents(); bool shouldGenerateMouseEvents();
@ -152,7 +147,7 @@ private:
Common::Queue<Common::Event> _event_queue; Common::Queue<Common::Event> _event_queue;
Common::Event _queuedEvent; Common::Event _queuedEvent;
uint32 _queuedEventTime; uint32 _queuedEventTime;
MutexRef _event_queue_lock; Common::Mutex *_event_queue_lock;
Common::Point _touch_pt_down, _touch_pt_scroll, _touch_pt_dt; Common::Point _touch_pt_down, _touch_pt_scroll, _touch_pt_dt;
int _eventScaleX; int _eventScaleX;
@ -174,6 +169,8 @@ public:
virtual void pushEvent(const Common::Event &event); virtual void pushEvent(const Common::Event &event);
virtual void pushKeyPressEvent(Common::Event &event); virtual void pushKeyPressEvent(Common::Event &event);
virtual bool pollEvent(Common::Event &event); virtual bool pollEvent(Common::Event &event);
virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings();
virtual uint32 getMillis(bool skipRecord = false); virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs); virtual void delayMillis(uint msecs);
@ -189,10 +186,11 @@ public:
int priority = 0); int priority = 0);
virtual bool openUrl(const Common::String &url); virtual bool openUrl(const Common::String &url);
virtual bool hasTextInClipboard(); virtual bool hasTextInClipboard();
virtual Common::String getTextFromClipboard(); virtual Common::U32String getTextFromClipboard();
virtual bool setTextInClipboard(const Common::String &text); virtual bool setTextInClipboard(const Common::U32String &text);
virtual bool isConnectionLimited(); virtual bool isConnectionLimited();
virtual Common::String getSystemLanguage() const; virtual Common::String getSystemLanguage() const;
virtual char *convertEncoding(const char *to, const char *from, const char *string, size_t length);
// ResidualVM specific method // ResidualVM specific method
virtual void launcherInitSize(uint w, uint h); virtual void launcherInitSize(uint w, uint h);

View file

@ -71,6 +71,9 @@ AssetInputStream::AssetInputStream(AAssetManager *as, const Common::String &path
} }
AssetInputStream::~AssetInputStream() { AssetInputStream::~AssetInputStream() {
if (_asset != NULL) {
AAsset_close(_asset);
}
} }
void AssetInputStream::close() { void AssetInputStream::close() {
@ -134,7 +137,7 @@ int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) con
dirs.push_back("shaders"); dirs.push_back("shaders");
int count = 0; int count = 0;
for (const auto& currentDir : dirs) { for (const auto& currentDir : dirs) {
AAssetDir *dir = AAssetManager_openDir(_am, currentDir.c_str()); AAssetDir *dir = AAssetManager_openDir(_am, "");
const char *file = AAssetDir_getNextFileName(dir); const char *file = AAssetDir_getNextFileName(dir);
while (file) { while (file) {

View file

@ -40,8 +40,8 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_printf #define FORBIDDEN_SYMBOL_EXCEPTION_printf
#include "backends/platform/android/android.h" #include "backends/platform/android/android.h"
#include "backends/platform/android/events.h"
#include "backends/platform/android/graphics.h" #include "backends/platform/android/graphics.h"
#include "backends/platform/android/events.h"
#include "backends/platform/android/jni-android.h" #include "backends/platform/android/jni-android.h"
#include "engines/engine.h" #include "engines/engine.h"
@ -755,9 +755,9 @@ bool OSystem_Android::shouldGenerateMouseEvents() {
} }
void OSystem_Android::pushEvent(const Common::Event &event) { void OSystem_Android::pushEvent(const Common::Event &event) {
lockMutex(_event_queue_lock); _event_queue_lock->lock();
_event_queue.push(event); _event_queue.push(event);
unlockMutex(_event_queue_lock); _event_queue_lock->unlock();
} }
void OSystem_Android::pushKeyPressEvent(Common::Event &event) { void OSystem_Android::pushKeyPressEvent(Common::Event &event) {

View file

@ -36,7 +36,7 @@ public:
void updateScreen() override; void updateScreen() override;
void displayMessageOnOSD(const char *msg); void displayMessageOnOSD(const Common::U32String &msg);
bool notifyMousePosition(Common::Point &mouse); bool notifyMousePosition(Common::Point &mouse);
Common::Point getMousePosition() { return Common::Point(_cursorX, _cursorY); } Common::Point getMousePosition() { return Common::Point(_cursorX, _cursorY); }

View file

@ -87,6 +87,7 @@ jmethodID JNI::_MID_setWindowCaption = 0;
jmethodID JNI::_MID_showVirtualKeyboard = 0; jmethodID JNI::_MID_showVirtualKeyboard = 0;
jmethodID JNI::_MID_showKeyboardControl = 0; jmethodID JNI::_MID_showKeyboardControl = 0;
jmethodID JNI::_MID_getSysArchives = 0; jmethodID JNI::_MID_getSysArchives = 0;
jmethodID JNI::_MID_convertEncoding = 0;
jmethodID JNI::_MID_getAllStorageLocations = 0; jmethodID JNI::_MID_getAllStorageLocations = 0;
jmethodID JNI::_MID_initSurface = 0; jmethodID JNI::_MID_initSurface = 0;
jmethodID JNI::_MID_deinitSurface = 0; jmethodID JNI::_MID_deinitSurface = 0;
@ -116,9 +117,7 @@ const JNINativeMethod JNI::_natives[] = {
{ "pushEvent", "(IIIIIII)V", { "pushEvent", "(IIIIIII)V",
(void *)JNI::pushEvent }, (void *)JNI::pushEvent },
{ "setPause", "(Z)V", { "setPause", "(Z)V",
(void *)JNI::setPause }, (void *)JNI::setPause }
{ "getCurrentCharset", "()Ljava/lang/String;",
(void *)JNI::getCurrentCharset }
}; };
JNI::JNI() { JNI::JNI() {
@ -227,24 +226,16 @@ void JNI::getDPI(float *values) {
env->DeleteLocalRef(array); env->DeleteLocalRef(array);
} }
void JNI::displayMessageOnOSD(const char *msg) { void JNI::displayMessageOnOSD(const Common::U32String &msg) {
// called from common/osd_message_queue, method: OSDMessageQueue::pollEvent() // called from common/osd_message_queue, method: OSDMessageQueue::pollEvent()
JNIEnv *env = JNI::getEnv(); JNIEnv *env = JNI::getEnv();
Common::String fromEncoding = "ISO-8859-1";
#ifdef USE_TRANSLATION
if (TransMan.getCurrentCharset() != "ASCII") {
fromEncoding = TransMan.getCurrentCharset();
}
#endif
Common::Encoding converter("UTF-8", fromEncoding.c_str());
const char *utf8Msg = converter.convert(msg, converter.stringLength(msg, fromEncoding) ); jstring java_msg = convertToJString(env, msg.encode(), "UTF-8");
if (utf8Msg == nullptr) { if (java_msg == nullptr) {
// Show a placeholder indicative of the translation error instead of silent failing // Show a placeholder indicative of the translation error instead of silent failing
utf8Msg = "?"; java_msg = env->NewStringUTF("?");
LOGE("Failed to convert message to UTF-8 for OSD!"); LOGE("Failed to convert message to UTF-8 for OSD!");
} }
jstring java_msg = env->NewStringUTF(utf8Msg);
env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg); env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg);
@ -258,10 +249,10 @@ void JNI::displayMessageOnOSD(const char *msg) {
env->DeleteLocalRef(java_msg); env->DeleteLocalRef(java_msg);
} }
bool JNI::openUrl(const char *url) { bool JNI::openUrl(const Common::String &url) {
bool success = true; bool success = true;
JNIEnv *env = JNI::getEnv(); JNIEnv *env = JNI::getEnv();
jstring javaUrl = env->NewStringUTF(url); jstring javaUrl = env->NewStringUTF(url.c_str());
env->CallVoidMethod(_jobj, _MID_openUrl, javaUrl); env->CallVoidMethod(_jobj, _MID_openUrl, javaUrl);
@ -292,10 +283,10 @@ bool JNI::hasTextInClipboard() {
return hasText; return hasText;
} }
Common::String JNI::getTextFromClipboard() { Common::U32String JNI::getTextFromClipboard() {
JNIEnv *env = JNI::getEnv(); JNIEnv *env = JNI::getEnv();
jbyteArray javaText = (jbyteArray)env->CallObjectMethod(_jobj, _MID_getTextFromClipboard); jstring javaText = (jstring)env->CallObjectMethod(_jobj, _MID_getTextFromClipboard);
if (env->ExceptionCheck()) { if (env->ExceptionCheck()) {
LOGE("Failed to retrieve text from the clipboard"); LOGE("Failed to retrieve text from the clipboard");
@ -303,23 +294,18 @@ Common::String JNI::getTextFromClipboard() {
env->ExceptionDescribe(); env->ExceptionDescribe();
env->ExceptionClear(); env->ExceptionClear();
return Common::String(); return Common::U32String();
} }
int len = env->GetArrayLength(javaText); Common::String text = convertFromJString(env, javaText, "UTF-8");
char* buf = new char[len]; env->DeleteLocalRef(javaText);
env->GetByteArrayRegion(javaText, 0, len, reinterpret_cast<jbyte*>(buf));
Common::String text(buf, len);
delete[] buf;
return text; return text.decode();
} }
bool JNI::setTextInClipboard(const Common::String &text) { bool JNI::setTextInClipboard(const Common::U32String &text) {
JNIEnv *env = JNI::getEnv(); JNIEnv *env = JNI::getEnv();
jstring javaText = convertToJString(env, text.encode(), "UTF-8");
jbyteArray javaText = env->NewByteArray(text.size());
env->SetByteArrayRegion(javaText, 0, text.size(), reinterpret_cast<const jbyte*>(text.c_str()));
bool success = env->CallBooleanMethod(_jobj, _MID_setTextInClipboard, javaText); bool success = env->CallBooleanMethod(_jobj, _MID_setTextInClipboard, javaText);
@ -350,9 +336,9 @@ bool JNI::isConnectionLimited() {
return limited; return limited;
} }
void JNI::setWindowCaption(const char *caption) { void JNI::setWindowCaption(const Common::String &caption) {
JNIEnv *env = JNI::getEnv(); JNIEnv *env = JNI::getEnv();
jstring java_caption = env->NewStringUTF(caption); jstring java_caption = convertToJString(env, caption, "ISO-8859-1");
env->CallVoidMethod(_jobj, _MID_setWindowCaption, java_caption); env->CallVoidMethod(_jobj, _MID_setWindowCaption, java_caption);
@ -423,6 +409,36 @@ void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
} }
} }
char *JNI::convertEncoding(const char *to, const char *from, const char *string, size_t length) {
JNIEnv *env = JNI::getEnv();
jstring javaTo = env->NewStringUTF(to);
jstring javaFrom = env->NewStringUTF(from);
jbyteArray javaString = env->NewByteArray(length);
env->SetByteArrayRegion(javaString, 0, length, reinterpret_cast<const jbyte*>(string));
jbyteArray javaOut = (jbyteArray)env->CallObjectMethod(_jobj, _MID_convertEncoding, javaTo, javaFrom, javaString);
if (!javaOut || env->ExceptionCheck()) {
LOGE("Failed to convert text from %s to %s", from, to);
env->ExceptionDescribe();
env->ExceptionClear();
return nullptr;
}
int outLength = env->GetArrayLength(javaOut);
char *buf = (char *)malloc(outLength + 1);
if (!buf)
return nullptr;
env->GetByteArrayRegion(javaOut, 0, outLength, reinterpret_cast<jbyte *>(buf));
buf[outLength] = 0;
return buf;
}
bool JNI::initSurface() { bool JNI::initSurface() {
JNIEnv *env = JNI::getEnv(); JNIEnv *env = JNI::getEnv();
@ -544,13 +560,14 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V"); FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V");
FIND_METHOD(, openUrl, "(Ljava/lang/String;)V"); FIND_METHOD(, openUrl, "(Ljava/lang/String;)V");
FIND_METHOD(, hasTextInClipboard, "()Z"); FIND_METHOD(, hasTextInClipboard, "()Z");
FIND_METHOD(, getTextFromClipboard, "()[B"); FIND_METHOD(, getTextFromClipboard, "()Ljava/lang/String;");
FIND_METHOD(, setTextInClipboard, "([B)Z"); FIND_METHOD(, setTextInClipboard, "(Ljava/lang/String;)Z");
FIND_METHOD(, isConnectionLimited, "()Z"); FIND_METHOD(, isConnectionLimited, "()Z");
FIND_METHOD(, showVirtualKeyboard, "(Z)V"); FIND_METHOD(, showVirtualKeyboard, "(Z)V");
FIND_METHOD(, showKeyboardControl, "(Z)V"); FIND_METHOD(, showKeyboardControl, "(Z)V");
FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;"); FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
FIND_METHOD(, getAllStorageLocations, "()[Ljava/lang/String;"); FIND_METHOD(, getAllStorageLocations, "()[Ljava/lang/String;");
FIND_METHOD(, convertEncoding, "(Ljava/lang/String;Ljava/lang/String;[B)[B");
FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;"); FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
FIND_METHOD(, deinitSurface, "()V"); FIND_METHOD(, deinitSurface, "()V");
@ -711,13 +728,31 @@ void JNI::setPause(JNIEnv *env, jobject self, jboolean value) {
} }
} }
jstring JNI::getCurrentCharset(JNIEnv *env, jobject self) { jstring JNI::convertToJString(JNIEnv *env, const Common::String &str, const Common::String &from) {
#ifdef USE_TRANSLATION Common::Encoding converter("UTF-8", from.c_str());
if (TransMan.getCurrentCharset() != "ASCII") { char *utf8Str = converter.convert(str.c_str(), converter.stringLength(str.c_str(), from));
return env->NewStringUTF(TransMan.getCurrentCharset().c_str()); if (utf8Str == nullptr)
} return nullptr;
#endif
return env->NewStringUTF("ISO-8859-1"); jstring jstr = env->NewStringUTF(utf8Str);
free(utf8Str);
return jstr;
}
Common::String JNI::convertFromJString(JNIEnv *env, const jstring &jstr, const Common::String &to) {
const char *utf8Str = env->GetStringUTFChars(jstr, 0);
if (!utf8Str)
return Common::String();
Common::Encoding converter(to.c_str(), "UTF-8");
char *asciiStr = converter.convert(utf8Str, env->GetStringUTFLength(jstr));
env->ReleaseStringUTFChars(jstr, utf8Str);
Common::String str(asciiStr);
free(asciiStr);
return str;
} }
Common::Array<Common::String> JNI::getAllStorageLocations() { Common::Array<Common::String> JNI::getAllStorageLocations() {

View file

@ -31,6 +31,7 @@
#include "common/fs.h" #include "common/fs.h"
#include "common/archive.h" #include "common/archive.h"
#include "common/array.h" #include "common/array.h"
#include "common/ustr.h"
#include "engines/engine.h" #include "engines/engine.h"
class OSystem_Android; class OSystem_Android;
@ -57,17 +58,18 @@ public:
static void setReadyForEvents(bool ready); static void setReadyForEvents(bool ready);
static void setWindowCaption(const char *caption); static void setWindowCaption(const Common::String &caption);
static void getDPI(float *values); static void getDPI(float *values);
static void displayMessageOnOSD(const char *msg); static void displayMessageOnOSD(const Common::U32String &msg);
static bool openUrl(const char *url); static bool openUrl(const Common::String &url);
static bool hasTextInClipboard(); static bool hasTextInClipboard();
static Common::String getTextFromClipboard(); static Common::U32String getTextFromClipboard();
static bool setTextInClipboard(const Common::String &text); static bool setTextInClipboard(const Common::U32String &text);
static bool isConnectionLimited(); static bool isConnectionLimited();
static void showVirtualKeyboard(bool enable); static void showVirtualKeyboard(bool enable);
static void showKeyboardControl(bool enable); static void showKeyboardControl(bool enable);
static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
static char *convertEncoding(const char *to, const char *from, const char *string, size_t length);
static inline bool haveSurface(); static inline bool haveSurface();
static inline bool swapBuffers(); static inline bool swapBuffers();
@ -108,6 +110,7 @@ private:
static jmethodID _MID_showVirtualKeyboard; static jmethodID _MID_showVirtualKeyboard;
static jmethodID _MID_showKeyboardControl; static jmethodID _MID_showKeyboardControl;
static jmethodID _MID_getSysArchives; static jmethodID _MID_getSysArchives;
static jmethodID _MID_convertEncoding;
static jmethodID _MID_getAllStorageLocations; static jmethodID _MID_getAllStorageLocations;
static jmethodID _MID_initSurface; static jmethodID _MID_initSurface;
static jmethodID _MID_deinitSurface; static jmethodID _MID_deinitSurface;
@ -139,7 +142,8 @@ private:
int arg2, int arg3, int arg4, int arg5, int arg6); int arg2, int arg3, int arg4, int arg5, int arg6);
static void setPause(JNIEnv *env, jobject self, jboolean value); static void setPause(JNIEnv *env, jobject self, jboolean value);
static jstring getCurrentCharset(JNIEnv *env, jobject self); static jstring convertToJString(JNIEnv *env, const Common::String &str, const Common::String &from);
static Common::String convertFromJString(JNIEnv *env, const jstring &jstr, const Common::String &to);
static PauseToken _pauseToken; static PauseToken _pauseToken;
}; };