11

I have a project setup with two build types: debug and release.

In my app module I have three different directories: debug, release and main.

What I want to do is test the code in the release directory but the only way I can seem to do that is to generate a signed apk and load it onto an emulator that way. This means I can't debug it correctly.

When I change my app module's build variant to release I get the following error in the "Edit Configuration" popup.

Error: The apk for your currently selected variant (app-release-unsigned.apk_ is not signed. Please specify a signing configuration for this variant (release).

What I was hoping to do was extend the release build variant with one called debugRelease in the build.gradle file of the app module which would then inherit the code in the release directory but I would be able to run it from within the IDE.

I may be looking at this the wrong way and I would be glad to hear any other techniques.

Can I do what I'm trying to do? If not what is the best solution for this?

StuStirling
  • 15,601
  • 23
  • 93
  • 150
  • Not literally. The syntax you seek would require `debug` to be a product flavor, and `debug` is already used for a build type. – CommonsWare Feb 25 '16 at 14:47
  • So what am I left with, copying my classes from the `release` directory into another called debugRelease or something like that? – StuStirling Feb 25 '16 at 14:48
  • IMHO, having significant Java code in `release` is a code smell. That being said, you could set up a third build type (e.g., `fakerelease`), where you configure that build type to pull its Java code, resources, etc. from `release` and use the `debug` signing configuration. Gradle is flexible enough that you shouldn't need to copy the actual code. – CommonsWare Feb 25 '16 at 14:53
  • Do you think a better approach is to check whether in debug or release mode at runtime? – StuStirling Feb 25 '16 at 14:55
  • It's more that I think that there should be little to no change in functionality for a `release` build, and not enough functionality to require a debugger. So, for example, having a few lines in a custom `Application` subclass to tie in ACRA or another crash-reporting framework is fine, but you shouldn't need a debugger for that. – CommonsWare Feb 25 '16 at 15:23
  • You are exactly right. That is what I am using it for to implement a crash reporter. I just want to test that I have set it up correctly. For now I have just copied the code across into my new buildType. It may be that after I have tested everything is working I remove it. I'm not familiar enough with gradle to this automatically... – StuStirling Feb 25 '16 at 18:48
  • "I just want to test that I have set it up correctly" -- when I did this, I temporarily threw a `RuntimeException` from `onCreate()` of my launcher activity, from its code in the `main` sourceset. I confirmed that I got the crash report, and I then removed that line. – CommonsWare Feb 25 '16 at 18:54

2 Answers2

13

After a lot of research I decided to go ahead with my debugRelease idea and it seems to be working well.

I create a new directory under app/src called debugRelease/java. In there I put any code that I wanted to be different when I generated a signed apk or release version.

Doing so enables me to test the code works and be able to debug it. Granted this isn't done very often and it's only crash reporting and logging differences but, on the off chance I need to fix a bug or something, I can.

In my build.gradle file, I have the following setup.

buildTypes {
    release {

    }

    debug {

    }

    debugRelease {
        signingConfig signingConfigs.debug
    }
}

sourceSets { 
    debugRelease {
        res.srcDirs = ['src/debug/res'] // this uses the debug's res directory which contains a "debug" icon
    }

    release {
        java.srcDirs = ['src/debugRelease/java'] // this avoids copying across code from the debugRelease java directory
    }
}

So now when I want to test the release code, I just change my build variant to debugRelease.

StuStirling
  • 15,601
  • 23
  • 93
  • 150
8

You can build a release variant of your app (to use your production environment for example), with the following properties:

  • Full debugging enabled
  • Disabled ProGuard obfuscation and code shrinking
  • Disabled APK signing with the release certificate

Make these temporary changes to your app/build.gradle:

/* ADD THIS BLOCK, IF NOT ALREADY THERE */
lintOptions {
    // When you make a Release Build, the Android Lint tool will run to check many things.
    // It is set to abort the build on a single Lint error/warning. Disable this.
    abortOnError false
}

buildTypes {
    release {
        //minifyEnabled true   // <-- COMMENT OUT
        //proguardFiles ...    // <-- COMMENT OUT
        //shrinkResources true // <-- COMMENT OUT
        signingConfig signingConfigs.debug // <-- ADD THIS TO SIGN WITH YOUR DEBUG CERTIFICATE
        debuggable true     // <-- ADD THIS
        minifyEnabled false // <-- ADD THIS
    }
}

Then do Android Studio ➔ View ➔ Tool Windows ➔ Build Variants ➔ Select appRelease or whatever yours is called, then press the Run button to build and install it.

More info/related articles:

Mr-IDE
  • 7,051
  • 1
  • 53
  • 59