Unable to create converter for class when enabling minify in gradle - android

I am trying to enable minifyEnabled true in my gradle file for deployment but i am getting the below error:
java.lang.IllegalArgumentException: Unable to create converter for class com.th3pl4gu3.mes.models.MesResponse
for method MesApiService.getServices
My code is as follows
AppContainer.kt
/**
* Dependency Injection container at the application level.
*/
interface AppContainer {
val onlineServiceRepository: ServiceRepository
}
/**
* Implementation for the Dependency Injection container at the application level.
*
* Variables are initialized lazily and the same instance is shared across the whole app.
*/
class DefaultAppContainer(private val context: Context): AppContainer {
private val BASE_URL = "https://..."
/**
* Use the Retrofit builder to build a retrofit object using a kotlinx.serialization converter
*/
#OptIn(ExperimentalSerializationApi::class)
private val retrofit: Retrofit = Retrofit.Builder()
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.baseUrl(BASE_URL)
.build()
/**
* Retrofit service object for creating api calls
*/
private val retrofitService: MesApiService by lazy {
retrofit.create(MesApiService::class.java)
}
}
ServiceRepository.kt
/**
* Repository that fetch service list from Mes API.
*/
interface ServiceRepository {
/** Fetches list of services from Mes API */
suspend fun getMesServices(): MesResponse
}
MesApiServiceRepository.kt
class MesApiServiceRepository(
private val mesApiService: MesApiService
) : ServiceRepository {
/** Fetches list of Services from Mes API */
override suspend fun getMesServices(): MesResponse = mesApiService.getServices()
}
MesResponse.kt
#kotlinx.serialization.Serializable
data class MesResponse(
val services: List<Service>,
val message: String,
val success: Boolean
)
proguard-rules.pro
#####################################
########## Kotlin Metadata ##########
#####################################
-dontwarn org.jetbrains.annotations.**
-keep class kotlin.Metadata { *; }
##################################
########### MES Models ###########
##################################
-keep class com.th3pl4gu3.mes.models.MesResponse
-keep class com.th3pl4gu3.mes.models.** {*;}
-keep class com.th3pl4gu3.mes.data.** {*;}
-keep class com.th3pl4gu3.mes.api.** {*;}
-keep class com.th3pl4gu3.mes.di.** {*;}
###############################
########## Retrofit2 ##########
###############################
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
-keepattributes AnnotationDefault
# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
#retrofit2.http.* <methods>;
}
# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit
# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*
# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { #retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
# Keep inherited services.
-if interface * { #retrofit2.http.* <methods>; }
-keep,allowobfuscation interface * extends <1>
# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
Can someone please help me out ?

I was able to fix it by adding #Keep to the MesResponse class.
#Keep
#kotlinx.serialization.Serializable
data class MesResponse(
val services: List<Service>,
val message: String,
val success: Boolean
)

Related

Could not compute caller for function: public constructor Error when enable proguard in Android

The project working well without enabling proguard, the problem comes when enable it, I am using retrofit with Moshi converter and Coroutines to fetch list of data, and Hilt for DI, and I added all rules and kept all models
This is the error:
Could not compute caller for function: public constructor MovieListEntity(movie_data: kotlin.collections.List<com...domain.entities.MovieData>) defined in com...domain.entities.MovieListEntity[c#dad1eb0] (member = null)
And these are the classes mentioned
data class MovieListEntity(
#field:Json(name = "movie_data")
val movie_data: List<MovieData>
)
data class MovieData(
#field:Json(name = "movie_id")
val movie_id: Int,
#field:Json(name = "sub_title")
val sub_title: String,
#field:Json(name = "title")
val title: String
)
Note: I tried also without annotations, and it didn't help
These are the proguard rules:
-keep class com.***.***.domain.entitie.** { *; }
-keep class com.***.***.domain.entities.*
-keep class com.***.***.domain.entities.MovieListEntity
-keep class com.***.***.domain.entities.MovieData
-keep class com.***.***.DataBinderMapperImpl { *; }
-keep class com.***.***.DataBinderMapperImpl { *; }
-keep class com.***.*****{
public ** component1();
<fields>;
}
Plus other rules for retrofit, OkHttp, hilt .. etc.
How Can I solve this error?
Solved by adding these rules
-keepclassmembers class kotlin.Metadata {
public <methods>;
}
-keepclassmembers class * {
#com.squareup.moshi.FromJson <methods>;
#com.squareup.moshi.ToJson <methods>;
}
-keepnames #kotlin.Metadata class com.******.domain.entities.**
-keep class com.******.domain.entities.** { *; }
-keepclassmembers class com.*****.domain.entities.** { *; }
The problem was in Moshi library, check this

I'm using dagger2 ,while genrating signed apk ,retrofit api calls are not working, in debug mode its working fine

Retrofit and moshi-kotlin Api's are not working in android.
I'm using dagger2 ,while genrating signed apk ,retrofit api calls are not working, in debug mode its working fine .
while we enabled minifyenable true and shrinkresource true.
#JsonClass(generateAdapter = true) #SuppressLint("ParcelCreator") #Keep data class DashboardListRes( #Json(name = "data") vardata: List<Data>?=ArrayList(), #Json(name = "lead_data") var leadData: LeadData= LeadData(), #Json(name = "message") var message: String="", #Json(name = "status") var status: String="", #Json(name = "status_code") var statusCode: Int=0, #Json(name = "user") var user: User=User() ):Serializable
1.
2. -keepattributes Signature, InnerClasses, EnclosingMethod
-keepattributes RuntimeVisibleAnnotations,
RuntimeVisibleParameterAnnotations -keepattributes
AnnotationDefault
-keepclassmembers,allowshrinking,allowobfuscation interface * {
#retrofit2.http.* <methods>; } -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement -dontwarn
javax.annotation.** -dontwarn kotlin.Unit -dontwarn
retrofit2.KotlinExtensions -dontwarn retrofit2.KotlinExtensions$*
-if interface * { #retrofit2.http.* <methods>; } -keep,allowobfuscation interface <1> -keep,allowobfuscation,allowshrinking interface retrofit2.Call -keep,allowobfuscation,allowshrinking class retrofit2.Response -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation -dontwarn javax.annotation.**
-keepclasseswithmembers class * {
#com.squareup.moshi.* <methods>; }
-keep #com.squareup.moshi.JsonQualifier #interface *
-keepclassmembers #com.squareup.moshi.JsonClass class * extends java.lang.Enum {
<fields>;
**[] values(); } -keepclassmembers class com.squareup.moshi.internal.Util {
private static java.lang.String getKotlinMetadataClassName(); } -keepclassmembers class * {
#com.squareup.moshi.FromJson
<methods>; #com.squareup.moshi.ToJson <methods>; }
-keep class kotlin.Metadata
-keep class com.package.models.**{*;}
-keepclassmembers class com.package.dataclasses.** { *; }
-keepattributes Signature -keepattributes Annotation -dontwarn sun.misc.** -keep class com.google.gson.stream.** { *; } -keep class com.google.gson.examples.android.model.** {
<fields>; } -keep class com.credright.nikhil.models.** { *; }
-keep class com.package.ui.** { *; } -keep class * extends com.google.gson.TypeAdapter -keep class * implements
com.google.gson.TypeAdapterFactory -keep class * implements
com.google.gson.JsonSerializer -keep class * implements
com.google.gson.JsonDeserializer
Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
#com.google.gson.annotations.SerializedName <fields>; }
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken -dontwarn javax.annotation.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase -dontwarn
org.codehaus.mojo.animal_sniffer.* -dontwarn
okhttp3.internal.platform.ConscryptPlatform
-keep class org.apache.commons.logging.**
-keepattributes Annotation
-dontwarn org.apache.**
-keepnames #dagger.hilt.android.lifecycle.HiltViewModel class *
extends androidx.lifecycle.ViewModel
If you are converting the data received into a POJO object using some built in function and then populating a data class or something, you need to make sure you exclude the data classes from proguard.
What I generally do is I put all my data classes in one package and then exclude everything in that package like so:
-keepclassmembers class com.credright.nikhil.dataclasses.** { *; }
The line above should be added to the file proguard-rules.pro and dataclasses is the name of the package that has all the data classes in it.
The reason why this is important is that when proguard obfuscates your code, it basically changes all class names and everything into arbitrary things and so after obfuscation data classes cannot be populated.
There have historically been some difficulties when using moshi-kotli. Updating to a newer Kotlin version + updating some proguard rules fixes it.
You can check out this
GitHub comment.

Moshi with Proguard Didn't find class JsonAdapter

I can't seem to figure out this issue...
I've tried all sorts of methods to keep required classes and searched for long time to find the solution....
When I apply pro guard, app crashes with this error.
I'm using retrofit 2.9.0 and moshi 1.13.0 with moshi-kotlin 1.13.0
Caused by: java.lang.ClassNotFoundException: Didn't find class ApiResponseJsonAdapter
ApiResponse is model with Generic type
#Keep
#JsonClass(generateAdapter = true)
data class ApiResponse<T>(
#Json(name = "detail")
val message: String,
#Json(name = "result")
val result: T
)
Please I need help.
Thanks in advance.
Update
This is my pro guard
-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.example.base.ApiResponse { *; }
-keepclassmembers class com.example.base.ApiResponse.** {
<init>(...);
<fields>;
}
-keep class com.example.data.entity.server.** { *; }
-keepclassmembers class com.example.data.entity.server.** {
<init>(...);
<fields>;
}
-keep class com.squareup.moshi.kotlin.reflect.** { *; }
-keepclasseswithmembers class * {
#com.squareup.moshi.* <methods>;
}
-keep #com.squareup.moshi.JsonQualifier interface *
-keepclassmembers #com.squareup.moshi.JsonClass class * extends java.lang.Enum {
<fields>;
}
-keepnames #com.squareup.moshi.JsonClass class *
-keepclasseswithmembers class **.*JsonAdapter extends com.squareup.moshi.JsonAdapter {
<init>(...);
<fields>;
}
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
-keepclasseswithmembers class * {
#com.squareup.moshi.* <methods>;
}
-keep #com.squareup.moshi.JsonQualifier #interface *
# Enum field names are used by the integrated EnumJsonAdapter.
# values() is synthesized by the Kotlin compiler and is used by EnumJsonAdapter indirectly
# Annotate enums with #JsonClass(generateAdapter = false) to use them with Moshi.
-keepclassmembers #com.squareup.moshi.JsonClass class * extends java.lang.Enum {
<fields>;
**[] values();
}
# Keep helper method to avoid R8 optimisation that would keep all Kotlin Metadata when unwanted
-keepclassmembers class com.squareup.moshi.internal.Util {
private static java.lang.String getKotlinMetadataClassName();
}
-keepclassmembers class * {
#com.squareup.moshi.FromJson <methods>;
#com.squareup.moshi.ToJson <methods>;
}
# Understand the #Keep support annotation.
-keep class androidx.annotation.Keep
-keep #androidx.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
#androidx.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
#androidx.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
#androidx.annotation.Keep <init>(...);
}
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-dump class_files.txt
-printseeds seeds.txt
-printusage unused.txt
-printmapping mapping.txt
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-allowaccessmodification
-keepattributes *Annotation*
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
-repackageclasses ''
-keep public class * extends androidx.appcompat.app.AppCompatActivity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# Preserve static fields of inner classes of R classes that might be accessed
# through introspection.
-keepclassmembers class **.R$* {
public static <fields>;
}
# Preserve the special static methods that are required in all enumeration classes.
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#-keep public class * {
# public protected *;
#}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepattributes Signature
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
-keepattributes *Annotation*
-dontwarn com.airbnb.lottie.**
-keep class com.airbnb.lottie.** {*;}
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
-keepattributes AnnotationDefault
# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
#retrofit2.http.* <methods>;
}
# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit
# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { #retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response
# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
-dontwarn com.google.auto.service.AutoService
-dontwarn javax.lang.model.SourceVersion
-dontwarn javax.lang.model.element.AnnotationMirror
-dontwarn javax.lang.model.element.Element
-dontwarn javax.lang.model.element.ElementKind
-dontwarn javax.lang.model.element.ElementVisitor
-dontwarn javax.lang.model.element.ExecutableElement
-dontwarn javax.lang.model.element.Modifier
-dontwarn javax.lang.model.element.Name
-dontwarn javax.lang.model.element.TypeElement
-dontwarn javax.lang.model.element.TypeParameterElement
-dontwarn javax.lang.model.element.VariableElement
-dontwarn javax.lang.model.type.ArrayType
-dontwarn javax.lang.model.type.DeclaredType
-dontwarn javax.lang.model.type.ExecutableType
-dontwarn javax.lang.model.type.TypeKind
-dontwarn javax.lang.model.type.TypeMirror
-dontwarn javax.lang.model.type.TypeVariable
-dontwarn javax.lang.model.type.TypeVisitor
-dontwarn javax.lang.model.util.AbstractTypeVisitor8
-dontwarn javax.lang.model.util.ElementFilter
-dontwarn javax.lang.model.util.Elements
-dontwarn javax.lang.model.util.SimpleElementVisitor8
-dontwarn javax.lang.model.util.SimpleTypeVisitor8
-dontwarn javax.lang.model.util.Types
-dontwarn org.bouncycastle.jsse.BCSSLParameters
-dontwarn org.bouncycastle.jsse.BCSSLSocket
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
-dontwarn org.conscrypt.Conscrypt$Version
-dontwarn org.conscrypt.Conscrypt
-dontwarn org.conscrypt.ConscryptHostnameVerifier
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
-dontwarn org.openjsse.net.ssl.OpenJSSE
-dontwarn java.util.concurrent.Flow*
Error Stacktrace
java.lang.IllegalArgumentException: Unable to create converter for com.example.base.ApiResponse<com.example.data.entity.server.Info>
for method a5.b
at an2.n(SourceFile:54)
at ii0.e(SourceFile:126)
at ii0.f(SourceFile:85)
at cz1.b(SourceFile:39)
at tt1.c(SourceFile:202)
at tt1$a.invoke(SourceFile:160)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy3.b(Unknown Source)
at k4.b(SourceFile:46)
at z4.b(SourceFile:72)
at jf0.a(SourceFile:6)
at com.example.presentation.ViewModel.m(SourceFile:27)
at p4.C1(SourceFile:70)
at td.G0(SourceFile:33)
at androidx.fragment.app.Fragment.f1(SourceFile:3019)
at androidx.fragment.app.h.f(SourceFile:551)
at androidx.fragment.app.h.m(SourceFile:261)
at androidx.fragment.app.FragmentManager.Z(SourceFile:1840)
at androidx.fragment.app.FragmentManager.X0(SourceFile:1758)
at androidx.fragment.app.FragmentManager.W(SourceFile:1701)
at androidx.fragment.app.FragmentManager$d.run(SourceFile:488)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7664)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.RuntimeException: Failed to find the generated JsonAdapter class for com.example.base.ApiResponse<com.example.data.entity.server.Info>
at com.squareup.moshi.internal.a.d(SourceFile:590)
at com.squareup.moshi.StandardJsonAdapters$b.create(SourceFile:61)
at com.squareup.moshi.g.f(SourceFile:146)
at com.squareup.moshi.g.e(SourceFile:106)
at a81.d(SourceFile:89)
at tt1.f(SourceFile:362)
at tt1.h(SourceFile:345)
at ii0.e(SourceFile:124)
at ii0.f(SourceFile:85) 
at cz1.b(SourceFile:39) 
at tt1.c(SourceFile:202) 
at tt1$a.invoke(SourceFile:160) 
at java.lang.reflect.Proxy.invoke(Proxy.java:1006) 
at $Proxy3.b(Unknown Source) 
at k4.b(SourceFile:46) 
at z4.b(SourceFile:72) 
at jf0.a(SourceFile:6) 
at com.example.presentation.ViewModel.m(SourceFile:27) 
at p4.C1(SourceFile:70) 
at td.G0(SourceFile:33) 
at androidx.fragment.app.Fragment.f1(SourceFile:3019) 
at androidx.fragment.app.h.f(SourceFile:551) 
at androidx.fragment.app.h.m(SourceFile:261) 
at androidx.fragment.app.FragmentManager.Z(SourceFile:1840) 
at androidx.fragment.app.FragmentManager.X0(SourceFile:1758) 
at androidx.fragment.app.FragmentManager.W(SourceFile:1701) 
at androidx.fragment.app.FragmentManager$d.run(SourceFile:488) 
at android.os.Handler.handleCallback(Handler.java:938) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7664) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
Caused by: java.lang.ClassNotFoundException: com.example.base.ApiResponseJsonAdapter
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:454)
at com.squareup.moshi.internal.a.d(SourceFile:564)
at com.squareup.moshi.StandardJsonAdapters$b.create(SourceFile:61) 
at com.squareup.moshi.g.f(SourceFile:146) 
at com.squareup.moshi.g.e(SourceFile:106) 
at a81.d(SourceFile:89) 
at tt1.f(SourceFile:362) 
at tt1.h(SourceFile:345) 
at ii0.e(SourceFile:124) 
at ii0.f(SourceFile:85) 
at cz1.b(SourceFile:39) 
at tt1.c(SourceFile:202) 
at tt1$a.invoke(SourceFile:160) 
at java.lang.reflect.Proxy.invoke(Proxy.java:1006) 
at $Proxy3.b(Unknown Source) 
at k4.b(SourceFile:46) 
at z4.b(SourceFile:72) 
at jf0.a(SourceFile:6) 
at com.example.presentation.ViewModel.m(SourceFile:27) 
at p4.C1(SourceFile:70) 
at td.G0(SourceFile:33) 
at androidx.fragment.app.Fragment.f1(SourceFile:3019) 
at androidx.fragment.app.h.f(SourceFile:551) 
at androidx.fragment.app.h.m(SourceFile:261) 
at androidx.fragment.app.FragmentManager.Z(SourceFile:1840) 
at androidx.fragment.app.FragmentManager.X0(SourceFile:1758) 
at androidx.fragment.app.FragmentManager.W(SourceFile:1701) 
at androidx.fragment.app.FragmentManager$d.run(SourceFile:488) 
at android.os.Handler.handleCallback(Handler.java:938) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7664) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.base.ApiResponseJsonAdapter" on path:
I've resolved the issues.
I realized that Kotlin-codegen artifact from Moshi wasn't generating so I ran gradle build from terminal and found that for Moshi it was required to use Java 16 but I was using default Android Java.
After switching everything worked like charm with miscellaneous fixes like
including below statement to gradle properties.
android.jetifier.ignorelist=moshi-1.13.0
This is what Moshi Docs tells about Reflection:
The reflection adapter uses Kotlin’s reflection library to
convert your Kotlin classes to and from JSON. Enable it by adding the
KotlinJsonAdapterFactory to your Moshi.Builder:
val moshi = Moshi.Builder()
.addLast(KotlinJsonAdapterFactory())
.build()
With this in mind, you should have Core Moshi JSON Library and Moshi's Kotlin support and converter factory in your gradle.
implementation "com.squareup.moshi:moshi:1.12.0"
implementation "com.squareup.moshi:moshi-kotlin:1.12.0"
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
If you are using DI, you can do something like this when building the Retrofit object:
#Provides
#Singleton
fun provideNeowsAPI(): NeowsAPI {
//add the JsonAdapter factory to use when build the Moshi object
val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
return Retrofit.Builder()
.baseUrl(NeowsAPI.BASE_URL)
. addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(NeowsAPI::class.java)
}
If you are not using DI you can build the Moshi Object and then add it to Retrofit Builder.
//Build Moshi Object
private val moshi =
Moshi.Builder()
.addLast(KotlinJsonAdapterFactory())
.build()
//Build Retrofit Object
val retrofit =
Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create()) // for parsing JSON String
.addConverterFactory(MoshiConverterFactory.create(moshi)) //for parsing KotlinObjects i.e.
// picture of the day
.baseUrl(BASE_URL)
.build()

