当我使用 proguard 并启用 minify 和 shrinkresources 时,Retrofit 的 Retrofit body 请求为空

Retrofit body request is blank with Retrofit, when I use proguard and enable minify and shrinkresources

当我将 minifyEnabled & shrinkResources 设置为 true 时,发送的 Retrofit 正文 JSON 请求是空白的,当它设置为 false 时,它​​工作得很好。

我已经发布了整个 gradle 文件,您可以帮我指出我做错了什么。

minifyEnabled & shrinkResourcestrue 时,我的改造请求 json 正文如下所示:

{}

minifyEnabled & shrinkResourcesfalse时工作正常:

{"Data":"demoToken","Key":"demokey","Token":"2a9a8677-ac79-49d6-9947-d797b3e4d8e5"}

我的 gradle 看起来像这样:

   apply {
    plugin 'com.android.application'
    plugin 'kotlin-android'
    plugin 'kotlin-android-extensions'
    plugin 'kotlin-kapt'
    plugin 'io.fabric'
    plugin 'com.google.firebase.firebase-perf'
}
android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.something.theapp"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 43 
        versionName "0.6.7"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        flavorDimensions "server"
        multiDexEnabled true
        vectorDrawables.useSupportLibrary = true
        javaCompileOptions {
            annotationProcessorOptions {
                includeCompileClasspath = true
            }
        }
    }
    signingConfigs {
        kaira {
            storeFile file('key_tts.jks')
            storePassword 'android'
            keyAlias 'tts_key'
            keyPassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.kaira
            minifyEnabled true
            shrinkResources true
            buildConfigField "boolean", "ALLOW_DATABASE", "false"
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        release {
            signingConfig signingConfigs.kaira
            minifyEnabled true
            shrinkResources true
            buildConfigField "boolean", "ALLOW_DATABASE", "false"
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    productFlavors {
        local {
            //buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.136:6264/siteapp/api/\""
//            buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.21:5678/api/\""
            //   buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.233:5677/api/\""
            //  buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.26:5678/api/\""
            //buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.25:5678/api/\""
//            buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.37:5678/api/\""
//            buildConfigField "String", "WebServiceUrl", "\"https://api.forsell.in/api/\""
            //  buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.23:5678/api/\""
            buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.29:5678/api/\""
            buildConfigField "String", "WebUrl", "\"https://someurl.in/\""
            buildConfigField "String", "ServerName", "\"-Local\""
            dimension "server"
            copy {
                from "src/local"
                include "google-services.json"
                into "."
            }
        }
        temp {
            buildConfigField "String", "WebServiceUrl", "\"http://api.lezza.in/api/\""
            buildConfigField "String", "WebUrl", "\"https://someurl.in/\""
            buildConfigField "String", "ServerName", "\"-Local\""
            dimension "server"
            copy {
                from "src/local"
                include "google-services.json"
                into "."
            }
        }
        live {
            buildConfigField "String", "WebServiceUrl", "\"https://api.someurl.in/api/\""
            buildConfigField "String", "WebUrl", "\"https://someurl.in/\""
            buildConfigField "String", "ExtClientNameNew", "\"ExtClientName:TTS\""
            dimension "server"
            copy {
                from "src/livegcm"
                include "google-services.json"
                into "."
            }
        }
        staging {
            //buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.233:85/api/\""//sunil
            //     buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.233:5677/api/\""//devang
            //   buildConfigField "String", "WebServiceUrl", "\"http://192.168.1.233:85/api/\""
            buildConfigField "String", "WebServiceUrl", "\"https://stageapi.someurl.in/api/\""
            buildConfigField "String", "WebUrl", "\"https://stageweb.someurl.in/\""
            buildConfigField "String", "ServerName", "\"-Staging\""
            dimension "server"
            copy {
                from "src/local"
                include "google-services.json"
                into "."
            }
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }
    dexOptions {
        preDexLibraries = false
        javaMaxHeapSize "4g" // 2g should be also OK
    }
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
    lintOptions {
        abortOnError false
        disable 'MissingTranslation'
    }
}
repositories {
    mavenCentral()
    maven { url 'https://maven.fabric.io/public' }
}

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '28.0.0'
            }
        }
    }
}
dependencies {
    def lifecycle_version = "2.0.0"
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'androidx.core:core-ktx:1.0.2'
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.vectordrawable:vectordrawable:1.0.0-alpha1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2') {
        exclude group: 'com.google.code.findbugs'
    }
    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
    implementation 'com.squareup.okhttp3:okhttp:3.12.1'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
    implementation 'com.google.android.material:material:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'com.github.bumptech.glide:glide:4.5.0'
    implementation 'com.karumi:dexter:5.0.0'
    implementation 'com.google.android.gms:play-services-maps:16.1.0'
    implementation 'com.google.android.gms:play-services-location:16.0.0'
    implementation 'com.google.android.gms:play-services-auth:16.0.1'
    implementation 'org.jetbrains.anko:anko-common:0.9'
    implementation 'com.google.android.gms:play-services-ads:17.2.0'
    implementation 'androidx.multidex:multidex:2.0.1'
    implementation project(path: ':imagepicker')
    implementation 'androidx.percentlayout:percentlayout:1.0.0'
    implementation 'com.google.firebase:firebase-core:16.0.9'
    implementation 'com.google.firebase:firebase-inappmessaging-display:17.2.0'
    implementation 'com.google.firebase:firebase-messaging:18.0.0'
    implementation 'com.google.firebase:firebase-config:17.0.0'
    implementation 'com.google.firebase:firebase-perf:17.0.2'
    implementation 'com.github.chrisbanes:PhotoView:2.3.0'
    implementation 'com.google.android.gms:play-services-places:16.1.0'
    implementation 'com.google.android.libraries.places:places:1.1.0'
    api 'com.theartofdev.edmodo:android-image-cropper:2.8.+'
    implementation 'com.github.faruktoptas:RetrofitRssConverterFactory:0.1.0'
    implementation 'com.wang.avi:library:2.1.3'
    implementation 'com.facebook.android:facebook-android-sdk:5.4.0'
    implementation('com.crashlytics.sdk.android:crashlytics:2.9.8@aar') {
        transitive = true
    }
    implementation 'com.haozhang.libary:android-slanted-textview:1.2'
    implementation 'com.facebook.shimmer:shimmer:0.4.0'
    implementation 'com.github.freshdesk:freshchat-android:1.5.3'
    implementation 'commons-io:commons-io:2.4'
    implementation 'com.getkeepsafe.taptargetview:taptargetview:1.12.0'
    implementation 'com.razorpay:checkout:1.5.6'
    implementation 'com.google.android.gms:play-services-analytics:17.0.0'

}
apply plugin: 'com.google.gms.google-services'

