Moshi with Proguard Didn't find class JsonAdapter - android

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()

Related

How to obfuscate Kotlin properties with R8?

I have a library on Kotlin I want to obfuscate almost completely but leave the public classes, properties and methods untouched. Here is an example of one of the public classes I intend to obfuscate:
class SomeClass(val propertyToShow: SomePublicClass, private val propertyToHide: SomeOtherPublicClass) {
fun methodToShow(someArg: SomeArg) {
// Some code
}
private fun methodToHide(someOtherArg: SomeOtherArg) {
// Some more code
}
}
The ProGuard file is based on a typical library ProGuard file and looks like this:
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile
-dontwarn javax.annotation.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.ConscryptPlatform
-keepattributes Signature
-keepattributes *Annotation*
-dontwarn sun.misc.**
-keep class com.google.gson.stream.** { *; }
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keepclassmembers,allowobfuscation class * {
#com.google.gson.annotations.SerializedName <fields>;
}
-keep public class * {
public protected *;
}
-keepclassmembernames class * {
java.lang.Class class$(java.lang.String);
java.lang.Class class$(java.lang.String, boolean);
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keeppackagenames **
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod,Synthetic,PermittedSubclasses
-keepparameternames
-renamesourcefileattribute SourceFile
-keepclassmembers class **$WhenMappings {
<fields>;
}
-keep class kotlin.Metadata { *; }
-keep class kotlin.** { *; }
-keep class kotlin.Metadata { *; }
-keep class kotlin.reflect.** { *; }
-dontwarn kotlin.reflect.**
-dontwarn kotlin.**
-keepclassmembers class **$WhenMappings {
<fields>;
}
-keepclassmembers class kotlin.Metadata {
public <methods>;
}
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
}
-keepclassmembers,allowobfuscation class * {
#javax.inject.* *;
#dagger.* *;
<init>();
}
-keep class javax.inject.** { *; }
-keep class **$$ModuleAdapter
-keep class **$$InjectAdapter
-keep class **$$StaticInjection
-keep class dagger.** { *; }
-keepclassmembers class * extends java.lang.Enum {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
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();
}
Running ./gradlew assembleRelease results in .aar file. The SomeClass.class from it looks like this (if we take a look at it via Android Studio)
public final class SomeClass public constructor(propertyToShow: SomePublicClass, propertyToHide: SomeOtherPublicClass) {
public final val propertyToShow: SomePublicClass /* compiled code */
private final val propertyToHide: SomeOtherPublicClass /* compiled code */
public final fun methodToShow(someArg: SomeArg): kotlin.Unit { /* compiled code */ }
private final fun a(someOtherArg: SomeOtherArg): kotlin.Unit { /* compiled code */ }
}
As we can see, the name of the private method has been obfuscated but its argument is not as well as the private property. It doesn’t matter if we obfuscate it with ProGuard or R8, the result is the same.
Is it possible to obfuscate private properties and private methods' arguments for Kotlin source code? Or is it pointless, since it will not interfere with others doing reverse engineering?
So the answer to this question was more or less explained in this article. Basically the issue was that the code was indeed obfuscated properly but there was still Kotlin Metadata and Android Studio was reconstructing the code based on this Metadata.

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.

kotlin object class not found when proguard is enabled