R8 stripping out Kotlin companion object needed for reflection

I have a class with a companion object which implements a factory interface.
class GoalInspectorData(
...
) {
companion object : DataClassFactory<GoalInspectorData> {
override fun fromV8Object(v8Object: V8Object): GoalInspectorData {
...
}
}
}
I have some code which examines this class at runtime using reflection to see if the class provides a factory method. It does this by checking to see if the class has a companion object (companionObjectInstance) and, if so, if that companion object implements the factory interface.
internal inline fun <reified T> convert(obj: Any): T {
val companionObject = T::class.companionObjectInstance
#Suppress("UNCHECKED_CAST")
return when {
T::class in builtInClasses -> obj as T
companionObject as? DataClassFactory<T> != null -> companionObject.fromV8Object(obj as V8Object)
else -> throw IllegalArgumentException("No converter for type ${T::class}")
}
}
This all works fine in a debug build.
It fails in a release build with R8 enabled (minifyEnabled true in build.gradle). It fails because companionObjectInstance returns null.
I'm using the don't optimize Proguard config:
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
and in my own proguard-rules.pro I've added just about every -keep rule I can imagine in an attempt to retain this companion object, and added #Keep annotations to everything, but nothing works. R8 is determined to strip it out.
For example:
-keep class my.package.** {
*;
}
-keep interface my.package.** {
*;
}
-if class **$Companion extends **
-keep class <2>
-if class **$Companion implements **
-keep class <2>
Are there any other -keep rules or configuration options which would instruct R8 to retain this companion object?
First of all, the keep rule
-keep class my.package.** {
*;
}
should be sufficient to keep all the classes - including companion classes in your program. You should not need the -dontoptimize flag, so using the configuration proguard-android-optimize.txt should be fine.
However, as you use Kotlin reflection you probably also need to keep the annotation class kotlin.Metadata and runtime visible annotations with these rules:
-keep #interface kotlin.Metadata {
*;
}
-keepattributes RuntimeVisibleAnnotations
If that does still not work could you please file an R8 issue? If you can include a simple reproduction that would be great.

