2

Whether I create the "release" APK by:

  • Using Generate Signed APK in Android Studio
  • Select the Release build variant and use Tools -> Build APK
  • Run the assembleRelease task

... the APK produced always has debuggable=true which I've confirmed by trying to upload them to Google Play, which says:

"Upload failed. You uploaded a debuggable APK. For security reasons you need to disable debugging before it can be published in Google Play."

The (only) manifest has no debuggable attribute specified. Gradle specifies debuggable=false for release, and true for debug, see below.

What am I missing? Where is the debuggable state coming from, and why is the debuggable=false in the release build type declaration being ignored? I do not want to add debuggable=false to the manifest and to have to keep manually enabling/disabling it.

app/build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion '26.0.0'
    defaultConfig {
        applicationId "com.myapp.android"
        minSdkVersion 14
        targetSdkVersion 26
        versionCode 5
        versionName 5
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    signingConfigs {
        release {
            storeFile rootProject.file("keystore.jks")
            if (storeFile.exists()) {
                def config = new Properties()
                config.load(new FileInputStream(rootProject.file("keystore.passwords")))
                storePassword config.KeystorePassword
                keyAlias config.KeyAlias
                keyPassword config.KeyPassword
            }
        }
    }

    buildTypes {
        release {
            debuggable false
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
        debug {
            debuggable true
            applicationIdSuffix ".debug"
        }
    }

    dataBinding {
        enabled = true
    }

    lintOptions {
        disable 'RtlHardcoded'
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    // Copy release APK to project root
    task copyReleaseApk(type: Copy) {
        from 'build/outputs/apk'
        into '..'
        include '**/*release.apk'
    }

    afterEvaluate {
        if (tasks.findByPath("packageRelease") == null) {tasks.create("packageRelease")}
        tasks.findByPath("packageRelease").finalizedBy(copyReleaseApk)
    }

}

ext {
    // Single place to specify the support library version
    supportLibraryVersion = '26.0.0-beta2'
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude group: 'com.google.code.findbugs'
        exclude module: 'espresso-idling-resource'
        exclude group: "javax.inject"
    })
    implementation 'com.android.support.test.espresso:espresso-contrib:2.2.2'

    // Dagger dependency injection
    implementation 'com.google.dagger:dagger:2.10'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.10'
    implementation 'com.google.dagger:dagger-android:2.10'
    implementation 'com.google.dagger:dagger-android-support:2.10'
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.10'

    implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
    implementation "com.android.support:design:$supportLibraryVersion"
    implementation "com.android.support.constraint:constraint-layout:1.0.2"

    implementation "com.jakewharton.timber:timber:4.5.1"
    implementation "com.squareup.phrase:phrase:1.1.0"
    implementation "com.squareup.retrofit2:retrofit:2.2.0"
    implementation "com.squareup.retrofit2:converter-gson:2.2.0"
    implementation "com.squareup.okhttp3:logging-interceptor:3.7.0"
    implementation 'net.danlew:android.joda:2.9.9'

    testImplementation 'junit:junit:4.12'
    implementation 'com.google.firebase:firebase-crash:11.0.0'
    androidTestImplementation 'junit:junit:4.12'
}

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

Update 1: I tried adding debuggable=false to the manifest and it makes no difference, the APK produced still cannot be uploaded to Google Play.

Update 2: I loaded the APKs back into Android Studio using the APK Analyzer that makes it easy to see the manifest, and they all include.... debuggable=true. Where is it coming from?

Update 3: assembleRelease produces a debuggable APK on both my local machine AND on the CI server (BuddyBuild).

Update 4: A clean rebuild (including deleting the build folders) and restarting Android Studio with its caches cleared makes no difference.

Update 5: It seems reasonable to assume that the debuggable=true state could be coming from one of the dependencies, but if that is the case which, and how can that be overridden?

