启用ProGuard时,改造2不发送数据

时间:2016-02-19 13:07:41

标签: android retrofit retrofit2 proguard

我尝试使用Retrofit 2登录我的用户。(基本上是使用基本标题对登录URL进行GET)它运行良好但是一旦我ProGuard它,标题授权就不再发送了。 (见日志输出)

示例代码:

用户模型:

public interface UserService {

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

登录活动:

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文件:

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

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

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

可在此处找到完整代码:https://github.com/supercairos/virtual-passport

8 个答案:

答案 0 :(得分:38)

我终于成功了。这是关于Retrofit 2

的proguard配置
# 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>;
}

感谢@ xudshen

<强>更新

主要问题:我使用了proguard-android-optimize所以我应该添加:

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

我还切换回由square提供的常规Retrofit 2 proguard配置:

# 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

答案 1 :(得分:11)

添加@ Romain的回答 您需要添加到proguard文件

N

如果您正在使用@Header,@ Query ...

此处参考Retrofit2 proguard remove param

答案 2 :(得分:7)

另一个简单的解决方案 从支持注释中使用@keep 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>

}

答案 3 :(得分:2)

对我来说使用注释@SerializedName

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

   ...
 }

答案 4 :(得分:0)

使用Proguard代码Obfuscator添加Retrofit 2兼容性

package test;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Test extends JFrame {

private static final long serialVersionUID = -5624404136485946868L;

String userWord = "";
JTextField userInput;

public Test() {
    JFrame jf = new JFrame();
    JPanel panel = new JPanel();
    JLabel jl = new JLabel("Test");
    JButton jButton = new JButton("Click");
    userInput = new JTextField("", 30);
    jButton.addActionListener( (e) -> {
        submitAction();
    });
    jf.setSize(500, 500);
    jf.setVisible(true);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.add(panel);
    panel.add(jl);
    panel.add(userInput);
    panel.add(jButton);
}

private void submitAction() {
    userWord = userInput.getText();
    System.out.println(userWord);//do whatever you want with the variable, I just printed it to the console
}

public static void main(String[] args) {
    new Test();
}

答案 5 :(得分:0)

最后我找到了。 如果您使用Gson,请尝试此操作, 将此添加到改造后卫:

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

然后在模型中使用@SerializedName("name")kotlin示例:

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

答案 6 :(得分:0)

将此添加到 progaurd

-keep public class com.data.YOurDataModels.* {
  public void set*(***);
  public *** get*();
  public protected private *;
}

答案 7 :(得分:-1)

您需要添加

 @SerializedName("yourInputParameter")

在您的bean(模型)类中作为请求正文

例如

 public class YourClass{
       @SerializedName("yourInputParameter") String yourInputParameter;

       ...
     }

它将起作用

因为现在改进,因为proguard(minifyEnabled)为true,所以无法读取您的请求正文

在请求正文中添加 @SerializedName 后,它肯定会为您服务