Gson do not deserialize fields that never used

Current situation
I have a model, where class UserSettingModel have two field : long UserId and have as field one exemplar of class UserSettings ( with many field ) with name Settings.
WARNING : none of this fields used directly in my code ( in Android Studio color of this fields is gray), but I need to resend it to server.
public class UserSettingsModel
{
#SerializedName("UserId")
public long UserId = -1L;
#SerializedName("Settings")
public UserSettings Settings;
}//end of class/ UserSettingsModel
class UserSettings
{
#SerializedName("showRegion")
public String showRegion = "";
#SerializedName("showAddress")
public String showAddress = "";
}
Problem
If working with apk in DEBUG mode : GSON deserialize all field of class UserSettingModel, including Settings
If working with apk in RELEASE mode : field Settings - not deserialize
My proguard :
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.google.gson.** { *; }
-keepclassmembers enum * { *; }
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
What I need
How to serialize/deserialize with GSON in Release mode ALL FIELD of classes, also with warning "field is never used" ?
This is because of obfuscation, as DQuade states in the comment.
To prevent gradle from removing them, you can either add the specific class in your proguard-rules.pro file:
-keepclassmembers class [yourPackageName].UserSettingsModel
-keepclassmembers class [yourPackageName].UserSettings
or prevent gradle from removing all members annotated with the SerializedName annotation:
-keepclassmembers class * {
#com.google.gson.annotations.SerializedName <fields>;
}

Categories

Resources