Search code examples
androidretrofitretrofit2proguard

Retrofit 2 not sending data when ProGuard is enabled


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


Solution

  • 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