Retrofit 2 not sending data when ProGuard is enabled

17,067

Solution 1

I finally managed to make it work. Here is the proguard configuration regarding Retrofit 2

# Retrofit
-dontwarn retrofit2.**
-dontwarn org.codehaus.mojo.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepattributes *Annotation*

-keepattributes RuntimeVisibleAnnotations
-keepattributes RuntimeInvisibleAnnotations
-keepattributes RuntimeVisibleParameterAnnotations
-keepattributes RuntimeInvisibleParameterAnnotations

-keepattributes EnclosingMethod

-keepclasseswithmembers class * {
    @retrofit2.* <methods>;
}

-keepclasseswithmembers interface * {
    @retrofit2.* <methods>;
}

Thanks @xudshen

UPDATE

The main problem: I used proguard-android-optimize So I should added:

-keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}

I also switched back to the regular Retrofit 2 proguard config provided by square :

# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on RoboVM on iOS. Will not be used at runtime.
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions

Solution 2

Adding to @Romain's answer You Need to add to proguard file

-keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}

If you are using @Header, @Query...

Reference from here Retrofit2 proguard remove param

Solution 3

finally i find. just try this if you use Gson , add this to retrofit pro-guard :

-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
} 

then use @SerializedName("name") in your model .kotlin example:

class PaymentRequestModel (
    @SerializedName("name")
    @Expose
    var name : String = "",
}

Solution 4

Another simple solution use @keep from support annotation https://developer.android.com/reference/android/support/annotation/Keep.html

@Keep
interface APIService 
{

    @GET("/user/auth")
    fun auth(@Header(Constants.AUTHORIZATION) authorization: String): Call<User>

}

Solution 5

for me works using annotation @SerializedName

public class YourJsonClass{
   @SerializedName("name") String username;

   ...
 }
Share:
17,067

Related videos on Youtube

Romain
Author by

Romain

A regular guy. Paris

Updated on June 04, 2022

Comments

  • Romain
    Romain almost 2 years

    I try to login my users using Retrofit 2. (Basically a GET to the login URL with a basic header) It works well but once I ProGuard it, the Header Authorization is not sent anymore. (See log outputs)

    Sample code :

    User Model :

    public interface UserService {
    
        @GET(GET_LOGIN)
        Observable<User> login(@Header("Authorization") String basic);
    }
    

    Login Activity :

    public void onClick(View v) {
        mRetrofit.create(UserService.class)
                 .login(Credentials.basic(email, password))
                 .subscribeOn(Schedulers.io())
                 .observeOn(AndroidSchedulers.mainThread())
                 .subscribe(user -> {
                    UserHelper.save(LoginActivity.this, user);
                 }, throwable -> Dog.d);
    }
    

    Proguard File :

    # Retrofit
    -dontwarn retrofit2.** 
    -dontwarn org.codehaus.mojo.**
    -keep class retrofit2.** { *; }
    -keepattributes Signature
    -keepattributes Exceptions
    -keepattributes *Annotation*
    -keepclasseswithmembers class * {
        @retrofit.* <methods>;
    }
    
    -keepclasseswithmembers interface * {
        @retrofit.* <methods>;
    }
    

    Logs (proguard) :

    D/OkHttp: --> GET http://passport-supercairos.rhcloud.com/users/login HTTP/1.1
    D/OkHttp: User-Agent: VirtualPassport-Client {Android-23} {Aquaris_E5}
    D/OkHttp: Cache-Control: max-stale=10800
    D/OkHttp: --> END GET
    D/OkHttp: <-- HTTP/1.1 401 Unauthorized (258ms)
    D/OkHttp: Date: Fri, 19 Feb 2016 12:57:19 GMT
    D/OkHttp: X-Powered-By: Express
    D/OkHttp: WWW-Authenticate: Basic realm="Users"
    D/OkHttp: Keep-Alive: timeout=15, max=100
    D/OkHttp: Connection: Keep-Alive
    D/OkHttp: Transfer-Encoding: chunked
    D/OkHttp: Content-Type: text/plain
    D/OkHttp: OkHttp-Sent-Millis: 1455886639681
    D/OkHttp: OkHttp-Received-Millis: 1455886639787
    D/OkHttp: Unauthorized
    D/OkHttp: <-- END HTTP (12-byte body)
    

    Logs (non-proguard) :

    D/OkHttp: --> GET http://passport-supercairos.rhcloud.com/users/login HTTP/1.1
    D/OkHttp: User-Agent: VirtualPassport-Client {Android-23} {Aquaris_E5}
    D/OkHttp: Cache-Control: max-stale=10800
    D/OkHttp: Authorization: Basic ZG9yb2ZyanVAZ21haWwuY29tOmN2dnZ2dnY=
    D/OkHttp: --> END GET
    D/OkHttp: <-- HTTP/1.1 401 Unauthorized (258ms)
    D/OkHttp: Date: Fri, 19 Feb 2016 12:57:19 GMT
    D/OkHttp: X-Powered-By: Express
    D/OkHttp: WWW-Authenticate: Basic realm="Users"
    D/OkHttp: Keep-Alive: timeout=15, max=100
    D/OkHttp: Connection: Keep-Alive
    D/OkHttp: Transfer-Encoding: chunked
    D/OkHttp: Content-Type: text/plain
    D/OkHttp: OkHttp-Sent-Millis: 1455886639681
    D/OkHttp: OkHttp-Received-Millis: 1455886639787
    D/OkHttp: Unauthorized
    D/OkHttp: <-- END HTTP (12-byte body)
    

    Full code can be found here : https://github.com/supercairos/virtual-passport

    • Romain
      Romain about 8 years
      I think the main problem is that proguard strip the @Header("Authorization") annotation. But i have no idea why. Especially since I explicitly told him to keep -keepattributes Annotation
  • Benni
    Benni over 7 years
    Didn't work for me...still got the same error after trying this and all the other rules i could possibly find. Linked the rules since it's too long for the comment. link
  • Shivang
    Shivang over 7 years
    Not working, I am still not able to send request parameters
  • Mansuu....
    Mansuu.... almost 7 years
    Yeah me too getting same problem
  • Kalaiselvan
    Kalaiselvan over 3 years
    I was facing issue in retrofit json parsing. This happened when I change minifyEnabled to true in release build. adding the above in line proguard fixed my issue. Also If you use data class for request body in retrofit post requests, then adding @SerializedName("") is also important.
  • Arbaz.in
    Arbaz.in over 3 years
    i used headers,query,post and body for request and that is not working when proguard is enable can you please tell me what i have to change?
  • mhKarami
    mhKarami over 3 years
    @Arbaz.in you should add pro-guards of all libraries you are using to your app pro-guard for example retrofit , Gson ,.. .
  • Abdul Salam
    Abdul Salam almost 2 years
    did not worked for me, i am using: Call<AssignmentResponse> fetchAssignment(@Query("user") String user);