Fix crash on Android 5 and 6 when PP type field (subtitle) has unicode > 0xFFFF

Signed-off-by: Alexander Borsuk <me@alex.bio>
This commit is contained in:
Alexander Borsuk
2025-05-23 23:41:26 +02:00
committed by Konstantin Pastbin
parent 9c392d3160
commit 377861f7d0
3 changed files with 38 additions and 2 deletions

View File

@@ -74,7 +74,7 @@ jobject CreateMapObject(JNIEnv * env, place_page::Info const & info, int mapObje
(jint)fID.m_index));
jni::TScopedLocalRef jTitle(env, jni::ToJavaString(env, info.GetTitle()));
jni::TScopedLocalRef jSecondaryTitle(env, jni::ToJavaString(env, info.GetSecondaryTitle()));
jni::TScopedLocalRef jSubtitle(env, jni::ToJavaString(env, info.GetSubtitle()));
jni::TScopedLocalRef jSubtitle(env, jni::ToJavaStringWithSupplementalCharsFix(env, info.GetSubtitle()));
jni::TScopedLocalRef jAddress(env, jni::ToJavaString(env, info.GetSecondarySubtitle()));
jni::TScopedLocalRef jApiId(env, jni::ToJavaString(env, parseApi ? info.GetApiUrl() : ""));
jni::TScopedLocalRef jWikiDescription(env, jni::ToJavaString(env, info.GetWikiDescription()));
@@ -118,7 +118,7 @@ jobject CreateBookmark(JNIEnv *env, const place_page::Info &info,
(jlong)info.GetID().GetMwmVersion(), (jint)info.GetID().m_index));
jni::TScopedLocalRef jTitle(env, jni::ToJavaString(env, info.GetTitle()));
jni::TScopedLocalRef jSecondaryTitle(env, jni::ToJavaString(env, info.GetSecondaryTitle()));
jni::TScopedLocalRef jSubtitle(env, jni::ToJavaString(env, info.GetSubtitle()));
jni::TScopedLocalRef jSubtitle(env, jni::ToJavaStringWithSupplementalCharsFix(env, info.GetSubtitle()));
jni::TScopedLocalRef jAddress(env, jni::ToJavaString(env, info.GetSecondarySubtitle()));
jni::TScopedLocalRef jWikiDescription(env, jni::ToJavaString(env, info.GetWikiDescription()));
jobject mapObject = env->NewObject(

View File

@@ -28,6 +28,21 @@ jclass g_elevationInfoClazz;
extern "C"
{
int __system_property_get(char const * name, char * value);
static bool IsAndroidLowerThan7()
{
char value[92] = { 0 };
if (__system_property_get("ro.build.version.sdk", value) < 1)
return false;
const int apiLevel = atoi(value);
if (apiLevel > 0 && apiLevel < 24)
return true;
return false;
}
static bool const g_isAndroidLowerThan7 = IsAndroidLowerThan7();
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM * jvm, void *)
{
@@ -154,6 +169,24 @@ jstring ToJavaString(JNIEnv * env, char const * s)
return env->NewStringUTF(s);
}
jstring ToJavaStringWithSupplementalCharsFix(JNIEnv * env, std::string const & s)
{
// Android 5 and 6 do not support unicode characters greater than 0xFFFF encoded in UTF-8.
if (g_isAndroidLowerThan7)
{
// Detect 4-byte sequence start marker to avoid unnecessary allocation + copy.
for (const auto c : s)
{
if (0b11110000 == (c & 0b11111000))
{
const auto utf16 = strings::ToUtf16(s);
return env->NewString(reinterpret_cast<jchar const *>(utf16.data()), utf16.size());
}
}
}
return env->NewStringUTF(s.c_str());
}
jclass GetStringClass(JNIEnv * env)
{
return env->FindClass(GetStringClassName());

View File

@@ -55,6 +55,9 @@ inline jstring ToJavaString(JNIEnv * env, std::string_view sv)
return ToJavaString(env, std::string(sv).c_str());
}
// Remove after dropping Android 5 and 6 support.
jstring ToJavaStringWithSupplementalCharsFix(JNIEnv * env, std::string const & s);
jclass GetStringClass(JNIEnv * env);
char const * GetStringClassName();