AniTrend / android-emojify

An android project to convert short codes, emoticons, html entities, emoticons to emoji and vice-versa
https://anitrend.github.io/android-emojify
Apache License 2.0
25 stars 12 forks source link

Issue in release mode #214

Closed yoobi closed 6 months ago

yoobi commented 6 months ago

Description of Bug

Hello just found an issue when isMinifyEnabled = true. The issue seems to be at the EmojiManager creation, for some reason the json doesn't get decoded. I have created a repo to showcase https://github.com/yoobi/emojifyreleaseissue

Reproduction Steps

Start the app mode when isMinifyEnabled = true and the text just shows :sweat_smile: instead of the real emoji

yoobi commented 6 months ago

After more investigation, it seems to be related to moshi package, kotlinx package is working fine.

Also the stacktrace looks like:

kotlin.reflect.jvm.internal.KotlinReflectionInternalError: This callable does not support a default call: public constructor MoshiEmoji(@com.squareup.moshi.Json aliases: kotlin.collections.List<kotlin.String>? = ..., @com.squareup.moshi.Json description: kotlin.String? = ..., @com.squareup.moshi.Json emoji: kotlin.String, @com.squareup.moshi.Json emojiChar: kotlin.String, @com.squareup.moshi.Json supportsFitzpatrick: kotlin.Boolean = ..., @com.squareup.moshi.Json supportsGender: kotlin.Boolean = ..., @com.squareup.moshi.Json tags: kotlin.collections.List<kotlin.String>? = ...) defined in io.wax911.emojify.serializer.moshi.MoshiEmoji[DeserializedClassConstructorDescriptor@4bda7bf]
    at kotlin.reflect.jvm.internal.KCallableImpl.callDefaultMethod$kotlin_reflection(KCallableImpl.kt:192)
    at kotlin.reflect.jvm.internal.KCallableImpl.callBy(KCallableImpl.kt:111)
    at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapter.fromJson(KotlinJsonAdapter.kt:118)
    at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:41)
    at com.squareup.moshi.CollectionJsonAdapter.fromJson(CollectionJsonAdapter.java:81)
    at com.squareup.moshi.CollectionJsonAdapter$2.fromJson(CollectionJsonAdapter.java:55)
    at com.squareup.moshi.internal.NullSafeJsonAdapter.fromJson(NullSafeJsonAdapter.java:41)
    at com.squareup.moshi.JsonAdapter.fromJson(JsonAdapter.java:58)
    at io.wax911.emojify.serializer.moshi.MoshiDeserializer.decodeFromStream(MoshiDeserializer.kt:36)
    at io.wax911.emojify.EmojiManager$Companion.initEmojiData(EmojiManager.kt:160)
    at io.wax911.emojify.EmojiManager$Companion.initEmojiData$default(EmojiManager.kt:154)
    at io.wax911.emojify.EmojiManager$Companion.create(EmojiManager.kt:177)
    at app.biiscuit.emojifyreleasevariantissue.MainActivity.onCreate(MainActivity.kt:15)
    at android.app.Activity.performCreate(Activity.java:7802)
    at android.app.Activity.performCreate(Activity.java:7791)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
yoobi commented 6 months ago

Oh okay, it seems that MoshiEmoji and probably GsonEmoji are missing proguard rules to keep the class.

Maybe something like in the proguard-rules.pro would solve the issue

-keepclasseswithmembers class io.wax911.emojify.serializer.gson.GsonEmoji
-keepclasseswithmembers class io.wax911.emojify.serializer.moshi.MoshiEmoji
wax911 commented 6 months ago

Oh okay, it seems that MoshiEmoji and probably GsonEmoji are missing proguard rules to keep the class.

Maybe something like in the proguard-rules.pro would solve the issue

-keepclasseswithmembers class io.wax911.emojify.serializer.gson.GsonEmoji
-keepclasseswithmembers class io.wax911.emojify.serializer.moshi.MoshiEmoji

Definately, was about to ask what your pro-guard rules were. Ideally all the serializer modules need proguard rules and we should be able to ship artifacts with default rules by using consumer-rules.pro (for each module)

yoobi commented 6 months ago

The working proguard rules are

-keep class io.wax911.emojify.serializer.moshi.MoshiEmoji { *;}

-dontwarn com.google.gson.Gson
-dontwarn com.google.gson.annotations.SerializedName
-dontwarn com.google.gson.reflect.TypeToken
-keep class io.wax911.emojify.serializer.gson.GsonEmoji { *;}

I also ran into a bug with Gson which has issue deserializing lazy value

 Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object kotlin.Lazy.getValue()' on a null object reference
    at io.wax911.emojify.contract.model.AbstractEmoji.getUnicode(AbstractEmoji.kt:26)
    at io.wax911.emojify.parser.EmojiParserKt.parseToUnicode(EmojiParser.kt:139)
    at app.biiscuit.emojifyreleasevariantissue.MainActivity.onCreate(MainActivity.kt:16)
    at android.app.Activity.performCreate(Activity.java:6662)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)

I'm not sure how to solve this as AbstractEmoji is abstract and doesn't know about Gson details https://stackoverflow.com/questions/34437052/deserializing-classes-with-lazy-properties-using-gson-and-kotlin-1-0-beta-4

wax911 commented 6 months ago

What if you override the fields in the implementing class and annotate them to mark them as transient, that being said having those fields generated as part of a github action would be nice though 🤔 I'm stretched on time though so would get to this at some later point in time

yoobi commented 6 months ago

I'll be able to test this end of next week to tell you but this could work yes

yoobi commented 6 months ago

I finally had some time to check it out, adding a consumer-rules.pro on moshi module fixed the issue. Unfortunately even using @Transient lead to crash so I'm not sure what to do about this :/

wax911 commented 6 months ago

I see, that's indeed unfortunate. I intend to create a workflow action to fetch the latest emoji spec and generate the .json file, I could probably do the conversion in the script that will generate the file. 🤔

yoobi commented 6 months ago

Yep doing the conversion in the script would avoid unnecessary computing when serializing Do you need me to push the fix for Moshi ?

wax911 commented 6 months ago

Yes please, feel free to push any issue you find 😃