下面是我的主模型class

class ServiceRequest {

    var Key: String? = "SiteAdminAppkey"
    var Token: String? = ""
    //    var Slug: String? = "admin"
    var Data: Any? = null
}

我可以通过添加 @SerializeName 注释来实现这一点,但我必须在每个模型中都这样做 class。在我的另一个项目中,Proguard 和一切都无需序列化即可工作。

由于您正在使用 GsonJson 转换为您的模型,因此您需要确保反射是在这些 classes 上正常工作(因为我假设您还没有为这些创建自定义适配器)。

保留 class 和字段名称的最简单方法,您可以使用 @Keep 来自 AndroidX Annotations:

的注释模型

Denotes that the annotated element should not be removed when the code is minified at build time. This is typically used on methods and classes that are accessed only via reflection so a compiler may think that the code is unused.

Add below line in your proguard-rules.pro File

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

Also add below line in gradle.properties file.

android.enableR8=false

我遇到了同样的问题,并在文件中添加了上面一行,它对我有用。

在 proguard-rules 中添加以下行

-keepclassmembers class <yourpackagename>.** { <fields>; }

yourpackagename 替换为所有模型所在的目录路径 类 ,就像我的例子

-keepclassmembers class com.demo.app.model.** { <fields>; }
  • 使用最新版本的改装库: com.squareup.retrofit2:改造:2.7.1 如果您使用的是 R8,则会自动包含收缩和混淆规则。 Latest Retrofit lib

  • 另外,Gson 实现的变化 'com.google.code.gson:gson:2.8.6' Latest GSON lib

  • 查看 R8 兼容性常见问题 r8-compatibility-faq for GSON

  • 如果您使用的是 OkHttp3,请更改为最新版本 okhttp3LibVersion = '4.3.1

这对我有用。

# Retrofit2
-keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}
-keepclassmembernames interface * {
    @retrofit2.http.* <methods>;
}

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

出于某种原因,如果没有 GSON 注释设置,它就无法工作,即使直接在模型上添加 @Keep 注释 class 也是如此。

这是一个更新的答案(05/20),因为在我的情况下似乎没有任何效果。

  1. 使用 Retrofit 文档中的 Proguard 规则 here

  2. 保持你的模型class喜欢丑寒的回答

对于我的情况,这是解决方案:

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