Ollie C
  • 28,313
  • 34
  • 134
  • 217
  • Are you sure that you're uploading the right APK? – Eselfar Jun 21 '17 at 17:29
  • Yes, I have tried many APKs from several folder locations produced in the various ways described above, and clearing the folder before the new APK is produced. – Ollie C Jun 21 '17 at 18:45
  • does it occur if you remove the `copyReleaseApk` usage? – petey Jun 21 '17 at 19:15
  • @petey I tried disabling this, but it had no effect - the APK still contained debug data. – Ollie C Jun 22 '17 at 09:48
  • "It seems reasonable to assume that the debuggable=true state could be coming from one of the dependencies, but if that is the case which, and how can that be overridden?" -- in Android Studio, open your manifest, then choose the "Merged Manifest" sub-tab. Also, if you use `aapt`, [does it also report that the APK is debuggable](https://stackoverflow.com/a/41607696/115145)? – CommonsWare Jun 22 '17 at 13:09
  • @CommonsWare The mystery deepens as in the merged manifest debuggable is "false". – Ollie C Jun 22 '17 at 13:20
  • If `aapt` says that the APK is debuggable, then that would seem to imply that Gradle is making your app debuggable, and I do not see why. If `aapt` says that your app is *not* debuggable, then your issue would seem to be with the Play Store. – CommonsWare Jun 22 '17 at 13:25
  • @commonsware './aapt dump xmltree "MyApp v0.22.0-release.apk" AndroidManifest.xml | grep debuggable' produces this output: "A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff" so the APK is def debuggable. – Ollie C Jun 22 '17 at 13:36
  • At this point, the only way that I can see to identify the source of the difficulty is classic binary-search debugging: clone the project, rip out half of it, see if that's debuggable. If it is, rip out more and repeat. If it is not, start adding stuff back in and repeat. Lather and rinse as appropriate. Or, create a brand-new project, confirm that `release` builds are not debuggable, then start adding things in until the state changes. – CommonsWare Jun 22 '17 at 13:46
  • See also https://stackoverflow.com/questions/40886001/debuggable-is-true-in-release-mode-build – Ollie C Apr 17 '18 at 18:36

2 Answers2

3

As the project is targeting API 26 and using 3.0.0-alpha4 of the android gradle plugin, 26.0.0-beta2 build tools, and gradle 4.0-rc1 I thought I should check that the issue does not relate to an issue with these pre-release tools. So I reverted to API 25 and the stable releases of gradle 3.3, gradle plugin 2.3.3 and build tools 25.0.3. This was a little tedious as I had to downgrade all the Java 8 syntax from the source to Java 7. But having done that, the build process now works as expected and produces release APK artifacts that do not contain the debuggable="true" flag and can be uploaded to Google Play.

I'm not clear specifically where the cause is but I've logged this in the Android tools bug tracker as it seems possible it is a bug: https://issuetracker.google.com/issues/62899843

UPDATE: The response from the tools team is that this is expected behaviour because the app targets API 26 and that is in preview. I thought as the 26 APIs were final that APKs could be built against it and released to Google Play but clearly not.

Ollie C
  • 28,313
  • 34
  • 134
  • 217
0

This is because you probably have incremental builds, by default all incremental builds are assumed debuggable.

Under the General Notes of the SDK Tools Revision 8, it states:

Support for a true debug build. Developers no longer need to add the android:debuggable attribute to the tag in the manifest — the build tools add the attribute automatically. In Eclipse/ADT, all incremental builds are assumed to be debug builds, so the tools insert android:debuggable="true". When exporting a signed release build, the tools do not add the attribute. In Ant, a ant debug command automatically inserts the android:debuggable="true" attribute, while ant release does not. If android:debuggable="true" is manually set, then ant release will actually do a debug build, rather than a release build.

Dayan
  • 7,634
  • 11
  • 49
  • 76
  • "When exporting a signed release build, the tools do not add the attribute" - if this means using Generate Signed APK or Build APK then this is not the issue, as both of those approaches still produce a debuggable APK. I've tried clean full rebuilds with no success. – Ollie C Jun 21 '17 at 18:32