Couchbase mobile 2.0 Emoji Support


#1

I have a working android app with couchbase mobile version 1.5. Now I am trying to upgrade to version 2.0, but i get following error when I try to read strings which contain Emojis:

07-01 23:31:53.000 21164-21188/lengo.online.app.enLang A/art: art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xf0
    art/runtime/check_jni.cc:65]     string: '🌎' 
07-01 23:31:53.001 21164-21188/lengo.online.app.enLang A/art: art/runtime/check_jni.cc:65]     in call to NewStringUTF
    art/runtime/check_jni.cc:65]     from java.lang.String com.couchbase.litecore.fleece.FLValue.asString(long)
    art/runtime/check_jni.cc:65] "ForkJoinPool.commonPool-worker-0" daemon prio=5 tid=14 Runnable
    art/runtime/check_jni.cc:65]   | group="main" sCount=0 dsCount=0 obj=0x12c0e920 self=0xada8cc00
    art/runtime/check_jni.cc:65]   | sysTid=21188 nice=0 cgrp=apps sched=0/0 handle=0xad4a1800
    art/runtime/check_jni.cc:65]   | state=R schedstat=( 0 0 0 ) utm=14 stm=1 core=1 HZ=100
    art/runtime/check_jni.cc:65]   | stack=0xa44fe000-0xa4500000 stackSize=1036KB
    art/runtime/check_jni.cc:65]   | held mutexes= "mutator lock"(shared held)
    art/runtime/check_jni.cc:65]   native: #00 pc 00004640  /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23)
    art/runtime/check_jni.cc:65]   native: #01 pc 00002e8d  /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8)
    art/runtime/check_jni.cc:65]   native: #02 pc 0023f455  /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::mirror::ArtMethod*)+68)
    art/runtime/check_jni.cc:65]   native: #03 pc 00224617  /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+146)
    art/runtime/check_jni.cc:65]   native: #04 pc 000af913  /system/lib/libart.so (art::JniAbort(char const*, char const*)+582)
    art/runtime/check_jni.cc:65]   native: #05 pc 000b004d  /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+60)
    art/runtime/check_jni.cc:65]   native: #06 pc 000b24a7  /system/lib/libart.so (art::ScopedCheck::Check(bool, char const*, ...) (.constprop.128)+882)
    art/runtime/check_jni.cc:65]   native: #07 pc 000baf11  /system/lib/libart.so (art::CheckJNI::NewStringUTF(_JNIEnv*, char const*)+36)
    art/runtime/check_jni.cc:65]   native: #08 pc 000d4def  /data/app/lengo.online.app.enLang-1/lib/arm/libLiteCoreJNI.so (litecore::jni::toJString(_JNIEnv*, C4Slice)+62)
    art/runtime/check_jni.cc:65]   native: #09 pc 000d63d1  /data/app/lengo.online.app.enLang-1/lib/arm/libLiteCoreJNI.so (Java_com_couchbase_litecore_fleece_FLValue_asString+32)
    art/runtime/check_jni.cc:65]   native: #10 pc 000a2311  /system/lib/libart.so (art_quick_generic_jni_trampoline+32)
    art/runtime/check_jni.cc:65]   native: #11 pc 0014e8f4  /dev/ashmem/dalvik-alloc space (deleted) (???)
    art/runtime/check_jni.cc:65]   at com.couchbase.litecore.fleece.FLValue.asString(Native method)
    art/runtime/check_jni.cc:65]   at com.couchbase.litecore.fleece.FLValue.asString(FLValue.java:101)
    art/runtime/check_jni.cc:65]   at com.couchbase.litecore.fleece.FLValue.toObject(FLValue.java:192)
    art/runtime/check_jni.cc:65]   at com.couchbase.lite.MValueDelegate.toNative(MValueDelegate.java:49)
    art/runtime/check_jni.cc:65]   at com.couchbase.litecore.fleece.MValue.toNative(MValue.java:117)
    art/runtime/check_jni.cc:65]   at com.couchbase.litecore.fleece.MValue.asNative(MValue.java:96)
    art/runtime/check_jni.cc:65]   at com.couchbase.lite.Dictionary.getString(Dictionary.java:129)
    art/runtime/check_jni.cc:65]   - locked <0x3dbc9de3> (a java.lang.Object)
    art/runtime/check_jni.cc:65]   at lengo.online.app.CouchBase.MyCouchBaseManager.getSysVocStructure(MyCouchBaseManager.kt:229)
    art/runtime/check_jni.cc:65]   at lengo.online.app.CouchBase.MyCouchBaseManager.getVocStructure(MyCouchBaseManager.kt:275)
    art/runtime/check_jni.cc:65]   at lengo.online.app.AppData$loadVokPckList$data$1.doResume(AppData.kt:39)
    art/runtime/check_jni.cc:65]   at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54)
    art/runtime/check_jni.cc:65]   at kotlinx.coroutines.experimental.DispatchedTask$DefaultImpls.run(Dispatched.kt:161)
    art/runtime/check_jni.cc:65]   at kotlinx.coroutines.experimental.DispatchedContinuation.run(Dispatched.kt:25)
    art/runtime/check_jni.cc:65]   at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1392)
    art/runtime/check_jni.cc:65]   at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:257)
    art/runtime/check_jni.cc:65]   at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:852)
    art/runtime/check_jni.cc:65]   at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1681)
    art/runtime/check_jni.cc:65]   at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1636)
    art/runtime/check_jni.cc:65]   at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:108)
    art/runtime/check_jni.cc:65] 

this is my code I used(It is written in Kotlin):

    val doc = database!!.getDocument("SysVok::Structure")
    val pcks = doc.getArray("Pcks")
    val pck = pcks.getDictionary(0)
    val emoji = pck.getString("Emoji") // <-- Error

Is this some kind of Bug? If so, are there workarounds?


#2

Looks like an issue with how JNI deals with strings. See https://stackoverflow.com/questions/7921016/what-does-it-mean-to-say-java-modified-utf-8-encoding

I’m not sure if this can be worked around in a platform agnostic way. In Java it looks like you want to use UTF 16 “surrogate code pairs”. See https://stackoverflow.com/questions/32205446/getting-true-utf-8-characters-in-java-jni

Please file an issue on GitHub so we can track this. Thanks.


#3

Thanks for your supply.
I have created a new issue on github: https://github.com/couchbase/couchbase-lite-android/issues/1742

But I dont know how to solve this without changing couchbase source code.

calling

 val emoji = pck.getValue("Emoji")

still causes the same issue.