Retrofit2 not working when enabling Proguard - android

I have an application which uses retrofit to fetch logo form an API.
When i don't obfuscate and shrink my code, everything works fine. But when i enable it, the API call stops working. I don't get any crash or error messages, i just don't get any values from the API.
gradle
buildTypes {
debug{
// Enables code shrinking, obfuscation, and optimization for only
// your project's release build type.
minifyEnabled true
// Enables resource shrinking, which is performed by the
// Android Gradle plugin.
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
release {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
I used it in debug just for testing purposes. If i use it in release, it has same output.
I checked the retrofit page and they advised to use the following file
proguard-rules.pro
# Uncomment this to preserve the line number information for
# debugging stack traces.
-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
-renamesourcefileattribute SourceFile
-printusage usage.txt
-keep class com.th3pl4gu3.locky_offline.core.main.** {*;}
-keep class com.th3pl4gu3.locky_offline.repository.network.** {*;}
-keep class com.th3pl4gu3.locky_offline.repository.database.** {*;}
# 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
# 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>
The API call still doesn't work. I tried many posts on stackoverflow but nothing works for me. Can someone help me by proposing a solution or an alternative to this ?
Thank you

Have you tried to put #SerializedName to Object field?
public class YourJsonClass{
#SerializedName("username")
String username;
}

Use progaurd rules from the official retrofit site
https://github.com/square/retrofit/blob/master/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro
Sometimes issue seems to be from retrofit but it is not. It’s a GSON and ProGuard problem. To fix it you just have to add a -keep class configuration in your proguard rules of the package where your Pojo class is stored For example my API response and request classes are stored like this (package name may differ according to your app):
-keep class com.sample.myapp.model.request. { ; }
-keep class com.sample.myapp.model.model.response.* { ; }*

Related

Android crash with minifyEnabled and AWS call

Using variety of aws-android-sdk's (version 2.22.0) (including DynamoDB).
With minifyEnabled = true, Android app crashes in DynamoDB call. App does not crash if I disable that flag.
Here are the proguard-rules I'm using:
In build.gradle (app):
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
And in the proguard-rules.pro I have the following:
# Class names are needed in reflection
-keepnames class com.amazonaws.**
-keepnames class com.amazon.**
# Enums are not obfuscated correctly in combination with Gson
-keepclassmembers enum * { *; }
# Request handlers defined in request.handlers
-keep class com.amazonaws.services.**.*Handler
# The following are referenced but aren't required to run
-dontwarn com.fasterxml.jackson.**
# Android 6.0 release removes support for the Apache HTTP client
-dontwarn org.apache.http.**
# The SDK has several references of Apache HTTP client
-dontwarn com.amazonaws.http.**
-dontwarn com.amazonaws.metrics.**
Here's the pertinent call stack:
E/AndroidRuntime: FATAL EXCEPTION: Thread-13
Process: com.icefield.eventtruly, PID: 20298
java.lang.IllegalArgumentException: Illegal query expression: No hash key condition is found in the query
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper.processKeyConditions(:2711)
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper.createQueryRequestFromExpression(:2671)
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper.query(:2438)
at com.amazonaws.mobileconnectors.dynamodbv2.dynamodbmapper.DynamoDBMapper.query(:2399)
at c.f.a.g.d$b.run(:339)
at java.lang.Thread.run(Thread.java:919)
Setting minifyEnabled = false results in everything working hunky-dory.
Any ideas on what else I might add to proguard rules?
I recommend using the following ProGuard rules.
-keep class com.amazon.** { *; }
-keep class com.amazonaws.** { *; }
-keep class com.amplifyframework.** { *; }
I suspect that you'll find a
ClassNotFoundException or and/or NoClassDefFoundError elsewhere in your logs, which will be more helpful to fine-tune the rules.
The particular error you're seeing arises when there are no key Conditions included in the request being sent to DyanmoDB.

Android app crashes in Release but not in Debug NullPointerException

I recently changed 2 lines of code as a workaround due to changes to the data being returned from an API I'm using. Now the app is crashing when using the release apk and aab. However, when I'm using the app through the Android Emulator on API 27 and connecting an API 27 device to my computer running the debug apk, the app works flawlessly.
I'm really stumped on this problem, and do not understand the error messages at all.
FATAL EXCEPTION: main
Process: com.guy.aqi, PID: 8328
java.lang.NullPointerException: throw with null exception
at com.guy.aqi.n.a(Unknown Source:3)
at com.guy.aqi.m.b(CurrentAirQualityFragment.java:8)
at com.guy.aqi.m.b(CurrentAirQualityFragment.java:6)
at com.guy.aqi.d.a(Unknown Source:4)
at b.a.a.a.m.c(StringRequest.java:4)
at b.a.a.a.m.a(StringRequest.java:1)
at b.a.a.h$a.run(ExecutorDelivery.java:4)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
My API stopped sending the "main pollutant" String, so I changed this line:
textViewMainPollutantUS.setText("U.S. Main Pollutant: " decodePollutant(mainPollutantUS));
to
textViewMainPollutantUS.setText("");
and this line:
textViewMainPollutantCN.setText("China Main Pollutant: " decodePollutant(mainPollutantCN));
to
textViewMainPollutantCN.setText("");
I expected changing these lines would fix the issue. But now the issue seems to be fixed in debug version of the app, but not the release version.
proguard-rules.pro
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
# OkHttp platform used only on JVM and when Conscrypt dependency is available.
-dontwarn okhttp3.internal.platform.ConscryptPlatform
# Prevent Proguard from inlining methods that are intentionally extracted to ensure locals have a
# constrained liveness scope by the GC. This is needed to avoid keeping previous request references
# alive for an indeterminate amount of time. See also https://github.com/google/volley/issues/114
-keepclassmembers,allowshrinking,allowobfuscation class com.android.volley.NetworkDispatcher {
void processRequest();
}
-keepclassmembers,allowshrinking,allowobfuscation class com.android.volley.CacheDispatcher {
void processRequest();
}
##---------------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.** { *; }
# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in #JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
##---------------End: proguard configuration for Gson ----------
-keep class com.crashlytics.** { *; }
-keepattributes SourceFile,LineNumberTable
For me, adding lines (you may have other name for package where you put your POJO files):
-keep class [mypackagename].model.** { *; }
-keep class [mypackagename].datamodel.** { *; }
to proguard.rules worked perfectly, then options:
android
{
...
buildTypes {
release {
minifyEnabled true
shrinkResources true
}
}
}
are set in build.gradle (Module: app)
Edit:-
Replace this
minifyEnabled true
to
minifyEnabled false

Runtime issues while using Proguard to minify

My app is completely ready to deploy and its using many libraries. I want to minify the code using Proguard and also want to remove unused classes and resources but while using proguard I am getting Runtime error
java.lang.RuntimeException: Unable to create application com.rig.onblick.App: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.hashCode()' on a null object reference
I gone through many tutorial but its seems too complicated to write proguard configuration because I have to write many rules to make sure my app will run perfectly. I have never used proguard in this kind of big project. Can anyone tell me the minimal configuration which make sure at least my code will be minified and will not get any runtime error.
My present configuration is as below.
-dontwarn com.witt.mspapp.**
-keep class com.github.mikephil.** { *; }
-dontwarn com.github.mikephil.**
-keep class com.github.mikephil.** { *; }
-dontwarn org.apache.**
-keep class com.google.gms.** { *; }
-dontwarn com.google.gms.**
-keep class com.viewpagerindicator.** { *; }
-dontwarn com.viewpagerindicator.**
-keep class org.jivesoftware.smackx.** { *; }
-dontwarn org.jivesoftware.smackx.**
I am testing in debug env. and my gradle configuration is as below
debug {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
There is nothing "minimal configuration" for proguard configuration. You will get the proguard configuration for each library on his official repo page. So whatever dependencies you have used go through these and add proguard configuration for each of that dependency.

How to fix Proguard issue with Google Drive REST API

I'm using the Google Rest API v3 to connect my android app to Google Drive. When I run without Proguard (minifyEnabled=false), all is well. However, when I enable proguard the wrong REST API methods are called. When I call Drive.Files.get().execute on the drive root alias "root" I get the result for a Drive.Files.list().execute. When I disable "minifyEnabled" I see the correct result. Here is the section of the build.gradle that controls running Proguard:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
The default Proguard file is the unmodified one that gets distributes with Android Studio 2.2 (not the optimized version)
And this is the contents of my proguard-rules.pro file
-keepattributes EnclosingMethod
-keepattributes InnerClasses
-dontoptimize
-keep class com.google.**
-keep class com.fasterxml.**
-dontwarn com.google.**
When I check in the generated mapping.txt I still see renamed members in classes that imo shoudl have been "kept". For example:
com.google.api.client.auth.oauth.OAuthParameters -> com.google.api.client.auth.oauth.OAuthParameters:
java.security.SecureRandom RANDOM -> l
com.google.api.client.auth.oauth.OAuthSigner signer -> a
java.lang.String callback -> b
java.lang.String consumerKey -> c
java.lang.String nonce -> d
java.lang.String realm -> e
I would have thought "-keep class com.google.** " would have avoided this?
Any idea how to fix this?
THanks in advance,
This one worked for me:
-keepclassmembers class * {
#com.google.api.client.util.Key <fields>;
}
As seen in the official google sample:
https://github.com/google/google-api-java-client-samples/blob/master/tasks-android-sample/proguard-google-api-client.txt
You need
-keep class com.google.** { *;}
and
-keep class com.fasterxml.** { *;}
Also you might try to keep less from the SDK. These rules are very wide.
Edit:
Wide rules means that it probably will keep more unused classes in your project hence the apk size and method count will be bigger.
In my case I had to put these keeps:
-keep class br.project.pine.** { *;}
-keep class com.google.api.services.drive.** { *;}
Tip: When enabling minify in debug mode, pay attention to the LogCat. It can help you to find out the real missing package/class/attribute.

Obfuscating the .aar files

I have created the .aar file (containing the resources & drawables) of an Android library project using
./gradlew assemble
I have enabled obfuscating by setting minify == true
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
However when I run the mentioned gradle command with minify enabled = true, I get java.io.IOException: The output jar is empty. Did you specify the proper '-keep' options?
What does this error pointing to and how can I obfuscate the library .aar file?
Best Regards
Using Proguard worked like a charm for me!
Proguard is used to shrink, obfuscate, optimize code. Proguard is
necessary for your library to remove unused code and make reverse
engineering little difficult. Proguard rules for the library are
different from the normal applications. As you know, Proguard renames
classes, variables, and methods using meaningless names. You would
like to keep the names of those methods and classes as it is that
developers will call. You will need to test and verify obfuscated code
from generated AAR file.
Library Module
build.gradle of your library
buildTypes {
release {
// Enables code shrinking, obfuscation, and optimization for only
// your project's release build type.
minifyEnabled true
// Includes the default ProGuard rules files that are packaged with
// the Android Gradle plugin. To learn more, go to the section about
// R8 configuration files.
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
Inside of your proguard-rules.pro of your library
# Save the obfuscation mapping to a file, so we can de-obfuscate any stack
# traces later on. Keep a fixed source file attribute and all line number
# tables to get line numbers in the stack traces.
# You can comment this out if you're not interested in stack traces.
-printmapping out.map
-keepparameternames
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,EnclosingMethod
# Preserve all annotations.
-keepattributes *Annotation*
# Preserve all public classes, and their public and protected fields and
# methods.
-keep public class * {
public protected *;
}
# Preserve all .class method names.
-keepclassmembernames class * {
java.lang.Class class$(java.lang.String);
java.lang.Class class$(java.lang.String, boolean);
}
# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
native <methods>;
}
# Preserve the special static methods that are required in all enumeration
# classes.
-keepclassmembers class * extends java.lang.Enum {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
# You can comment this out if your library doesn't use serialization.
# If your code contains serializable classes that have to be backward
# compatible, please refer to the manual.
-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();
}
# The library may contain more items that need to be preserved;
# typically classes that are dynamically created using Class.forName:
# -keep public class mypackage.MyClass
# -keep public interface mypackage.MyInterface
# -keep public class * implements mypackage.MyInterface
Thanks to .... reference
https://dev.to/mohitrajput987/develop--publish-your-own-sdk-in-android---part-2getting-started-with-sdk-development-3159
Proguard cuts unused classes. Libraries are standalone products, and has some specific entry points, which should not be obfsuscated. So you need to add rules to keep this entry points. Rules lookes like this:
-keep class packagename {public *;}
Copy library.pro file to your library project from this location:
...\android-sdk\tools\proguard\examples
Comment these lines when building from Android Studio, it should be probably kept/updated when building from the command line:
-injars in.jar
-outjars out.jar
-libraryjars /lib/rt.jar
Update your library project build.gradle file to use library.pro:
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'library.pro'
}
Sync and build the project and it should generate an obfuscated AAR file now.
Two suggestions:
Please ensure this file exist in the library module:
proguard-rules.pro.
Please try running "./gradlew :mylib:assembleRelease" with the
"mylib" be replaced with your library module name.

Categories

Resources