haroldadmin / Vector

Kotlin Coroutines based MVI architecture library for Android
https://haroldadmin.github.io/Vector/
Apache License 2.0
193 stars 9 forks source link

Add proguard rule to keep names of ViewModel's companion factory classes #23

Open haroldadmin opened 4 years ago

haroldadmin commented 4 years ago

Describe the bug On an app with code obfuscation turned on, there are crashes with the message "Incomplete class hierarchy" for VectorViewModel classes.

Here's the stacktrace from an obfuscated release build of MoonShot. This error is not present on unobfuscated builds.

? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.haroldadmin.moonshot, PID: 6083
    java.lang.IllegalStateException: Incomplete hierarchy for class Companion, unresolved classes [com.haroldadmin.vector.VectorViewModelFactory]
        at kotlin.reflect.jvm.internal.components.RuntimeErrorReporter.reportIncompleteHierarchy(Unknown Source:32)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassTypeConstructor.computeSupertypes(Unknown Source:211)
        at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor$supertypes$1.invoke(Unknown Source:4)
        at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor$supertypes$1.invoke(Unknown Source:0)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(Unknown Source:86)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(Unknown Source:0)
        at kotlin.reflect.jvm.internal.impl.types.AbstractTypeConstructor.getSupertypes(Unknown Source:2)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.getNonDeclaredVariableNames(Unknown Source:8)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$variableNamesLazy$2.invoke(Unknown Source:12)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$variableNamesLazy$2.invoke(Unknown Source:0)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(Unknown Source:86)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(Unknown Source:0)
        at kotlin.reflect.jvm.internal.impl.storage.StorageKt.getValue(Unknown Source:5)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.getVariableNamesLazy(Unknown Source:7)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.getVariableNames(Unknown Source:0)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.addFunctionsAndProperties(Unknown Source:14)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.computeDescriptors(Unknown Source:28)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$allDescriptors$1.invoke(Unknown Source:12)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$allDescriptors$1.invoke(Unknown Source:0)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(Unknown Source:86)
        at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(Unknown Source:0)
        at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.getContributedDescriptors(Unknown Source:7)
        at kotlin.reflect.jvm.internal.impl.resolve.scopes.ResolutionScope$DefaultImpls.getContributedDescriptors$default(Unknown Source:18)
        at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.getMembers(Unknown Source:11)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(Unknown Source:10)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(Unknown Source:0)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(Unknown Source:17)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(Unknown Source:0)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.getDeclaredNonStaticMembers(Unknown Source:8)
        at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredMembers$2.invoke(Unknown Source:2)
? E/AndroidRuntime:     at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredMembers$2.invoke(Unknown Source:0)
        at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(Unknown Source:17)
        at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(Unknown Source:0)
        at kotlin.reflect.jvm.internal.KClassImpl$Data.getDeclaredMembers(Unknown Source:8)
        at m.e.d.d.a(:4)
        at m.e.d.q.a(:1)
        at com.haroldadmin.moonshot.nextLaunch.NextLaunchFragment$b.invoke(:1)
        at m.e.d.v.getValue(Unknown Source:19)
        at com.haroldadmin.moonshot.nextLaunch.NextLaunchFragment.a(:20)
        at androidx.fragment.app.Fragment.b(Unknown Source:15)
        at k.n.d.k.a(:73)
        at k.n.d.k.a(Unknown Source:32)
        at k.n.d.k.a(:28)
        at k.n.d.k.c(Unknown Source:94)
        at k.n.d.k.d(Unknown Source:21)
        at k.n.d.k.a(Unknown Source:9)
        at androidx.fragment.app.Fragment.e(:2)
        at k.n.d.k.a(:74)
        at k.n.d.k.l(:1)
        at k.n.d.k.a(Unknown Source:43)
        at k.n.d.k.a(Unknown Source:4)
        at k.n.d.c.onStart(:2)
        at k.b.k.h.onStart(Unknown Source:0)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1432)
        at android.app.Activity.performStart(Activity.java:7825)
        at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3294)
        at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
        at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
        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)

This could possibly be because of obfuscation of Companion Objects of these classes. Investigate more and add the proguard rule if necessary.

haroldadmin commented 4 years ago

This issue is not resolved with just -keepnames class implements com.haroldadmin.vector.VectorViewModelFactory.

Currently using the following additional proguard rules in MoonShot:

-keepnames class com.haroldadmin.vector.** { *; }
-keep class kotlin.Metadata { *; }
-keep class kotlin.reflect.jvm.internal.** { *; }
-keep class androidx.lifecycle.SavedStateHandle { *; }