My application works well when proguard is disabled, but once enable it breaks the functionality.
I have a class called CachecManager which is not accessible once proguard is enabled.
Here is my class
object CacheManger {
fun setData(data: String) {
val yourFilePath: String = BaseClass.appContext.filesDir.toString() + "/" + USER_DATA
val yourFile = File(yourFilePath)
val fileOutputStream = FileOutputStream(yourFile)
fileOutputStream.write(data.toByteArray())
fileOutputStream.flush()
fileOutputStream.close()
}
}
This is my proguard file
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON #Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { <fields>; }
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in #JsonAdapter)
-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>;
}
##---------------End: proguard configuration for Gson ----------
#project related
-keep class com.appname.constants
-keep class com.appname.models.** { *; }
-keepnames class androidx.navigation.fragment.NavHostFragment
#-keep class <class>$Companion { *; }
-keep class kotlin.** { *; }
-keep class kotlin.Metadata { *; }
-dontwarn kotlin.**
-keepclassmembers class **$WhenMappings {
<fields>;
}
-keepclassmembers class kotlin.Metadata {
public <methods>;
}
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
}
This is error which i am getting
java.lang.ClassNotFoundException: Didn't find class "com.appname.cachemanager.CacheManger" on path: DexPathList[[zip file "/data/app/com.appname-2/base.apk"],nativeLibraryDirectories=[/data/app/com.appname-2/lib/arm64, /data/app/com.appname-2/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]

JsonProperty not working while minification enabled

I have the following class
class CodeRequest(#JsonProperty("phone") val phoneNumber: String)
When I send request (using retrofit) with an object of this class as body (while minification is not enabled) everything works and request will be send in this form {"phone": "123"}
But enabling minification with the following proguard-rules.pro will result in a {"phoneNumber": "123"} request body.
# Jackson
-keep class com.fasterxml.jackson.databind.ObjectMapper {
public <methods>;
protected <methods>;
}
-keep class com.fasterxml.jackson.databind.ObjectWriter {
public ** writeValueAsString(**);
}
-keep #com.fasterxml.jackson.annotation.* class * { *; }
-keep #com.fasterxml.jackson.annotation.** class * { *; }
-keep class com.fasterxml.** { *; }
-keepattributes *Annotation*,EnclosingMethod,Signature,Exceptions,InnerClasses
-keep class * {
#com.fasterxml.jackson.annotation.* *;
}
-keep class * { #com.fasterxml.jackson.annotation.JsonProperty *;}
# Application classes that will be serialized/deserialized over Jackson
-keepclassmembers class my.application.data.models.** { *; }
-keepclassmembers class my.application.domain.network.rest.** { *; }
What's missing here?
Thank you.
Found solution a couple of minutes after posting the question.
The problem is not with proguard nor jackson, it's that Kotlin erases required data which are stored in kotlin.Metadata.
Adding the following rule to proguard fixed the issue:
-keep class kotlin.Metadata { *; }

proguard configuration with groundy Tasks

I'm using the android "Groundy" library containing the GroundTask class, which makes use of annotations. Further I created a class
public class DownloadTask extends GroundyTask
and a callback object:
private final Object mCallback = new Object() {
#OnProgress(DownloadTask.class)
public void onNiceProgress(#Param(Groundy.PROGRESS) int progress) {
mProgressDialog.setProgress(progress);
}
....
But after obfusecation using proguard the method annotated with "OnProgress" never gets called (but no errors occure)
In the proguard file I added
-keep class com.telly.groundy.*** {
public protected private *;
}
-keepattributes *Annotation*, EnclosingMethod
-keepattributes *OnSuccess*
-keepattributes *OnProgress*
-keepattributes *OnCancel*
-keepattributes *OnCallback*
-keepattributes *OnFailure*
-keepattributes *OnStart*
-keepattributes *Param*
-keepattributes *Traverse*
-keep class com.my.namespace.DownloadTask {
public protected private *;
}
Any idea what "keep" configurations could be missing here ?
I just added a basic proguard configuration to the readme. It looks like this:
-keepattributes *Annotation*
-keepclassmembers,allowobfuscation class * {
#com.telly.groundy.annotations.* *;
<init>();
}
-keepnames class com.telly.groundy.generated.*
-keep class com.telly.groundy.generated.*
-keep class com.telly.groundy.ResultProxy
-keepnames class * extends com.telly.groundy.ResultProxy
-keep class * extends com.telly.groundy.GroundyTask
ProGuard doesn't know that the code accesses the annotation through reflection, so you probably need to preserve it explicitly:
-keep #interface com.telly.groundy.annotations.OnProgress

Categories

Resources