24

Before Android Studio, testing and Android app involved a separate Android project that would be ignored when building for production. With Android Studio, production code and test code exist within the same project, which itself only has one set of anything else (manifest, assets, resources).

This being the case, how would I define a custom Activity to be used only for testing? For Android to allow any Activity to be started, it must be declared in the manifest. Is there a way around this restriction? How can Android be instructed to load test-only Activities without polluting the production facets of the project?

jneander
  • 1,150
  • 14
  • 34
  • See http://stackoverflow.com/questions/21913619/test-specific-androidmanifest-file-attributes-and-extra-activities/21914630#21914630 – Scott Barta Feb 25 '14 at 19:51
  • Is there a way to achieve this using build types? – jneander Feb 25 '14 at 22:16
  • Yes, you should be able to do this with a build type instead of a flavor. – Scott Barta Feb 25 '14 at 22:22
  • The build system user guide states "The sourceSet should not contain an AndroidManifest.xml as it is automatically generated." What is necessary to inject an Activity element into the generated manifest? – jneander Feb 25 '14 at 23:06
  • 1
    That's the instrumentTest sourceSet, which is a special case for the APK for the driver app that tests your target APK. In this instance you're talking about setting up a build type, which for build type "foo" will have its source in src/foo, and which can have a manifest that's merged with the main manifest at build time. – Scott Barta Feb 25 '14 at 23:10

2 Answers2

25

Here's how to do it.

1. Define a new build type in your build.gradle:

buildTypes {
    extraActivity {
        signingConfig signingConfigs.debug
        debuggable true
    }
}

In mine I've given it the debug signing configuration and set it to debuggable; configure as you see fit.

2. Click the Sync Project with Gradle Files button.

3. Choose your new build type from the Build Variants window.

4. Set up source directories for your new build type

In my example, my files are going in the com.example.myapplication3.app Java package.

src/extraActivity/java/com/example/myapplication3/app
src/extraActivity/res

5. Create your new activity in the folders for your build type

Be aware that if you right-click on the package and choose New > Activity, there's a bug and it will not put the files for the activity into your new build type's folder, but it will put them in src/main instead. If you do that, you'll have to move the filers over to the correct folder by hand.

6. Create an AndroidManifest.xml file in src/extraActivity

This manifest gets merged with the version in src/main, so only add the bits that you need to overlay on top of the original:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication3.app" >

    <application>
        <activity
            android:name=".ExtraActivity"
            android:label="Extra Activity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

In my example, I've set up my new activity as a launcher activity so I can see it in the Apps screen and confirm it's working; you may not need to do that. Since I'm giving my app two launcher icons, I also need to follow the advice at Two launcher activities and add this to my main actvity's intent-filter (in src/main/AndroidManifest.xml); you may not need to do this either:

<category android:name="android.intent.category.DEFAULT"/>

Here's a screenshot of my project layout after all this is done:

Screen shot showing project structure

This works for me. I can switch build types back and forth with the Build Variants window (you can see the tab for it on the left-hand side of the screenshot above); building the debug variant only gives me one activity, and building the extraActivity variant gives me two.

Community
  • 1
  • 1
Scott Barta
  • 79,344
  • 24
  • 180
  • 163
  • This is pretty much exactly the solution I derived based on your earlier advice. Having this great breakdown here will be a valuable reference. Thank you. – jneander Feb 26 '14 at 02:06
  • I posted my followup question [here](https://stackoverflow.com/questions/22151390/recognize-custom-build-types-when-standard-build-variant-is-active). – jneander Mar 03 '14 at 16:05
1

I had the same problem. By following the answer by Scott Barta, I simply created a folder named "debug" in the "src" folder and created an AndroidManifest.xml with the activity used only for testing. This way the activity is added in the debug variant without creating a new variant like in the Scott Barta's answer.

  • Thanks! How do you call this activity from another? Do you need to write some code inside `debug` folder in any way? – CoolMind Jun 25 '20 at 13:39
  • Just see Scott Brata's answer, changing the folder "extraActivity" with "debug". – Pasquale Piccolo Jun 29 '20 at 07:34
  • 1
    Thanks, it works! In `release` mode we cannot access this new activity, as expected. But if we write a code in `debug` mode to launch the activity, it won't compile in `release`. So, you should add an empty activity with the same name in the `release` branch. See https://stackoverflow.com/questions/30442405/use-a-set-of-class-and-resource-only-in-debug-mode-with-gradle for details. – CoolMind Jul 09 '20 at 08:44